FreeBSD regtest: add missing helgrind expecteds
[valgrind.git] / helgrind / tests / safe-pthread.h
blob788f7b89b63627085a7500c3d1418577d1f5a1ec
1 #include <pthread.h>
2 #include <signal.h>
3 #include <setjmp.h>
4 #include <errno.h>
5 #include <assert.h>
7 static sigjmp_buf env;
9 /*
10 * Starting with glibc 2.20 some pthread calls may execute
11 * an xend instruction unconditionally when a lock is used in
12 * a way that is invalid so defined a sigill handler that can
13 * convert these invalid instructions to a normal error.
15 static void sigill_handler( int signum, siginfo_t *siginfo, void *sigcontext ) {
16 unsigned char *pc = siginfo->si_addr;
17 assert( pc[0] == 0x0f && pc[1] == 0x01 && pc[2] == 0xd5 );
18 siglongjmp( env, EPERM );
22 * Same as above, but in case we do recognize the xend,
23 * but detect it is invalid (used outside a transaction)
24 * and generate a segv. Unfortunately then si_addr is,
25 * just zero, so we cannot add an assert/sanity check.
27 static void segv_handler( int signum, siginfo_t *siginfo, void *sigcontext ) {
28 siglongjmp( env, EPERM );
31 static int safe_pthread_rwlock_unlock( pthread_rwlock_t *rwlock ) __attribute__((unused));
33 * Wrapper for pthread_rwlock_unlock which may execute xend
34 * unconditionally when used on a lock that is not locked.
36 * Note that we return 0 instead of EPERM because that is what
37 * glibc normally does - error reporting is optional.
39 static int safe_pthread_rwlock_unlock( pthread_rwlock_t *rwlock ) {
40 struct sigaction sa_ill, sa_segv;
41 struct sigaction oldsa_ill, oldsa_segv;
42 int r;
44 sa_ill.sa_handler = NULL;
45 sa_ill.sa_sigaction = sigill_handler;
46 sigemptyset( &sa_ill.sa_mask );
47 sa_ill.sa_flags = SA_SIGINFO;
49 sigaction( SIGILL, &sa_ill, &oldsa_ill );
51 sa_segv.sa_handler = NULL;
52 sa_segv.sa_sigaction = segv_handler;
53 sigemptyset( &sa_segv.sa_mask );
54 sa_segv.sa_flags = SA_SIGINFO;
56 sigaction( SIGSEGV, &sa_segv, &oldsa_segv );
58 if ( ( r = sigsetjmp( env, 1 ) ) == 0 ) {
59 r = pthread_rwlock_unlock( rwlock );
60 } else {
61 r = 0;
64 sigaction( SIGILL, &oldsa_ill, NULL );
65 sigaction( SIGSEGV, &oldsa_segv, NULL );
67 return r;
70 #define pthread_rwlock_unlock safe_pthread_rwlock_unlock