1 /* Copyright (C) 2021-2024 Free Software Foundation, Inc.
4 This file is part of GNU Binutils.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 51 Franklin Street - Fifth Floor, Boston,
19 MA 02110-1301, USA. */
21 #ifndef _LIBCOL_UTIL_H
22 #define _LIBCOL_UTIL_H
28 // LIBCOLLECTOR NOT I18N
32 extern int __collector_tracelevel
;
34 /* Initialization function */
35 extern int __collector_util_init();
36 extern void __collector_libkstat_funcs_init();
37 extern void __collector_libscf_funcs_init();
39 /* ------- functions from libcol_util.c ----------------- */
40 extern void * __collector_memcpy (void *s1
, const void *s2
, size_t n
);
41 extern int (*__collector_sscanfp
)(const char *restrict s
, const char *restrict fmt
, ...)
42 __attribute__ ((format (scanf
, 2, 3)));
43 extern char * __collector_strcat (char *s1
, const char *s2
);
44 extern char * __collector_strchr (const char *s1
, int chr
);
45 extern size_t __collector_strlcpy (char *dst
, const char *src
, size_t dstsize
);
46 extern char* __collector_strrchr (const char *str
, int chr
);
47 extern size_t __collector_strlen (const char *s
);
48 extern size_t __collector_strlcat (char *dst
, const char *src
, size_t dstsize
);
49 extern char* __collector_strchr (const char *str
, int chr
);
50 extern int __collector_strcmp (const char *s1
, const char *s2
);
51 extern int __collector_strncmp (const char *s1
, const char *s2
, size_t n
);
52 extern char * __collector_strstr (const char *s1
, const char *s2
);
53 extern size_t __collector_strncpy (char *dst
, const char *src
, size_t dstsize
);
54 extern size_t __collector_strncat (char *dst
, const char *src
, size_t dstsize
);
55 extern void * __collector_malloc (size_t size
);
56 extern void * __collector_calloc (size_t nelem
, size_t elsize
);
57 extern char * __collector_strdup (const char * str
);
58 extern int __collector_strStartWith (const char *s1
, const char *s2
);
59 extern int __collector_xml_snprintf (char *s
, size_t n
, const char *format
, ...) __attribute__ ((format (printf
, 3, 4)));
60 extern int __collector_xml_vsnprintf (char *s
, size_t n
, const char *format
, va_list args
);
62 /* ------- collector_thread ----------------- */
63 extern pid_t
__collector_gettid ();
64 extern void __collector_ext_gettid_tsd_create_key ();
65 typedef pthread_t collector_thread_t
;
66 #define __collector_lwp_self() ((collector_thread_t) ((unsigned long) __collector_gettid()))
67 #define __collector_thr_self() ((collector_thread_t) ((unsigned long) __collector_gettid()))
69 /* ------- collector_mutex ----------------- */
71 * mutex_init is defined in libthread. If we don't want to interact
72 * with libthread we should use memset to initialize mutexes
75 typedef volatile int collector_mutex_t
;
76 #define COLLECTOR_MUTEX_INITIALIZER 0
77 extern int __collector_mutex_lock (collector_mutex_t
*mp
);
78 extern int __collector_mutex_unlock (collector_mutex_t
*mp
);
79 extern int __collector_mutex_trylock (collector_mutex_t
*mp
);
81 #define __collector_mutex_init(xx) \
82 do { collector_mutex_t tmp=COLLECTOR_MUTEX_INITIALIZER; *(xx)=tmp; } while(0)
84 void __collector_sample (char *name
);
85 void __collector_terminate_expt ();
86 void __collector_pause ();
87 void __collector_pause_m ();
88 void __collector_resume ();
94 DFUNC_API
= 1, /* dynamic function declared with API */
95 DFUNC_JAVA
, /* dynamically compiled java method */
96 DFUNC_KERNEL
/* dynamic code mapped by the kernel (Linux) */
99 extern void __collector_int_func_load (dfunc_mode_t mode
, char *name
,
100 char *sourcename
, void *vaddr
,
101 int size
, int lntsize
,
102 struct DT_lineno
*lntable
);
103 extern void __collector_int_func_unload (dfunc_mode_t mode
, void *vaddr
);
105 extern int __collector_sigaction (int sig
, const struct sigaction
*nact
,
106 struct sigaction
*oact
);
107 extern void __collector_SIGDFL_handler (int sig
);
108 extern int __collector_ext_itimer_set (int period
);
111 /* Atomic functions on x86/x64 */
114 * This function enables the inrementing (by one) of the value stored in target
115 * to occur in an atomic manner.
117 static __attribute__ ((always_inline
)) inline void
118 __collector_inc_32 (uint32_t *ptr
)
120 __asm__
__volatile__("lock; incl %0"
121 : // "=m" (*ptr) // output
122 : "m" (*ptr
)); // input
126 * This function enables the decrementing (by one) of the value stored in target
127 * to occur in an atomic manner.
129 static __attribute__ ((always_inline
)) inline void
130 __collector_dec_32 (volatile uint32_t *ptr
)
132 __asm__
__volatile__("lock; decl %0"
133 : // "=m" (*ptr) // output
134 : "m" (*ptr
)); // input
138 * This function subtrackts the value "off" of the value stored in target
139 * to occur in an atomic manner, and returns new value stored in target.
141 static __attribute__ ((always_inline
)) inline uint32_t
142 __collector_subget_32 (uint32_t *ptr
, uint32_t off
)
145 uint32_t offset
= off
;
146 __asm__
__volatile__("movl %2, %0; negl %0; lock; xaddl %0, %1"
147 : "=r" (r
), "=m" (*ptr
) /* output */
148 : "a" (off
), "r" (*ptr
) /* input */
154 * This function returns the value of the stack pointer register
156 static __attribute__ ((always_inline
)) inline void *
160 #if WSIZE(32) || defined(__ILP32__)
161 __asm__
__volatile__("movl %%esp, %0"
163 __asm__
__volatile__("movq %%rsp, %0"
165 : "=r" (r
)); // output
170 * This function returns the value of the frame pointer register
172 static __attribute__ ((always_inline
)) inline void *
176 #if WSIZE(32) || defined(__ILP32__)
177 __asm__
__volatile__("movl %%ebp, %0"
179 __asm__
__volatile__("movq %%rbp, %0"
181 : "=r" (r
)); // output
186 * This function returns the value of the processor counter register
188 static __attribute__ ((always_inline
)) inline void *
192 #if defined(__x86_64)
193 __asm__
__volatile__("lea (%%rip), %0" : "=r" (r
));
195 __asm__
__volatile__("call 1f \n"
196 "1: popl %0" : "=r" (r
));
202 * This function enables a compare and swap operation to occur atomically.
203 * The 32-bit value stored in target is compared with "old". If these values
204 * are equal, the value stored in target is replaced with "new". The old
205 * 32-bit value stored in target is returned by the function whether or not
206 * the replacement occurred.
208 static __attribute__ ((always_inline
)) inline uint32_t
209 __collector_cas_32 (volatile uint32_t *pdata
, uint32_t old
, uint32_t new)
212 __asm__
__volatile__("lock; cmpxchgl %2, %1"
213 : "=a" (r
), "=m" (*pdata
) : "r" (new),
214 "a" (old
), "m" (*pdata
));
218 * This function enables a compare and swap operation to occur atomically.
219 * The 64-bit value stored in target is compared with "old". If these values
220 * are equal, the value stored in target is replaced with "new". The old
221 * 64-bit value stored in target is returned by the function whether or not
222 * the replacement occurred.
224 static __attribute__ ((always_inline
)) inline uint64_t
225 __collector_cas_64p (volatile uint64_t *mem
, uint64_t *old
, uint64_t * new)
229 uint32_t old1
= (uint32_t) (*old
& 0xFFFFFFFFL
);
230 uint32_t old2
= (uint32_t) ((*old
>> 32) & 0xFFFFFFFFL
);
231 uint32_t new1
= (uint32_t) (*new & 0xFFFFFFFFL
);
232 uint32_t new2
= (uint32_t) ((*new >> 32) & 0xFFFFFFFFL
);
235 __asm__
__volatile__(
236 "movl %3, %%esi; lock; cmpxchg8b (%%esi); movl %%edx, %2; movl %%eax, %1"
237 : "=m" (r
), "=m" (res1
), "=m" (res2
) /* output */
238 : "m" (mem
), "a" (old1
), "d" (old2
), "b" (new1
), "c" (new2
) /* input */
239 : "memory", "cc", "esi" //, "edx", "ecx", "ebx", "eax" /* clobbered register */
241 r
= (((uint64_t) res2
) << 32) | ((uint64_t) res1
);
243 __asm__
__volatile__( "lock; cmpxchgq %2, %1"
244 : "=a" (r
), "=m" (*mem
) /* output */
245 : "r" (*new), "a" (*old
), "m" (*mem
) /* input */
246 : "%rcx", "rdx" /* clobbered register */
252 * This function enables a compare and swap operation to occur atomically.
253 * The 32-/64-bit value stored in target is compared with "cmp". If these values
254 * are equal, the value stored in target is replaced with "new".
255 * The old value stored in target is returned by the function whether or not
256 * the replacement occurred.
258 static __attribute__ ((always_inline
)) inline void *
259 __collector_cas_ptr (void *mem
, void *cmp
, void *new)
262 #if WSIZE(32) || defined(__ILP32__)
263 r
= (void *) __collector_cas_32 ((volatile uint32_t *)mem
, (uint32_t) cmp
, (uint32_t)new);
265 __asm__
__volatile__("lock; cmpxchgq %2, (%1)"
266 : "=a" (r
), "=b" (mem
) /* output */
267 : "r" (new), "a" (cmp
), "b" (mem
) /* input */
274 static __attribute__ ((always_inline
)) inline uint32_t
275 __collector_inc_32 (volatile uint32_t *ptr
)
277 return __sync_add_and_fetch (ptr
, 1);
280 static __attribute__ ((always_inline
)) inline uint32_t
281 __collector_dec_32 (volatile uint32_t *ptr
)
283 return __sync_sub_and_fetch (ptr
, 1);
286 static __attribute__ ((always_inline
)) inline uint32_t
287 __collector_subget_32 (volatile uint32_t *ptr
, uint32_t off
)
289 return __sync_sub_and_fetch (ptr
, off
);
292 static __attribute__ ((always_inline
)) inline uint32_t
293 __collector_cas_32 (volatile uint32_t *ptr
, uint32_t old
, uint32_t new)
295 return __sync_val_compare_and_swap (ptr
, old
, new);
298 static __attribute__ ((always_inline
)) inline uint64_t
299 __collector_cas_64p (volatile uint64_t *ptr
, uint64_t *old
, uint64_t * new)
301 return __sync_val_compare_and_swap (ptr
, *old
, *new);
304 static __attribute__ ((always_inline
)) inline void *
305 __collector_cas_ptr (void *ptr
, void *old
, void *new)
307 return (void *) __sync_val_compare_and_swap ((unsigned long *) ptr
, (unsigned long) old
, (unsigned long) new);
311 extern void __collector_flushw (); /* defined for SPARC only */
312 extern void* __collector_getpc ();
313 extern void* __collector_getsp ();
314 extern void* __collector_getfp ();
315 extern void __collector_inc_32 (volatile uint32_t *);
316 extern void __collector_dec_32 (volatile uint32_t *);
317 extern void* __collector_cas_ptr (volatile void *, void *, void *);
318 extern uint32_t __collector_cas_32 (volatile uint32_t *, uint32_t, uint32_t);
319 extern uint32_t __collector_subget_32 (volatile uint32_t *, uint32_t);
320 extern uint64_t __collector_cas_64p (volatile uint64_t *, uint64_t *, uint64_t *);
322 #endif /* _LIBCOL_UTIL_H */