preprocessor.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. #pragma once
  2. #include "check.h"
  3. #include "perf.h"
  4. #include "symbol.h"
  5. #include <util/generic/hide_ptr.h>
  6. #include <util/system/platform.h>
  7. #include <stddef.h> //size_t
  8. #ifdef _win_
  9. #ifndef LWTRACE_DISABLE
  10. #define LWTRACE_DISABLE
  11. #endif // LWTRACE_DISABLE
  12. #endif // _win_
  13. // Maximum number of executors that can be attached to a probe
  14. #define LWTRACE_MAX_ACTIONS 100
  15. // Maximum number of groups that can be assigned to a probe
  16. #define LWTRACE_MAX_GROUPS 100
  17. #ifndef LWTRACE_DISABLE
  18. /*
  19. * WARNING: All macros define in this header must be considered as implementation details and should NOT be used directly
  20. * WARNING: See lwtrace/all.h for macros that represent a user interface of lwtrace library
  21. *
  22. */
  23. // Use for code generation to handle parameter types. USAGE:
  24. // 1. #define FOREACH_PARAMTYPE_MACRO(n, t, v, your_p1, your_p2) your code snippet
  25. // 2. FOREACH_PARAMTYPE(FOREACH_PARAMTYPE_MACRO, your_p1_value, your_p1_value)
  26. // FOREACH_PARAMTYPE(FOREACH_PARAMTYPE_MACRO, your_p1_another_value, your_p1_another_value)
  27. // 3. #undef FOREACH_PARAMTYPE_MACRO
  28. // Type order matters!
  29. #define FOREACH_PARAMTYPE(MACRO, ...) \
  30. MACRO("i64", i64, I64, ##__VA_ARGS__) \
  31. MACRO("ui64", ui64, Ui64, ##__VA_ARGS__) \
  32. MACRO("double", double, Double, ##__VA_ARGS__) \
  33. MACRO("string", TString, Str, ##__VA_ARGS__) \
  34. MACRO("symbol", NLWTrace::TSymbol, Symbol, ##__VA_ARGS__) \
  35. MACRO("check", NLWTrace::TCheck, Check, ##__VA_ARGS__) \
  36. /**/
  37. // Used with FOREACH_PARAMTYPE to handle TNil parameter type also
  38. #define FOR_NIL_PARAMTYPE(MACRO, ...) \
  39. MACRO(NULL, TNil, Nil, ##__VA_ARGS__) \
  40. /**/
  41. // Used for math statements
  42. #define FOR_MATH_PARAMTYPE(MACRO, ...) \
  43. MACRO("i64", i64, I64, ##__VA_ARGS__) \
  44. MACRO("ui64", ui64, Ui64, ##__VA_ARGS__) \
  45. MACRO("check", NLWTrace::TCheck, Check, ##__VA_ARGS__) \
  46. /**/
  47. // Use for code generation to handle parameter lists
  48. // NOTE: this is the only place to change if more parameters needed
  49. #define FOREACH_PARAMNUM(MACRO, ...) \
  50. MACRO(0, ##__VA_ARGS__) \
  51. MACRO(1, ##__VA_ARGS__) \
  52. MACRO(2, ##__VA_ARGS__) \
  53. MACRO(3, ##__VA_ARGS__) \
  54. MACRO(4, ##__VA_ARGS__) \
  55. MACRO(5, ##__VA_ARGS__) \
  56. MACRO(6, ##__VA_ARGS__) \
  57. MACRO(7, ##__VA_ARGS__) \
  58. MACRO(8, ##__VA_ARGS__) \
  59. MACRO(9, ##__VA_ARGS__) \
  60. MACRO(10, ##__VA_ARGS__) \
  61. MACRO(11, ##__VA_ARGS__) \
  62. MACRO(12, ##__VA_ARGS__) \
  63. MACRO(13, ##__VA_ARGS__) \
  64. MACRO(14, ##__VA_ARGS__) \
  65. MACRO(15, ##__VA_ARGS__) \
  66. MACRO(16, ##__VA_ARGS__) \
  67. /**/
  68. #define FOREACH_LEFT_TYPE(MACRO, ...) \
  69. MACRO(__VA_ARGS__, OT_VARIABLE) \
  70. MACRO(__VA_ARGS__, OT_LITERAL) \
  71. MACRO(__VA_ARGS__, OT_PARAMETER) \
  72. /**/
  73. #define FOREACH_RIGHT_TYPE(MACRO, ...) \
  74. MACRO(__VA_ARGS__, OT_VARIABLE) \
  75. MACRO(__VA_ARGS__, OT_LITERAL) \
  76. MACRO(__VA_ARGS__, OT_PARAMETER) \
  77. /**/
  78. #define FOREACH_DESTINATION_TYPE(MACRO, ...) \
  79. MACRO(__VA_ARGS__, OT_VARIABLE) \
  80. /**/
  81. // Auxilary macros
  82. #define LWTRACE_EXPAND(x) x
  83. #define LWTRACE_EAT(...)
  84. // Eat last/first comma trick
  85. #define LWTRACE_COMMA(bit) LWTRACE_COMMA_##bit()
  86. #define LWTRACE_COMMA_0()
  87. #define LWTRACE_COMMA_1() ,
  88. // Macros to pack/unpack tuples, e.g. (x,y,z)
  89. #define LWTRACE_UNROLL(...) __VA_ARGS__
  90. #define LWTRACE_ENROLL(...) (__VA_ARGS__)
  91. // Param types list handling macros
  92. #define LWTRACE_TEMPLATE_PARAMS_I(i) (1) class TP##i = TNil LWTRACE_COMMA
  93. #define LWTRACE_TEMPLATE_PARAMS LWTRACE_EXPAND(LWTRACE_EAT FOREACH_PARAMNUM(LWTRACE_TEMPLATE_PARAMS_I)(0))
  94. #define LWTRACE_TEMPLATE_PARAMS_NODEF_I(i) (1) class TP##i LWTRACE_COMMA
  95. #define LWTRACE_TEMPLATE_PARAMS_NODEF LWTRACE_EXPAND(LWTRACE_EAT FOREACH_PARAMNUM(LWTRACE_TEMPLATE_PARAMS_NODEF_I)(0))
  96. #define LWTRACE_TEMPLATE_ARGS_I(i) (1) TP##i LWTRACE_COMMA
  97. #define LWTRACE_TEMPLATE_ARGS LWTRACE_EXPAND(LWTRACE_EAT FOREACH_PARAMNUM(LWTRACE_TEMPLATE_ARGS_I)(0))
  98. #define LWTRACE_FUNCTION_PARAMS_I(i) (1) typename ::NLWTrace::TParamTraits<TP##i>::TFuncParam p##i = ERROR_not_enough_parameters() LWTRACE_COMMA
  99. #define LWTRACE_FUNCTION_PARAMS LWTRACE_EXPAND(LWTRACE_EAT FOREACH_PARAMNUM(LWTRACE_FUNCTION_PARAMS_I)(0))
  100. #define LWTRACE_PREPARE_PARAMS_I(i, params) params.Param[i].template CopyConstruct<typename ::NLWTrace::TParamTraits<TP##i>::TStoreType>(::NLWTrace::TParamTraits<TP##i>::ToStoreType(p##i));
  101. #define LWTRACE_PREPARE_PARAMS(params) \
  102. do { \
  103. FOREACH_PARAMNUM(LWTRACE_PREPARE_PARAMS_I, params) \
  104. } while (false)
  105. #define LWTRACE_COUNT_PARAMS_I(i) +(std::is_same<TP##i, ::NLWTrace::TNil>::value ? 0 : 1)
  106. #define LWTRACE_COUNT_PARAMS (0 FOREACH_PARAMNUM(LWTRACE_COUNT_PARAMS_I))
  107. #define LWTRACE_MAX_PARAMS_I(i) +1
  108. #define LWTRACE_MAX_PARAMS (0 FOREACH_PARAMNUM(LWTRACE_MAX_PARAMS_I))
  109. // Determine maximum sizeof(t) over all supported types
  110. #define LWTRACE_MAX_PARAM_SIZE_TA_TAIL_I(n, t, v) v,
  111. #define LWTRACE_MAX_PARAM_SIZE_TA_TAIL \
  112. FOREACH_PARAMTYPE(LWTRACE_MAX_PARAM_SIZE_TA_TAIL_I) \
  113. 0
  114. #define LWTRACE_MAX_PARAM_SIZE_TP_I(n, t, v) , size_t v = 0
  115. #define LWTRACE_MAX_PARAM_SIZE_TP size_t Head = 0 FOREACH_PARAMTYPE(LWTRACE_MAX_PARAM_SIZE_TP_I)
  116. #define LWTRACE_MAX_PARAM_SIZE_TA_I(n, t, v) , sizeof(t)
  117. #define LWTRACE_MAX_PARAM_SIZE_TA 0 FOREACH_PARAMTYPE(LWTRACE_MAX_PARAM_SIZE_TA_I)
  118. #define LWTRACE_MAX_PARAM_SIZE ::NLWTrace::TMaxParamSize<LWTRACE_MAX_PARAM_SIZE_TA>::Result
  119. namespace NLWTrace {
  120. template <LWTRACE_MAX_PARAM_SIZE_TP>
  121. struct TMaxParamSize {
  122. static const size_t Tail = TMaxParamSize<LWTRACE_MAX_PARAM_SIZE_TA_TAIL>::Result;
  123. static const size_t Result = (Head > Tail ? Head : Tail);
  124. };
  125. template <>
  126. struct TMaxParamSize<> {
  127. static const size_t Result = 0;
  128. };
  129. }
  130. // Define stuff that is needed to register probes before main()
  131. #define LWTRACE_REGISTER_PROBES(provider) \
  132. namespace LWTRACE_GET_NAMESPACE(provider) { \
  133. struct TInitLWTrace##provider { \
  134. TInitLWTrace##provider() { \
  135. Singleton<NLWTrace::TProbeRegistry>()->AddProbesList(LWTRACE_GET_PROBES(provider)); \
  136. } \
  137. /* This may not be in anonymous namespace because otherwise */ \
  138. /* it is called twice when .so loaded twice */ \
  139. }* InitLWTrace##provider = Singleton<TInitLWTrace##provider>(); \
  140. } \
  141. /**/
  142. // Macro for TSignature POD structure static initialization
  143. #define LWTRACE_SIGNATURE_CTOR(types, names) \
  144. { \
  145. /* ParamTypes */ ::NLWTrace::TUserSignature<LWTRACE_EXPAND(LWTRACE_UNROLL types)>::ParamTypes, \
  146. /* ParamNames */ {LWTRACE_EXPAND(LWTRACE_UNROLL names)}, \
  147. /* ParamCount */ ::NLWTrace::TUserSignature<LWTRACE_EXPAND(LWTRACE_UNROLL types)>::ParamCount, \
  148. /* SerializeParams */ &::NLWTrace::TUserSignature<LWTRACE_EXPAND(LWTRACE_UNROLL types)>::SerializeParams, \
  149. /* CloneParams */ &::NLWTrace::TUserSignature<LWTRACE_EXPAND(LWTRACE_UNROLL types)>::CloneParams, \
  150. /* DestroyParams */ &::NLWTrace::TUserSignature<LWTRACE_EXPAND(LWTRACE_UNROLL types)>::DestroyParams, \
  151. /* SerializeToPb */ &::NLWTrace::TUserSignature<LWTRACE_EXPAND(LWTRACE_UNROLL types)>::SerializeToPb, \
  152. /* DeserializeFromPb */ &::NLWTrace::TUserSignature<LWTRACE_EXPAND(LWTRACE_UNROLL types)>::DeserializeFromPb\
  153. }
  154. // Macro for TEvent POD structure static initialization
  155. #define LWTRACE_EVENT_CTOR(name, groups, types, names) \
  156. { \
  157. /* Name */ #name, \
  158. /* Groups */ {LWTRACE_EXPAND(LWTRACE_UNROLL_GROUPS groups)}, \
  159. /* Signature */ LWTRACE_SIGNATURE_CTOR(types, names) \
  160. }
  161. // Macro for TProbe POD structure static initialization
  162. #define LWTRACE_PROBE_CTOR(name, groups, types, names) \
  163. { \
  164. /* Event */ LWTRACE_EVENT_CTOR(name, groups, types, names), \
  165. /* ExecutorsCount */ 0, \
  166. /* Lock */ {0}, \
  167. /* Executors */ {0}, \
  168. /* Front */ 0, \
  169. /* Back */ 0 \
  170. }
  171. // Provider static data accessors
  172. #define LWTRACE_GET_NAMESPACE(provider) NLWTrace_##provider
  173. #define LWTRACE_GET_NAME(name) lwtrace_##name
  174. #define LWTRACE_GET_TYPE(name) TLWTrace_##name
  175. #define LWTRACE_GET_PROBES_I(provider) gProbes##provider
  176. #define LWTRACE_GET_EVENTS_I(provider) gEvents##provider
  177. // Declaration of provider static data
  178. #define LWTRACE_DECLARE_PROBE(name, groups, types, names) \
  179. typedef ::NLWTrace::TUserProbe<LWTRACE_EXPAND(LWTRACE_UNROLL types)> LWTRACE_GET_TYPE(name); \
  180. extern LWTRACE_GET_TYPE(name) LWTRACE_GET_NAME(name); \
  181. /**/
  182. #define LWTRACE_DECLARE_EVENT(name, groups, types, names) \
  183. typedef ::NLWTrace::TUserEvent<LWTRACE_EXPAND(LWTRACE_UNROLL types)> LWTRACE_GET_TYPE(name); \
  184. extern LWTRACE_GET_TYPE(name) LWTRACE_GET_NAME(name); \
  185. /**/
  186. #define LWTRACE_DECLARE_PROVIDER_I(provider) \
  187. namespace LWTRACE_GET_NAMESPACE(provider) { \
  188. provider(LWTRACE_DECLARE_PROBE, LWTRACE_DECLARE_EVENT, LWTRACE_ENROLL, LWTRACE_ENROLL, LWTRACE_ENROLL) \
  189. } \
  190. extern ::NLWTrace::TProbe* LWTRACE_GET_PROBES_I(provider)[]; \
  191. extern ::NLWTrace::TEvent* LWTRACE_GET_EVENTS_I(provider)[]; \
  192. /**/
  193. // Initialization of provider static data
  194. #define LWTRACE_UNROLL_GROUPS(x) #x, LWTRACE_UNROLL
  195. #define LWTRACE_DEFINE_PROBE(name, groups, types, names) \
  196. LWTRACE_GET_TYPE(name) \
  197. LWTRACE_GET_NAME(name) = \
  198. {LWTRACE_PROBE_CTOR(name, groups, types, names)}; \
  199. /**/
  200. #define LWTRACE_DEFINE_EVENT(name, groups, types, names) \
  201. LWTRACE_GET_TYPE(name) \
  202. LWTRACE_GET_NAME(name) = \
  203. {LWTRACE_EVENT_CTOR(name, groups, types, names)}; \
  204. /**/
  205. #define LWTRACE_PROBE_ADDRESS_I(name, groups, types, names) \
  206. LWTRACE_GET_NAME(name).Probe, /**/
  207. #define LWTRACE_PROBE_ADDRESS(provider) \
  208. &LWTRACE_GET_NAMESPACE(provider)::LWTRACE_PROBE_ADDRESS_I /**/
  209. #define LWTRACE_EVENT_ADDRESS_I(name, groups, types, names) \
  210. LWTRACE_GET_NAME(name).Event, /**/
  211. #define LWTRACE_EVENT_ADDRESS(provider) \
  212. &LWTRACE_GET_NAMESPACE(provider)::LWTRACE_EVENT_ADDRESS_I /**/
  213. #define LWTRACE_DEFINE_PROVIDER_I(provider) \
  214. namespace LWTRACE_GET_NAMESPACE(provider) { \
  215. provider(LWTRACE_DEFINE_PROBE, LWTRACE_DEFINE_EVENT, (provider)LWTRACE_ENROLL, LWTRACE_ENROLL, LWTRACE_ENROLL) \
  216. } \
  217. ::NLWTrace::TProbe* LWTRACE_GET_PROBES_I(provider)[] = { \
  218. provider(LWTRACE_PROBE_ADDRESS(provider), LWTRACE_EAT, LWTRACE_ENROLL, LWTRACE_ENROLL, LWTRACE_ENROLL) \
  219. NULL}; \
  220. ::NLWTrace::TEvent* LWTRACE_GET_EVENTS_I(provider)[] = { \
  221. provider(LWTRACE_EAT, LWTRACE_EVENT_ADDRESS(provider), LWTRACE_ENROLL, LWTRACE_ENROLL, LWTRACE_ENROLL) \
  222. NULL}; \
  223. LWTRACE_REGISTER_PROBES(provider)
  224. /**/
  225. #define LWPROBE_I(probe, ...) \
  226. do { \
  227. if ((probe).Probe.GetExecutorsCount() > 0) { \
  228. ::NLWTrace::TScopedThreadCpuTracker _cpuTracker(probe); \
  229. TReadSpinLockGuard g((probe).Probe.Lock); \
  230. if ((probe).Probe.GetExecutorsCount() > 0) { \
  231. (probe)(__VA_ARGS__); \
  232. } \
  233. } \
  234. } while (false) /**/
  235. #define LWPROBE_ENABLED_I(probe) ((probe).Probe.GetExecutorsCount() > 0)
  236. #define LWPROBE_DURATION_I(probetype, uniqid, probe, ...) probetype ::TScopedDuration uniqid(probe, 0 /* fake P0 - used for duration */, ##__VA_ARGS__);
  237. #define LWTRACK_I(probe, orbit, ...) \
  238. do { \
  239. if ((probe).Probe.GetExecutorsCount() > 0) { \
  240. ::NLWTrace::TScopedThreadCpuTracker _cpuTracker(probe); \
  241. TReadSpinLockGuard g((probe).Probe.Lock); \
  242. if ((probe).Probe.GetExecutorsCount() > 0) { \
  243. (probe).Run(orbit, ##__VA_ARGS__); \
  244. } \
  245. } else { \
  246. auto& _orbit = (orbit); \
  247. if (HasShuttles(_orbit)) { \
  248. ::NLWTrace::TScopedThreadCpuTracker _cpuTracker(probe); \
  249. (probe).RunShuttles(_orbit, ##__VA_ARGS__); \
  250. } \
  251. } \
  252. } while (false) /**/
  253. #define LWEVENT_I(event, ...) (event)(__VA_ARGS__)
  254. #else
  255. #define LWTRACE_MAX_PARAM_SIZE sizeof(void*)
  256. #define LWTRACE_MAX_PARAMS 1
  257. #define FOREACH_PARAMTYPE(MACRO, ...)
  258. #endif