#pragma once #include "check.h" #include "perf.h" #include "symbol.h" #include #include #include //size_t #ifdef _win_ #ifndef LWTRACE_DISABLE #define LWTRACE_DISABLE #endif // LWTRACE_DISABLE #endif // _win_ // Maximum number of executors that can be attached to a probe #define LWTRACE_MAX_ACTIONS 100 // Maximum number of groups that can be assigned to a probe #define LWTRACE_MAX_GROUPS 100 #ifndef LWTRACE_DISABLE /* * WARNING: All macros define in this header must be considered as implementation details and should NOT be used directly * WARNING: See lwtrace/all.h for macros that represent a user interface of lwtrace library * */ // Use for code generation to handle parameter types. USAGE: // 1. #define FOREACH_PARAMTYPE_MACRO(n, t, v, your_p1, your_p2) your code snippet // 2. FOREACH_PARAMTYPE(FOREACH_PARAMTYPE_MACRO, your_p1_value, your_p1_value) // FOREACH_PARAMTYPE(FOREACH_PARAMTYPE_MACRO, your_p1_another_value, your_p1_another_value) // 3. #undef FOREACH_PARAMTYPE_MACRO // Type order matters! #define FOREACH_PARAMTYPE(MACRO, ...) \ MACRO("i64", i64, I64, ##__VA_ARGS__) \ MACRO("ui64", ui64, Ui64, ##__VA_ARGS__) \ MACRO("double", double, Double, ##__VA_ARGS__) \ MACRO("string", TString, Str, ##__VA_ARGS__) \ MACRO("symbol", NLWTrace::TSymbol, Symbol, ##__VA_ARGS__) \ MACRO("check", NLWTrace::TCheck, Check, ##__VA_ARGS__) \ /**/ // Used with FOREACH_PARAMTYPE to handle TNil parameter type also #define FOR_NIL_PARAMTYPE(MACRO, ...) \ MACRO(NULL, TNil, Nil, ##__VA_ARGS__) \ /**/ // Used for math statements #define FOR_MATH_PARAMTYPE(MACRO, ...) \ MACRO("i64", i64, I64, ##__VA_ARGS__) \ MACRO("ui64", ui64, Ui64, ##__VA_ARGS__) \ MACRO("check", NLWTrace::TCheck, Check, ##__VA_ARGS__) \ /**/ // Use for code generation to handle parameter lists // NOTE: this is the only place to change if more parameters needed #define FOREACH_PARAMNUM(MACRO, ...) \ MACRO(0, ##__VA_ARGS__) \ MACRO(1, ##__VA_ARGS__) \ MACRO(2, ##__VA_ARGS__) \ MACRO(3, ##__VA_ARGS__) \ MACRO(4, ##__VA_ARGS__) \ MACRO(5, ##__VA_ARGS__) \ MACRO(6, ##__VA_ARGS__) \ MACRO(7, ##__VA_ARGS__) \ MACRO(8, ##__VA_ARGS__) \ MACRO(9, ##__VA_ARGS__) \ MACRO(10, ##__VA_ARGS__) \ MACRO(11, ##__VA_ARGS__) \ MACRO(12, ##__VA_ARGS__) \ MACRO(13, ##__VA_ARGS__) \ MACRO(14, ##__VA_ARGS__) \ MACRO(15, ##__VA_ARGS__) \ MACRO(16, ##__VA_ARGS__) \ /**/ #define FOREACH_LEFT_TYPE(MACRO, ...) \ MACRO(__VA_ARGS__, OT_VARIABLE) \ MACRO(__VA_ARGS__, OT_LITERAL) \ MACRO(__VA_ARGS__, OT_PARAMETER) \ /**/ #define FOREACH_RIGHT_TYPE(MACRO, ...) \ MACRO(__VA_ARGS__, OT_VARIABLE) \ MACRO(__VA_ARGS__, OT_LITERAL) \ MACRO(__VA_ARGS__, OT_PARAMETER) \ /**/ #define FOREACH_DESTINATION_TYPE(MACRO, ...) \ MACRO(__VA_ARGS__, OT_VARIABLE) \ /**/ // Auxilary macros #define LWTRACE_EXPAND(x) x #define LWTRACE_EAT(...) // Eat last/first comma trick #define LWTRACE_COMMA(bit) LWTRACE_COMMA_##bit() #define LWTRACE_COMMA_0() #define LWTRACE_COMMA_1() , // Macros to pack/unpack tuples, e.g. (x,y,z) #define LWTRACE_UNROLL(...) __VA_ARGS__ #define LWTRACE_ENROLL(...) (__VA_ARGS__) // Param types list handling macros #define LWTRACE_TEMPLATE_PARAMS_I(i) (1) class TP##i = TNil LWTRACE_COMMA #define LWTRACE_TEMPLATE_PARAMS LWTRACE_EXPAND(LWTRACE_EAT FOREACH_PARAMNUM(LWTRACE_TEMPLATE_PARAMS_I)(0)) #define LWTRACE_TEMPLATE_PARAMS_NODEF_I(i) (1) class TP##i LWTRACE_COMMA #define LWTRACE_TEMPLATE_PARAMS_NODEF LWTRACE_EXPAND(LWTRACE_EAT FOREACH_PARAMNUM(LWTRACE_TEMPLATE_PARAMS_NODEF_I)(0)) #define LWTRACE_TEMPLATE_ARGS_I(i) (1) TP##i LWTRACE_COMMA #define LWTRACE_TEMPLATE_ARGS LWTRACE_EXPAND(LWTRACE_EAT FOREACH_PARAMNUM(LWTRACE_TEMPLATE_ARGS_I)(0)) #define LWTRACE_FUNCTION_PARAMS_I(i) (1) typename ::NLWTrace::TParamTraits::TFuncParam p##i = ERROR_not_enough_parameters() LWTRACE_COMMA #define LWTRACE_FUNCTION_PARAMS LWTRACE_EXPAND(LWTRACE_EAT FOREACH_PARAMNUM(LWTRACE_FUNCTION_PARAMS_I)(0)) #define LWTRACE_PREPARE_PARAMS_I(i, params) params.Param[i].template CopyConstruct::TStoreType>(::NLWTrace::TParamTraits::ToStoreType(p##i)); #define LWTRACE_PREPARE_PARAMS(params) \ do { \ FOREACH_PARAMNUM(LWTRACE_PREPARE_PARAMS_I, params) \ } while (false) #define LWTRACE_COUNT_PARAMS_I(i) +(std::is_same::value ? 0 : 1) #define LWTRACE_COUNT_PARAMS (0 FOREACH_PARAMNUM(LWTRACE_COUNT_PARAMS_I)) #define LWTRACE_MAX_PARAMS_I(i) +1 #define LWTRACE_MAX_PARAMS (0 FOREACH_PARAMNUM(LWTRACE_MAX_PARAMS_I)) // Determine maximum sizeof(t) over all supported types #define LWTRACE_MAX_PARAM_SIZE_TA_TAIL_I(n, t, v) v, #define LWTRACE_MAX_PARAM_SIZE_TA_TAIL \ FOREACH_PARAMTYPE(LWTRACE_MAX_PARAM_SIZE_TA_TAIL_I) \ 0 #define LWTRACE_MAX_PARAM_SIZE_TP_I(n, t, v) , size_t v = 0 #define LWTRACE_MAX_PARAM_SIZE_TP size_t Head = 0 FOREACH_PARAMTYPE(LWTRACE_MAX_PARAM_SIZE_TP_I) #define LWTRACE_MAX_PARAM_SIZE_TA_I(n, t, v) , sizeof(t) #define LWTRACE_MAX_PARAM_SIZE_TA 0 FOREACH_PARAMTYPE(LWTRACE_MAX_PARAM_SIZE_TA_I) #define LWTRACE_MAX_PARAM_SIZE ::NLWTrace::TMaxParamSize::Result namespace NLWTrace { template struct TMaxParamSize { static const size_t Tail = TMaxParamSize::Result; static const size_t Result = (Head > Tail ? Head : Tail); }; template <> struct TMaxParamSize<> { static const size_t Result = 0; }; } // Define stuff that is needed to register probes before main() #define LWTRACE_REGISTER_PROBES(provider) \ namespace LWTRACE_GET_NAMESPACE(provider) { \ struct TInitLWTrace##provider { \ TInitLWTrace##provider() { \ Singleton()->AddProbesList(LWTRACE_GET_PROBES(provider)); \ } \ /* This may not be in anonymous namespace because otherwise */ \ /* it is called twice when .so loaded twice */ \ }* InitLWTrace##provider = Singleton(); \ } \ /**/ // Macro for TSignature POD structure static initialization #define LWTRACE_SIGNATURE_CTOR(types, names) \ { \ /* ParamTypes */ ::NLWTrace::TUserSignature::ParamTypes, \ /* ParamNames */ {LWTRACE_EXPAND(LWTRACE_UNROLL names)}, \ /* ParamCount */ ::NLWTrace::TUserSignature::ParamCount, \ /* SerializeParams */ &::NLWTrace::TUserSignature::SerializeParams, \ /* CloneParams */ &::NLWTrace::TUserSignature::CloneParams, \ /* DestroyParams */ &::NLWTrace::TUserSignature::DestroyParams, \ /* SerializeToPb */ &::NLWTrace::TUserSignature::SerializeToPb, \ /* DeserializeFromPb */ &::NLWTrace::TUserSignature::DeserializeFromPb\ } // Macro for TEvent POD structure static initialization #define LWTRACE_EVENT_CTOR(name, groups, types, names) \ { \ /* Name */ #name, \ /* Groups */ {LWTRACE_EXPAND(LWTRACE_UNROLL_GROUPS groups)}, \ /* Signature */ LWTRACE_SIGNATURE_CTOR(types, names) \ } // Macro for TProbe POD structure static initialization #define LWTRACE_PROBE_CTOR(name, groups, types, names) \ { \ /* Event */ LWTRACE_EVENT_CTOR(name, groups, types, names), \ /* ExecutorsCount */ 0, \ /* Lock */ {0}, \ /* Executors */ {0}, \ /* Front */ 0, \ /* Back */ 0 \ } // Provider static data accessors #define LWTRACE_GET_NAMESPACE(provider) NLWTrace_##provider #define LWTRACE_GET_NAME(name) lwtrace_##name #define LWTRACE_GET_TYPE(name) TLWTrace_##name #define LWTRACE_GET_PROBES_I(provider) gProbes##provider #define LWTRACE_GET_EVENTS_I(provider) gEvents##provider // Declaration of provider static data #define LWTRACE_DECLARE_PROBE(name, groups, types, names) \ typedef ::NLWTrace::TUserProbe LWTRACE_GET_TYPE(name); \ extern LWTRACE_GET_TYPE(name) LWTRACE_GET_NAME(name); \ /**/ #define LWTRACE_DECLARE_EVENT(name, groups, types, names) \ typedef ::NLWTrace::TUserEvent LWTRACE_GET_TYPE(name); \ extern LWTRACE_GET_TYPE(name) LWTRACE_GET_NAME(name); \ /**/ #define LWTRACE_DECLARE_PROVIDER_I(provider) \ namespace LWTRACE_GET_NAMESPACE(provider) { \ provider(LWTRACE_DECLARE_PROBE, LWTRACE_DECLARE_EVENT, LWTRACE_ENROLL, LWTRACE_ENROLL, LWTRACE_ENROLL) \ } \ extern ::NLWTrace::TProbe* LWTRACE_GET_PROBES_I(provider)[]; \ extern ::NLWTrace::TEvent* LWTRACE_GET_EVENTS_I(provider)[]; \ /**/ // Initialization of provider static data #define LWTRACE_UNROLL_GROUPS(x) #x, LWTRACE_UNROLL #define LWTRACE_DEFINE_PROBE(name, groups, types, names) \ LWTRACE_GET_TYPE(name) \ LWTRACE_GET_NAME(name) = \ {LWTRACE_PROBE_CTOR(name, groups, types, names)}; \ /**/ #define LWTRACE_DEFINE_EVENT(name, groups, types, names) \ LWTRACE_GET_TYPE(name) \ LWTRACE_GET_NAME(name) = \ {LWTRACE_EVENT_CTOR(name, groups, types, names)}; \ /**/ #define LWTRACE_PROBE_ADDRESS_I(name, groups, types, names) \ LWTRACE_GET_NAME(name).Probe, /**/ #define LWTRACE_PROBE_ADDRESS(provider) \ &LWTRACE_GET_NAMESPACE(provider)::LWTRACE_PROBE_ADDRESS_I /**/ #define LWTRACE_EVENT_ADDRESS_I(name, groups, types, names) \ LWTRACE_GET_NAME(name).Event, /**/ #define LWTRACE_EVENT_ADDRESS(provider) \ &LWTRACE_GET_NAMESPACE(provider)::LWTRACE_EVENT_ADDRESS_I /**/ #define LWTRACE_DEFINE_PROVIDER_I(provider) \ namespace LWTRACE_GET_NAMESPACE(provider) { \ provider(LWTRACE_DEFINE_PROBE, LWTRACE_DEFINE_EVENT, (provider)LWTRACE_ENROLL, LWTRACE_ENROLL, LWTRACE_ENROLL) \ } \ ::NLWTrace::TProbe* LWTRACE_GET_PROBES_I(provider)[] = { \ provider(LWTRACE_PROBE_ADDRESS(provider), LWTRACE_EAT, LWTRACE_ENROLL, LWTRACE_ENROLL, LWTRACE_ENROLL) \ NULL}; \ ::NLWTrace::TEvent* LWTRACE_GET_EVENTS_I(provider)[] = { \ provider(LWTRACE_EAT, LWTRACE_EVENT_ADDRESS(provider), LWTRACE_ENROLL, LWTRACE_ENROLL, LWTRACE_ENROLL) \ NULL}; \ LWTRACE_REGISTER_PROBES(provider) /**/ #define LWPROBE_I(probe, ...) \ do { \ if ((probe).Probe.GetExecutorsCount() > 0) { \ ::NLWTrace::TScopedThreadCpuTracker _cpuTracker(probe); \ TReadSpinLockGuard g((probe).Probe.Lock); \ if ((probe).Probe.GetExecutorsCount() > 0) { \ (probe)(__VA_ARGS__); \ } \ } \ } while (false) /**/ #define LWPROBE_ENABLED_I(probe) ((probe).Probe.GetExecutorsCount() > 0) #define LWPROBE_DURATION_I(probetype, uniqid, probe, ...) probetype ::TScopedDuration uniqid(probe, 0 /* fake P0 - used for duration */, ##__VA_ARGS__); #define LWTRACK_I(probe, orbit, ...) \ do { \ if ((probe).Probe.GetExecutorsCount() > 0) { \ ::NLWTrace::TScopedThreadCpuTracker _cpuTracker(probe); \ TReadSpinLockGuard g((probe).Probe.Lock); \ if ((probe).Probe.GetExecutorsCount() > 0) { \ (probe).Run(orbit, ##__VA_ARGS__); \ } \ } else { \ auto& _orbit = (orbit); \ if (HasShuttles(_orbit)) { \ ::NLWTrace::TScopedThreadCpuTracker _cpuTracker(probe); \ (probe).RunShuttles(_orbit, ##__VA_ARGS__); \ } \ } \ } while (false) /**/ #define LWEVENT_I(event, ...) (event)(__VA_ARGS__) #else #define LWTRACE_MAX_PARAM_SIZE sizeof(void*) #define LWTRACE_MAX_PARAMS 1 #define FOREACH_PARAMTYPE(MACRO, ...) #endif