chiark / gitweb /
Apply https://sourceware.org/git/?p=glibc.git;a=commit;h=d5dd6189d506068ed11c8bfa1e1e...
[eglibc.git] / linuxthreads / ecmutex.c
1 /* Test of the error checking mutex and incidently also barriers.  */
2
3 #include <errno.h>
4 #include <pthread.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7
8
9 static pthread_mutex_t locks[] =
10 {
11   PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP,
12   PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP,
13   PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP,
14   PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP,
15   PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
16 };
17 #define nlocks ((int) (sizeof (locks) / sizeof (locks[0])))
18
19 static pthread_barrier_t barrier;
20 #define SYNC pthread_barrier_wait (&barrier)
21
22 #define NTHREADS nlocks
23
24 #define ROUNDS 20
25
26
27 static void *
28 worker (void *arg)
29 {
30   /* We are locking the and unlocked the locks and check the errors.
31      Since we are using the error-checking variant the implementation
32      should report them.  */
33   int nr = (long int) arg;
34   int i;
35   void *result = NULL;
36   int retval;
37
38   for (i = 0; i < ROUNDS; ++i)
39     {
40       /* Skip the rounds which would make other == own.  */
41       if (i % nlocks == 0)
42         continue;
43
44       /* Get the "own" mutex.  */
45       if (pthread_mutex_trylock (&locks[nr]) != 0)
46         {
47           printf ("thread %d failed getting own mutex\n", nr);
48           result = (void *) 1;
49         }
50
51       /* Try locking "own" mutex again.  */
52       retval = pthread_mutex_lock (&locks[nr]);
53       if (retval != EDEADLK)
54         {
55           printf ("thread %d failed getting own mutex\n", nr);
56           result = (void *) 1;
57         }
58
59       /* Try to get a different semaphore.  */
60       SYNC;
61       retval = pthread_mutex_trylock (&locks[(nr + i) % nlocks]);
62       if (retval != EBUSY)
63         {
64           printf ("thread %d didn't deadlock on getting %d's lock\n",
65                   nr, (nr + i) % nlocks);
66           result = (void *) 1;
67         }
68
69       /* Try unlocking other's lock.  */
70       retval = pthread_mutex_unlock (&locks[(nr + i) % nlocks]);
71       if (retval != EPERM)
72         {
73           printf ("thread %d managed releasing mutex %d\n",
74                   nr, (nr + i) % nlocks);
75           result = (void *) 1;
76         }
77
78       /* All lock one mutex now.  */
79       SYNC;
80       retval = pthread_mutex_lock (&locks[i % nlocks]);
81       if (nr == (i % nlocks))
82         {
83           if (retval != EDEADLK)
84             {
85               printf ("thread %d didn't deadlock on getting %d's lock\n",
86                       nr, (nr + i) % nlocks);
87               result = (void *) 1;
88             }
89           if (pthread_mutex_unlock (&locks[i % nlocks]) != 0)
90             {
91               printf ("thread %d failed releasing own mutex\n", nr);
92               result = (void *) 1;
93             }
94         }
95       else
96         {
97           if (retval != 0)
98             {
99               printf ("thread %d failed acquiring mutex %d\n",
100                       nr, i % nlocks);
101               result = (void *) 1;
102             }
103           else if (pthread_mutex_unlock (&locks[i % nlocks]) != 0)
104             {
105               printf ("thread %d failed releasing mutex %d\n",
106                       nr, i % nlocks);
107               result = (void *) 1;
108             }
109         }
110
111       /* Unlock the own lock.  */
112       SYNC;
113       if (nr != (i % nlocks) && pthread_mutex_unlock (&locks[nr]) != 0)
114         {
115           printf ("thread %d failed releasing own mutex\n", nr);
116           result = (void *) 1;
117         }
118
119       /* Try unlocking again.  */
120       retval = pthread_mutex_unlock (&locks[nr]);
121       if (retval == 0)
122         {
123           printf ("thread %d managed releasing own mutex twice\n", nr);
124           result = (void *) 1;
125         }
126     }
127
128   return result;
129 }
130
131
132 #define TEST_FUNCTION do_test ()
133 static int
134 do_test (void)
135 {
136   pthread_t threads[NTHREADS];
137   int i;
138   void *res;
139   int result = 0;
140
141   pthread_barrier_init (&barrier, NULL, NTHREADS);
142
143   for (i = 0; i < NTHREADS; ++i)
144     if (pthread_create (&threads[i], NULL, worker, (void *) (long int) i) != 0)
145       {
146         printf ("failed to create thread %d: %m\n", i);
147         exit (1);
148       }
149
150   for (i = 0; i < NTHREADS; ++i)
151     if (pthread_join (threads[i], &res) != 0 || res != NULL)
152       result = 1;
153
154   return result;
155 }
156
157 #include "../test-skeleton.c"