1/* testing pthread mutex behaviour with various attributes */ 2#include <pthread.h> 3#include <semaphore.h> 4#include <stdio.h> 5#include <errno.h> 6#include <string.h> 7#include "test.h" 8 9#define T(f) if ((r=(f))) t_error(#f " failed: %s\n", strerror(r)) 10#define E(f) if (f) t_error(#f " failed: %s\n", strerror(errno)) 11 12static void *relock(void *arg) 13{ 14 void **a = arg; 15 int r; 16 17 T(pthread_mutex_lock(a[0])); 18 E(sem_post(a[1])); 19 *(int*)a[2] = pthread_mutex_lock(a[0]); 20 E(sem_post(a[1])); 21 22 T(pthread_mutex_unlock(a[0])); 23 if (*(int*)a[2] == 0) 24 T(pthread_mutex_unlock(a[0])); 25 return 0; 26} 27 28static int test_relock(int mtype) 29{ 30 struct timespec ts; 31 pthread_t t; 32 pthread_mutex_t m; 33 pthread_mutexattr_t ma; 34 sem_t s; 35 int i; 36 int r; 37 void *p; 38 void *a[] = {&m,&s,&i}; 39 40 T(pthread_mutexattr_init(&ma)); 41 T(pthread_mutexattr_settype(&ma, mtype)); 42 T(pthread_mutexattr_setprotocol(&ma, PTHREAD_PRIO_INHERIT)); 43 T(pthread_mutex_init(a[0], &ma)); 44 T(pthread_mutexattr_destroy(&ma)); 45 E(sem_init(a[1], 0, 0)); 46 T(pthread_create(&t, 0, relock, a)); 47 E(sem_wait(a[1])); 48 E(clock_gettime(CLOCK_REALTIME, &ts)); 49 ts.tv_nsec += 100*1000*1000; 50 if (ts.tv_nsec >= 1000*1000*1000) { 51 ts.tv_nsec -= 1000*1000*1000; 52 ts.tv_sec += 1; 53 } 54 r = sem_timedwait(a[1],&ts); 55 if (r == -1) { 56 if (errno != ETIMEDOUT) 57 t_error("sem_timedwait failed with unexpected error: %s\n", strerror(errno)); 58 /* leave the deadlocked relock thread running */ 59 return -1; 60 } 61 T(pthread_join(t, &p)); 62 T(pthread_mutex_destroy(a[0])); 63 E(sem_destroy(a[1])); 64 return i; 65} 66 67static void *unlock(void *arg) 68{ 69 void **a = arg; 70 71 *(int*)a[1] = pthread_mutex_unlock(a[0]); 72 return 0; 73} 74 75static int test_unlock(int mtype) 76{ 77 pthread_t t; 78 pthread_mutex_t m; 79 pthread_mutexattr_t ma; 80 int i; 81 int r; 82 void *p; 83 void *a[] = {&m,&i}; 84 85 T(pthread_mutexattr_init(&ma)); 86 T(pthread_mutexattr_settype(&ma, mtype)); 87 T(pthread_mutexattr_setprotocol(&ma, PTHREAD_PRIO_INHERIT)); 88 T(pthread_mutex_init(a[0], &ma)); 89 T(pthread_mutexattr_destroy(&ma)); 90 T(pthread_create(&t, 0, unlock, a)); 91 T(pthread_join(t, &p)); 92 T(pthread_mutex_destroy(a[0])); 93 return i; 94} 95 96static int test_unlock_other(int mtype) 97{ 98 pthread_t t; 99 pthread_mutex_t m; 100 pthread_mutexattr_t ma; 101 int i; 102 int r; 103 void *p; 104 void *a[] = {&m,&i}; 105 106 T(pthread_mutexattr_init(&ma)); 107 T(pthread_mutexattr_settype(&ma, mtype)); 108 T(pthread_mutexattr_setprotocol(&ma, PTHREAD_PRIO_INHERIT)); 109 T(pthread_mutex_init(a[0], &ma)); 110 T(pthread_mutexattr_destroy(&ma)); 111 T(pthread_mutex_lock(a[0])); 112 T(pthread_create(&t, 0, unlock, a)); 113 T(pthread_join(t, &p)); 114 T(pthread_mutex_unlock(a[0])); 115 T(pthread_mutex_destroy(a[0])); 116 return i; 117} 118 119static void test_mutexattr() 120{ 121 pthread_mutex_t m; 122 pthread_mutexattr_t a; 123 int r; 124 int i; 125 126 T(pthread_mutexattr_init(&a)); 127 T(pthread_mutexattr_gettype(&a, &i)); 128 if (i != PTHREAD_MUTEX_DEFAULT) 129 t_error("default mutex type is %d, wanted PTHREAD_MUTEX_DEFAULT (%d)\n", i, PTHREAD_MUTEX_DEFAULT); 130 T(pthread_mutexattr_settype(&a, PTHREAD_MUTEX_ERRORCHECK)); 131 T(pthread_mutexattr_gettype(&a, &i)); 132 if (i != PTHREAD_MUTEX_ERRORCHECK) 133 t_error("setting error check mutex type failed failed: got %d, wanted %d\n", i, PTHREAD_MUTEX_ERRORCHECK); 134 T(pthread_mutexattr_destroy(&a)); 135} 136 137int main(void) 138{ 139 int i; 140 141 test_mutexattr(); 142 143 i = test_relock(PTHREAD_MUTEX_NORMAL); 144 if (i != -1) 145 t_error("PTHREAD_MUTEX_NORMAL relock did not deadlock, got %s\n", strerror(i)); 146 i = test_relock(PTHREAD_MUTEX_ERRORCHECK); 147 if (i != EDEADLK) 148 t_error("PTHREAD_MUTEX_ERRORCHECK relock did not return EDEADLK, got %s\n", i==-1?"deadlock":strerror(i)); 149 i = test_relock(PTHREAD_MUTEX_RECURSIVE); 150 if (i != 0) 151 t_error("PTHREAD_MUTEX_RECURSIVE relock did not succed, got %s\n", i==-1?"deadlock":strerror(i)); 152 153 i = test_unlock(PTHREAD_MUTEX_ERRORCHECK); 154 if (i != EPERM) 155 t_error("PTHREAD_MUTEX_ERRORCHECK unlock did not return EPERM, got %s\n", strerror(i)); 156 i = test_unlock(PTHREAD_MUTEX_RECURSIVE); 157 if (i != EPERM) 158 t_error("PTHREAD_MUTEX_RECURSIVE unlock did not return EPERM, got %s\n", strerror(i)); 159 160 i = test_unlock_other(PTHREAD_MUTEX_ERRORCHECK); 161 if (i != EPERM) 162 t_error("PTHREAD_MUTEX_ERRORCHECK unlock did not return EPERM, got %s\n", strerror(i)); 163 i = test_unlock_other(PTHREAD_MUTEX_RECURSIVE); 164 if (i != EPERM) 165 t_error("PTHREAD_MUTEX_RECURSIVE unlock did not return EPERM, got %s\n", strerror(i)); 166 167 return t_status; 168} 169