1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
|
/* thread and state timing time object and functions, for libreswan
*
* Copyright (C) 2019 Andrew Cagney <cagney@gnu.org>
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Library General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <https://www.gnu.org/licenses/lgpl-2.1.txt>.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
* License for more details.
*
*/
#ifndef PLUTO_TIMING_H
#define PLUTO_TIMING_H /* seen it, no need to see it again */
#include <stdbool.h> /* for bool */
#include <time.h> /* for struct timespec */
#include "lswcdefs.h" /* for PRINTF_LIKE() */
#include "monotime.h"
struct state;
struct logger;
/*
* Try to format all cpu usage messaages the same. All delta-times
* use double and are in seconds.
*/
struct cpu_timing {
struct timespec thread_clock;
struct timespec wall_clock;
};
struct cpu_usage {
double thread_seconds;
double wall_seconds;
};
#define PRI_CPU_USAGE "spent %.3g (%.3g) milliseconds"
#define pri_cpu_usage(C) ((C).thread_seconds * 1000), ((C).wall_seconds * 1000)
#define cpu_usage_add(TOTAL, USAGE) \
{ \
(TOTAL).thread_seconds += (USAGE).thread_seconds; \
(TOTAL).wall_seconds += (USAGE).wall_seconds; \
}
/*
* For when on a helper thread (or anything that doesn't have a
* state).
*
* threadtime_t start = threadtime_start();
* do something;
* seconds_used = threadtime_stop(&start, serialno, "do something");
*/
typedef struct cpu_timing threadtime_t;
threadtime_t threadtime_start(void);
void threadtime_stop(const threadtime_t *start, long serialno, const char *fmt, ...) PRINTF_LIKE(3);
monotime_t monotime_from_threadtime(const threadtime_t start);
/*
* For helper threads that have some context.
*/
typedef struct {
struct cpu_timing time;
struct logger *logger;
int level;
} logtime_t;
logtime_t logtime_start(struct logger *logger);
struct cpu_usage logtime_stop(const logtime_t *start, const char *fmt, ...) PRINTF_LIKE(2);
/*
* For state timing:
*
* In theory:
*
* p0 = statetime_start(st);
* p1 = statetime_start(st)
* do something
* statetime_start(&p1, "did something else");
* p1 = statetime_start(st)
* do something else;
* statetime_stop(&p1, "did something else");
* statetime_stop(&p0, "did several things");
*
* But several things bite:
*
* - "do something" might delete the state (complete_v2*() likes to
* delete it, and or zap mpd), so forced to use so_serial_t when
* performing statetime_update.
*
* - "do something" might create the state so need to poke around in
* state.c to find what the next serialno might be
*
* - should be layered on top of push/pop state, except that is a
* bigger mess!
*
* - the call statetime_start(NULL) returns the start time of the next
* (yet to be created) state. When the state is created a second
* statetime_start(new) gets things kind of in sync. Ewww!
*/
struct state_timing {
struct cpu_usage helper_usage;
struct cpu_usage main_usage;
int level;
/*
* Track last time something was logged and its level. Used
* when checking for unaccounted time.
*/
struct {
struct cpu_timing time;
int level;
} last_log;
};
typedef struct {
so_serial_t so;
int level;
struct cpu_timing time;
} statetime_t;
statetime_t statetime_backdate(struct state *st, const threadtime_t *inception);
statetime_t statetime_start(struct state *st);
void statetime_stop(const statetime_t *start, const char *fmt, ...) PRINTF_LIKE(2);
#endif
|