diff options
-rw-r--r-- | linuxthreads/ecmutex.c | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/linuxthreads/ecmutex.c b/linuxthreads/ecmutex.c new file mode 100644 index 0000000000..b9d1d54352 --- /dev/null +++ b/linuxthreads/ecmutex.c @@ -0,0 +1,157 @@ +/* Test of the error checking mutex and incidently also barriers. */ + +#include <errno.h> +#include <pthread.h> +#include <stdio.h> +#include <stdlib.h> + + +static pthread_mutex_t locks[] = +{ + PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP, + PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP, + PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP, + PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP, + PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP +}; +#define nlocks (sizeof (locks) / sizeof (locks[0])) + +static pthread_barrier_t barrier; +#define SYNC pthread_barrier_wait (&barrier) + +#define NTHREADS nlocks + +#define ROUNDS 20 + + +static void * +worker (void *arg) +{ + /* We are locking the and unlocked the locks and check the errors. + Since we are using the error-checking variant the implementation + should report them. */ + int nr = (int) arg; + int i; + void *result = NULL; + int retval; + + for (i = 0; i < ROUNDS; ++i) + { + /* Skip the rounds which would make other == own. */ + if (i % nlocks == 0) + continue; + + /* Get the "own" mutex. */ + if (pthread_mutex_trylock (&locks[nr]) != 0) + { + printf ("thread %d failed getting own mutex\n", nr); + result = (void *) 1; + } + + /* Try locking "own" mutex again. */ + retval = pthread_mutex_lock (&locks[nr]); + if (retval != EDEADLK) + { + printf ("thread %d failed getting own mutex\n", nr); + result = (void *) 1; + } + + /* Try to get a different semaphore. */ + SYNC; + retval = pthread_mutex_trylock (&locks[(nr + i) % nlocks]); + if (retval != EBUSY) + { + printf ("thread %d didn't deadlock on getting %d's lock\n", + nr, (nr + i) % nlocks); + result = (void *) 1; + } + + /* Try unlocking other's lock. */ + retval = pthread_mutex_unlock (&locks[(nr + i) % nlocks]); + if (retval != EPERM) + { + printf ("thread %d managed releasing mutex %d\n", + nr, (nr + i) % nlocks); + result = (void *) 1; + } + + /* All lock one mutex now. */ + SYNC; + retval = pthread_mutex_lock (&locks[i % nlocks]); + if (nr == (i % nlocks)) + { + if (retval != EDEADLK) + { + printf ("thread %d didn't deadlock on getting %d's lock\n", + nr, (nr + i) % nlocks); + result = (void *) 1; + } + if (pthread_mutex_unlock (&locks[i % nlocks]) != 0) + { + printf ("thread %d failed releasing own mutex\n", nr); + result = (void *) 1; + } + } + else + { + if (retval != 0) + { + printf ("thread %d failed acquiring mutex %d\n", + nr, i % nlocks); + result = (void *) 1; + } + else if (pthread_mutex_unlock (&locks[i % nlocks]) != 0) + { + printf ("thread %d failed releasing mutex %d\n", + nr, i % nlocks); + result = (void *) 1; + } + } + + /* Unlock the own lock. */ + SYNC; + if (nr != (i % nlocks) && pthread_mutex_unlock (&locks[nr]) != 0) + { + printf ("thread %d failed releasing own mutex\n", nr); + result = (void *) 1; + } + + /* Try unlocking again. */ + retval = pthread_mutex_unlock (&locks[nr]); + if (retval == 0) + { + printf ("thread %d managed releasing own mutex twice\n", nr); + result = (void *) 1; + } + } + + return result; +} + + +#define TEST_FUNCTION do_test () +int +do_test (void) +{ + pthread_t threads[NTHREADS]; + int i; + void *res; + int result = 0; + + pthread_barrier_init (&barrier, NULL, NTHREADS); + + for (i = 0; i < NTHREADS; ++i) + if (pthread_create (&threads[i], NULL, worker, (void *) i) != 0) + { + printf ("failed to create thread %d: %m\n", i); + exit (1); + } + + for (i = 0; i < NTHREADS; ++i) + if (pthread_join (threads[i], &res) != 0 || res != NULL) + result = 1; + + return result; +} + +#include "../test-skeleton.c" |