set test pthreadprobes if {! [installtest_p]} { untested $test; return } if {! [uprobes_p]} { untested "$test"; return } # compile the testcase catch {exec gcc -g -o $test $srcdir/$subdir/$test.c -lpthread -lrt} err if {$err != "" && [file exists $test]} then { fail "$test compile $err" } else { # find the location of the pthread library catch {exec /usr/bin/ldd $test | egrep {^\s*libpthread.so} | awk {{print $3}} } pthread } # First thing, do we have a version of glibc with the probes?? set cmd [concat -L process(\"$pthread\").mark(\"pthread_create\")] if {[catch {exec stap $cmd } res2]} { # can happen on systems without pthread probes in glibc, so don't complain untested "$test" return } else { pass "$test" } # The "cond_timedwait" mark doesn't exist in some versions of glibc # (such as RHEL7 ppc64), so figure out if it exists in this # glibc. Notice that that probe is optional in the script below. set cmd [concat -L process(\"$pthread\").mark(\"cond_timedwait\")] set cond_timedwait_available 0 if {![catch {exec stap $cmd } res2]} { set cond_timedwait_available 1 } # Now we exercise every probe available set script $srcdir/$subdir/$test.stp foreach runtime [get_runtime_list] { set test_name $test if {$runtime != ""} { # Suppress warnings (-w) because dyninst can't place some probes, and the WARNINGs # make tcl catch return non-zero. This way we'll still get individual results. verbose -log "Running: stap -u -w --runtime=$runtime $script $pthread -c ./$test" set rc [catch {exec stap -w --runtime=$runtime $script $pthread -c ./$test } res3] lappend test_name "($runtime)" } else { verbose -log "Running: stap -u $script $pthread -c ./$test" set rc [catch {exec stap $script $pthread -c ./$test } res3] } verbose -log "$res3" # error executing? if {$rc} { fail "$test_name (rc=$rc)" exec rm -f $test return } set cond_broadcast_correct 0 set cond_destroy_correct 0 set cond_init_correct 0 set cond_signal_correct 0 set cond_timedwait_correct 0 set cond_wait_correct 0 set mutex_acquired_correct 0 set mutex_destroy_correct 0 set mutex_entry_correct 0 set mutex_init_correct 0 set mutex_release_correct 0 set mutex_timedlock_acquired_correct 0 set mutex_timedlock_entry_correct 0 set pthread_create_correct 0 set pthread_join_correct 0 set pthread_join_ret_correct 0 set pthread_start_correct 0 set rdlock_entry_correct 0 set rwlock_destroy_correct 0 set wrlock_entry_correct 0 # make sure the numbers match foreach line $res3 { if {[regexp {cond_broadcast=[1-9]} $line]} { set cond_broadcast_correct 1 } if {[regexp "cond_destroy=0" $line]} { set cond_destroy_correct 1 } if {[regexp "cond_init=3" $line]} { set cond_init_correct 1 } if {[regexp {cond_signal=[1-9]} $line]} { set cond_signal_correct 1 } # Handle optional 'cond_timedwait'. if {[regexp {cond_timedwait=([01])} $line matched sub1]} { if {[expr $cond_timedwait_available && $sub1] \ || [expr !$cond_timedwait_available && !$sub1]} { set cond_timedwait_correct 1 } } if {[regexp {cond_wait=[1-9]} $line]} { set cond_wait_correct 1 } if {[regexp {mutex_acquired=([1-9][0-9]+)} $line]} { set mutex_acquired_correct 1 } if {[regexp "mutex_destroy=1" $line]} { set mutex_destroy_correct 1 } if {[regexp {mutex_entry=([1-9][0-9]+)} $line]} { set mutex_entry_correct 1 } if {[regexp "mutex_init=3" $line]} { set mutex_init_correct 1 } if {[regexp {mutex_release=([1-9][0-9]+)} $line]} { set mutex_release_correct 1 } # pthread_mutex_timedlock is called with a timeout of 1 second in a # loop while the mutex is held by the other thread for about 5 seconds # resulting in a couple of entries resulting in a ETIMEDOUT before it # is actually acquired. Expect 2 till 6 tries before success. if {[regexp {mutex_timedlock_entry=[2-6]} $line]} { set mutex_timedlock_entry_correct 1 } if {[regexp "mutex_timedlock_acquired=1" $line]} { set mutex_timedlock_acquired_correct 1 } if {[regexp "pthread_create=6" $line]} { set pthread_create_correct 1 } if {[regexp "pthread_join=4" $line]} { set pthread_join_correct 1 } if {[regexp "pthread_join_ret=4" $line]} { set pthread_join_ret_correct 1 } if {[regexp "pthread_start=6" $line]} { set pthread_start_correct 1 } if {[regexp {rdlock_entry=[1-9][0-9]*} $line]} { set rdlock_entry_correct 1 } if {[regexp "rwlock_destroy=0" $line]} { set rwlock_destroy_correct 1 } if {[regexp {wrlock_entry=[1-9]} $line]} { set wrlock_entry_correct 1 } } if { $cond_broadcast_correct == 0 } { fail "$test_name cond_broadcast" } else { pass "$test_name cond_broadcast" } if { $cond_destroy_correct == 0 } { fail "$test_name cond_destroy" } else { pass "$test_name cond_destroy" } if { $cond_init_correct == 0 } { fail "$test_name cond_init" } else { pass "$test_name cond_init" } if { $cond_signal_correct == 0 } { fail "$test_name cond_signal" } else { pass "$test_name cond_signal" } if { $cond_timedwait_correct == 0 } { fail "$test_name cond_timedwait" } else { pass "$test_name cond_timedwait" } if { $cond_wait_correct == 0 } { fail "$test_name cond_wait" } else { pass "$test_name cond_wait" } if { $mutex_acquired_correct == 0 } { fail "$test_name mutex_acquired" } else { pass "$test_name mutex_acquired" } if { $mutex_destroy_correct == 0 } { fail "$test_name mutex_destroy" } else { pass "$test_name mutex_destroy" } if { $mutex_entry_correct == 0 } { fail "$test_name mutex_entry" } else { pass "$test_name mutex_entry" } if { $mutex_init_correct == 0 } { fail "$test_name mutex_init" } else { pass "$test_name mutex_init" } if { $mutex_release_correct == 0 } { fail "$test_name mutex_release" } else { pass "$test_name mutex_release" } if { $mutex_timedlock_acquired_correct == 0 } { fail "$test_name mutex_timedlock_acquired" } else { pass "$test_name mutex_timedlock_acquired" } if { $mutex_timedlock_entry_correct == 0 } { fail "$test_name mutex_timedlock_entry" } else { pass "$test_name mutex_timedlock_entry" } if { $pthread_create_correct == 0 } { fail "$test_name pthread_create" } else { pass "$test_name pthread_create" } if { $pthread_join_correct == 0 } { fail "$test_name pthread_join" } else { pass "$test_name pthread_join" } if { $pthread_join_ret_correct == 0 } { fail "$test_name pthread_join_ret" } else { pass "$test_name pthread_join_ret" } if { $pthread_start_correct == 0 } { fail "$test_name pthread_start" } else { pass "$test_name pthread_start" } if { $rdlock_entry_correct == 0 } { fail "$test_name rdlock_entry" } else { pass "$test_name rdlock_entry" } if { $rwlock_destroy_correct == 0 } { fail "$test_name rwlock_destroy" } else { pass "$test_name rwlock_destroy" } if { $wrlock_entry_correct == 0 } { fail "$test_name wrlock_entry" } else { pass "$test_name wrlock_entry" } } exec rm -f $test