1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 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 ((int) (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 = (long 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 ()
static 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 *) (long int) 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"
|