Home | History | Annotate | Line # | Download | only in internal
      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