1570af302Sopenharmony_ci/* testing pthread mutex behaviour with various attributes */ 2570af302Sopenharmony_ci#include <pthread.h> 3570af302Sopenharmony_ci#include <semaphore.h> 4570af302Sopenharmony_ci#include <stdio.h> 5570af302Sopenharmony_ci#include <errno.h> 6570af302Sopenharmony_ci#include <string.h> 7570af302Sopenharmony_ci#include "test.h" 8570af302Sopenharmony_ci 9570af302Sopenharmony_ci#define T(f) if ((r=(f))) t_error(#f " failed: %s\n", strerror(r)) 10570af302Sopenharmony_ci#define E(f) if (f) t_error(#f " failed: %s\n", strerror(errno)) 11570af302Sopenharmony_ci 12570af302Sopenharmony_cistatic void *relock(void *arg) 13570af302Sopenharmony_ci{ 14570af302Sopenharmony_ci void **a = arg; 15570af302Sopenharmony_ci int r; 16570af302Sopenharmony_ci 17570af302Sopenharmony_ci T(pthread_mutex_lock(a[0])); 18570af302Sopenharmony_ci E(sem_post(a[1])); 19570af302Sopenharmony_ci *(int*)a[2] = pthread_mutex_lock(a[0]); 20570af302Sopenharmony_ci E(sem_post(a[1])); 21570af302Sopenharmony_ci 22570af302Sopenharmony_ci T(pthread_mutex_unlock(a[0])); 23570af302Sopenharmony_ci if (*(int*)a[2] == 0) 24570af302Sopenharmony_ci T(pthread_mutex_unlock(a[0])); 25570af302Sopenharmony_ci return 0; 26570af302Sopenharmony_ci} 27570af302Sopenharmony_ci 28570af302Sopenharmony_cistatic int test_relock(int mtype) 29570af302Sopenharmony_ci{ 30570af302Sopenharmony_ci struct timespec ts; 31570af302Sopenharmony_ci pthread_t t; 32570af302Sopenharmony_ci pthread_mutex_t m; 33570af302Sopenharmony_ci pthread_mutexattr_t ma; 34570af302Sopenharmony_ci sem_t s; 35570af302Sopenharmony_ci int i; 36570af302Sopenharmony_ci int r; 37570af302Sopenharmony_ci void *p; 38570af302Sopenharmony_ci void *a[] = {&m,&s,&i}; 39570af302Sopenharmony_ci 40570af302Sopenharmony_ci T(pthread_mutexattr_init(&ma)); 41570af302Sopenharmony_ci T(pthread_mutexattr_settype(&ma, mtype)); 42570af302Sopenharmony_ci T(pthread_mutex_init(a[0], &ma)); 43570af302Sopenharmony_ci T(pthread_mutexattr_destroy(&ma)); 44570af302Sopenharmony_ci E(sem_init(a[1], 0, 0)); 45570af302Sopenharmony_ci T(pthread_create(&t, 0, relock, a)); 46570af302Sopenharmony_ci E(sem_wait(a[1])); 47570af302Sopenharmony_ci E(clock_gettime(CLOCK_REALTIME, &ts)); 48570af302Sopenharmony_ci ts.tv_nsec += 100*1000*1000; 49570af302Sopenharmony_ci if (ts.tv_nsec >= 1000*1000*1000) { 50570af302Sopenharmony_ci ts.tv_nsec -= 1000*1000*1000; 51570af302Sopenharmony_ci ts.tv_sec += 1; 52570af302Sopenharmony_ci } 53570af302Sopenharmony_ci r = sem_timedwait(a[1],&ts); 54570af302Sopenharmony_ci if (r == -1) { 55570af302Sopenharmony_ci if (errno != ETIMEDOUT) 56570af302Sopenharmony_ci t_error("sem_timedwait failed with unexpected error: %s\n", strerror(errno)); 57570af302Sopenharmony_ci /* leave the deadlocked relock thread running */ 58570af302Sopenharmony_ci return -1; 59570af302Sopenharmony_ci } 60570af302Sopenharmony_ci T(pthread_join(t, &p)); 61570af302Sopenharmony_ci T(pthread_mutex_destroy(a[0])); 62570af302Sopenharmony_ci E(sem_destroy(a[1])); 63570af302Sopenharmony_ci return i; 64570af302Sopenharmony_ci} 65570af302Sopenharmony_ci 66570af302Sopenharmony_cistatic void *unlock(void *arg) 67570af302Sopenharmony_ci{ 68570af302Sopenharmony_ci void **a = arg; 69570af302Sopenharmony_ci 70570af302Sopenharmony_ci *(int*)a[1] = pthread_mutex_unlock(a[0]); 71570af302Sopenharmony_ci return 0; 72570af302Sopenharmony_ci} 73570af302Sopenharmony_ci 74570af302Sopenharmony_cistatic int test_unlock(int mtype) 75570af302Sopenharmony_ci{ 76570af302Sopenharmony_ci pthread_t t; 77570af302Sopenharmony_ci pthread_mutex_t m; 78570af302Sopenharmony_ci pthread_mutexattr_t ma; 79570af302Sopenharmony_ci int i; 80570af302Sopenharmony_ci int r; 81570af302Sopenharmony_ci void *p; 82570af302Sopenharmony_ci void *a[] = {&m,&i}; 83570af302Sopenharmony_ci 84570af302Sopenharmony_ci T(pthread_mutexattr_init(&ma)); 85570af302Sopenharmony_ci T(pthread_mutexattr_settype(&ma, mtype)); 86570af302Sopenharmony_ci T(pthread_mutex_init(a[0], &ma)); 87570af302Sopenharmony_ci T(pthread_mutexattr_destroy(&ma)); 88570af302Sopenharmony_ci T(pthread_create(&t, 0, unlock, a)); 89570af302Sopenharmony_ci T(pthread_join(t, &p)); 90570af302Sopenharmony_ci T(pthread_mutex_destroy(a[0])); 91570af302Sopenharmony_ci return i; 92570af302Sopenharmony_ci} 93570af302Sopenharmony_ci 94570af302Sopenharmony_cistatic int test_unlock_other(int mtype) 95570af302Sopenharmony_ci{ 96570af302Sopenharmony_ci pthread_t t; 97570af302Sopenharmony_ci pthread_mutex_t m; 98570af302Sopenharmony_ci pthread_mutexattr_t ma; 99570af302Sopenharmony_ci int i; 100570af302Sopenharmony_ci int r; 101570af302Sopenharmony_ci void *p; 102570af302Sopenharmony_ci void *a[] = {&m,&i}; 103570af302Sopenharmony_ci 104570af302Sopenharmony_ci T(pthread_mutexattr_init(&ma)); 105570af302Sopenharmony_ci T(pthread_mutexattr_settype(&ma, mtype)); 106570af302Sopenharmony_ci T(pthread_mutex_init(a[0], &ma)); 107570af302Sopenharmony_ci T(pthread_mutexattr_destroy(&ma)); 108570af302Sopenharmony_ci T(pthread_mutex_lock(a[0])); 109570af302Sopenharmony_ci T(pthread_create(&t, 0, unlock, a)); 110570af302Sopenharmony_ci T(pthread_join(t, &p)); 111570af302Sopenharmony_ci T(pthread_mutex_unlock(a[0])); 112570af302Sopenharmony_ci T(pthread_mutex_destroy(a[0])); 113570af302Sopenharmony_ci return i; 114570af302Sopenharmony_ci} 115570af302Sopenharmony_ci 116570af302Sopenharmony_cistatic void test_mutexattr() 117570af302Sopenharmony_ci{ 118570af302Sopenharmony_ci pthread_mutex_t m; 119570af302Sopenharmony_ci pthread_mutexattr_t a; 120570af302Sopenharmony_ci int r; 121570af302Sopenharmony_ci int i; 122570af302Sopenharmony_ci 123570af302Sopenharmony_ci T(pthread_mutexattr_init(&a)); 124570af302Sopenharmony_ci T(pthread_mutexattr_gettype(&a, &i)); 125570af302Sopenharmony_ci if (i != PTHREAD_MUTEX_DEFAULT) 126570af302Sopenharmony_ci t_error("default mutex type is %d, wanted PTHREAD_MUTEX_DEFAULT (%d)\n", i, PTHREAD_MUTEX_DEFAULT); 127570af302Sopenharmony_ci T(pthread_mutexattr_settype(&a, PTHREAD_MUTEX_ERRORCHECK)); 128570af302Sopenharmony_ci T(pthread_mutexattr_gettype(&a, &i)); 129570af302Sopenharmony_ci if (i != PTHREAD_MUTEX_ERRORCHECK) 130570af302Sopenharmony_ci t_error("setting error check mutex type failed failed: got %d, wanted %d\n", i, PTHREAD_MUTEX_ERRORCHECK); 131570af302Sopenharmony_ci T(pthread_mutexattr_destroy(&a)); 132570af302Sopenharmony_ci} 133570af302Sopenharmony_ci 134570af302Sopenharmony_ciint main(void) 135570af302Sopenharmony_ci{ 136570af302Sopenharmony_ci int i; 137570af302Sopenharmony_ci 138570af302Sopenharmony_ci test_mutexattr(); 139570af302Sopenharmony_ci 140570af302Sopenharmony_ci i = test_relock(PTHREAD_MUTEX_NORMAL); 141570af302Sopenharmony_ci if (i != -1) 142570af302Sopenharmony_ci t_error("PTHREAD_MUTEX_NORMAL relock did not deadlock, got %s\n", strerror(i)); 143570af302Sopenharmony_ci i = test_relock(PTHREAD_MUTEX_ERRORCHECK); 144570af302Sopenharmony_ci if (i != EDEADLK) 145570af302Sopenharmony_ci t_error("PTHREAD_MUTEX_ERRORCHECK relock did not return EDEADLK, got %s\n", i==-1?"deadlock":strerror(i)); 146570af302Sopenharmony_ci i = test_relock(PTHREAD_MUTEX_RECURSIVE); 147570af302Sopenharmony_ci if (i != 0) 148570af302Sopenharmony_ci t_error("PTHREAD_MUTEX_RECURSIVE relock did not succed, got %s\n", i==-1?"deadlock":strerror(i)); 149570af302Sopenharmony_ci 150570af302Sopenharmony_ci i = test_unlock(PTHREAD_MUTEX_ERRORCHECK); 151570af302Sopenharmony_ci if (i != EPERM) 152570af302Sopenharmony_ci t_error("PTHREAD_MUTEX_ERRORCHECK unlock did not return EPERM, got %s\n", strerror(i)); 153570af302Sopenharmony_ci i = test_unlock(PTHREAD_MUTEX_RECURSIVE); 154570af302Sopenharmony_ci if (i != EPERM) 155570af302Sopenharmony_ci t_error("PTHREAD_MUTEX_RECURSIVE unlock did not return EPERM, got %s\n", strerror(i)); 156570af302Sopenharmony_ci 157570af302Sopenharmony_ci i = test_unlock_other(PTHREAD_MUTEX_ERRORCHECK); 158570af302Sopenharmony_ci if (i != EPERM) 159570af302Sopenharmony_ci t_error("PTHREAD_MUTEX_ERRORCHECK unlock did not return EPERM, got %s\n", strerror(i)); 160570af302Sopenharmony_ci i = test_unlock_other(PTHREAD_MUTEX_RECURSIVE); 161570af302Sopenharmony_ci if (i != EPERM) 162570af302Sopenharmony_ci t_error("PTHREAD_MUTEX_RECURSIVE unlock did not return EPERM, got %s\n", strerror(i)); 163570af302Sopenharmony_ci 164570af302Sopenharmony_ci return t_status; 165570af302Sopenharmony_ci} 166