[PATCH] Adding systemtap probe points in pthread library (slightly revised again)

Bert Wesarg bert.wesarg@googlemail.com
Wed Jan 12 20:14:00 GMT 2011


On Wed, Jan 12, 2011 at 19:50, Rayson Ho <rho@redhat.com> wrote:
> Thanks a lot for the comment.
>
> - fixed missing space before paren for the MARCOs
> - removed comments (most of the comments were originally written to
> explain why the probes were placed in the specific locations...)
>
>
> What is it?
> This is a patch against the "remotes/origin/roland/systemtap" branch. It
> adds SystemTap probe points to the Pthread library to allow developers
> and system administrators to trace and debug pthread programs.
>
> ChangeLog:
>
> 2011-01-12  Rayson Ho <rho@redhat.com>
>
>        * DESIGN-systemtap-probes.txt: New file. (documentation)
>        * pthread_create.c: Added SystemTap Pthreads probes.
>        * pthread_join.c: Likewise.
>        * pthread_mutex_destroy.c: Likewise.
>        * pthread_mutex_init.c: Likewise.
>        * pthread_mutex_lock.c: Likewise.
>        * pthread_mutex_unlock.c: Likewise.
>        * pthread_rwlock_destroy.c: Likewise.
>        * pthread_rwlock_rdlock.c: Likewise.
>        * pthread_rwlock_unlock.c: Likewise.
>        * pthread_rwlock_wrlock.c: Likewise.
>        * sysdeps/unix/sysv/linux/x86_64/lowlevellock.S: Likewise.
>
> Testing:
> - no regressions with or without systemtap probes compiled into pthread
> - compilation works with or without systemtap enabled
>
> diff --git a/nptl/DESIGN-systemtap-probes.txt
> b/nptl/DESIGN-systemtap-probes.txt
> index e69de29..17ec433 100644
> --- a/nptl/DESIGN-systemtap-probes.txt
> +++ b/nptl/DESIGN-systemtap-probes.txt
> @@ -0,0 +1,33 @@
> +Systemtap is a dynamic tracing/instrumenting tool available on Linux.
> Probes that are not fired have close to zero runtime overhead.
> +
> +The following probes are available for NPTL:
> +
> +Thread creation & Join Probes
> +=============================
> +create   - probe for pthread_create(3) - arg1 = thread ID, arg2 =
> start_routine, arg3 = arguments
> +start    - probe for actual thread creation, arg1 = struct pthread
> (members include thread ID, process ID)
> +join     - probe for pthread_join(3)   - arg1 = thread ID
> +join_ret - probe for pthread_join(3) return - arg1 = thread ID, arg2 =
> return value
> +
> +Lock-related Probes
> +===================
> +mutex_init    - probe for pthread_mutex_init(3) - arg1 = address of
> mutex lock
> +mutex_acquired- probe for pthread_mutex_lock(3) - arg1 = address of
> mutex lock
> +mutex_block   - probe for resume from _possible_ mutex block event -
> arg1 = address of mutex lock
> +mutex_entry   - probe for entry to the pthread_mutex_lock(3) function,
> - arg1 = address of mutex lock
> +mutex_release - probe for pthread_mutex_unlock(3) after the successful
> release of a mutex lock - arg1 = address of mutex lock
> +mutex_destroy - probe for pthread_mutex_destroy(3) - arg1 = address of
> mutex lock
> +rwlock_destroy- probe for pthread_rwlock_destroy(3) - arg1 = address of
> rw lock
> +rwlock_acquire_write-probe for pthread_rwlock_wrlock(3) - arg1 =
> address of rw lock
> +rwlock_unlock - probe for pthread_rwlock_unlock(3) - arg1 = address of
> rw lock
> +
> +lock_wait         - probe in low-level lock code, only fired when futex
> is called (i.e. when trying to acquire a contented lock)
> +lock_wait_private - probe in low-level lock code, only fired when futex
> is called (i.e. when trying to acquire a contented lock)
> +
> +Condition variable Probes
> +=========================
> +cond_init - probe for pthread_cond_init(3) - arg1 = condition, arg2 =
> attr
> +cond_destroy- probe for pthread_condattr_destroy(3) - arg1 = attr
> +cond_wait - probe for pthread_cond_wait(3) - arg1 = condition, arg2 =
> mutex lock
> +cond_signal - probe for pthread_cond_signal(3) - arg1 = condition
> +cond_broadcast - probe for pthread_cond_broadcast(3) - arg1 = condition
> diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c
> index 4075dd9..5fdf2c9 100644
> --- a/nptl/pthread_create.c
> +++ b/nptl/pthread_create.c
> @@ -556,6 +556,8 @@ __pthread_create_2_1 (newthread, attr,
> start_routine, arg)
>   /* Pass the descriptor to the caller.  */
>   *newthread = (pthread_t) pd;
>
> +  LIBC_PROBE (newthread, 2, start_routine, arg);

I'm not familiar with this macro, but I suspect that the first
argument will be the name of the probe. In this case 'newthread'. Is
this intended? There is no 'newthread' probe documented in
nptl/DESIGN-systemtap-probes.txt but a 'create' probe. Also, there is
a parameter named 'newthread'. I must also missed the 'start' probe.

> +
>   /* Start the thread.  */
>   return create_thread (pd, iattr, STACK_VARIABLES_ARGS);
>  }
> diff --git a/nptl/pthread_join.c b/nptl/pthread_join.c
> index 6a87a8b..7cbeb1d 100644
> --- a/nptl/pthread_join.c
> +++ b/nptl/pthread_join.c
> @@ -23,6 +23,8 @@
>  #include <atomic.h>
>  #include "pthreadP.h"
>
> +#include <stap-probe.h>
> +
>
>  static void
>  cleanup (void *arg)
> @@ -55,6 +57,8 @@ pthread_join (threadid, thread_return)
>   struct pthread *self = THREAD_SELF;
>   int result = 0;
>
> +  LIBC_PROBE (join,1, threadid);
> +
>   /* During the wait we change to asynchronous cancellation.  If we
>      are canceled the thread we are waiting for must be marked as
>      un-wait-ed for again.  */
> @@ -110,5 +114,7 @@ pthread_join (threadid, thread_return)
>       __free_tcb (pd);
>     }
>
> +  LIBC_PROBE (join_ret, 3, threadid, result, pd->result);
> +
>   return result;
>  }
> diff --git a/nptl/pthread_mutex_destroy.c b/nptl/pthread_mutex_destroy.c
> index e2c9f8a..00037c5 100644
> --- a/nptl/pthread_mutex_destroy.c
> +++ b/nptl/pthread_mutex_destroy.c
> @@ -20,11 +20,15 @@
>  #include <errno.h>
>  #include "pthreadP.h"
>
> +#include <stap-probe.h>
> +
>
>  int
>  __pthread_mutex_destroy (mutex)
>      pthread_mutex_t *mutex;
>  {
> +  LIBC_PROBE (cond_destroy, 1, mutex);
> +
>   if ((mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) == 0
>       && mutex->__data.__nusers != 0)
>     return EBUSY;
> diff --git a/nptl/pthread_mutex_init.c b/nptl/pthread_mutex_init.c
> index d9b1ef0..a025a38 100644
> --- a/nptl/pthread_mutex_init.c
> +++ b/nptl/pthread_mutex_init.c
> @@ -24,6 +24,8 @@
>  #include <kernel-features.h>
>  #include "pthreadP.h"
>
> +#include <stap-probe.h>
> +
>  static const struct pthread_mutexattr default_attr =
>   {
>     /* Default is a normal mutex, not shared between processes.  */
> @@ -135,6 +137,8 @@ __pthread_mutex_init (mutex, mutexattr)
>   // mutex->__spins = 0;       already done by memset
>   // mutex->__next = NULL;     already done by memset
>
> +  LIBC_PROBE (mutex_init, 1, mutex);
> +
>   return 0;
>  }
>  strong_alias (__pthread_mutex_init, pthread_mutex_init)
> diff --git a/nptl/pthread_mutex_lock.c b/nptl/pthread_mutex_lock.c
> index 50dc188..fdec784 100644
> --- a/nptl/pthread_mutex_lock.c
> +++ b/nptl/pthread_mutex_lock.c
> @@ -24,6 +24,7 @@
>  #include <not-cancel.h>
>  #include "pthreadP.h"
>  #include <lowlevellock.h>
> +#include <stap-probe.h>
>
>
>  #ifndef LLL_MUTEX_LOCK
> @@ -48,6 +49,9 @@ __pthread_mutex_lock (mutex)
>   assert (sizeof (mutex->__size) >= sizeof (mutex->__data));
>
>   unsigned int type = PTHREAD_MUTEX_TYPE (mutex);
> +
> +  LIBC_PROBE (mutex_entry, 1, mutex);
> +
>   if (__builtin_expect (type & ~PTHREAD_MUTEX_KIND_MASK_NP, 0))
>     return __pthread_mutex_lock_full (mutex);
>
> @@ -60,6 +64,8 @@ __pthread_mutex_lock (mutex)
>       /* Normal mutex.  */
>       LLL_MUTEX_LOCK (mutex);
>       assert (mutex->__data.__owner == 0);
> +
> +      LIBC_PROBE (mutex_block, 1, mutex);
>     }
>   else if (__builtin_expect (type == PTHREAD_MUTEX_RECURSIVE_NP, 1))
>     {
> @@ -83,6 +89,8 @@ __pthread_mutex_lock (mutex)
>
>       assert (mutex->__data.__owner == 0);
>       mutex->__data.__count = 1;
> +
> +      LIBC_PROBE (mutex_block, 1, mutex);
>     }
>   else if (__builtin_expect (type == PTHREAD_MUTEX_ADAPTIVE_NP, 1))
>     {
> @@ -108,6 +116,8 @@ __pthread_mutex_lock (mutex)
>            }
>          while (LLL_MUTEX_TRYLOCK (mutex) != 0);
>
> +          LIBC_PROBE (mutex_block, 1, mutex);
> +
>          mutex->__data.__spins += (cnt - mutex->__data.__spins) / 8;
>        }
>       assert (mutex->__data.__owner == 0);
> @@ -127,6 +137,8 @@ __pthread_mutex_lock (mutex)
>   ++mutex->__data.__nusers;
>  #endif
>
> +  LIBC_PROBE (mutex_acquire, 1, mutex);
> +
>   return 0;
>  }
>
> @@ -451,6 +463,8 @@ __pthread_mutex_lock_full (pthread_mutex_t *mutex)
>          }
>        while ((oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK) != ceilval);
>
> +        LIBC_PROBE (mutex_block, 1, mutex);
> +
>        assert (mutex->__data.__owner == 0);
>        mutex->__data.__count = 1;
>       }
> @@ -467,6 +481,8 @@ __pthread_mutex_lock_full (pthread_mutex_t *mutex)
>   ++mutex->__data.__nusers;
>  #endif
>
> +  LIBC_PROBE (mutex_acquire, 1, mutex);
> +
>   return 0;
>  }
>  #ifndef __pthread_mutex_lock
> diff --git a/nptl/pthread_mutex_unlock.c b/nptl/pthread_mutex_unlock.c
> index f9fe10b..479e500 100644
> --- a/nptl/pthread_mutex_unlock.c
> +++ b/nptl/pthread_mutex_unlock.c
> @@ -22,6 +22,7 @@
>  #include <stdlib.h>
>  #include "pthreadP.h"
>  #include <lowlevellock.h>
> +#include <stap-probe.h>
>
>  static int
>  internal_function
> @@ -50,6 +51,9 @@ __pthread_mutex_unlock_usercnt (mutex, decr)
>
>       /* Unlock.  */
>       lll_unlock (mutex->__data.__lock, PTHREAD_MUTEX_PSHARED (mutex));
> +
> +      LIBC_PROBE (mutex_release, 1, mutex);
> +
>       return 0;
>     }
>   else if (__builtin_expect (type == PTHREAD_MUTEX_RECURSIVE_NP, 1))
> @@ -272,6 +276,9 @@ __pthread_mutex_unlock_full (pthread_mutex_t *mutex,
> int decr)
>                        PTHREAD_MUTEX_PSHARED (mutex));
>
>       int oldprio = newval >> PTHREAD_MUTEX_PRIO_CEILING_SHIFT;
> +
> +      LIBC_PROBE (mutex_release, 1, mutex);
> +
>       return __pthread_tpp_change_priority (oldprio, -1);
>
>     default:
> @@ -279,6 +286,7 @@ __pthread_mutex_unlock_full (pthread_mutex_t *mutex,
> int decr)
>       return EINVAL;
>     }
>
> +  LIBC_PROBE (mutex_release, 1, mutex);
>   return 0;
>  }
>
> diff --git a/nptl/pthread_rwlock_destroy.c
> b/nptl/pthread_rwlock_destroy.c
> index 28fd24b..84aa693 100644
> --- a/nptl/pthread_rwlock_destroy.c
> +++ b/nptl/pthread_rwlock_destroy.c
> @@ -18,12 +18,15 @@
>    02111-1307 USA.  */
>
>  #include "pthreadP.h"
> +#include <stap-probe.h>
>
>
>  int
>  __pthread_rwlock_destroy (rwlock)
>      pthread_rwlock_t *rwlock;
>  {
> +  LIBC_PROBE (rwlock_destroy, 1, rwlock);
> +
>   /* Nothing to be done.  For now.  */
>   return 0;
>  }
> diff --git a/nptl/pthread_rwlock_rdlock.c b/nptl/pthread_rwlock_rdlock.c
> index 31eb508..610f223 100644
> --- a/nptl/pthread_rwlock_rdlock.c
> +++ b/nptl/pthread_rwlock_rdlock.c
> @@ -22,6 +22,7 @@
>  #include <lowlevellock.h>
>  #include <pthread.h>
>  #include <pthreadP.h>
> +#include <stap-probe.h>
>
>
>  /* Acquire read lock for RWLOCK.  */
> @@ -31,6 +32,8 @@ __pthread_rwlock_rdlock (rwlock)
>  {
>   int result = 0;
>
> +  LIBC_PROBE (rlock_entry, 1, rwlock);
> +

Again, there is no 'rlock_entry' probe documented, and should it
probably called 'rwlock_entry'?

>   /* Make sure we are along.  */
>   lll_lock (rwlock->__data.__lock, rwlock->__data.__shared);
>
> @@ -49,6 +52,8 @@ __pthread_rwlock_rdlock (rwlock)
>              --rwlock->__data.__nr_readers;
>              result = EAGAIN;
>            }
> +          else
> +            LIBC_PROBE (rwlock_acquire_read, 1, rwlock);

This one is also not documented, isn't it?

>
>          break;
>        }
> diff --git a/nptl/pthread_rwlock_unlock.c b/nptl/pthread_rwlock_unlock.c
> index a7ef71a..a6e8d87 100644
> --- a/nptl/pthread_rwlock_unlock.c
> +++ b/nptl/pthread_rwlock_unlock.c
> @@ -22,11 +22,14 @@
>  #include <lowlevellock.h>
>  #include <pthread.h>
>  #include <pthreadP.h>
> +#include <stap-probe.h>
>
>  /* Unlock RWLOCK.  */
>  int
>  __pthread_rwlock_unlock (pthread_rwlock_t *rwlock)
>  {
> +  LIBC_PROBE (rwlock_unlock, 1, rwlock);
> +
>   lll_lock (rwlock->__data.__lock, rwlock->__data.__shared);
>   if (rwlock->__data.__writer)
>     rwlock->__data.__writer = 0;
> diff --git a/nptl/pthread_rwlock_wrlock.c b/nptl/pthread_rwlock_wrlock.c
> index 64fe970..748062e 100644
> --- a/nptl/pthread_rwlock_wrlock.c
> +++ b/nptl/pthread_rwlock_wrlock.c
> @@ -22,6 +22,7 @@
>  #include <lowlevellock.h>
>  #include <pthread.h>
>  #include <pthreadP.h>
> +#include <stap-probe.h>
>
>
>  /* Acquire write lock for RWLOCK.  */
> @@ -31,6 +32,8 @@ __pthread_rwlock_wrlock (rwlock)
>  {
>   int result = 0;
>
> +  LIBC_PROBE (wlock_entry, 1, rwlock);
> +

Also not documented, and name should be 'rwlock_entry_write' or something.

>   /* Make sure we are along.  */
>   lll_lock (rwlock->__data.__lock, rwlock->__data.__shared);
>
> @@ -41,6 +44,9 @@ __pthread_rwlock_wrlock (rwlock)
>        {
>          /* Mark self as writer.  */
>          rwlock->__data.__writer = THREAD_GETMEM (THREAD_SELF, tid);
> +
> +          LIBC_PROBE (rwlock_acquire_write, 1, rwlock);
> +
>          break;
>        }
>
> diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S
> b/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S
> index 3195db2..f0664f9 100644
> --- a/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S
> +++ b/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S
> @@ -22,6 +22,15 @@
>  #include <kernel-features.h>
>  #include <lowlevellock.h>
>
> +#if defined USE_STAP_PROBE && (defined IN_LIB || !defined NOT_IN_libc)
> + #include <stap-probe.h>
> + #define PTHREAD_PROBE_LL_LOCKWAIT_PRIVATE(arg1)
> LIBC_PROBE_ASM(lll_lock_wait_private, arg1)

If 'lll_lock_wait_private' will be the name of the probe, than the
documentation should be updated.

> + #define PTHREAD_PROBE_LL_LOCKWAIT(arg1)
> LIBC_PROBE_ASM(lll_lock_wait, arg1)

Likewise.

> +#else
> + #define PTHREAD_PROBE_LL_LOCKWAIT_PRIVATE(arg1)
> + #define PTHREAD_PROBE_LL_LOCKWAIT(arg1)
> +#endif
> +
>        .text
>
>  #ifdef __ASSUME_PRIVATE_FUTEX
> @@ -91,7 +100,8 @@ __lll_lock_wait_private:
>        cmpl    %edx, %eax      /* NB:   %edx == 2 */
>        jne     2f
>
> -1:     movl    $SYS_futex, %eax
> +1:     PTHREAD_PROBE_LL_LOCKWAIT_PRIVATE (%rdi)
> +       movl    $SYS_futex, %eax
>        syscall
>
>  2:     movl    %edx, %eax
> @@ -130,7 +140,8 @@ __lll_lock_wait:
>        cmpl    %edx, %eax      /* NB:   %edx == 2 */
>        jne     2f
>
> -1:     movl    $SYS_futex, %eax
> +1:     PTHREAD_PROBE_LL_LOCKWAIT (%rdi)
> +       movl    $SYS_futex, %eax
>        syscall
>
>  2:     movl    %edx, %eax

Bert

>
> Rayson



More information about the Libc-alpha mailing list