diff options
author | Vladimir Mezentsev <vladimir.mezentsev@oracle.com> | 2022-03-11 08:58:31 +0000 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2022-03-11 08:58:31 +0000 |
commit | bb368aad297fe3ad40cf397e6fc85aa471429a28 (patch) | |
tree | 0ab25909b8fe789d676bbdb00d501d4d485e4afe /gprofng/libcollector/libcol_util.h | |
parent | a655f19af95eb685ba64f48ee8fc2b3b7a3d886a (diff) | |
download | fsf-binutils-gdb-bb368aad297fe3ad40cf397e6fc85aa471429a28.zip fsf-binutils-gdb-bb368aad297fe3ad40cf397e6fc85aa471429a28.tar.gz fsf-binutils-gdb-bb368aad297fe3ad40cf397e6fc85aa471429a28.tar.bz2 |
gprofng: a new GNU profiler
top-level
* Makefile.def: Add gprofng module.
* configure.ac: Add --enable-gprofng option.
* src-release.sh: Add gprofng.
* Makefile.in: Regenerate.
* configure: Regenerate.
* gprofng: New directory.
binutils
* MAINTAINERS: Add gprofng maintainer.
* README-how-to-make-a-release: Add gprofng.
include.
* collectorAPI.h: New file.
* libcollector.h: New file.
* libfcollector.h: New file.
Diffstat (limited to 'gprofng/libcollector/libcol_util.h')
-rw-r--r-- | gprofng/libcollector/libcol_util.h | 321 |
1 files changed, 321 insertions, 0 deletions
diff --git a/gprofng/libcollector/libcol_util.h b/gprofng/libcollector/libcol_util.h new file mode 100644 index 0000000..4384d47 --- /dev/null +++ b/gprofng/libcollector/libcol_util.h @@ -0,0 +1,321 @@ +/* Copyright (C) 2021 Free Software Foundation, Inc. + Contributed by Oracle. + + This file is part of GNU Binutils. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#ifndef _LIBCOL_UTIL_H +#define _LIBCOL_UTIL_H + +#include <stdarg.h> +#include <pthread.h> +#include <signal.h> + +// LIBCOLLECTOR NOT I18N +#define NTXT(x) x +#define STXT(x) x + +extern int __collector_tracelevel; + +/* Initialization function */ +extern int __collector_util_init(); +extern void __collector_libkstat_funcs_init(); +extern void __collector_libscf_funcs_init(); + +/* ------- functions from libcol_util.c ----------------- */ +extern void * __collector_memcpy (void *s1, const void *s2, size_t n); +extern int (*__collector_sscanfp)(const char *restrict s, const char *restrict fmt, ...); +extern char * __collector_strcat (char *s1, const char *s2); +extern char * __collector_strchr (const char *s1, int chr); +extern size_t __collector_strlcpy (char *dst, const char *src, size_t dstsize); +extern char* __collector_strrchr (const char *str, int chr); +extern size_t __collector_strlen (const char *s); +extern size_t __collector_strlcat (char *dst, const char *src, size_t dstsize); +extern char* __collector_strchr (const char *str, int chr); +extern int __collector_strcmp (const char *s1, const char *s2); +extern int __collector_strncmp (const char *s1, const char *s2, size_t n); +extern char * __collector_strstr (const char *s1, const char *s2); +extern size_t __collector_strncpy (char *dst, const char *src, size_t dstsize); +extern size_t __collector_strncat (char *dst, const char *src, size_t dstsize); +extern void * __collector_malloc (size_t size); +extern void * __collector_calloc (size_t nelem, size_t elsize); +extern char * __collector_strdup (const char * str); +extern int __collector_strStartWith (const char *s1, const char *s2); +extern int __collector_xml_snprintf (char *s, size_t n, const char *format, ...) __attribute__ ((format (printf, 3, 4))); +extern int __collector_xml_vsnprintf (char *s, size_t n, const char *format, va_list args); + +/* ------- collector_thread ----------------- */ +pid_t __collector_gettid (); +extern void __collector_ext_gettid_tsd_create_key (); +#define collector_thread_t pthread_t // not using pid_t, since tid is defined as pthread_t in package structures, and other codes assume this type +#define statvfs_t struct statvfs +#define __collector_lwp_self() (collector_thread_t)__collector_gettid() // not using pthread_self() +#define __collector_thr_self() (collector_thread_t)__collector_gettid() // not using pthread_self() + +/* ------- collector_mutex ----------------- */ +/* + * mutex_init is defined in libthread. If we don't want to interact + * with libthread we should use memset to initialize mutexes + */ + +typedef volatile int collector_mutex_t; +#define COLLECTOR_MUTEX_INITIALIZER 0 +extern int __collector_mutex_lock (collector_mutex_t *mp); +extern int __collector_mutex_unlock (collector_mutex_t *mp); +extern int __collector_mutex_trylock (collector_mutex_t *mp); + +#define __collector_mutex_init(xx) \ + do { collector_mutex_t tmp=COLLECTOR_MUTEX_INITIALIZER; *(xx)=tmp; } while(0) + +void __collector_sample (char *name); +void __collector_terminate_expt (); +void __collector_pause (); +void __collector_pause_m (); +void __collector_resume (); + +struct DT_lineno; + +typedef enum +{ + DFUNC_API = 1, /* dynamic function declared with API */ + DFUNC_JAVA, /* dynamically compiled java method */ + DFUNC_KERNEL /* dynamic code mapped by the kernel (Linux) */ +} dfunc_mode_t; + +extern void __collector_int_func_load (dfunc_mode_t mode, char *name, + char *sourcename, void *vaddr, + int size, int lntsize, + struct DT_lineno *lntable); +extern void __collector_int_func_unload (dfunc_mode_t mode, void *vaddr); + +extern int __collector_sigaction (int sig, const struct sigaction *nact, + struct sigaction *oact); +extern void __collector_SIGDFL_handler (int sig); +extern int __collector_ext_itimer_set (int period); + +#if ARCH(Intel) +/* Atomic functions on x86/x64 */ + +/** + * This function enables the inrementing (by one) of the value stored in target + * to occur in an atomic manner. + */ +static __attribute__ ((always_inline)) inline void +__collector_inc_32 (uint32_t *ptr) +{ + __asm__ __volatile__("lock; incl %0" + : // "=m" (*ptr) // output + : "m" (*ptr)); // input +} + +/** + * This function enables the decrementing (by one) of the value stored in target + * to occur in an atomic manner. + */ +static __attribute__ ((always_inline)) inline void +__collector_dec_32 (volatile uint32_t *ptr) +{ + __asm__ __volatile__("lock; decl %0" + : // "=m" (*ptr) // output + : "m" (*ptr)); // input +} +/** + * This function subtrackts the value "off" of the value stored in target + * to occur in an atomic manner, and returns new value stored in target. + */ +static __attribute__ ((always_inline)) inline uint32_t +__collector_subget_32 (uint32_t *ptr, uint32_t off) +{ + uint32_t r; + uint32_t offset = off; + __asm__ __volatile__("movl %2, %0; negl %0; lock; xaddl %0, %1" + : "=r" (r), "=m" (*ptr) /* output */ + : "a" (off), "r" (*ptr) /* input */ + ); + return (r - offset); +} +/** + * This function returns the value of the stack pointer register + */ +static __attribute__ ((always_inline)) inline void * +__collector_getsp () +{ + void *r; +#if WSIZE(64) + __asm__ __volatile__("movq %%rsp, %0" +#else + __asm__ __volatile__("movl %%esp, %0" +#endif + : "=r" (r)); // output + return r; +} +/** + * This function returns the value of the frame pointer register + */ +static __attribute__ ((always_inline)) inline void * +__collector_getfp () +{ + void *r; +#if WSIZE(64) + __asm__ __volatile__("movq %%rbp, %0" +#else + __asm__ __volatile__("movl %%ebp, %0" +#endif + : "=r" (r)); // output + return r; +} +/** + * This function returns the value of the processor counter register + */ +static __attribute__ ((always_inline)) inline void * +__collector_getpc () +{ + void *r; + __asm__ __volatile__( +#if WSIZE(32) + " call 1f \n" + "1: popl %0 \n" +#else + " call 1f \n" + "1: popq %0 \n" +#endif + : "=r" (r)); // output + return r; +} + +/** + * This function enables a compare and swap operation to occur atomically. + * The 32-bit value stored in target is compared with "old". If these values + * are equal, the value stored in target is replaced with "new". The old + * 32-bit value stored in target is returned by the function whether or not + * the replacement occurred. + */ +static __attribute__ ((always_inline)) inline uint32_t +__collector_cas_32 (volatile uint32_t *pdata, uint32_t old, uint32_t new) +{ + uint32_t r; + __asm__ __volatile__("lock; cmpxchgl %2, %1" + : "=a" (r), "=m" (*pdata) : "r" (new), + "a" (old), "m" (*pdata)); + return r; +} +/** + * This function enables a compare and swap operation to occur atomically. + * The 64-bit value stored in target is compared with "old". If these values + * are equal, the value stored in target is replaced with "new". The old + * 64-bit value stored in target is returned by the function whether or not + * the replacement occurred. + */ +static __attribute__ ((always_inline)) inline uint64_t +__collector_cas_64p (volatile uint64_t *mem, uint64_t *old, uint64_t * new) +{ + uint64_t r; +#if WSIZE(32) + uint32_t old1 = (uint32_t) (*old & 0xFFFFFFFFL); + uint32_t old2 = (uint32_t) ((*old >> 32) & 0xFFFFFFFFL); + uint32_t new1 = (uint32_t) (*new & 0xFFFFFFFFL); + uint32_t new2 = (uint32_t) ((*new >> 32) & 0xFFFFFFFFL); + uint32_t res1 = 0; + uint32_t res2 = 0; + __asm__ __volatile__( + "movl %3, %%esi; lock; cmpxchg8b (%%esi); movl %%edx, %2; movl %%eax, %1" + : "=m" (r), "=m" (res1), "=m" (res2) /* output */ + : "m" (mem), "a" (old1), "d" (old2), "b" (new1), "c" (new2) /* input */ + : "memory", "cc", "esi" //, "edx", "ecx", "ebx", "eax" /* clobbered register */ + ); + r = (((uint64_t) res2) << 32) | ((uint64_t) res1); +#else + __asm__ __volatile__( "lock; cmpxchgq %2, %1" + : "=a" (r), "=m" (*mem) /* output */ + : "r" (*new), "a" (*old), "m" (*mem) /* input */ + : "%rcx", "rdx" /* clobbered register */ + ); +#endif + return r; +} +/** + * This function enables a compare and swap operation to occur atomically. + * The 32-/64-bit value stored in target is compared with "cmp". If these values + * are equal, the value stored in target is replaced with "new". + * The old value stored in target is returned by the function whether or not + * the replacement occurred. + */ +static __attribute__ ((always_inline)) inline void * +__collector_cas_ptr (void *mem, void *cmp, void *new) +{ + void *r; +#if WSIZE(32) + r = (void *) __collector_cas_32 ((volatile uint32_t *)mem, (uint32_t) cmp, (uint32_t)new); +#else + __asm__ __volatile__("lock; cmpxchgq %2, (%1)" + : "=a" (r), "=b" (mem) /* output */ + : "r" (new), "a" (cmp), "b" (mem) /* input */ + ); +#endif + return r; +} + +#elif ARCH(Aarch64) +static __attribute__ ((always_inline)) inline uint32_t +__collector_inc_32 (volatile uint32_t *ptr) +{ + return __sync_add_and_fetch (ptr, 1); +} + +static __attribute__ ((always_inline)) inline uint32_t +__collector_dec_32 (volatile uint32_t *ptr) +{ + return __sync_sub_and_fetch (ptr, 1); +} + +static __attribute__ ((always_inline)) inline uint32_t +__collector_subget_32 (volatile uint32_t *ptr, uint32_t off) +{ + return __sync_sub_and_fetch (ptr, off); +} + +static __attribute__ ((always_inline)) inline uint32_t +__collector_cas_32 (volatile uint32_t *ptr, uint32_t old, uint32_t new) +{ + return __sync_val_compare_and_swap (ptr, old, new); +} + +static __attribute__ ((always_inline)) inline uint64_t +__collector_cas_64p (volatile uint64_t *ptr, uint64_t *old, uint64_t * new) +{ + return __sync_val_compare_and_swap (ptr, *old, *new); +} + +static __attribute__ ((always_inline)) inline void * +__collector_cas_ptr (void *ptr, void *old, void *new) +{ + return (void *) __sync_val_compare_and_swap ((unsigned long *) ptr, (unsigned long) old, (unsigned long) new); +} + +#else +extern void __collector_flushw (); /* defined for SPARC only */ +extern void* __collector_getpc (); +extern void* __collector_getsp (); +extern void* __collector_getfp (); +extern void __collector_inc_32 (volatile uint32_t *); +extern void __collector_dec_32 (volatile uint32_t *); +extern void* __collector_cas_ptr (volatile void *, void *, void *); +extern uint32_t __collector_cas_32 (volatile uint32_t *, uint32_t, uint32_t); +extern uint32_t __collector_subget_32 (volatile uint32_t *, uint32_t); +extern uint64_t __collector_cas_64p (volatile uint64_t *, uint64_t *, uint64_t *); +#endif /* ARCH() */ +#endif /* _LIBCOL_UTIL_H */ |