dhcpcd: 02-dump is no longer supplied
[dragonfly.git] / test / libpthread / mutex_d.c
blobdf52c290e5afac6e77d25c32470eedce9316d382
1 /*
2 * Copyright (c) 1998 Daniel M. Eischen <eischen@vigrid.com>
3 * All rights reserved.
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.
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.
32 * $FreeBSD: src/lib/libc_r/test/mutex_d.c,v 1.1.2.2 2003/01/05 19:59:39 semenu Exp $
34 #include <stdlib.h>
35 #include <unistd.h>
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>
50 #ifndef NELEMENTS
51 #define NELEMENTS(arr) (sizeof (arr) / sizeof (arr[0]))
52 #endif
54 #ifndef NUM_THREADS
55 #define NUM_THREADS 10
56 #endif
58 #define MAX_THREAD_CMDS 10
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);
64 /*------------------------------------------------------------
65 * Types
66 *----------------------------------------------------------*/
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;
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;
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;
93 typedef struct {
94 thread_cmd_id_t cmd_id;
95 pthread_mutex_t *mutex;
96 pthread_cond_t *cond;
97 } thread_cmd_t;
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;
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;
119 /*------------------------------------------------------------
120 * Constants
121 *----------------------------------------------------------*/
123 const char *protocol_strs[] = {
124 "PTHREAD_PRIO_NONE",
125 "PTHREAD_PRIO_INHERIT",
126 "PTHREAD_PRIO_PROTECT"
129 const int protocols[] = {
130 PTHREAD_PRIO_NONE,
131 PTHREAD_PRIO_INHERIT,
132 PTHREAD_PRIO_PROTECT
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"
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 */
152 /*------------------------------------------------------------
153 * Objects
154 *----------------------------------------------------------*/
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];
162 static pthread_mutex_t waiter_mutex;
163 static pthread_mutex_t cond_mutex;
164 static pthread_cond_t cond_var;
166 static FILE *logfile;
167 static int error_count = 0, pass_count = 0, total = 0;
170 /*------------------------------------------------------------
171 * Prototypes
172 *----------------------------------------------------------*/
173 extern char *strtok_r(char *str, const char *sep, char **last);
176 /*------------------------------------------------------------
177 * Functions
178 *----------------------------------------------------------*/
180 #ifdef DEBUG
181 static void
182 kern_switch (pthread_t pthread_out, pthread_t pthread_in)
184 if (pthread_out != NULL)
185 printf ("Swapping out thread 0x%x, ", (int) pthread_out);
186 else
187 printf ("Swapping out kernel thread, ");
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");
194 #endif
197 static void
198 log_error (const char *fmt, ...)
200 va_list ap;
202 va_start (ap, fmt);
203 fprintf (logfile, "FAIL: ");
204 vfprintf (logfile, fmt, ap);
205 error_count = error_count + 1;
206 total = total + 1;
210 static void
211 log_pass (void)
213 fprintf (logfile, "PASS\n");
214 pass_count = pass_count + 1;
215 total = total + 1;
219 static void
220 log_trace (const char *fmt, ...)
222 va_list ap;
224 if (trace_enabled) {
225 va_start (ap, fmt);
226 vfprintf (logfile, fmt, ap);
231 static void
232 log_info (const char *fmt, ...)
234 va_list ap;
236 va_start (ap, fmt);
237 vfprintf (logfile, fmt, ap);
241 static void
242 check_result (int expected, int actual)
244 if (expected != actual)
245 log_error ("expected %d, returned %d\n", expected, actual);
246 else
247 log_pass ();
252 * Check to see that the threads ran in the specified order.
254 static void
255 check_run_order (char *order)
257 const char *sep = ":,";
258 char *tok, *last, *idstr, *endptr;
259 int expected_id, bytes, count = 0, errors = 0;
260 u_int8_t id;
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);
267 for (idstr = strtok_r (tok, sep, &last);
268 (idstr != NULL) && (count < bytes);
269 idstr = strtok_r (NULL, sep, &last)) {
271 /* Get the expected id: */
272 expected_id = (int) strtol (idstr, &endptr, 10);
273 assert ((endptr != NULL) && (*endptr == '\0'));
275 /* Read the actual id from the pipe: */
276 assert (read (pipefd[0], &id, sizeof (id)) == sizeof (id));
277 count = count + sizeof (id);
279 if (id != expected_id) {
280 log_trace ("Thread %d ran out of order.\n", id);
281 errors = errors + 1;
283 else {
284 log_trace ("Thread %d at priority %d reporting.\n",
285 (int) id, states[id].priority);
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;
297 else if (bytes < count)
298 errors = errors + count - bytes;
300 if (errors == 0)
301 log_pass ();
302 else
303 log_error ("%d threads ran out of order\n", errors);
307 static void *
308 waiter (void *arg)
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;
318 statep->status = STAT_INITIAL;
320 /* Block all signals except for interrupt.*/
321 sigfillset (&mask);
322 sigdelset (&mask, SIGINT);
323 sigprocmask (SIG_BLOCK, &mask, NULL);
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);
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);
338 /* Wait for a command. */
339 statep->status = STAT_WAITCONDVAR;
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).
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);
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);
358 log_trace ("Thread %d: received cond_var signal.\n",
359 (int) statep->id);
361 /* Get a copy of the command before releasing the mutex. */
362 cmd = statep->cmd;
364 /* Clear the command after copying it. */
365 statep->cmd.cmd_id = CMD_NONE;
367 /* Unlock the condition variable mutex. */
368 assert (pthread_mutex_unlock (&cond_mutex) == 0);
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++;
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);
386 break;
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;
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;
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);
414 statep->flags &= ~FLAGS_IS_BUSY;
415 statep->flags |= FLAGS_WAS_BUSY;
417 /* Do we report our status? */
418 if (statep->flags & FLAGS_REPORT_BUSY_LOOP)
419 write (pipefd[1], &statep->id,
420 sizeof (statep->id));
422 log_trace ("Thread %d: Leaving busy loop.\n",
423 (int) statep->id);
424 break;
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));
434 assert (pthread_mutex_unlock (cmd.mutex) == 0);
435 break;
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);
445 mutex_count = 0;
446 break;
448 case CMD_NONE:
449 default:
450 break;
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);
466 log_trace ("Thread %d: Exiting thread 0x%p\n", (int) statep->id,
467 pthread_self());
468 pthread_exit (arg);
469 return (NULL);
473 static void *
474 lock_twice (void *arg)
476 thread_state_t *statep = (thread_state_t *) arg;
477 sigset_t mask;
479 statep->status = STAT_INITIAL;
481 /* Block all signals except for interrupt.*/
482 sigfillset (&mask);
483 sigdelset (&mask, SIGINT);
484 sigprocmask (SIG_BLOCK, &mask, NULL);
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);
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);
494 log_trace ("Thread %d: received cond_var signal.\n", (int) statep->id);
496 /* Unlock the condition variable mutex. */
497 assert (pthread_mutex_unlock (&cond_mutex) == 0);
499 statep->status = STAT_WAITMUTEX;
500 /* Lock the mutex once. */
501 assert (pthread_mutex_lock (statep->cmd.mutex) == 0);
503 /* Lock it again and capture the error. */
504 statep->ret = pthread_mutex_lock (statep->cmd.mutex);
505 statep->status = 0;
507 assert (pthread_mutex_unlock (statep->cmd.mutex) == 0);
509 /* Unlock it again if it is locked recursively. */
510 if (statep->ret == 0)
511 pthread_mutex_unlock (statep->cmd.mutex);
513 log_trace ("Thread %d: Exiting thread 0x%p\n", (int) statep->id,
514 pthread_self());
515 pthread_exit (arg);
516 return (NULL);
520 static void
521 sighandler (int signo)
523 log_info ("Signal handler caught signal %d, thread id 0x%p\n",
524 signo, pthread_self());
526 if (signo == SIGINT)
527 done = 1;
531 static void
532 send_cmd (int id, thread_cmd_id_t cmd)
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);
546 static void
547 send_mutex_cmd (int id, thread_cmd_id_t cmd, pthread_mutex_t *m)
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);
561 static void
562 send_mutex_cv_cmd (int id, thread_cmd_id_t cmd, pthread_mutex_t *m,
563 pthread_cond_t *cv)
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);
577 static void
578 mutex_init_test (void)
580 pthread_mutexattr_t mattr;
581 pthread_mutex_t mutex;
582 mutex_kind_t mkind;
583 int mproto, ret;
586 * Initialize a mutex attribute.
588 * pthread_mutexattr_init not tested for: ENOMEM
590 assert (pthread_mutexattr_init (&mattr) == 0);
593 * Initialize a mutex.
595 * pthread_mutex_init not tested for: EAGAIN ENOMEM EPERM EBUSY
597 log_info ("Testing pthread_mutex_init\n");
598 log_info ("--------------------------\n");
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);
608 * Ensure that the first mutex type is a POSIX
609 * compliant mutex.
611 if (mkind != M_POSIX) {
612 assert (pthread_mutexattr_settype (&mattr,
613 mutex_types[mkind]) == 0);
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);
623 * Destroy a mutex attribute.
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.
630 * pthread_mutexattr_destroy not tested for: EINVAL
632 assert (pthread_mutexattr_destroy (&mattr) == 0);
638 static void
639 mutex_destroy_test (void)
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
653 * Destroy a mutex.
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.
659 * pthread_mutex_destroy not tested for:
661 log_info ("Testing pthread_mutex_destroy\n");
662 log_info ("-----------------------------\n");
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
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);
679 * Ensure that the first mutex type is a POSIX
680 * compliant mutex.
682 if (mkind != M_POSIX) {
683 assert (pthread_mutexattr_settype (&mattr,
684 mutex_types[mkind]) == 0);
687 /* Create the mutex. */
688 assert (pthread_mutex_init (&mutex, &mattr) == 0);
690 log_info (" Protocol %s, Type %s\n",
691 protocol_strs[mproto], mutextype_strs[mkind]);
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);
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);
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);
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);
734 static void
735 mutex_lock_test (void)
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;
745 * Lock a mutex.
747 * pthread_lock not tested for:
749 log_info ("Testing pthread_mutex_lock\n");
750 log_info ("--------------------------\n");
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. */
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);
765 * Ensure that the first mutex type is a POSIX
766 * compliant mutex.
768 if (mkind != M_POSIX) {
769 assert (pthread_mutexattr_settype (&mattr,
770 mutex_types[mkind]) == 0);
773 /* Create the mutex. */
774 assert (pthread_mutex_init (&mutex, &mattr) == 0);
776 log_info (" Protocol %s, Type %s\n",
777 protocol_strs[mproto], mutextype_strs[mkind]);
779 log_info (" Lock on unlocked mutex - ");
780 ret = pthread_mutex_lock (&mutex);
781 check_result (/* expected */ 0, ret);
782 pthread_mutex_unlock (&mutex);
784 log_info (" Lock on invalid mutex - ");
785 ret = pthread_mutex_lock (NULL);
786 check_result (/* expected */ EINVAL, ret);
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);
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;
822 pthread_mutex_destroy (&mutex);
823 pthread_mutexattr_destroy (&mattr);
829 static void
830 mutex_unlock_test (void)
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;
839 * Unlock a mutex.
841 * pthread_unlock not tested for:
843 log_info ("Testing pthread_mutex_unlock\n");
844 log_info ("----------------------------\n");
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);
854 * Ensure that the first mutex type is a POSIX
855 * compliant mutex.
857 if (mkind != M_POSIX) {
858 assert (pthread_mutexattr_settype (&mattr,
859 mutex_types[mkind]) == 0);
862 /* Create the mutex. */
863 assert (pthread_mutex_init (&mutex, &mattr) == 0);
865 log_info (" Protocol %s, Type %s\n",
866 protocol_strs[mproto], mutextype_strs[mkind]);
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);
873 log_info (" Unlock on invalid mutex - ");
874 ret = pthread_mutex_unlock (NULL);
875 check_result (/* expected */ EINVAL, ret);
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;
898 if (ret == 0) {
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.
904 pthread_mutex_lock (&mutex);
906 send_cmd (test_thread_id, CMD_RELEASE_ALL);
907 sleep (1);
909 pthread_mutex_destroy (&mutex);
910 pthread_mutexattr_destroy (&mattr);
916 static void
917 queueing_order_test (void)
919 int i;
921 log_info ("Testing queueing order\n");
922 log_info ("----------------------\n");
923 assert (pthread_mutex_lock (&waiter_mutex) == 0);
925 * Tell the threads to report when they take the waiters mutex.
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);
932 assert (pthread_mutex_unlock (&cond_mutex) == 0);
934 /* Signal the threads to continue. */
935 sleep (1);
937 /* Use the global condition variable next time. */
938 use_global_condvar = 1;
940 /* Release the waiting threads and allow them to run again. */
941 assert (pthread_mutex_unlock (&waiter_mutex) == 0);
942 sleep (1);
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;
952 * Prevent the threads from continuing their loop after we
953 * signal them.
955 assert (pthread_mutex_lock (&waiter_mutex) == 0);
958 log_info (" Queueing order on a condition variable - ");
960 * Signal one thread to run and see that the highest priority
961 * thread executes.
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");
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);
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;
982 /* Use the thread unique condition variable next time. */
983 use_global_condvar = 0;
985 /* Allow the threads to continue their loop. */
986 assert (pthread_mutex_unlock (&waiter_mutex) == 0);
987 sleep (1);
991 static void
992 mutex_prioceiling_test (void)
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;
1001 log_info ("Testing priority ceilings\n");
1002 log_info ("-------------------------\n");
1003 for (mkind = M_POSIX; mkind <= M_SS2_RECURSIVE; mkind++) {
1005 log_info (" Protype PTHREAD_PRIO_PROTECT, Type %s\n",
1006 mutextype_strs[mkind]);
1009 * Initialize and create a mutex.
1011 assert (pthread_mutexattr_init (&mattr) == 0);
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);
1021 * Initialize and create 3 priority protection mutexes with
1022 * default (max priority) ceilings.
1024 assert (pthread_mutexattr_setprotocol(&mattr,
1025 PTHREAD_PRIO_PROTECT) == 0);
1028 * Ensure that the first mutex type is a POSIX
1029 * compliant mutex.
1031 if (mkind != M_POSIX) {
1032 assert (pthread_mutexattr_settype (&mattr,
1033 mutex_types[mkind]) == 0);
1036 for (i = 0; i < 3; i++)
1037 assert (pthread_mutex_init (&m[i], &mattr) == 0);
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.
1044 for (i = 0; i < 3; i++)
1045 assert (pthread_mutex_setprioceiling (&m[i],
1046 my_prio - 5 + 5*i, &old_ceiling) == 0);
1049 * Check that if we attempt to take a mutex whose priority
1050 * ceiling is lower than our priority, we get an error.
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]);
1059 * Check that we can take a mutex whose priority ceiling
1060 * is equal to our priority.
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]);
1069 * Check that we can take a mutex whose priority ceiling
1070 * is higher than our priority.
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]);
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).
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);
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 ();
1106 states[test_thread_id].flags &= ~FLAGS_WAS_BUSY;
1108 /* Have the test thread release mutex 0. */
1109 send_cmd (test_thread_id, CMD_RELEASE_ALL);
1110 sleep (1);
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.
1120 log_info (" Preemption with ceiling priority = thread "
1121 "priority - ");
1123 /* Have the test thread take mutex 1. */
1124 send_mutex_cmd (test_thread_id, CMD_TAKE_MUTEX, &m[1]);
1125 sleep (1);
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 ();
1144 states[test_thread_id].flags &= ~FLAGS_WAS_BUSY;
1146 /* Have the test thread release mutex 1. */
1147 send_cmd (test_thread_id, CMD_RELEASE_ALL);
1148 sleep (1);
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.
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);
1164 /* Have the test thread take mutex 1. */
1165 send_mutex_cmd (test_thread_id, CMD_TAKE_MUTEX, &m[1]);
1166 sleep (1);
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);
1178 else
1179 log_pass ();
1180 states[test_thread_id].flags &= ~FLAGS_WAS_BUSY;
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);
1187 /* Have the test thread release mutex 1. */
1188 send_cmd (test_thread_id, CMD_RELEASE_ALL);
1189 sleep (1);
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.
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);
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);
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;
1221 /* Have the test thread release mutex 2. */
1222 send_cmd (test_thread_id, CMD_RELEASE_ALL);
1223 sleep (1);
1225 /* Destroy the mutexes. */
1226 for (i = 0; i < 3; i++)
1227 assert (pthread_mutex_destroy (&m[i]) == 0);
1232 static void
1233 mutex_prioinherit_test (void)
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;
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);
1248 log_info ("Testing priority inheritance\n");
1249 log_info ("----------------------------\n");
1250 for (mkind = M_POSIX; mkind <= M_SS2_RECURSIVE; mkind++) {
1252 log_info (" Protype PTHREAD_PRIO_INHERIT, Type %s\n",
1253 mutextype_strs[mkind]);
1256 * Initialize and create a mutex.
1258 assert (pthread_mutexattr_init (&mattr) == 0);
1261 * Initialize and create 3 priority inheritance mutexes with
1262 * default (max priority) ceilings.
1264 assert (pthread_mutexattr_setprotocol(&mattr,
1265 PTHREAD_PRIO_INHERIT) == 0);
1268 * Ensure that the first mutex type is a POSIX
1269 * compliant mutex.
1271 if (mkind != M_POSIX) {
1272 assert (pthread_mutexattr_settype (&mattr,
1273 mutex_types[mkind]) == 0);
1276 for (i = 0; i < 3; i++)
1277 assert (pthread_mutex_init (&m[i], &mattr) == 0);
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.
1289 * Expected results:
1290 * Threads complete in order 4, 6, 5, 3, 2
1292 log_info (" Simple inheritance test - ");
1295 * Command thread 4 to take mutexes 0 and 1.
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);
1303 * Tell the threads to report themselves when they are
1304 * at the bottom of their loop (waiting on wait_mutex).
1306 for (i = 0; i < NUM_THREADS; i++)
1307 states[i].flags |= FLAGS_REPORT_WAITMUTEX;
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.
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);
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.
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");
1345 * Clear the flags.
1347 for (i = 0; i < NUM_THREADS; i++)
1348 states[i].flags = 0;
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
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).
1368 log_info (" Inheritance test with change of priority - ");
1371 * Change threads 2 and 4 scheduling policies to be
1372 * SCHED_FIFO.
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);
1382 * Command thread 4 to take mutex 0.
1384 send_mutex_cmd (4, CMD_TAKE_MUTEX, &m[0]);
1385 sleep (1);
1388 * Command thread 2 to enter busy loop.
1390 send_cmd (2, CMD_BUSY_LOOP);
1391 sleep (1); /* Allow command to be received. */
1394 * Command thread 4 to enter busy loop.
1396 send_cmd (4, CMD_BUSY_LOOP);
1397 sleep (1); /* Allow command to be received. */
1399 /* Have threads 2 and 4 report themselves. */
1400 states[2].flags = FLAGS_REPORT_WAITMUTEX;
1401 states[4].flags = FLAGS_REPORT_WAITMUTEX;
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");
1410 /* Clear the flags */
1411 states[2].flags = 0;
1412 states[4].flags = 0;
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);
1422 send_cmd (4, CMD_RELEASE_MUTEX);
1423 sleep (1);
1425 /* Destroy the mutexes. */
1426 for (i = 0; i < 3; i++)
1427 assert (pthread_mutex_destroy (&m[i]) == 0);
1432 int main (int argc, char *argv[])
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];
1444 logfile = stdout;
1446 assert (pthread_getschedparam (pthread_self (), &policy, &param) == 0);
1447 main_prio = param.sched_priority;
1449 /* Setupt our signal mask. */
1450 sigfillset (&mask);
1451 sigdelset (&mask, SIGINT);
1452 sigprocmask (SIG_SETMASK, &mask, NULL);
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);
1462 * Initialize the thread attribute.
1464 assert (pthread_attr_init (&pattr) == 0);
1465 assert (pthread_attr_setdetachstate (&pattr,
1466 PTHREAD_CREATE_JOINABLE) == 0);
1469 * Initialize and create the waiter and condvar mutexes.
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);
1476 * Initialize and create a condition variable.
1478 assert (pthread_condattr_init (&cattr) == 0);
1479 assert (pthread_cond_init (&cond_var, &cattr) == 0);
1481 /* Create a pipe to catch the results of thread wakeups. */
1482 assert (pipe (pipefd) == 0);
1484 #ifdef DEBUG
1485 assert (pthread_switch_add_np (kern_switch) == 0);
1486 #endif
1489 * Create the waiting threads.
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);
1507 /* Allow the threads to start. */
1508 sleep (1);
1509 log_trace ("Done creating threads.\n");
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");
1527 log_info ("Total tests %d, passed %d, failed %d\n",
1528 total, pass_count, error_count);
1530 /* Set the done flag and signal the threads to exit. */
1531 log_trace ("Setting done flag.\n");
1532 done = 1;
1535 * Wait for the threads to finish.
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);
1543 /* Clean up after ourselves. */
1544 close (pipefd[0]);
1545 close (pipefd[1]);
1547 if (error_count != 0)
1548 exit (EX_OSERR); /* any better ideas??? */
1549 else
1550 exit (EX_OK);