1 #ifndef JEMALLOC_INTERNAL_JEMALLOC_PROBE_CUSTOM_H 2 #define JEMALLOC_INTERNAL_JEMALLOC_PROBE_CUSTOM_H 3 4 /* clang-format off */ 5 6 /* 7 * This section is based on sys/sdt.h and 8 * https://sourceware.org/systemtap/wiki/UserSpaceProbeImplementation 9 */ 10 11 /* Emit NOP for the probe. */ 12 #if (defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || \ 13 defined(__arm__)) && defined(__linux__) 14 #define JE_SDT_NOP nop 15 #else 16 #error "Architecture not supported" 17 #endif 18 19 /* Assembly macros */ 20 #define JE_SDT_S(x) #x 21 22 #define JE_SDT_ASM_1(x) JE_SDT_S(x) "\n" 23 24 #define JE_SDT_ASM_2(x, y) \ 25 JE_SDT_S(x) "," JE_SDT_S(y) "\n" 26 27 #define JE_SDT_ASM_3(x, y, z) \ 28 JE_SDT_S(x) "," JE_SDT_S(y) "," JE_SDT_S(z) "\n" 29 30 #define JE_SDT_ASM_3(x, y, z) \ 31 JE_SDT_S(x) "," JE_SDT_S(y) "," JE_SDT_S(z) "\n" 32 33 #define JE_SDT_ASM_4(x, y, z, p) \ 34 JE_SDT_S(x) "," JE_SDT_S(y) "," JE_SDT_S(z) "," JE_SDT_S(p) "\n" 35 36 #define JE_SDT_ASM_5(x, y, z, p, q) \ 37 JE_SDT_S(x) "," JE_SDT_S(y) "," JE_SDT_S(z) "," JE_SDT_S(p) "," \ 38 JE_SDT_S(q) "\n" 39 40 /* Arg size */ 41 #ifdef __LP64__ 42 #define JE_SDT_ASM_ADDR .8byte 43 #else 44 #define JE_SDT_ASM_ADDR .4byte 45 #endif 46 47 #define JE_SDT_NOTE_NAME "stapsdt" 48 #define JE_SDT_NOTE_TYPE 3 49 50 #define JE_SDT_SEMAPHORE_NONE(provider, name) \ 51 JE_SDT_ASM_1(JE_SDT_ASM_ADDR 0) /* No Semaphore support */ 52 #define JE_SDT_SEMAPHORE_OPERAND(provider, name) \ 53 [__sdt_semaphore] "ip" (0) /* No Semaphore */ 54 55 #define JE_SDT_ASM_STRING(x) JE_SDT_ASM_1(.asciz JE_SDT_S(x)) 56 57 #define JE_SDT_NOTE(provider, name, arg_template) \ 58 JE_SDT_ASM_1(990: JE_SDT_NOP) \ 59 JE_SDT_ASM_3( .pushsection .note.stapsdt,"?","note") \ 60 JE_SDT_ASM_1( .balign 4) \ 61 JE_SDT_ASM_3( .4byte 992f-991f, 994f-993f, JE_SDT_NOTE_TYPE) \ 62 JE_SDT_ASM_1(991: .asciz JE_SDT_NOTE_NAME) \ 63 JE_SDT_ASM_1(992: .balign 4) \ 64 JE_SDT_ASM_1(993: JE_SDT_ASM_ADDR 990b) \ 65 JE_SDT_ASM_1( JE_SDT_ASM_ADDR _.stapsdt.base) \ 66 JE_SDT_SEMAPHORE_NONE(provider, name) \ 67 JE_SDT_ASM_STRING(provider) \ 68 JE_SDT_ASM_STRING(name) \ 69 JE_SDT_ASM_STRING(arg_template) \ 70 JE_SDT_ASM_1(994: .balign 4) \ 71 JE_SDT_ASM_1( .popsection) 72 73 #define JE_SDT_BASE \ 74 JE_SDT_ASM_1( .ifndef _.stapsdt.base) \ 75 JE_SDT_ASM_5( .pushsection .stapsdt.base, "aG", "progbits", \ 76 .stapsdt.base,comdat) \ 77 JE_SDT_ASM_1( .weak _.stapsdt.base) \ 78 JE_SDT_ASM_1( .hidden _.stapsdt.base) \ 79 JE_SDT_ASM_1( _.stapsdt.base: .space 1) \ 80 JE_SDT_ASM_2( .size _.stapsdt.base, 1) \ 81 JE_SDT_ASM_1( .popsection) \ 82 JE_SDT_ASM_1( .endif) 83 84 85 /* 86 * Default constraint for probes arguments. 87 * See https://gcc.gnu.org/onlinedocs/gcc/Constraints.html 88 */ 89 #ifndef JE_SDT_ARG_CONSTRAINT 90 #define JE_SDT_ARG_CONSTRAINT "nor" 91 #endif 92 93 #define JE_SDT_ARGARRAY(x) ((__builtin_classify_type(x) == 14) || \ 94 (__builtin_classify_type(x) == 5)) 95 #define JE_SDT_ARGSIZE(x) (JE_SDT_ARGARRAY(x) ? sizeof(void*) : sizeof(x)) 96 97 /* 98 * Format of each probe argument as operand. Size tagged with JE_SDT_Sn, 99 * with "n" constraint. Value is tagged with JE_SDT_An with configured 100 * constraint. 101 */ 102 #define JE_SDT_ARG(n, x) \ 103 [JE_SDT_S##n] "n" ((size_t)JE_SDT_ARGSIZE(x)), \ 104 [JE_SDT_A##n] JE_SDT_ARG_CONSTRAINT(x) 105 106 /* Templates to append arguments as operands. */ 107 #define JE_SDT_OPERANDS_0() [__sdt_dummy] "g" (0) 108 #define JE_SDT_OPERANDS_1(_1) JE_SDT_ARG(1, _1) 109 #define JE_SDT_OPERANDS_2(_1, _2) JE_SDT_OPERANDS_1(_1), JE_SDT_ARG(2, _2) 110 #define JE_SDT_OPERANDS_3(_1, _2, _3) JE_SDT_OPERANDS_2(_1, _2), JE_SDT_ARG(3, _3) 111 #define JE_SDT_OPERANDS_4(_1, _2, _3, _4) \ 112 JE_SDT_OPERANDS_3(_1, _2, _3), JE_SDT_ARG(4, _4) 113 #define JE_SDT_OPERANDS_5(_1, _2, _3, _4, _5) \ 114 JE_SDT_OPERANDS_4(_1, _2, _3, _4), JE_SDT_ARG(5, _5) 115 #define JE_SDT_OPERANDS_6(_1, _2, _3, _4, _5, _6) \ 116 JE_SDT_OPERANDS_5(_1, _2, _3, _4, _5), JE_SDT_ARG(6, _6) 117 #define JE_SDT_OPERANDS_7(_1, _2, _3, _4, _5, _6, _7) \ 118 JE_SDT_OPERANDS_6(_1, _2, _3, _4, _5, _6), JE_SDT_ARG(7, _7) 119 120 /* Templates to reference the arguments from operands. */ 121 #define JE_SDT_ARGFMT(num) %n[JE_SDT_S##num]@%[JE_SDT_A##num] 122 #define JE_SDT_ARG_TEMPLATE_0 /* No args */ 123 #define JE_SDT_ARG_TEMPLATE_1 JE_SDT_ARGFMT(1) 124 #define JE_SDT_ARG_TEMPLATE_2 JE_SDT_ARG_TEMPLATE_1 JE_SDT_ARGFMT(2) 125 #define JE_SDT_ARG_TEMPLATE_3 JE_SDT_ARG_TEMPLATE_2 JE_SDT_ARGFMT(3) 126 #define JE_SDT_ARG_TEMPLATE_4 JE_SDT_ARG_TEMPLATE_3 JE_SDT_ARGFMT(4) 127 #define JE_SDT_ARG_TEMPLATE_5 JE_SDT_ARG_TEMPLATE_4 JE_SDT_ARGFMT(5) 128 #define JE_SDT_ARG_TEMPLATE_6 JE_SDT_ARG_TEMPLATE_5 JE_SDT_ARGFMT(6) 129 #define JE_SDT_ARG_TEMPLATE_7 JE_SDT_ARG_TEMPLATE_6 JE_SDT_ARGFMT(7) 130 131 #define JE_SDT_PROBE( \ 132 provider, name, n, arglist) \ 133 do { \ 134 __asm__ __volatile__( \ 135 JE_SDT_NOTE(provider, name, \ 136 JE_SDT_ARG_TEMPLATE_##n) \ 137 :: JE_SDT_SEMAPHORE_OPERAND(provider, name), \ 138 JE_SDT_OPERANDS_##n arglist); \ 139 __asm__ __volatile__(JE_SDT_BASE); \ 140 } while (0) 141 142 #define JE_USDT(name, N, ...) \ 143 JE_SDT_PROBE(jemalloc, name, N, (__VA_ARGS__)) 144 145 146 #endif /* JEMALLOC_INTERNAL_JEMALLOC_PROBE_CUSTOM_H */ 147 148 /* clang-format on */ 149