1 #ifndef __PROFILE_H_
2 #define __PROFILE_H_
3 
4 #include <sys/time.h>
5 
6 #ifndef PROFILE_MAX_VAR
7 #define PROFILE_MAX_VAR 20
8 #endif
9 
10 #ifdef PROFILE_STATIC
11 #define STATIC static
12 #else
13 #define STATIC
14 #endif
15 
16 #ifdef PROFILE_ON
17 
18 #define PROFILE_LOCK() \
19 	__lock = __sync_lock_test_and_set(&__st_lock, 1)
20 
21 #define PROFILE_UNLOCK() \
22 	if (__lock == 0) __sync_lock_release(&__st_lock)
23 
24 #define PROFILE_INIT() \
25 	STATIC struct timeval __tv_total_from, __tv_total_to; \
26 STATIC long __c_total_us = 0, __c_etc_us = 0; \
27 STATIC long *__var_list[PROFILE_MAX_VAR] = {NULL}; \
28 STATIC char *__name_list[PROFILE_MAX_VAR] = {NULL}; \
29 char __lock = 0; \
30 static char __st_lock = 0
31 
32 #define PROFILE_START() \
33 	do { \
34 		if (__lock == 0) gettimeofday(&__tv_total_from, NULL); \
35 	} while (0)
36 
37 #define PROFILE_END() \
38 	do {\
39 		if (__lock == 0) { \
40 			gettimeofday(&__tv_total_to, NULL); \
41 			__c_total_us \
42 			+= (__tv_total_to.tv_sec - __tv_total_from.tv_sec) * 1000000 \
43 			+ (__tv_total_to.tv_usec - __tv_total_from.tv_usec); \
44 		} \
45 	} while (0)
46 
47 #define PROFILE_VAR(var) \
48 	STATIC struct timeval __##var##_tv_from, __##var##_tv_to; \
49 STATIC long __##var##_us = 0; \
50 STATIC int __iter_##var = -1; \
51 {if (__lock == 0 && __iter_##var == -1) \
52 	for (__iter_##var = 0; __iter_##var < PROFILE_MAX_VAR; __iter_##var++) \
53 	if (__var_list[__iter_##var] == NULL) { \
54 		__var_list[__iter_##var] = &__##var##_us; \
55 		__name_list[__iter_##var] = (char *)#var; break;}}
56 
57 #define PROFILE_FROM(var) \
58 	do { \
59 		if (__lock == 0) \
60 		gettimeofday(&__##var##_tv_from, NULL); \
61 	} while (0)
62 
63 #define PROFILE_TO(var) \
64 	do { \
65 		if (__lock == 0) { \
66 			gettimeofday(&__##var##_tv_to, NULL); \
67 			__##var##_us \
68 			+= (__##var##_tv_to.tv_sec - __##var##_tv_from.tv_sec) * 1000000 \
69 			+ (__##var##_tv_to.tv_usec - __##var##_tv_from.tv_usec); \
70 		} \
71 	} while (0)
72 
73 #define PROFILE_PRINT(fp) \
74 	do { int i; \
75 		if (__lock == 0) { \
76 			__c_etc_us = __c_total_us; \
77 			for (i = 0; i < PROFILE_MAX_VAR; i++) \
78 			if (__var_list[i]) __c_etc_us -= *__var_list[i]; \
79 			fprintf(fp, "[PROFILE %s]\n", __func__); \
80 			for (i = 0; i < PROFILE_MAX_VAR; i++) \
81 			if (__var_list[i] != NULL) { \
82 				printf("                              : %11.3lf ms (%5.2lf %%)", \
83 						(double)*__var_list[i] / 1000.0, \
84 						100 * (double)*__var_list[i] / (double)__c_total_us); \
85 				printf("\r%s\n", __name_list[i]); \
86 			} \
87 			fprintf(fp, "etc. (includes the overhead)  : %11.3lf ms (%5.2lf %%)\n", \
88 					(double)__c_etc_us / 1000.0, \
89 					100 * (double)__c_etc_us / (double)__c_total_us); \
90 			fprintf(fp, "total                         : %11.3lf ms\n", \
91 					(double)__c_total_us / 1000.0); \
92 			fflush(fp); \
93 		} \
94 	} while (0)
95 
96 #else /* PROFILE_ON */
97 #define PROFILE_LOCK()
98 #define PROFILE_UNLOCK()
99 #define PROFILE_INIT()
100 #define PROFILE_START()
101 #define PROFILE_END()
102 #define PROFILE_VAR(args...)
103 #define PROFILE_FROM(args...)
104 #define PROFILE_TO(args...)
105 #define PROFILE_PRINT(args...)
106 #endif /* PROFILE_ON */
107 
108 #endif /* __PROFILE_H_ */
109