Threading primitives separated.
[strongswan.git] / src / libstrongswan / threading / lock_profiler.h
1 /*
2 * Copyright (C) 2008 Tobias Brunner
3 * Copyright (C) 2008 Martin Willi
4 * Hochschule fuer Technik Rapperswil
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 */
16
17 #ifndef THREADING_LOCK_PROFILER_H_
18 #define THREADING_LOCK_PROFILER_H_
19
20 #ifdef LOCK_PROFILER
21
22 #include <time.h>
23
24 /**
25 * Do not report mutexes with an overall waiting time smaller than this (in us)
26 */
27 #define PROFILE_TRESHHOLD 1000
28
29 #include <utils/backtrace.h>
30
31 typedef struct lock_profile_t lock_profile_t;
32
33 struct lock_profile_t {
34 /**
35 * how long threads have waited for the lock in this mutex so far
36 */
37 timeval_t waited;
38
39 /**
40 * backtrace where mutex has been created
41 */
42 backtrace_t *backtrace;
43 };
44
45 /**
46 * Print and cleanup mutex profiler
47 */
48 static inline void profiler_cleanup(lock_profile_t *profile)
49 {
50 if (profile->waited.tv_sec > 0 ||
51 profile->waited.tv_usec > PROFILE_TRESHHOLD)
52 {
53 fprintf(stderr, "%d.%06ds in lock created at:",
54 profile->waited.tv_sec, profile->waited.tv_usec);
55 profile->backtrace->log(profile->backtrace, stderr);
56 }
57 profile->backtrace->destroy(profile->backtrace);
58 }
59
60 /**
61 * Initialize mutex profiler
62 */
63 static inline void profiler_init(lock_profile_t *profile)
64 {
65 profile->backtrace = backtrace_create(2);
66 timerclear(&profile->waited);
67 }
68
69 #define profiler_start(profile) { \
70 struct timeval _start, _end, _diff; \
71 time_monotonic(&_start);
72
73 #define profiler_end(profile) \
74 time_monotonic(&_end); \
75 timersub(&_end, &_start, &_diff); \
76 timeradd(&(profile)->waited, &_diff, &(profile)->waited); }
77
78 #else /* !LOCK_PROFILER */
79
80 #define lock_profile_t struct {}
81 #define profiler_cleanup(...) {}
82 #define profiler_init(...) {}
83 #define profiler_start(...) {}
84 #define profiler_end(...) {}
85
86 #endif /* LOCK_PROFILER */
87
88 #endif /* THREADING_LOCK_PROFILER_H_ */
89