libefivar: Fix (instead of silence) the remaining warnings in libefivar.
[dragonfly.git] / test / libpthread / mutex_d.c
1 /*
2  * Copyright (c) 1998 Daniel M. Eischen <eischen@vigrid.com>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by Daniel M. Eischen.
16  * 4. Neither the name of the author nor the names of any co-contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY DANIEL M. EISCHEN AND CONTRIBUTORS ``AS IS''
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  *
32  * $FreeBSD: src/lib/libc_r/test/mutex_d.c,v 1.1.2.2 2003/01/05 19:59:39 semenu Exp $
33  */
34 #include <stdlib.h>
35 #include <unistd.h>
36
37 #include <sys/ioctl.h>
38 #include <assert.h>
39 #include <errno.h>
40 #include <pthread.h>
41 #include <pthread_np.h>
42 #include <sys/sched.h>
43 #include <signal.h>
44 #include <stdarg.h>
45 #include <stdio.h>
46 #include <string.h>
47 #include <sysexits.h>
48 #include <sys/time.h>
49
50 #ifndef NELEMENTS
51 #define NELEMENTS(arr)  (sizeof (arr) / sizeof (arr[0]))
52 #endif
53
54 #ifndef NUM_THREADS
55 #define NUM_THREADS     10
56 #endif
57
58 #define MAX_THREAD_CMDS 10
59
60 static void log_error(const char *, ...) __printflike(1, 2);
61 static void log_trace (const char *, ...) __printflike(1, 2);
62 static void log_info (const char *, ...) __printflike(1, 2);
63
64 /*------------------------------------------------------------
65  * Types
66  *----------------------------------------------------------*/
67
68 typedef enum {
69         STAT_INITIAL,           /* initial state */
70         STAT_WAITCONDVAR,       /* waiting for condition variable signal */
71         STAT_WAITMUTEX          /* waiting for mutex lock */
72 } thread_status_t;
73
74 typedef enum {
75         FLAGS_REPORT_WAITCONDMUTEX      = 0x01,
76         FLAGS_REPORT_WAITCONDVAR        = 0x02,
77         FLAGS_REPORT_WAITMUTEX          = 0x04,
78         FLAGS_REPORT_BUSY_LOOP          = 0x08,
79         FLAGS_IS_BUSY                   = 0x10,
80         FLAGS_WAS_BUSY                  = 0x20
81 } thread_flags_t;
82
83 typedef enum {
84         CMD_NONE,
85         CMD_TAKE_MUTEX,
86         CMD_RELEASE_MUTEX,
87         CMD_WAIT_FOR_SIGNAL,
88         CMD_BUSY_LOOP,
89         CMD_PROTECTED_OP,
90         CMD_RELEASE_ALL
91 } thread_cmd_id_t;
92
93 typedef struct {
94         thread_cmd_id_t cmd_id;
95         pthread_mutex_t *mutex;
96         pthread_cond_t  *cond;
97 } thread_cmd_t;
98
99 typedef struct {
100         pthread_cond_t  cond_var;
101         thread_status_t status;
102         thread_cmd_t    cmd;
103         int             flags;
104         int             priority;
105         int             ret;
106         pthread_t       tid;
107         u_int8_t        id;
108 } thread_state_t;
109
110 typedef enum {
111         M_POSIX,
112         M_SS2_DEFAULT,
113         M_SS2_ERRORCHECK,
114         M_SS2_NORMAL,
115         M_SS2_RECURSIVE
116 } mutex_kind_t;
117
118
119 /*------------------------------------------------------------
120  * Constants
121  *----------------------------------------------------------*/
122
123 const char *protocol_strs[] = {
124         "PTHREAD_PRIO_NONE",
125         "PTHREAD_PRIO_INHERIT",
126         "PTHREAD_PRIO_PROTECT"
127 };
128
129 const int protocols[] = {
130         PTHREAD_PRIO_NONE,
131         PTHREAD_PRIO_INHERIT,
132         PTHREAD_PRIO_PROTECT
133 };
134
135 const char *mutextype_strs[] = {
136         "POSIX (type not specified)",
137         "SS2 PTHREAD_MUTEX_DEFAULT",
138         "SS2 PTHREAD_MUTEX_ERRORCHECK",
139         "SS2 PTHREAD_MUTEX_NORMAL",
140         "SS2 PTHREAD_MUTEX_RECURSIVE"
141 };
142
143 const int mutex_types[] = {
144         0,                              /* M_POSIX              */
145         PTHREAD_MUTEX_DEFAULT,          /* M_SS2_DEFAULT        */
146         PTHREAD_MUTEX_ERRORCHECK,       /* M_SS2_ERRORCHECK     */
147         PTHREAD_MUTEX_NORMAL,           /* M_SS2_NORMAL         */
148         PTHREAD_MUTEX_RECURSIVE         /* M_SS2_RECURSIVE      */
149 };
150
151
152 /*------------------------------------------------------------
153  * Objects
154  *----------------------------------------------------------*/
155
156 static int              done = 0;
157 static int              trace_enabled = 0;
158 static int              use_global_condvar = 0;
159 static thread_state_t   states[NUM_THREADS];
160 static int              pipefd[2];
161
162 static pthread_mutex_t  waiter_mutex;
163 static pthread_mutex_t  cond_mutex;
164 static pthread_cond_t   cond_var;
165
166 static FILE *logfile;
167 static int error_count = 0, pass_count = 0, total = 0;
168
169
170 /*------------------------------------------------------------
171  * Prototypes
172  *----------------------------------------------------------*/
173 extern char *strtok_r(char *str, const char *sep, char **last);
174
175
176 /*------------------------------------------------------------
177  * Functions
178  *----------------------------------------------------------*/
179
180 #ifdef DEBUG
181 static void
182 kern_switch (pthread_t pthread_out, pthread_t pthread_in)
183 {
184         if (pthread_out != NULL)
185                 printf ("Swapping out thread 0x%x, ", (int) pthread_out);
186         else
187                 printf ("Swapping out kernel thread, ");
188
189         if (pthread_in != NULL)
190                 printf ("swapping in thread 0x%x\n", (int) pthread_in);
191         else
192                 printf ("swapping in kernel thread.\n");
193 }
194 #endif
195
196
197 static void
198 log_error (const char *fmt, ...)
199 {
200         va_list ap;
201
202         va_start (ap, fmt);
203         fprintf (logfile, "FAIL: ");
204         vfprintf (logfile, fmt, ap);
205         error_count = error_count + 1;
206         total = total + 1;
207 }
208
209
210 static void
211 log_pass (void)
212 {
213         fprintf (logfile, "PASS\n");
214         pass_count = pass_count + 1;
215         total = total + 1;
216 }
217
218
219 static void
220 log_trace (const char *fmt, ...)
221 {
222         va_list ap;
223
224         if (trace_enabled) {
225                 va_start (ap, fmt);
226                 vfprintf (logfile, fmt, ap);
227         }
228 }
229
230
231 static void
232 log_info (const char *fmt, ...)
233 {
234         va_list ap;
235
236         va_start (ap, fmt);
237         vfprintf (logfile, fmt, ap);
238 }
239
240
241 static void
242 check_result (int expected, int actual)
243 {
244         if (expected != actual)
245                 log_error ("expected %d, returned %d\n", expected, actual);
246         else
247                 log_pass ();
248 }
249
250
251 /*
252  * Check to see that the threads ran in the specified order.
253  */
254 static void
255 check_run_order (char *order)
256 {
257         const char *sep = ":,";
258         char *tok, *last, *idstr, *endptr;
259         int expected_id, bytes, count = 0, errors = 0;
260         u_int8_t id;
261
262         assert ((tok = (char *) malloc (strlen(order) + 1)) != NULL);
263         strcpy (tok, order);    /* tok has to be larger than order */
264         assert (ioctl (pipefd[0], FIONREAD, &bytes) == 0);
265         log_trace ("%d bytes read from FIFO.\n", bytes);
266
267         for (idstr = strtok_r (tok, sep, &last);
268              (idstr != NULL) && (count < bytes);
269              idstr = strtok_r (NULL, sep, &last)) {
270
271                 /* Get the expected id: */
272                 expected_id = (int) strtol (idstr, &endptr, 10);
273                 assert ((endptr != NULL) && (*endptr == '\0'));
274
275                 /* Read the actual id from the pipe: */
276                 assert (read (pipefd[0], &id, sizeof (id)) == sizeof (id));
277                 count = count + sizeof (id);
278
279                 if (id != expected_id) {
280                         log_trace ("Thread %d ran out of order.\n", id);
281                         errors = errors + 1;
282                 }
283                 else {
284                         log_trace ("Thread %d at priority %d reporting.\n",
285                             (int) id, states[id].priority);
286                 }
287         }
288
289         if (count < bytes) {
290                 /* Clear the pipe: */
291                 while (count < bytes) {
292                         read (pipefd[0], &id, sizeof (id));
293                         count = count + 1;
294                         errors = errors + 1;
295                 }
296         }
297         else if (bytes < count)
298                 errors = errors + count - bytes;
299
300         if (errors == 0)
301                 log_pass ();
302         else
303                 log_error ("%d threads ran out of order\n", errors);
304 }
305
306
307 static void *
308 waiter (void *arg)
309 {
310         thread_state_t  *statep = (thread_state_t *) arg;
311         pthread_mutex_t *held_mutex[MAX_THREAD_CMDS];
312         int             held_mutex_owned[MAX_THREAD_CMDS];
313         sigset_t        mask;
314         struct timeval  tv1, tv2;
315         thread_cmd_t    cmd;
316         int             i, mutex_count = 0;
317
318         statep->status = STAT_INITIAL;
319
320         /* Block all signals except for interrupt.*/
321         sigfillset (&mask);
322         sigdelset (&mask, SIGINT);
323         sigprocmask (SIG_BLOCK, &mask, NULL);
324
325         while (done == 0) {
326                 /* Wait for signal from the main thread to continue. */
327                 statep->status = STAT_WAITMUTEX;
328                 log_trace ("Thread %d: locking cond_mutex.\n",
329                     (int) statep->id);
330                 pthread_mutex_lock (&cond_mutex);
331
332                 /* Do we report our status. */
333                 if (statep->flags & FLAGS_REPORT_WAITCONDMUTEX)
334                         write (pipefd[1], &statep->id, sizeof (statep->id));
335                 log_trace ("Thread %d: waiting for cond_var.\n",
336                     (int) statep->id);
337
338                 /* Wait for a command. */
339                 statep->status = STAT_WAITCONDVAR;
340
341                 /*
342                  * The threads are allowed commanded to wait either on
343                  * their own unique condition variable (so they may be
344                  * separately signaled) or on one global condition variable
345                  * (so they may be signaled together).
346                  */
347                 if (use_global_condvar != 0)
348                         pthread_cond_wait (&cond_var, &cond_mutex);
349                 else
350                         pthread_cond_wait (&statep->cond_var, &cond_mutex);
351
352                 /* Do we report our status? */
353                 if (statep->flags & FLAGS_REPORT_WAITCONDVAR) {
354                         write (pipefd[1], &statep->id, sizeof (statep->id));
355                         log_trace ("Thread %d: wrote to pipe.\n",
356                             (int) statep->id);
357                 }
358                 log_trace ("Thread %d: received cond_var signal.\n",
359                     (int) statep->id);
360
361                 /* Get a copy of the command before releasing the mutex. */
362                 cmd = statep->cmd;
363
364                 /* Clear the command after copying it. */
365                 statep->cmd.cmd_id = CMD_NONE;
366
367                 /* Unlock the condition variable mutex. */
368                 assert (pthread_mutex_unlock (&cond_mutex) == 0);
369
370                 /* Peform the command.*/
371                 switch (cmd.cmd_id) {
372                 case CMD_TAKE_MUTEX:
373                         statep->ret = pthread_mutex_lock (cmd.mutex);
374                         if (statep->ret == 0) {
375                                 assert (mutex_count < sizeof (held_mutex));
376                                 held_mutex[mutex_count] = cmd.mutex;
377                                 held_mutex_owned[mutex_count] = 1;
378                                 mutex_count++;
379                         }
380                         else {
381                                 held_mutex_owned[mutex_count] = 0;
382                                 log_trace ("Thread id %d unable to lock mutex, "
383                                     "error = %d\n", (int) statep->id,
384                                     statep->ret);
385                         }
386                         break;
387
388                 case CMD_RELEASE_MUTEX:
389                         assert ((mutex_count <= sizeof (held_mutex)) &&
390                             (mutex_count > 0));
391                         mutex_count--;
392                         if (held_mutex_owned[mutex_count] != 0)
393                                 assert (pthread_mutex_unlock
394                                     (held_mutex[mutex_count]) == 0);
395                         break;
396
397                 case CMD_WAIT_FOR_SIGNAL:
398                         assert (pthread_mutex_lock (cmd.mutex) == 0);
399                         assert (pthread_cond_wait (cmd.cond, cmd.mutex) == 0);
400                         assert (pthread_mutex_unlock (cmd.mutex) == 0);
401                         break;
402
403                 case CMD_BUSY_LOOP:
404                         log_trace ("Thread %d: Entering busy loop.\n",
405                             (int) statep->id);
406                         /* Spin for 15 seconds. */
407                         assert (gettimeofday (&tv2, NULL) == 0);
408                         tv1.tv_sec = tv2.tv_sec + 5;
409                         tv1.tv_usec = tv2.tv_usec;
410                         statep->flags |= FLAGS_IS_BUSY;
411                         while (timercmp (&tv2, &tv1,<)) {
412                                 assert (gettimeofday (&tv2, NULL) == 0);
413                         }
414                         statep->flags &= ~FLAGS_IS_BUSY;
415                         statep->flags |= FLAGS_WAS_BUSY;
416
417                         /* Do we report our status? */
418                         if (statep->flags & FLAGS_REPORT_BUSY_LOOP)
419                                 write (pipefd[1], &statep->id,
420                                     sizeof (statep->id));
421
422                         log_trace ("Thread %d: Leaving busy loop.\n",
423                             (int) statep->id);
424                         break;
425
426                 case CMD_PROTECTED_OP:
427                         assert (pthread_mutex_lock (cmd.mutex) == 0);
428                         statep->flags |= FLAGS_WAS_BUSY;
429                         /* Do we report our status? */
430                         if (statep->flags & FLAGS_REPORT_BUSY_LOOP)
431                                 write (pipefd[1], &statep->id,
432                                     sizeof (statep->id));
433
434                         assert (pthread_mutex_unlock (cmd.mutex) == 0);
435                         break;
436
437                 case CMD_RELEASE_ALL:
438                         assert ((mutex_count <= sizeof (held_mutex)) &&
439                             (mutex_count > 0));
440                         for (i = mutex_count - 1; i >= 0; i--) {
441                                 if (held_mutex_owned[i] != 0)
442                                         assert (pthread_mutex_unlock
443                                             (held_mutex[i]) == 0);
444                         }
445                         mutex_count = 0;
446                         break;
447
448                 case CMD_NONE:
449                 default:
450                         break;
451                 }
452
453                 /* Wait for the big giant waiter lock. */
454                 statep->status = STAT_WAITMUTEX;
455                 log_trace ("Thread %d: waiting for big giant lock.\n",
456                     (int) statep->id);
457                 pthread_mutex_lock (&waiter_mutex);
458                 if (statep->flags & FLAGS_REPORT_WAITMUTEX)
459                         write (pipefd[1], &statep->id, sizeof (statep->id));
460                 log_trace ("Thread %d: got big giant lock.\n",
461                     (int) statep->id);
462                 statep->status = STAT_INITIAL;
463                 pthread_mutex_unlock (&waiter_mutex);
464         }
465
466         log_trace ("Thread %d: Exiting thread 0x%p\n", (int) statep->id,
467             pthread_self());
468         pthread_exit (arg);
469         return (NULL);
470 }
471
472
473 static void *
474 lock_twice (void *arg)
475 {
476         thread_state_t  *statep = (thread_state_t *) arg;
477         sigset_t        mask;
478
479         statep->status = STAT_INITIAL;
480
481         /* Block all signals except for interrupt.*/
482         sigfillset (&mask);
483         sigdelset (&mask, SIGINT);
484         sigprocmask (SIG_BLOCK, &mask, NULL);
485
486         /* Wait for a signal to continue. */
487         log_trace ("Thread %d: locking cond_mutex.\n", (int) statep->id);
488         pthread_mutex_lock (&cond_mutex);
489
490         log_trace ("Thread %d: waiting for cond_var.\n", (int) statep->id);
491         statep->status = STAT_WAITCONDVAR;
492         pthread_cond_wait (&cond_var, &cond_mutex);
493
494         log_trace ("Thread %d: received cond_var signal.\n", (int) statep->id);
495
496         /* Unlock the condition variable mutex. */
497         assert (pthread_mutex_unlock (&cond_mutex) == 0);
498
499         statep->status = STAT_WAITMUTEX;
500         /* Lock the mutex once. */
501         assert (pthread_mutex_lock (statep->cmd.mutex) == 0);
502
503         /* Lock it again and capture the error. */
504         statep->ret = pthread_mutex_lock (statep->cmd.mutex);
505         statep->status = 0;
506
507         assert (pthread_mutex_unlock (statep->cmd.mutex) == 0);
508
509         /* Unlock it again if it is locked recursively. */
510         if (statep->ret == 0)
511                 pthread_mutex_unlock (statep->cmd.mutex);
512
513         log_trace ("Thread %d: Exiting thread 0x%p\n", (int) statep->id,
514             pthread_self());
515         pthread_exit (arg);
516         return (NULL);
517 }
518
519
520 static void
521 sighandler (int signo)
522 {
523         log_info ("Signal handler caught signal %d, thread id 0x%p\n",
524             signo, pthread_self());
525
526         if (signo == SIGINT)
527                 done = 1;
528 }
529
530
531 static void
532 send_cmd (int id, thread_cmd_id_t cmd)
533 {
534         assert (pthread_mutex_lock (&cond_mutex) == 0);
535         assert (states[id].status == STAT_WAITCONDVAR);
536         states[id].cmd.cmd_id = cmd;
537         states[id].cmd.mutex = NULL;
538         states[id].cmd.cond = NULL;
539         /* Clear the busy flags. */
540         states[id].flags &= ~(FLAGS_WAS_BUSY | FLAGS_IS_BUSY);
541         assert (pthread_cond_signal (&states[id].cond_var) == 0);
542         assert (pthread_mutex_unlock (&cond_mutex) == 0);
543 }
544
545
546 static void
547 send_mutex_cmd (int id, thread_cmd_id_t cmd, pthread_mutex_t *m)
548 {
549         assert (pthread_mutex_lock (&cond_mutex) == 0);
550         assert (states[id].status == STAT_WAITCONDVAR);
551         states[id].cmd.cmd_id = cmd;
552         states[id].cmd.mutex = m;
553         states[id].cmd.cond = NULL;
554         /* Clear the busy flags. */
555         states[id].flags &= ~(FLAGS_WAS_BUSY | FLAGS_IS_BUSY);
556         assert (pthread_cond_signal (&states[id].cond_var) == 0);
557         assert (pthread_mutex_unlock (&cond_mutex) == 0);
558 }
559
560
561 static void
562 send_mutex_cv_cmd (int id, thread_cmd_id_t cmd, pthread_mutex_t *m,
563     pthread_cond_t *cv)
564 {
565         assert (pthread_mutex_lock (&cond_mutex) == 0);
566         assert (states[id].status == STAT_WAITCONDVAR);
567         states[id].cmd.cmd_id = cmd;
568         states[id].cmd.mutex = m;
569         states[id].cmd.cond = cv;
570         /* Clear the busy flags. */
571         states[id].flags &= ~(FLAGS_WAS_BUSY | FLAGS_IS_BUSY);
572         assert (pthread_cond_signal (&states[id].cond_var) == 0);
573         assert (pthread_mutex_unlock (&cond_mutex) == 0);
574 }
575
576
577 static void
578 mutex_init_test (void)
579 {
580         pthread_mutexattr_t mattr;
581         pthread_mutex_t mutex;
582         mutex_kind_t mkind;
583         int mproto, ret;
584
585         /*
586          * Initialize a mutex attribute.
587          *
588          * pthread_mutexattr_init not tested for: ENOMEM
589          */
590         assert (pthread_mutexattr_init (&mattr) == 0);
591
592         /*
593          * Initialize a mutex.
594          *
595          * pthread_mutex_init not tested for: EAGAIN ENOMEM EPERM EBUSY
596          */
597         log_info ("Testing pthread_mutex_init\n");
598         log_info ("--------------------------\n");
599
600         for (mproto = 0; mproto < NELEMENTS(protocols); mproto++) {
601                 for (mkind = M_POSIX; mkind <= M_SS2_RECURSIVE; mkind++) {
602                         /* Initialize the mutex attribute. */
603                         assert (pthread_mutexattr_init (&mattr) == 0);
604                         assert (pthread_mutexattr_setprotocol (&mattr,
605                             protocols[mproto]) == 0);
606
607                         /*
608                          * Ensure that the first mutex type is a POSIX
609                          * compliant mutex.
610                          */
611                         if (mkind != M_POSIX) {
612                                 assert (pthread_mutexattr_settype (&mattr,
613                                     mutex_types[mkind]) == 0);
614                         }
615
616                         log_info ("  Protocol %s, Type %s - ",
617                             protocol_strs[mproto], mutextype_strs[mkind]);
618                         ret = pthread_mutex_init (&mutex, &mattr);
619                         check_result (/* expected */ 0, ret);
620                         assert (pthread_mutex_destroy (&mutex) == 0);
621
622                         /*
623                          * Destroy a mutex attribute.
624                          *
625                          * XXX - There should probably be a magic number
626                          *       associated with a mutex attribute so that
627                          *       destroy can be reasonably sure the attribute
628                          *       is valid.
629                          *
630                          * pthread_mutexattr_destroy not tested for: EINVAL
631                          */
632                         assert (pthread_mutexattr_destroy (&mattr) == 0);
633                 }
634         }
635 }
636
637
638 static void
639 mutex_destroy_test (void)
640 {
641         pthread_mutexattr_t mattr;
642         pthread_mutex_t mutex;
643         pthread_condattr_t cattr;
644         pthread_cond_t  cv;
645         pthread_attr_t pattr;
646         int mproto, ret;
647         mutex_kind_t mkind;
648 #if 0
649         thread_state_t state;
650 #endif
651
652         /*
653          * Destroy a mutex.
654          *
655          * XXX - There should probably be a magic number associated
656          *       with a mutex so that destroy can be reasonably sure
657          *       the mutex is valid.
658          *
659          * pthread_mutex_destroy not tested for: 
660          */
661         log_info ("Testing pthread_mutex_destroy\n");
662         log_info ("-----------------------------\n");
663
664         assert (pthread_attr_init (&pattr) == 0);
665         assert (pthread_attr_setdetachstate (&pattr,
666             PTHREAD_CREATE_DETACHED) == 0);
667 #if 0
668         state.flags = 0;        /* No flags yet. */
669 #endif
670
671         for (mproto = 0; mproto < NELEMENTS(protocols); mproto++) {
672                 for (mkind = M_POSIX; mkind <= M_SS2_RECURSIVE; mkind++) {
673                         /* Initialize the mutex attribute. */
674                         assert (pthread_mutexattr_init (&mattr) == 0);
675                         assert (pthread_mutexattr_setprotocol (&mattr,
676                             protocols[mproto]) == 0);
677
678                         /*
679                          * Ensure that the first mutex type is a POSIX
680                          * compliant mutex.
681                          */
682                         if (mkind != M_POSIX) {
683                                 assert (pthread_mutexattr_settype (&mattr,
684                                     mutex_types[mkind]) == 0);
685                         }
686
687                         /* Create the mutex. */
688                         assert (pthread_mutex_init (&mutex, &mattr) == 0);
689
690                         log_info ("  Protocol %s, Type %s\n",
691                             protocol_strs[mproto], mutextype_strs[mkind]);
692
693                         log_info ("    Destruction of unused mutex - ");
694                         assert (pthread_mutex_init (&mutex, &mattr) == 0);
695                         ret = pthread_mutex_destroy (&mutex);
696                         check_result (/* expected */ 0, ret);
697
698                         log_info ("    Destruction of mutex locked by self - ");
699                         assert (pthread_mutex_init (&mutex, &mattr) == 0);
700                         assert (pthread_mutex_lock (&mutex) == 0);
701                         ret = pthread_mutex_destroy (&mutex);
702                         check_result (/* expected */ EBUSY, ret);
703                         assert (pthread_mutex_unlock (&mutex) == 0);
704                         assert (pthread_mutex_destroy (&mutex) == 0);
705
706                         log_info ("    Destruction of mutex locked by another "
707                             "thread - ");
708                         assert (pthread_mutex_init (&mutex, &mattr) == 0);
709                         send_mutex_cmd (0, CMD_TAKE_MUTEX, &mutex);
710                         sleep (1);
711                         ret = pthread_mutex_destroy (&mutex);
712                         check_result (/* expected */ EBUSY, ret);
713                         send_cmd (0, CMD_RELEASE_ALL);
714                         sleep (1);
715                         assert (pthread_mutex_destroy (&mutex) == 0);
716
717                         log_info ("    Destruction of mutex while being used in "
718                             "cond_wait - ");
719                         assert (pthread_mutex_init (&mutex, &mattr) == 0);
720                         assert (pthread_condattr_init (&cattr) == 0);
721                         assert (pthread_cond_init (&cv, &cattr) == 0);
722                         send_mutex_cv_cmd (0, CMD_WAIT_FOR_SIGNAL, &mutex, &cv);
723                         sleep (1);
724                         ret = pthread_mutex_destroy (&mutex);
725                         check_result (/* expected */ EBUSY, ret);
726                         pthread_cond_signal (&cv);
727                         sleep (1);
728                         assert (pthread_mutex_destroy (&mutex) == 0);
729                 }
730         }
731 }
732
733
734 static void
735 mutex_lock_test (void)
736 {
737         pthread_mutexattr_t mattr;
738         pthread_mutex_t mutex;
739         pthread_attr_t pattr;
740         int mproto, ret;
741         mutex_kind_t mkind;
742         thread_state_t state;
743
744         /*
745          * Lock a mutex.
746          *
747          * pthread_lock not tested for: 
748          */
749         log_info ("Testing pthread_mutex_lock\n");
750         log_info ("--------------------------\n");
751
752         assert (pthread_attr_init (&pattr) == 0);
753         assert (pthread_attr_setdetachstate (&pattr,
754             PTHREAD_CREATE_DETACHED) == 0);
755         state.flags = 0;        /* No flags yet. */
756
757         for (mproto = 0; mproto < NELEMENTS(protocols); mproto++) {
758                 for (mkind = M_POSIX; mkind <= M_SS2_RECURSIVE; mkind++) {
759                         /* Initialize the mutex attribute. */
760                         assert (pthread_mutexattr_init (&mattr) == 0);
761                         assert (pthread_mutexattr_setprotocol (&mattr,
762                             protocols[mproto]) == 0);
763
764                         /*
765                          * Ensure that the first mutex type is a POSIX
766                          * compliant mutex.
767                          */
768                         if (mkind != M_POSIX) {
769                                 assert (pthread_mutexattr_settype (&mattr,
770                                     mutex_types[mkind]) == 0);
771                         }
772
773                         /* Create the mutex. */
774                         assert (pthread_mutex_init (&mutex, &mattr) == 0);
775
776                         log_info ("  Protocol %s, Type %s\n",
777                             protocol_strs[mproto], mutextype_strs[mkind]);
778
779                         log_info ("    Lock on unlocked mutex - ");
780                         ret = pthread_mutex_lock (&mutex);
781                         check_result (/* expected */ 0, ret);
782                         pthread_mutex_unlock (&mutex);
783
784                         log_info ("    Lock on invalid mutex - ");
785                         ret = pthread_mutex_lock (NULL);
786                         check_result (/* expected */ EINVAL, ret);
787
788                         log_info ("    Lock on mutex held by self - ");
789                         assert (pthread_create (&state.tid, &pattr, lock_twice,
790                             (void *) &state) == 0);
791                         /* Let the thread start. */
792                         sleep (1);
793                         state.cmd.mutex = &mutex;
794                         state.ret = 0xdeadbeef;
795                         assert (pthread_mutex_lock (&cond_mutex) == 0);
796                         assert (pthread_cond_signal (&cond_var) == 0);
797                         assert (pthread_mutex_unlock (&cond_mutex) == 0);
798                         /* Let the thread receive and process the command. */
799                         sleep (1);
800
801                         switch (mkind) {
802                         case M_POSIX:
803                                 check_result (/* expected */ EDEADLK,
804                                     state.ret);
805                                 break;
806                         case M_SS2_DEFAULT:
807                                 check_result (/* expected */ EDEADLK,
808                                     state.ret);
809                                 break;
810                         case M_SS2_ERRORCHECK:
811                                 check_result (/* expected */ EDEADLK,
812                                     state.ret);
813                                 break;
814                         case M_SS2_NORMAL:
815                                 check_result (/* expected */ 0xdeadbeef,
816                                     state.ret);
817                                 break;
818                         case M_SS2_RECURSIVE:
819                                 check_result (/* expected */ 0, state.ret);
820                                 break;
821                         }
822                         pthread_mutex_destroy (&mutex);
823                         pthread_mutexattr_destroy (&mattr);
824                 }
825         }
826 }
827
828
829 static void
830 mutex_unlock_test (void)
831 {
832         const int test_thread_id = 0;   /* ID of test thread */
833         pthread_mutexattr_t mattr;
834         pthread_mutex_t mutex;
835         int mproto, ret;
836         mutex_kind_t mkind;
837
838         /*
839          * Unlock a mutex.
840          *
841          * pthread_unlock not tested for: 
842          */
843         log_info ("Testing pthread_mutex_unlock\n");
844         log_info ("----------------------------\n");
845
846         for (mproto = 0; mproto < NELEMENTS(protocols); mproto++) {
847                 for (mkind = M_POSIX; mkind <= M_SS2_RECURSIVE; mkind++) {
848                         /* Initialize the mutex attribute. */
849                         assert (pthread_mutexattr_init (&mattr) == 0);
850                         assert (pthread_mutexattr_setprotocol (&mattr,
851                             protocols[mproto]) == 0);
852
853                         /*
854                          * Ensure that the first mutex type is a POSIX
855                          * compliant mutex.
856                          */
857                         if (mkind != M_POSIX) {
858                                 assert (pthread_mutexattr_settype (&mattr,
859                                     mutex_types[mkind]) == 0);
860                         }
861
862                         /* Create the mutex. */
863                         assert (pthread_mutex_init (&mutex, &mattr) == 0);
864
865                         log_info ("  Protocol %s, Type %s\n",
866                             protocol_strs[mproto], mutextype_strs[mkind]);
867
868                         log_info ("    Unlock on mutex held by self - ");
869                         assert (pthread_mutex_lock (&mutex) == 0);
870                         ret = pthread_mutex_unlock (&mutex);
871                         check_result (/* expected */ 0, ret);
872
873                         log_info ("    Unlock on invalid mutex - ");
874                         ret = pthread_mutex_unlock (NULL);
875                         check_result (/* expected */ EINVAL, ret);
876
877                         log_info ("    Unlock on mutex locked by another thread - ");
878                         send_mutex_cmd (test_thread_id, CMD_TAKE_MUTEX, &mutex);
879                         sleep (1);
880                         ret = pthread_mutex_unlock (&mutex);
881                         switch (mkind) {
882                         case M_POSIX:
883                                 check_result (/* expected */ EPERM, ret);
884                                 break;
885                         case M_SS2_DEFAULT:
886                                 check_result (/* expected */ EPERM, ret);
887                                 break;
888                         case M_SS2_ERRORCHECK:
889                                 check_result (/* expected */ EPERM, ret);
890                                 break;
891                         case M_SS2_NORMAL:
892                                 check_result (/* expected */ EPERM, ret);
893                                 break;
894                         case M_SS2_RECURSIVE:
895                                 check_result (/* expected */ EPERM, ret);
896                                 break;
897                         }
898                         if (ret == 0) {
899                                 /*
900                                  * If for some reason we were able to unlock
901                                  * the mutex, relock it so that the test
902                                  * thread has no problems releasing the mutex.
903                                  */
904                                 pthread_mutex_lock (&mutex);
905                         }
906                         send_cmd (test_thread_id, CMD_RELEASE_ALL);
907                         sleep (1);
908
909                         pthread_mutex_destroy (&mutex);
910                         pthread_mutexattr_destroy (&mattr);
911                 }
912         }
913 }
914
915
916 static void
917 queueing_order_test (void)
918 {
919         int i;
920
921         log_info ("Testing queueing order\n");
922         log_info ("----------------------\n");
923         assert (pthread_mutex_lock (&waiter_mutex) == 0);
924         /*
925          * Tell the threads to report when they take the waiters mutex.
926          */
927         assert (pthread_mutex_lock (&cond_mutex) == 0);
928         for (i = 0; i < NUM_THREADS; i++) {
929                 states[i].flags = FLAGS_REPORT_WAITMUTEX;
930                 assert (pthread_cond_signal (&states[i].cond_var) == 0);
931         }
932         assert (pthread_mutex_unlock (&cond_mutex) == 0);
933
934         /* Signal the threads to continue. */
935         sleep (1);
936
937         /* Use the global condition variable next time. */
938         use_global_condvar = 1;
939
940         /* Release the waiting threads and allow them to run again. */
941         assert (pthread_mutex_unlock (&waiter_mutex) == 0);
942         sleep (1);
943
944         log_info ("  Queueing order on a mutex - ");
945         check_run_order ("9,8,7,6,5,4,3,2,1,0");
946         for (i = 0; i < NUM_THREADS; i = i + 1) {
947                 /* Tell the threads to report when they've been signaled. */
948                 states[i].flags = FLAGS_REPORT_WAITCONDVAR;
949         }
950
951         /*
952          * Prevent the threads from continuing their loop after we
953          * signal them.
954          */
955         assert (pthread_mutex_lock (&waiter_mutex) == 0);
956
957
958         log_info ("  Queueing order on a condition variable - ");
959         /*
960          * Signal one thread to run and see that the highest priority
961          * thread executes.
962          */
963         assert (pthread_mutex_lock (&cond_mutex) == 0);
964         assert (pthread_cond_signal (&cond_var) == 0);
965         assert (pthread_mutex_unlock (&cond_mutex) == 0);
966         sleep (1);
967         if (states[NUM_THREADS - 1].status != STAT_WAITMUTEX)
968                 log_error ("highest priority thread does not run.\n");
969
970         /* Signal the remaining threads. */
971         assert (pthread_mutex_lock (&cond_mutex) == 0);
972         assert (pthread_cond_broadcast (&cond_var) == 0);
973         assert (pthread_mutex_unlock (&cond_mutex) == 0);
974         sleep (1);
975
976         check_run_order ("9,8,7,6,5,4,3,2,1,0");
977         for (i = 0; i < NUM_THREADS; i = i + 1) {
978                 /* Tell the threads not to report anything. */
979                 states[i].flags = 0;
980         }
981
982         /* Use the thread unique condition variable next time. */
983         use_global_condvar = 0;
984
985         /* Allow the threads to continue their loop. */
986         assert (pthread_mutex_unlock (&waiter_mutex) == 0);
987         sleep (1);
988 }
989
990
991 static void
992 mutex_prioceiling_test (void)
993 {
994         const int test_thread_id = 0;   /* ID of test thread */
995         pthread_mutexattr_t mattr;
996         struct sched_param param;
997         pthread_mutex_t m[3];
998         mutex_kind_t    mkind;
999         int             i, ret, policy, my_prio, old_ceiling;
1000
1001         log_info ("Testing priority ceilings\n");
1002         log_info ("-------------------------\n");
1003         for (mkind = M_POSIX; mkind <= M_SS2_RECURSIVE; mkind++) {
1004
1005                 log_info ("  Protype PTHREAD_PRIO_PROTECT, Type %s\n",
1006                     mutextype_strs[mkind]);
1007
1008                 /*
1009                  * Initialize and create a mutex.
1010                  */
1011                 assert (pthread_mutexattr_init (&mattr) == 0);
1012
1013                 /* Get this threads current priority. */
1014                 assert (pthread_getschedparam (pthread_self(), &policy,
1015                     &param) == 0);
1016                 my_prio = param.sched_priority; /* save for later use */
1017                 log_trace ("Current scheduling policy %d, priority %d\n",
1018                     policy, my_prio);
1019
1020                 /*
1021                  * Initialize and create 3 priority protection mutexes with
1022                  * default (max priority) ceilings.
1023                  */
1024                 assert (pthread_mutexattr_setprotocol(&mattr,
1025                     PTHREAD_PRIO_PROTECT) == 0);
1026
1027                 /*
1028                  * Ensure that the first mutex type is a POSIX
1029                  * compliant mutex.
1030                  */
1031                 if (mkind != M_POSIX) {
1032                         assert (pthread_mutexattr_settype (&mattr,
1033                             mutex_types[mkind]) == 0);
1034                 }
1035
1036                 for (i = 0; i < 3; i++)
1037                         assert (pthread_mutex_init (&m[i], &mattr) == 0);
1038
1039                 /*
1040                  * Set the ceiling priorities for the 3 priority protection
1041                  * mutexes to, 5 less than, equal to, and 5 greater than,
1042                  * this threads current priority.
1043                  */
1044                 for (i = 0; i < 3; i++)
1045                         assert (pthread_mutex_setprioceiling (&m[i],
1046                             my_prio - 5 + 5*i, &old_ceiling) == 0);
1047
1048                 /*
1049                  * Check that if we attempt to take a mutex whose priority
1050                  * ceiling is lower than our priority, we get an error.
1051                  */
1052                 log_info ("    Lock with ceiling priority < thread priority - ");
1053                 ret = pthread_mutex_lock (&m[0]);
1054                 check_result (/* expected */ EINVAL, ret);
1055                 if (ret == 0)
1056                         pthread_mutex_unlock (&m[0]);
1057
1058                 /*
1059                  * Check that we can take a mutex whose priority ceiling
1060                  * is equal to our priority.
1061                  */
1062                 log_info ("    Lock with ceiling priority = thread priority - ");
1063                 ret = pthread_mutex_lock (&m[1]);
1064                 check_result (/* expected */ 0, ret);
1065                 if (ret == 0)
1066                         pthread_mutex_unlock (&m[1]);
1067
1068                 /*
1069                  * Check that we can take a mutex whose priority ceiling
1070                  * is higher than our priority.
1071                  */
1072                 log_info ("    Lock with ceiling priority > thread priority - ");
1073                 ret = pthread_mutex_lock (&m[2]);
1074                 check_result (/* expected */ 0, ret);
1075                 if (ret == 0)
1076                         pthread_mutex_unlock (&m[2]);
1077
1078                 /*
1079                  * Have the test thread go into a busy loop for 5 seconds
1080                  * and see that it doesn't block this thread (since the
1081                  * priority ceiling of mutex 0 and the priority of the test
1082                  * thread are both less than the priority of this thread).
1083                  */
1084                 log_info ("    Preemption with ceiling priority < thread "
1085                     "priority - ");
1086                 /* Have the test thread take mutex 0. */
1087                 send_mutex_cmd (test_thread_id, CMD_TAKE_MUTEX, &m[0]);
1088                 sleep (1);
1089
1090                 log_trace ("Sending busy command.\n");
1091                 send_cmd (test_thread_id, CMD_BUSY_LOOP);
1092                 log_trace ("Busy sent, yielding\n");
1093                 pthread_yield ();
1094                 log_trace ("Returned from yield.\n");
1095                 if (states[test_thread_id].flags &
1096                     (FLAGS_IS_BUSY | FLAGS_WAS_BUSY))
1097                         log_error ("test thread inproperly preempted us.\n");
1098                 else {
1099                         /* Let the thread finish its busy loop. */
1100                         sleep (6);
1101                         if ((states[test_thread_id].flags & FLAGS_WAS_BUSY) == 0)
1102                                 log_error ("test thread never finished.\n");
1103                         else
1104                                 log_pass ();
1105                 }
1106                 states[test_thread_id].flags &= ~FLAGS_WAS_BUSY;
1107
1108                 /* Have the test thread release mutex 0. */
1109                 send_cmd (test_thread_id, CMD_RELEASE_ALL);
1110                 sleep (1);
1111
1112                 /*
1113                  * Have the test thread go into a busy loop for 5 seconds
1114                  * and see that it preempts this thread (since the priority
1115                  * ceiling of mutex 1 is the same as the priority of this
1116                  * thread).  The test thread should not run to completion
1117                  * as its time quantum should expire before the 5 seconds
1118                  * are up.
1119                  */
1120                 log_info ("    Preemption with ceiling priority = thread "
1121                     "priority - ");
1122
1123                 /* Have the test thread take mutex 1. */
1124                 send_mutex_cmd (test_thread_id, CMD_TAKE_MUTEX, &m[1]);
1125                 sleep (1);
1126
1127                 log_trace ("Sending busy\n");
1128                 send_cmd (test_thread_id, CMD_BUSY_LOOP);
1129                 log_trace ("Busy sent, yielding\n");
1130                 pthread_yield ();
1131                 log_trace ("Returned from yield.\n");
1132                 if ((states[test_thread_id].flags & FLAGS_IS_BUSY) == 0)
1133                         log_error ("test thread did not switch in on yield.\n");
1134                 else if (states[test_thread_id].flags & FLAGS_WAS_BUSY)
1135                         log_error ("test thread ran to completion.\n");
1136                 else {
1137                         /* Let the thread finish its busy loop. */
1138                         sleep (6);
1139                         if ((states[test_thread_id].flags & FLAGS_WAS_BUSY) == 0)
1140                                 log_error ("test thread never finished.\n");
1141                         else
1142                                 log_pass ();
1143                 }
1144                 states[test_thread_id].flags &= ~FLAGS_WAS_BUSY;
1145
1146                 /* Have the test thread release mutex 1. */
1147                 send_cmd (test_thread_id, CMD_RELEASE_ALL);
1148                 sleep (1);
1149
1150                 /*
1151                  * Set the scheduling policy of the test thread to SCHED_FIFO
1152                  * and have it go into a busy loop for 5 seconds.  This
1153                  * thread is SCHED_RR, and since the priority ceiling of
1154                  * mutex 1 is the same as the priority of this thread, the
1155                  * test thread should run to completion once it is switched
1156                  * in.
1157                  */
1158                 log_info ("    SCHED_FIFO scheduling and ceiling priority = "
1159                     "thread priority - ");
1160                 param.sched_priority = states[test_thread_id].priority;
1161                 assert (pthread_setschedparam (states[test_thread_id].tid,
1162                     SCHED_FIFO, &param) == 0);
1163
1164                 /* Have the test thread take mutex 1. */
1165                 send_mutex_cmd (test_thread_id, CMD_TAKE_MUTEX, &m[1]);
1166                 sleep (1);
1167
1168                 log_trace ("Sending busy\n");
1169                 send_cmd (test_thread_id, CMD_BUSY_LOOP);
1170                 log_trace ("Busy sent, yielding\n");
1171                 pthread_yield ();
1172                 log_trace ("Returned from yield.\n");
1173                 if ((states[test_thread_id].flags & FLAGS_WAS_BUSY) == 0) {
1174                         log_error ("test thread did not run to completion.\n");
1175                         /* Let the thread finish it's busy loop. */
1176                         sleep (6);
1177                 }
1178                 else
1179                         log_pass ();
1180                 states[test_thread_id].flags &= ~FLAGS_WAS_BUSY;
1181
1182                 /* Restore the test thread scheduling parameters. */
1183                 param.sched_priority = states[test_thread_id].priority;
1184                 assert (pthread_setschedparam (states[test_thread_id].tid,
1185                     SCHED_RR, &param) == 0);
1186
1187                 /* Have the test thread release mutex 1. */
1188                 send_cmd (test_thread_id, CMD_RELEASE_ALL);
1189                 sleep (1);
1190
1191                 /*
1192                  * Have the test thread go into a busy loop for 5 seconds
1193                  * and see that it preempts this thread (since the priority
1194                  * ceiling of mutex 2 is the greater than the priority of
1195                  * this thread).  The test thread should run to completion
1196                  * and block this thread because its active priority is
1197                  * higher.
1198                  */
1199                 log_info ("    SCHED_FIFO scheduling and ceiling priority > "
1200                     "thread priority - ");
1201                 /* Have the test thread take mutex 2. */
1202                 send_mutex_cmd (test_thread_id, CMD_TAKE_MUTEX, &m[2]);
1203                 sleep (1);
1204
1205                 log_trace ("Sending busy\n");
1206                 send_cmd (test_thread_id, CMD_BUSY_LOOP);
1207                 log_trace ("Busy sent, yielding\n");
1208                 pthread_yield ();
1209                 log_trace ("Returned from yield.\n");
1210                 if ((states[test_thread_id].flags & FLAGS_IS_BUSY) != 0) {
1211                         log_error ("test thread did not run to completion.\n");
1212                         /* Let the thread finish it's busy loop. */
1213                         sleep (6);
1214                 }
1215                 else if ((states[test_thread_id].flags & FLAGS_WAS_BUSY) == 0)
1216                         log_error ("test thread never finished.\n");
1217                 else
1218                         log_pass ();
1219                 states[test_thread_id].flags &= ~FLAGS_WAS_BUSY;
1220
1221                 /* Have the test thread release mutex 2. */
1222                 send_cmd (test_thread_id, CMD_RELEASE_ALL);
1223                 sleep (1);
1224
1225                 /* Destroy the mutexes. */
1226                 for (i = 0; i < 3; i++)
1227                         assert (pthread_mutex_destroy (&m[i]) == 0);
1228         }
1229 }
1230
1231
1232 static void
1233 mutex_prioinherit_test (void)
1234 {
1235         pthread_mutexattr_t mattr;
1236         struct sched_param param;
1237         pthread_mutex_t m[3];
1238         mutex_kind_t    mkind;
1239         int             i, policy, my_prio;
1240
1241         /* Get this threads current priority. */
1242         assert (pthread_getschedparam (pthread_self(), &policy,
1243             &param) == 0);
1244         my_prio = param.sched_priority; /* save for later use */
1245         log_trace ("Current scheduling policy %d, priority %d\n",
1246             policy, my_prio);
1247
1248         log_info ("Testing priority inheritance\n");
1249         log_info ("----------------------------\n");
1250         for (mkind = M_POSIX; mkind <= M_SS2_RECURSIVE; mkind++) {
1251
1252                 log_info ("  Protype PTHREAD_PRIO_INHERIT, Type %s\n",
1253                     mutextype_strs[mkind]);
1254
1255                 /*
1256                  * Initialize and create a mutex.
1257                  */
1258                 assert (pthread_mutexattr_init (&mattr) == 0);
1259
1260                 /*
1261                  * Initialize and create 3 priority inheritance mutexes with
1262                  * default (max priority) ceilings.
1263                  */
1264                 assert (pthread_mutexattr_setprotocol(&mattr,
1265                     PTHREAD_PRIO_INHERIT) == 0);
1266
1267                 /*
1268                  * Ensure that the first mutex type is a POSIX
1269                  * compliant mutex.
1270                  */
1271                 if (mkind != M_POSIX) {
1272                         assert (pthread_mutexattr_settype (&mattr,
1273                             mutex_types[mkind]) == 0);
1274                 }
1275
1276                 for (i = 0; i < 3; i++)
1277                         assert (pthread_mutex_init (&m[i], &mattr) == 0);
1278
1279                 /*
1280                  * Test setup:
1281                  *   Thread 4 - take mutex 0, 1
1282                  *   Thread 2 - enter protected busy loop with mutex 0
1283                  *   Thread 3 - enter protected busy loop with mutex 1
1284                  *   Thread 4 - enter protected busy loop with mutex 2
1285                  *   Thread 5 - enter busy loop
1286                  *   Thread 6 - enter protected busy loop with mutex 0
1287                  *   Thread 4 - releases mutexes 1 and 0.
1288                  *
1289                  * Expected results:
1290                  *   Threads complete in order 4, 6, 5, 3, 2
1291                  */
1292                 log_info ("    Simple inheritance test - ");
1293
1294                 /*
1295                  * Command thread 4 to take mutexes 0 and 1.
1296                  */
1297                 send_mutex_cmd (4, CMD_TAKE_MUTEX, &m[0]);
1298                 sleep (1);      /* Allow command to be received. */
1299                 send_mutex_cmd (4, CMD_TAKE_MUTEX, &m[1]);
1300                 sleep (1);
1301
1302                 /*
1303                  * Tell the threads to report themselves when they are
1304                  * at the bottom of their loop (waiting on wait_mutex).
1305                  */
1306                 for (i = 0; i < NUM_THREADS; i++)
1307                         states[i].flags |= FLAGS_REPORT_WAITMUTEX;
1308
1309                 /*
1310                  * Command thread 2 to take mutex 0 and thread 3 to take
1311                  * mutex 1, both via a protected operation command.  Since
1312                  * thread 4 owns mutexes 0 and 1, both threads 2 and 3
1313                  * will block until the mutexes are released by thread 4.
1314                  */
1315                 log_trace ("Commanding protected operation to thread 2.\n");
1316                 send_mutex_cmd (2, CMD_PROTECTED_OP, &m[0]);
1317                 log_trace ("Commanding protected operation to thread 3.\n");
1318                 send_mutex_cmd (3, CMD_PROTECTED_OP, &m[1]);
1319                 sleep (1);
1320
1321                 /*
1322                  * Command thread 4 to take mutex 2 via a protected operation
1323                  * and thread 5 to enter a busy loop for 5 seconds.  Since
1324                  * thread 5 has higher priority than thread 4, thread 5 will
1325                  * enter the busy loop before thread 4 is activated.
1326                  */
1327                 log_trace ("Commanding protected operation to thread 4.\n");
1328                 send_mutex_cmd (4, CMD_PROTECTED_OP, &m[2]);
1329                 log_trace ("Commanding busy loop to thread 5.\n");
1330                 send_cmd (5, CMD_BUSY_LOOP);
1331                 sleep (1);
1332                 if ((states[5].flags & FLAGS_IS_BUSY) == 0)
1333                         log_error ("thread 5 is not running.\n");
1334                 log_trace ("Commanding protected operation thread 6.\n");
1335                 send_mutex_cmd (6, CMD_PROTECTED_OP, &m[0]);
1336                 sleep (1);
1337                 if ((states[4].flags & FLAGS_WAS_BUSY) == 0)
1338                         log_error ("thread 4 failed to inherit priority.\n");
1339                 states[4].flags = 0;
1340                 send_cmd (4, CMD_RELEASE_ALL);
1341                 sleep (5);
1342                 check_run_order ("4,6,5,3,2");
1343
1344                 /*
1345                  * Clear the flags.
1346                  */
1347                 for (i = 0; i < NUM_THREADS; i++)
1348                         states[i].flags = 0;
1349
1350                 /*
1351                  * Test setup:
1352                  *   Thread 2 - enter busy loop (SCHED_FIFO)
1353                  *   Thread 4 - take mutex 0
1354                  *   Thread 4 - priority change to same priority as thread 2
1355                  *   Thread 4 - release mutex 0
1356                  *
1357                  * Expected results:
1358                  *   Since thread 4 owns a priority mutex, it should be
1359                  *   placed at the front of the run queue (for its new
1360                  *   priority slot) when its priority is lowered to the
1361                  *   same priority as thread 2.  If thread 4 did not own
1362                  *   a priority mutex, then it would have been added to
1363                  *   the end of the run queue and thread 2 would have
1364                  *   executed until it blocked (because it's scheduling
1365                  *   policy is SCHED_FIFO).
1366                  *   
1367                  */
1368                 log_info ("    Inheritance test with change of priority - ");
1369
1370                 /*
1371                  * Change threads 2 and 4 scheduling policies to be
1372                  * SCHED_FIFO.
1373                  */
1374                 param.sched_priority = states[2].priority;
1375                 assert (pthread_setschedparam (states[2].tid, SCHED_FIFO,
1376                     &param) == 0);
1377                 param.sched_priority = states[4].priority;
1378                 assert (pthread_setschedparam (states[4].tid, SCHED_FIFO,
1379                     &param) == 0);
1380
1381                 /*
1382                  * Command thread 4 to take mutex 0.
1383                  */
1384                 send_mutex_cmd (4, CMD_TAKE_MUTEX, &m[0]);
1385                 sleep (1);
1386
1387                 /*
1388                  * Command thread 2 to enter busy loop.
1389                  */
1390                 send_cmd (2, CMD_BUSY_LOOP);
1391                 sleep (1);      /* Allow command to be received. */
1392
1393                 /*
1394                  * Command thread 4 to enter busy loop.
1395                  */
1396                 send_cmd (4, CMD_BUSY_LOOP);
1397                 sleep (1);      /* Allow command to be received. */
1398
1399                 /* Have threads 2 and 4 report themselves. */
1400                 states[2].flags = FLAGS_REPORT_WAITMUTEX;
1401                 states[4].flags = FLAGS_REPORT_WAITMUTEX;
1402
1403                 /* Change the priority of thread 4. */
1404                 param.sched_priority = states[2].priority;
1405                 assert (pthread_setschedparam (states[4].tid, SCHED_FIFO,
1406                     &param) == 0);
1407                 sleep (5);
1408                 check_run_order ("4,2");
1409
1410                 /* Clear the flags */
1411                 states[2].flags = 0;
1412                 states[4].flags = 0;
1413
1414                 /* Reset the policies. */
1415                 param.sched_priority = states[2].priority;
1416                 assert (pthread_setschedparam (states[2].tid, SCHED_RR,
1417                     &param) == 0);
1418                 param.sched_priority = states[4].priority;
1419                 assert (pthread_setschedparam (states[4].tid, SCHED_RR,
1420                     &param) == 0);
1421
1422                 send_cmd (4, CMD_RELEASE_MUTEX);
1423                 sleep (1);
1424
1425                 /* Destroy the mutexes. */
1426                 for (i = 0; i < 3; i++)
1427                         assert (pthread_mutex_destroy (&m[i]) == 0);
1428         }
1429 }
1430
1431
1432 int main (int argc, char *argv[])
1433 {
1434         pthread_mutexattr_t mattr;
1435         pthread_condattr_t cattr;
1436         pthread_attr_t  pattr;
1437         int             i, policy, main_prio;
1438         void *          exit_status;
1439         sigset_t        mask;
1440         struct sigaction act;
1441         struct sched_param param;
1442         char buf[30];
1443
1444         logfile = stdout;
1445  
1446         assert (pthread_getschedparam (pthread_self (), &policy, &param) == 0);
1447         main_prio = param.sched_priority;
1448
1449         /* Setupt our signal mask. */
1450         sigfillset (&mask);
1451         sigdelset (&mask, SIGINT);
1452         sigprocmask (SIG_SETMASK, &mask, NULL);
1453
1454         /* Install a signal handler for SIGINT */
1455         sigemptyset (&act.sa_mask);
1456         sigaddset (&act.sa_mask, SIGINT);
1457         act.sa_handler = sighandler;
1458         act.sa_flags = SA_RESTART;
1459         sigaction (SIGINT, &act, NULL);
1460
1461         /*
1462          * Initialize the thread attribute.
1463          */
1464         assert (pthread_attr_init (&pattr) == 0);
1465         assert (pthread_attr_setdetachstate (&pattr,
1466             PTHREAD_CREATE_JOINABLE) == 0);
1467
1468         /*
1469          * Initialize and create the waiter and condvar mutexes.
1470          */
1471         assert (pthread_mutexattr_init (&mattr) == 0);
1472         assert (pthread_mutex_init (&waiter_mutex, &mattr) == 0);
1473         assert (pthread_mutex_init (&cond_mutex, &mattr) == 0);
1474
1475         /*
1476          * Initialize and create a condition variable.
1477          */
1478         assert (pthread_condattr_init (&cattr) == 0);
1479         assert (pthread_cond_init (&cond_var, &cattr) == 0);
1480
1481         /* Create a pipe to catch the results of thread wakeups. */
1482         assert (pipe (pipefd) == 0);
1483
1484 #ifdef DEBUG
1485         assert (pthread_switch_add_np (kern_switch) == 0);
1486 #endif
1487
1488         /*
1489          * Create the waiting threads.
1490          */
1491         for (i = 0; i < NUM_THREADS; i++) {
1492                 assert (pthread_cond_init (&states[i].cond_var, &cattr) == 0);
1493                 states[i].id = (u_int8_t) i;  /* NUM_THREADS must be <= 256 */
1494                 states[i].status = 0;
1495                 states[i].cmd.cmd_id = CMD_NONE;
1496                 states[i].flags = 0;    /* No flags yet. */
1497                 assert (pthread_create (&states[i].tid, &pattr, waiter,
1498                     (void *) &states[i]) == 0);
1499                 param.sched_priority = main_prio - 10 + i;
1500                 states[i].priority = param.sched_priority;
1501                 assert (pthread_setschedparam (states[i].tid, SCHED_OTHER,
1502                     &param) == 0);
1503                 snprintf (buf, sizeof(buf), "waiter_%d", i);
1504                 pthread_set_name_np (states[i].tid, buf);
1505         }
1506
1507         /* Allow the threads to start. */
1508         sleep (1);
1509         log_trace ("Done creating threads.\n");
1510
1511         log_info ("\n");
1512         mutex_init_test ();
1513         log_info ("\n");
1514         mutex_destroy_test ();
1515         log_info ("\n");
1516         mutex_lock_test ();
1517         log_info ("\n");
1518         mutex_unlock_test ();
1519         log_info ("\n");
1520         queueing_order_test ();
1521         log_info ("\n");
1522         mutex_prioinherit_test ();
1523         log_info ("\n");
1524         mutex_prioceiling_test ();
1525         log_info ("\n");
1526
1527         log_info ("Total tests %d, passed %d, failed %d\n",
1528             total, pass_count, error_count);
1529
1530         /* Set the done flag and signal the threads to exit. */
1531         log_trace ("Setting done flag.\n");
1532         done = 1;
1533
1534         /*
1535          * Wait for the threads to finish.
1536          */
1537         log_trace ("Trying to join threads.\n");
1538         for (i = 0; i < NUM_THREADS; i++) {
1539                 send_cmd (i, CMD_NONE);
1540                 assert (pthread_join (states[i].tid, &exit_status) == 0);
1541         }
1542
1543         /* Clean up after ourselves. */
1544         close (pipefd[0]);
1545         close (pipefd[1]);
1546
1547         if (error_count != 0)
1548                 exit (EX_OSERR);        /* any better ideas??? */
1549         else
1550                 exit (EX_OK);
1551 }