2
0

profile.h 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. /*
  2. * Copyright (C) 2007 iptelorg GmbH
  3. *
  4. * Permission to use, copy, modify, and distribute this software for any
  5. * purpose with or without fee is hereby granted, provided that the above
  6. * copyright notice and this permission notice appear in all copies.
  7. *
  8. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  9. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  11. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  13. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  14. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. /*
  17. * Basic profile using the cpu cycle counter
  18. *
  19. * cycles_t - an unsigned interger type used for storing the cpu cycles
  20. * (unsigned long long for now)
  21. *
  22. * cycles_t get_cpu_cycles() - returns the current cpu cycles counter
  23. *
  24. * void get_cpu_cycles_uint(unsigned* u1, unsigned* u2)
  25. * - sets u1 and u2 to the least significant,
  26. * respective most significant 32 bit word of
  27. * the cpu cycles counter
  28. * struct profile_data; - holds all the profile results
  29. * (last call cycles, max cycles, total cycles,
  30. * no. of profile_start calls, no. of
  31. * profile_end calls, name use in profile_init)
  32. * void profile_init(pd, name) - initialize a profile structure
  33. * void profile_start(pd) - starts profiling (call before calling
  34. * the target function)
  35. * void profile_end(pd) - stops profiling (call after the target
  36. * function returns)
  37. *
  38. */
  39. /*
  40. * Config defines: CC_GCC_LIKE_ASM - the compiler support gcc style
  41. * inline asm,
  42. * __CPU_x86, __CPU_x86_64, __CPU_sparc64
  43. */
  44. /*
  45. * History:
  46. * --------
  47. * 2007-06-23 created by andrei
  48. */
  49. #ifndef _profile_h
  50. #define _profile_h
  51. #include <string.h>
  52. /*
  53. * cycles_t - an unsigned interger type used for storing the cpu cycles
  54. * (unsigned long long for now)
  55. *
  56. * cycles_t get_cpu_cycles() - returns the current cpu cycles counter
  57. * void get_cpu_cycles_uint(unsigned* u1, unsigned* u2)
  58. * - sets u1 and u2 to the least significant,
  59. * respective most significant 32 bit word of
  60. * the cpu cycles counter
  61. */
  62. #if defined __CPU_i386 && ! defined __CPU_x86
  63. #define __CPU_x86
  64. #endif
  65. #ifdef __CPU_x86
  66. typedef unsigned long long cycles_t;
  67. inline static cycles_t get_cpu_cycles()
  68. {
  69. cycles_t r;
  70. asm volatile( "rdtsc \n\t" : "=A"(r));
  71. return r;
  72. }
  73. #define get_cpu_cycles_uint(u1, u2) \
  74. do{ \
  75. /* result in edx:eax */ \
  76. asm volatile( "rdtsc \n\t" : "=a"(*(u1)), "=d"(*(u2))); \
  77. }while(0)
  78. #elif defined __CPU_x86_64
  79. typedef unsigned long long cycles_t;
  80. inline static cycles_t get_cpu_cycles()
  81. {
  82. unsigned int u1, u2;
  83. asm volatile( "rdtsc \n\t" : "=a"(u1), "=d"(u2));
  84. return ((cycles_t)u2<<32ULL)|u1;
  85. }
  86. #define get_cpu_cycles_uint(u1, u2) \
  87. do{ \
  88. /* result in edx:eax */ \
  89. asm volatile( "rdtsc \n\t" : "=a"(*(u1)), "=d"(*(u2))); \
  90. }while(0)
  91. #elif defined __CPU_sparc64
  92. typedef unsigned long long cycles_t;
  93. inline static cycles_t get_cpu_cycles()
  94. {
  95. #if ! defined(_LP64)
  96. #warning "ilp32 mode "
  97. struct uint_64{
  98. unsigned int u2;
  99. unsigned int u1;
  100. };
  101. union{
  102. cycles_t c;
  103. struct uint_64 u;
  104. }r;
  105. asm volatile("rd %%tick, %0 \n\t"
  106. "srlx %0, 32, %1 \n\t"
  107. : "=r"(r.u.u1), "=r"(r.u.u2));
  108. return r.c;
  109. #else
  110. cycles_t r;
  111. /* normal 64 bit mode (e.g. gcc -m64) */
  112. asm volatile("rd %%tick, %0" : "=r"(r));
  113. return r;
  114. #endif
  115. }
  116. inline static void get_cpu_cycles_uint(unsigned int* u1, unsigned int* u2)
  117. {
  118. cycles_t r;
  119. asm volatile("rd %%tick, %0" : "=r"(r));
  120. *u1=(unsigned int)r;
  121. *u2=(unsigned int)(r>>32);
  122. }
  123. #else /* __CPU_xxx */
  124. #error "no get_cycles support for this CPU"
  125. #endif /* __CPU_xxx */
  126. union profile_cycles{
  127. cycles_t c;
  128. struct{
  129. unsigned int u1;
  130. unsigned int u2;
  131. }uint;
  132. };
  133. struct profile_data{
  134. cycles_t cycles; /* last call */
  135. cycles_t total_cycles;
  136. cycles_t max_cycles;
  137. unsigned long entries; /* no. profile_start calls */
  138. unsigned long exits; /* no. profile_end calls */
  139. char * name;
  140. /* private stuff */
  141. union profile_cycles init_rdtsc;
  142. };
  143. inline static void profile_init(struct profile_data* pd, char *name)
  144. {
  145. memset(pd, 0, sizeof(*pd));
  146. pd->name=name;
  147. }
  148. inline static void profile_start(struct profile_data* pd)
  149. {
  150. pd->entries++;
  151. pd->init_rdtsc.c=get_cpu_cycles();
  152. }
  153. inline static void profile_end(struct profile_data* pd)
  154. {
  155. pd->cycles=get_cpu_cycles()-pd->init_rdtsc.c;
  156. if (pd->max_cycles<pd->cycles) pd->max_cycles=pd->cycles;
  157. pd->total_cycles+=pd->cycles;
  158. pd->exits++;
  159. }
  160. #endif