mutex_d.c revision 99239
11592Srgrimes/* 21592Srgrimes * Copyright (c) 1998 Daniel M. Eischen <eischen@vigrid.com> 31592Srgrimes * All rights reserved. 41592Srgrimes * 51592Srgrimes * Redistribution and use in source and binary forms, with or without 61592Srgrimes * modification, are permitted provided that the following conditions 71592Srgrimes * are met: 81592Srgrimes * 1. Redistributions of source code must retain the above copyright 91592Srgrimes * notice, this list of conditions and the following disclaimer. 101592Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111592Srgrimes * notice, this list of conditions and the following disclaimer in the 121592Srgrimes * documentation and/or other materials provided with the distribution. 131592Srgrimes * 3. All advertising materials mentioning features or use of this software 141592Srgrimes * must display the following acknowledgement: 151592Srgrimes * This product includes software developed by Daniel M. Eischen. 161592Srgrimes * 4. Neither the name of the author nor the names of any co-contributors 171592Srgrimes * may be used to endorse or promote products derived from this software 181592Srgrimes * without specific prior written permission. 191592Srgrimes * 201592Srgrimes * THIS SOFTWARE IS PROVIDED BY DANIEL M. EISCHEN AND CONTRIBUTORS ``AS IS'' 211592Srgrimes * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 221592Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 231592Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 241592Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 251592Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 261592Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 271592Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 281592Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 291592Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 301592Srgrimes * SUCH DAMAGE. 311592Srgrimes * 321592Srgrimes * $FreeBSD: head/lib/libkse/test/mutex_d.c 99239 2002-07-02 01:26:16Z deischen $ 331592Srgrimes */ 341592Srgrimes#include <stdlib.h> 351592Srgrimes#include <unistd.h> 361592Srgrimes 371592Srgrimes#include <sys/ioctl.h> 381592Srgrimes#include <assert.h> 391592Srgrimes#include <errno.h> 401592Srgrimes#include "pthread.h" 411592Srgrimes#include <sched.h> 421592Srgrimes#include <signal.h> 431592Srgrimes#include <stdarg.h> 4431329Scharnier#include <stdio.h> 451592Srgrimes#include <string.h> 4631329Scharnier#include <sysexits.h> 4731329Scharnier 4850476Speter#if defined(_LIBC_R_) 491592Srgrimes#include <pthread_np.h> 501592Srgrimes#endif 511592Srgrimes 521592Srgrimes#ifndef NELEMENTS 531592Srgrimes#define NELEMENTS(arr) (sizeof (arr) / sizeof (arr[0])) 541592Srgrimes#endif 551592Srgrimes 561592Srgrimes#ifndef NUM_THREADS 571592Srgrimes#define NUM_THREADS 10 581592Srgrimes#endif 591592Srgrimes 601592Srgrimes#define MAX_THREAD_CMDS 10 6156668Sshin 621592Srgrimesstatic void log_error(const char *, ...) __printflike(1, 2); 631592Srgrimesstatic void log_trace (const char *, ...) __printflike(1, 2); 641592Srgrimesstatic void log (const char *, ...) __printflike(1, 2); 651592Srgrimes 661592Srgrimes/*------------------------------------------------------------ 671592Srgrimes * Types 681592Srgrimes *----------------------------------------------------------*/ 691592Srgrimes 701592Srgrimestypedef enum { 7113139Speter STAT_INITIAL, /* initial state */ 721592Srgrimes STAT_WAITCONDVAR, /* waiting for condition variable signal */ 731592Srgrimes STAT_WAITMUTEX /* waiting for mutex lock */ 741592Srgrimes} thread_status_t; 7556668Sshin 761592Srgrimestypedef enum { 771592Srgrimes FLAGS_REPORT_WAITCONDMUTEX = 0x01, 781592Srgrimes FLAGS_REPORT_WAITCONDVAR = 0x02, 7917435Spst FLAGS_REPORT_WAITMUTEX = 0x04, 801592Srgrimes FLAGS_REPORT_BUSY_LOOP = 0x08, 811592Srgrimes FLAGS_IS_BUSY = 0x10, 821592Srgrimes FLAGS_WAS_BUSY = 0x20 831592Srgrimes} thread_flags_t; 841592Srgrimes 851592Srgrimestypedef enum { 861592Srgrimes CMD_NONE, 8727650Sdavidn CMD_TAKE_MUTEX, 8827650Sdavidn CMD_RELEASE_MUTEX, 891592Srgrimes CMD_WAIT_FOR_SIGNAL, 901592Srgrimes CMD_BUSY_LOOP, 911592Srgrimes CMD_PROTECTED_OP, 921592Srgrimes CMD_RELEASE_ALL 931592Srgrimes} thread_cmd_id_t; 941592Srgrimes 951592Srgrimestypedef struct { 961592Srgrimes thread_cmd_id_t cmd_id; 971592Srgrimes pthread_mutex_t *mutex; 981592Srgrimes pthread_cond_t *cond; 991592Srgrimes} thread_cmd_t; 1001592Srgrimes 1011592Srgrimestypedef struct { 10256668Sshin pthread_cond_t cond_var; 10356668Sshin thread_status_t status; 1041592Srgrimes thread_cmd_t cmd; 1051592Srgrimes int flags; 1061592Srgrimes int priority; 1071592Srgrimes int ret; 1081592Srgrimes pthread_t tid; 1091592Srgrimes u_int8_t id; 1101592Srgrimes} thread_state_t; 1111592Srgrimes 1121592Srgrimestypedef enum { 1131592Srgrimes M_POSIX, 11456668Sshin M_SS2_DEFAULT, 1151592Srgrimes M_SS2_ERRORCHECK, 1161592Srgrimes M_SS2_NORMAL, 1171592Srgrimes M_SS2_RECURSIVE 1181592Srgrimes} mutex_kind_t; 1191592Srgrimes 1201592Srgrimes 1211592Srgrimes/*------------------------------------------------------------ 1221592Srgrimes * Constants 1231592Srgrimes *----------------------------------------------------------*/ 1241592Srgrimes 12556668Sshinconst char *protocol_strs[] = { 1261592Srgrimes "PTHREAD_PRIO_NONE", 1271592Srgrimes "PTHREAD_PRIO_INHERIT", 1281592Srgrimes "PTHREAD_PRIO_PROTECT" 1291592Srgrimes}; 1301592Srgrimes 1311592Srgrimesconst int protocols[] = { 1321592Srgrimes PTHREAD_PRIO_NONE, 1331592Srgrimes PTHREAD_PRIO_INHERIT, 1341592Srgrimes PTHREAD_PRIO_PROTECT 1351592Srgrimes}; 13656668Sshin 13756668Sshinconst char *mutextype_strs[] = { 1381592Srgrimes "POSIX (type not specified)", 1391592Srgrimes "SS2 PTHREAD_MUTEX_DEFAULT", 1401592Srgrimes "SS2 PTHREAD_MUTEX_ERRORCHECK", 1411592Srgrimes "SS2 PTHREAD_MUTEX_NORMAL", 1421592Srgrimes "SS2 PTHREAD_MUTEX_RECURSIVE" 1431592Srgrimes}; 1441592Srgrimes 1451592Srgrimesconst int mutex_types[] = { 1461592Srgrimes 0, /* M_POSIX */ 1471592Srgrimes PTHREAD_MUTEX_DEFAULT, /* M_SS2_DEFAULT */ 1481592Srgrimes PTHREAD_MUTEX_ERRORCHECK, /* M_SS2_ERRORCHECK */ 1491592Srgrimes PTHREAD_MUTEX_NORMAL, /* M_SS2_NORMAL */ 1501592Srgrimes PTHREAD_MUTEX_RECURSIVE /* M_SS2_RECURSIVE */ 1511592Srgrimes}; 1521592Srgrimes 1531592Srgrimes 1541592Srgrimes/*------------------------------------------------------------ 1551592Srgrimes * Objects 1561592Srgrimes *----------------------------------------------------------*/ 1571592Srgrimes 1581592Srgrimesstatic int done = 0; 1591592Srgrimesstatic int trace_enabled = 0; 1601592Srgrimesstatic int use_global_condvar = 0; 1611592Srgrimesstatic thread_state_t states[NUM_THREADS]; 1621592Srgrimesstatic int pipefd[2]; 1631592Srgrimes 16417433Spststatic pthread_mutex_t waiter_mutex; 1651592Srgrimesstatic pthread_mutex_t cond_mutex; 16656668Sshinstatic pthread_cond_t cond_var; 16756668Sshin 16856668Sshinstatic FILE *logfile; 16956668Sshinstatic int error_count = 0, pass_count = 0, total = 0; 17056668Sshin 17156668Sshin 17256668Sshin/*------------------------------------------------------------ 17356668Sshin * Prototypes 17456668Sshin *----------------------------------------------------------*/ 17556668Sshinextern char *strtok_r(char *str, const char *sep, char **last); 17656668Sshin 17756668Sshin 17856668Sshin/*------------------------------------------------------------ 17956668Sshin * Functions 18056668Sshin *----------------------------------------------------------*/ 18156668Sshin 18256668Sshin#ifdef DEBUG 18356668Sshinstatic void 18456668Sshinkern_switch (pthread_t pthread_out, pthread_t pthread_in) 18556668Sshin{ 18656668Sshin if (pthread_out != NULL) 18756668Sshin printf ("Swapping out thread 0x%x, ", (int) pthread_out); 18856668Sshin else 18956668Sshin printf ("Swapping out kernel thread, "); 19056668Sshin 19156668Sshin if (pthread_in != NULL) 19256668Sshin printf ("swapping in thread 0x%x\n", (int) pthread_in); 19356668Sshin else 19456668Sshin printf ("swapping in kernel thread.\n"); 19556668Sshin} 19656668Sshin#endif 19756668Sshin 19856668Sshin 19956668Sshinstatic void 20056668Sshinlog_error (const char *fmt, ...) 20156668Sshin{ 20256668Sshin va_list ap; 20356668Sshin 20456668Sshin va_start (ap, fmt); 20556668Sshin fprintf (logfile, "FAIL: "); 20656668Sshin vfprintf (logfile, fmt, ap); 20756668Sshin error_count = error_count + 1; 20856668Sshin total = total + 1; 20956668Sshin} 21056668Sshin 21156668Sshin 21256668Sshinstatic void 21356668Sshinlog_pass (void) 21456668Sshin{ 21556668Sshin fprintf (logfile, "PASS\n"); 21656668Sshin pass_count = pass_count + 1; 21756668Sshin total = total + 1; 21856668Sshin} 21956668Sshin 22056668Sshin 22156668Sshinstatic void 22256668Sshinlog_trace (const char *fmt, ...) 22356668Sshin{ 22456668Sshin va_list ap; 22556668Sshin 22656668Sshin if (trace_enabled) { 22756668Sshin va_start (ap, fmt); 22856668Sshin vfprintf (logfile, fmt, ap); 22956668Sshin } 23056668Sshin} 23156668Sshin 23256668Sshin 23356668Sshinstatic void 23456668Sshinlog (const char *fmt, ...) 23556668Sshin{ 23656668Sshin va_list ap; 23756668Sshin 23856668Sshin va_start (ap, fmt); 23956668Sshin vfprintf (logfile, fmt, ap); 24056668Sshin} 24156668Sshin 24256668Sshin 24356668Sshinstatic void 24417433Spstcheck_result (int expected, int actual) 24556668Sshin{ 24617433Spst if (expected != actual) 24756668Sshin log_error ("expected %d, returned %d\n", expected, actual); 24856668Sshin else 24956668Sshin log_pass (); 25056668Sshin} 25156668Sshin 2521592Srgrimes 25356668Sshin/* 25456668Sshin * Check to see that the threads ran in the specified order. 25556668Sshin */ 25656668Sshinstatic void 25756668Sshincheck_run_order (char *order) 25856668Sshin{ 25956668Sshin const char *sep = ":,"; 26056668Sshin char *tok, *last, *idstr, *endptr; 26156668Sshin int expected_id, bytes, count = 0, errors = 0; 26256668Sshin u_int8_t id; 26356668Sshin 26456668Sshin assert ((tok = (char *) malloc (strlen(order) + 1)) != NULL); 26556668Sshin strcpy (tok, order); /* tok has to be larger than order */ 26656668Sshin assert (ioctl (pipefd[0], FIONREAD, &bytes) == 0); 26756668Sshin log_trace ("%d bytes read from FIFO.\n", bytes); 26856668Sshin 26956668Sshin for (idstr = strtok_r (tok, sep, &last); 27056668Sshin (idstr != NULL) && (count < bytes); 27156668Sshin idstr = strtok_r (NULL, sep, &last)) { 27256668Sshin 27356668Sshin /* Get the expected id: */ 27456668Sshin expected_id = (int) strtol (idstr, &endptr, 10); 27556668Sshin assert ((endptr != NULL) && (*endptr == '\0')); 27656668Sshin 27756668Sshin /* Read the actual id from the pipe: */ 27856668Sshin assert (read (pipefd[0], &id, sizeof (id)) == sizeof (id)); 27956668Sshin count = count + sizeof (id); 28056668Sshin 28156668Sshin if (id != expected_id) { 28256668Sshin log_trace ("Thread %d ran out of order.\n", id); 28356668Sshin errors = errors + 1; 28456668Sshin } 28556668Sshin else { 28656668Sshin log_trace ("Thread %d at priority %d reporting.\n", 28756668Sshin (int) id, states[id].priority); 28856668Sshin } 28956668Sshin } 29056668Sshin 29156668Sshin if (count < bytes) { 29256668Sshin /* Clear the pipe: */ 29356668Sshin while (count < bytes) { 29456668Sshin read (pipefd[0], &id, sizeof (id)); 29556668Sshin count = count + 1; 29656668Sshin errors = errors + 1; 29756668Sshin } 29856668Sshin } 29956668Sshin else if (bytes < count) 30056668Sshin errors = errors + count - bytes; 30156668Sshin 30256668Sshin if (errors == 0) 30356668Sshin log_pass (); 30456668Sshin else 30556668Sshin log_error ("%d threads ran out of order", errors); 3061592Srgrimes} 30717433Spst 3081592Srgrimes 30956668Sshinstatic void * 31056668Sshinwaiter (void *arg) 31156668Sshin{ 31217433Spst thread_state_t *statep = (thread_state_t *) arg; 3131592Srgrimes pthread_mutex_t *held_mutex[MAX_THREAD_CMDS]; 31456668Sshin int held_mutex_owned[MAX_THREAD_CMDS]; 31556668Sshin sigset_t mask; 31656668Sshin struct timeval tv1, tv2; 31756668Sshin thread_cmd_t cmd; 31856668Sshin int i, mutex_count = 0; 31956668Sshin 32056668Sshin statep->status = STAT_INITIAL; 32156668Sshin 32256668Sshin /* Block all signals except for interrupt.*/ 32356668Sshin sigfillset (&mask); 32456668Sshin sigdelset (&mask, SIGINT); 32556668Sshin sigprocmask (SIG_BLOCK, &mask, NULL); 32656668Sshin 32756668Sshin while (done == 0) { 32856668Sshin /* Wait for signal from the main thread to continue. */ 32956668Sshin statep->status = STAT_WAITMUTEX; 33056668Sshin log_trace ("Thread %d: locking cond_mutex.\n", 33156668Sshin (int) statep->id); 33256668Sshin pthread_mutex_lock (&cond_mutex); 33356668Sshin 33456668Sshin /* Do we report our status. */ 33556668Sshin if (statep->flags & FLAGS_REPORT_WAITCONDMUTEX) 33656668Sshin write (pipefd[1], &statep->id, sizeof (statep->id)); 33756668Sshin log_trace ("Thread %d: waiting for cond_var.\n", 33856668Sshin (int) statep->id); 33956668Sshin 34056668Sshin /* Wait for a command. */ 34156668Sshin statep->status = STAT_WAITCONDVAR; 34256668Sshin 34356668Sshin /* 34456668Sshin * The threads are allowed commanded to wait either on 34556668Sshin * their own unique condition variable (so they may be 34656668Sshin * separately signaled) or on one global condition variable 34756668Sshin * (so they may be signaled together). 34856668Sshin */ 34956668Sshin if (use_global_condvar != 0) 35056668Sshin pthread_cond_wait (&cond_var, &cond_mutex); 35156668Sshin else 35256668Sshin pthread_cond_wait (&statep->cond_var, &cond_mutex); 35356668Sshin 3541592Srgrimes /* Do we report our status? */ 3551592Srgrimes if (statep->flags & FLAGS_REPORT_WAITCONDVAR) { 3561592Srgrimes write (pipefd[1], &statep->id, sizeof (statep->id)); 3571592Srgrimes log_trace ("Thread %d: wrote to pipe.\n", 3581592Srgrimes (int) statep->id); 3591592Srgrimes } 3601592Srgrimes log_trace ("Thread %d: received cond_var signal.\n", 3611592Srgrimes (int) statep->id); 3621592Srgrimes 3631592Srgrimes /* Get a copy of the command before releasing the mutex. */ 3641592Srgrimes cmd = statep->cmd; 3651592Srgrimes 3661592Srgrimes /* Clear the command after copying it. */ 3671592Srgrimes statep->cmd.cmd_id = CMD_NONE; 3681592Srgrimes 3691592Srgrimes /* Unlock the condition variable mutex. */ 3701592Srgrimes assert (pthread_mutex_unlock (&cond_mutex) == 0); 3711592Srgrimes 3721592Srgrimes /* Peform the command.*/ 3731592Srgrimes switch (cmd.cmd_id) { 3741592Srgrimes case CMD_TAKE_MUTEX: 3751592Srgrimes statep->ret = pthread_mutex_lock (cmd.mutex); 3761592Srgrimes if (statep->ret == 0) { 3771592Srgrimes assert (mutex_count < sizeof (held_mutex)); 3781592Srgrimes held_mutex[mutex_count] = cmd.mutex; 3791592Srgrimes held_mutex_owned[mutex_count] = 1; 3801592Srgrimes mutex_count++; 3811592Srgrimes } 3821592Srgrimes else { 3831592Srgrimes held_mutex_owned[mutex_count] = 0; 3841592Srgrimes log_trace ("Thread id %d unable to lock mutex, " 3851592Srgrimes "error = %d\n", (int) statep->id, 3861592Srgrimes statep->ret); 3871592Srgrimes } 3881592Srgrimes break; 3891592Srgrimes 3901592Srgrimes case CMD_RELEASE_MUTEX: 3911592Srgrimes assert ((mutex_count <= sizeof (held_mutex)) && 3921592Srgrimes (mutex_count > 0)); 3931592Srgrimes mutex_count--; 3941592Srgrimes if (held_mutex_owned[mutex_count] != 0) 3951592Srgrimes assert (pthread_mutex_unlock 3961592Srgrimes (held_mutex[mutex_count]) == 0); 3971592Srgrimes break; 3981592Srgrimes 3991592Srgrimes case CMD_WAIT_FOR_SIGNAL: 4001592Srgrimes assert (pthread_mutex_lock (cmd.mutex) == 0); 4011592Srgrimes assert (pthread_cond_wait (cmd.cond, cmd.mutex) == 0); 4021592Srgrimes assert (pthread_mutex_unlock (cmd.mutex) == 0); 4031592Srgrimes break; 4041592Srgrimes 4051592Srgrimes case CMD_BUSY_LOOP: 4061592Srgrimes log_trace ("Thread %d: Entering busy loop.\n", 4071592Srgrimes (int) statep->id); 4081592Srgrimes /* Spin for 15 seconds. */ 4091592Srgrimes assert (gettimeofday (&tv2, NULL) == 0); 4101592Srgrimes tv1.tv_sec = tv2.tv_sec + 5; 4111592Srgrimes tv1.tv_usec = tv2.tv_usec; 4121592Srgrimes statep->flags |= FLAGS_IS_BUSY; 4131592Srgrimes while (timercmp (&tv2, &tv1,<)) { 4141592Srgrimes assert (gettimeofday (&tv2, NULL) == 0); 4151592Srgrimes } 4161592Srgrimes statep->flags &= ~FLAGS_IS_BUSY; 4171592Srgrimes statep->flags |= FLAGS_WAS_BUSY; 4181592Srgrimes 4191592Srgrimes /* Do we report our status? */ 4201592Srgrimes if (statep->flags & FLAGS_REPORT_BUSY_LOOP) 4211592Srgrimes write (pipefd[1], &statep->id, 4221592Srgrimes sizeof (statep->id)); 4231592Srgrimes 4241592Srgrimes log_trace ("Thread %d: Leaving busy loop.\n", 4251592Srgrimes (int) statep->id); 4261592Srgrimes break; 4271592Srgrimes 4281592Srgrimes case CMD_PROTECTED_OP: 4291592Srgrimes assert (pthread_mutex_lock (cmd.mutex) == 0); 4301592Srgrimes statep->flags |= FLAGS_WAS_BUSY; 4311592Srgrimes /* Do we report our status? */ 4321592Srgrimes if (statep->flags & FLAGS_REPORT_BUSY_LOOP) 4331592Srgrimes write (pipefd[1], &statep->id, 4341592Srgrimes sizeof (statep->id)); 4351592Srgrimes 4361592Srgrimes assert (pthread_mutex_unlock (cmd.mutex) == 0); 4371592Srgrimes break; 4381592Srgrimes 4391592Srgrimes case CMD_RELEASE_ALL: 4401592Srgrimes assert ((mutex_count <= sizeof (held_mutex)) && 4411592Srgrimes (mutex_count > 0)); 4421592Srgrimes for (i = mutex_count - 1; i >= 0; i--) { 4431592Srgrimes if (held_mutex_owned[i] != 0) 4441592Srgrimes assert (pthread_mutex_unlock 4451592Srgrimes (held_mutex[i]) == 0); 4461592Srgrimes } 4471592Srgrimes mutex_count = 0; 4481592Srgrimes break; 4491592Srgrimes 4501592Srgrimes case CMD_NONE: 4511592Srgrimes default: 4521592Srgrimes break; 4531592Srgrimes } 4541592Srgrimes 4551592Srgrimes /* Wait for the big giant waiter lock. */ 4561592Srgrimes statep->status = STAT_WAITMUTEX; 4571592Srgrimes log_trace ("Thread %d: waiting for big giant lock.\n", 4581592Srgrimes (int) statep->id); 4591592Srgrimes pthread_mutex_lock (&waiter_mutex); 4601592Srgrimes if (statep->flags & FLAGS_REPORT_WAITMUTEX) 4611592Srgrimes write (pipefd[1], &statep->id, sizeof (statep->id)); 4621592Srgrimes log_trace ("Thread %d: got big giant lock.\n", 4631592Srgrimes (int) statep->id); 4641592Srgrimes statep->status = STAT_INITIAL; 4651592Srgrimes pthread_mutex_unlock (&waiter_mutex); 4661592Srgrimes } 4671592Srgrimes 4681592Srgrimes log_trace ("Thread %d: Exiting thread 0x%x\n", (int) statep->id, 4691592Srgrimes (int) pthread_self()); 4701592Srgrimes pthread_exit (arg); 4711592Srgrimes return (NULL); 4721592Srgrimes} 4731592Srgrimes 4741592Srgrimes 4751592Srgrimesstatic void * 4761592Srgrimeslock_twice (void *arg) 4771592Srgrimes{ 4781592Srgrimes thread_state_t *statep = (thread_state_t *) arg; 4791592Srgrimes sigset_t mask; 4801592Srgrimes 4811592Srgrimes statep->status = STAT_INITIAL; 4821592Srgrimes 4831592Srgrimes /* Block all signals except for interrupt.*/ 48417433Spst sigfillset (&mask); 4851592Srgrimes sigdelset (&mask, SIGINT); 48617433Spst sigprocmask (SIG_BLOCK, &mask, NULL); 48717433Spst 48817433Spst /* Wait for a signal to continue. */ 48917433Spst log_trace ("Thread %d: locking cond_mutex.\n", (int) statep->id); 49017433Spst pthread_mutex_lock (&cond_mutex); 49117433Spst 49217433Spst log_trace ("Thread %d: waiting for cond_var.\n", (int) statep->id); 49317433Spst statep->status = STAT_WAITCONDVAR; 4941592Srgrimes pthread_cond_wait (&cond_var, &cond_mutex); 49517433Spst 4961592Srgrimes log_trace ("Thread %d: received cond_var signal.\n", (int) statep->id); 4971592Srgrimes 4981592Srgrimes /* Unlock the condition variable mutex. */ 4991592Srgrimes assert (pthread_mutex_unlock (&cond_mutex) == 0); 5001592Srgrimes 5011592Srgrimes statep->status = STAT_WAITMUTEX; 5021592Srgrimes /* Lock the mutex once. */ 5031592Srgrimes assert (pthread_mutex_lock (statep->cmd.mutex) == 0); 5041592Srgrimes 5051592Srgrimes /* Lock it again and capture the error. */ 5061592Srgrimes statep->ret = pthread_mutex_lock (statep->cmd.mutex); 5071592Srgrimes statep->status = 0; 5081592Srgrimes 5091592Srgrimes assert (pthread_mutex_unlock (statep->cmd.mutex) == 0); 5101592Srgrimes 5111592Srgrimes /* Unlock it again if it is locked recursively. */ 5121592Srgrimes if (statep->ret == 0) 5131592Srgrimes pthread_mutex_unlock (statep->cmd.mutex); 5141592Srgrimes 5151592Srgrimes log_trace ("Thread %d: Exiting thread 0x%x\n", (int) statep->id, 5161592Srgrimes (int) pthread_self()); 5171592Srgrimes pthread_exit (arg); 5181592Srgrimes return (NULL); 5191592Srgrimes} 5201592Srgrimes 5211592Srgrimes 5221592Srgrimesstatic void 5231592Srgrimessighandler (int signo) 5241592Srgrimes{ 5251592Srgrimes log ("Signal handler caught signal %d, thread id 0x%x\n", 5261592Srgrimes signo, (int) pthread_self()); 5271592Srgrimes 5281592Srgrimes if (signo == SIGINT) 5291592Srgrimes done = 1; 5301592Srgrimes} 5311592Srgrimes 5321592Srgrimes 5331592Srgrimesstatic void 5341592Srgrimessend_cmd (int id, thread_cmd_id_t cmd) 5351592Srgrimes{ 5361592Srgrimes assert (pthread_mutex_lock (&cond_mutex) == 0); 5371592Srgrimes assert (states[id].status == STAT_WAITCONDVAR); 5381592Srgrimes states[id].cmd.cmd_id = cmd; 5391592Srgrimes states[id].cmd.mutex = NULL; 5401592Srgrimes states[id].cmd.cond = NULL; 5411592Srgrimes /* Clear the busy flags. */ 5421592Srgrimes states[id].flags &= ~(FLAGS_WAS_BUSY | FLAGS_IS_BUSY); 5431592Srgrimes assert (pthread_cond_signal (&states[id].cond_var) == 0); 5441592Srgrimes assert (pthread_mutex_unlock (&cond_mutex) == 0); 5451592Srgrimes} 5461592Srgrimes 5471592Srgrimes 5481592Srgrimesstatic void 5491592Srgrimessend_mutex_cmd (int id, thread_cmd_id_t cmd, pthread_mutex_t *m) 5501592Srgrimes{ 5511592Srgrimes assert (pthread_mutex_lock (&cond_mutex) == 0); 5521592Srgrimes assert (states[id].status == STAT_WAITCONDVAR); 5531592Srgrimes states[id].cmd.cmd_id = cmd; 5541592Srgrimes states[id].cmd.mutex = m; 5551592Srgrimes states[id].cmd.cond = NULL; 5561592Srgrimes /* Clear the busy flags. */ 5571592Srgrimes states[id].flags &= ~(FLAGS_WAS_BUSY | FLAGS_IS_BUSY); 5581592Srgrimes assert (pthread_cond_signal (&states[id].cond_var) == 0); 5591592Srgrimes assert (pthread_mutex_unlock (&cond_mutex) == 0); 5601592Srgrimes} 5611592Srgrimes 5621592Srgrimes 5631592Srgrimesstatic void 5641592Srgrimessend_mutex_cv_cmd (int id, thread_cmd_id_t cmd, pthread_mutex_t *m, 5651592Srgrimes pthread_cond_t *cv) 5661592Srgrimes{ 5671592Srgrimes assert (pthread_mutex_lock (&cond_mutex) == 0); 5681592Srgrimes assert (states[id].status == STAT_WAITCONDVAR); 5691592Srgrimes states[id].cmd.cmd_id = cmd; 5701592Srgrimes states[id].cmd.mutex = m; 5711592Srgrimes states[id].cmd.cond = cv; 5721592Srgrimes /* Clear the busy flags. */ 5731592Srgrimes states[id].flags &= ~(FLAGS_WAS_BUSY | FLAGS_IS_BUSY); 5741592Srgrimes assert (pthread_cond_signal (&states[id].cond_var) == 0); 5751592Srgrimes assert (pthread_mutex_unlock (&cond_mutex) == 0); 5761592Srgrimes} 5771592Srgrimes 5781592Srgrimes 5791592Srgrimesstatic void 5801592Srgrimesmutex_init_test (void) 5811592Srgrimes{ 5821592Srgrimes pthread_mutexattr_t mattr; 5831592Srgrimes pthread_mutex_t mutex; 5841592Srgrimes mutex_kind_t mkind; 5851592Srgrimes int mproto, ret; 5861592Srgrimes 5871592Srgrimes /* 5881592Srgrimes * Initialize a mutex attribute. 5891592Srgrimes * 5901592Srgrimes * pthread_mutexattr_init not tested for: ENOMEM 5911592Srgrimes */ 5921592Srgrimes assert (pthread_mutexattr_init (&mattr) == 0); 5931592Srgrimes 5941592Srgrimes /* 5951592Srgrimes * Initialize a mutex. 5961592Srgrimes * 5971592Srgrimes * pthread_mutex_init not tested for: EAGAIN ENOMEM EPERM EBUSY 5981592Srgrimes */ 5991592Srgrimes log ("Testing pthread_mutex_init\n"); 6001592Srgrimes log ("--------------------------\n"); 6011592Srgrimes 6021592Srgrimes for (mproto = 0; mproto < NELEMENTS(protocols); mproto++) { 6031592Srgrimes for (mkind = M_POSIX; mkind <= M_SS2_RECURSIVE; mkind++) { 6041592Srgrimes /* Initialize the mutex attribute. */ 6051592Srgrimes assert (pthread_mutexattr_init (&mattr) == 0); 6061592Srgrimes assert (pthread_mutexattr_setprotocol (&mattr, 6071592Srgrimes protocols[mproto]) == 0); 6081592Srgrimes 6091592Srgrimes /* 6101592Srgrimes * Ensure that the first mutex type is a POSIX 6111592Srgrimes * compliant mutex. 6121592Srgrimes */ 6131592Srgrimes if (mkind != M_POSIX) { 6141592Srgrimes assert (pthread_mutexattr_settype (&mattr, 6151592Srgrimes mutex_types[mkind]) == 0); 6161592Srgrimes } 6171592Srgrimes 6181592Srgrimes log (" Protocol %s, Type %s - ", 6191592Srgrimes protocol_strs[mproto], mutextype_strs[mkind]); 6201592Srgrimes ret = pthread_mutex_init (&mutex, &mattr); 6211592Srgrimes check_result (/* expected */ 0, ret); 6221592Srgrimes assert (pthread_mutex_destroy (&mutex) == 0); 6231592Srgrimes 6241592Srgrimes /* 6251592Srgrimes * Destroy a mutex attribute. 6261592Srgrimes * 6271592Srgrimes * XXX - There should probably be a magic number 6281592Srgrimes * associated with a mutex attribute so that 6291592Srgrimes * destroy can be reasonably sure the attribute 6301592Srgrimes * is valid. 6311592Srgrimes * 6321592Srgrimes * pthread_mutexattr_destroy not tested for: EINVAL 6331592Srgrimes */ 6341592Srgrimes assert (pthread_mutexattr_destroy (&mattr) == 0); 6351592Srgrimes } 6361592Srgrimes } 6371592Srgrimes} 6381592Srgrimes 6391592Srgrimes 6401592Srgrimesstatic void 6411592Srgrimesmutex_destroy_test (void) 6421592Srgrimes{ 6431592Srgrimes pthread_mutexattr_t mattr; 6441592Srgrimes pthread_mutex_t mutex; 6451592Srgrimes pthread_condattr_t cattr; 6461592Srgrimes pthread_cond_t cv; 6471592Srgrimes pthread_attr_t pattr; 6481592Srgrimes int mproto, ret; 6491592Srgrimes mutex_kind_t mkind; 6501592Srgrimes thread_state_t state; 6511592Srgrimes 6521592Srgrimes /* 6531592Srgrimes * Destroy a mutex. 6541592Srgrimes * 6551592Srgrimes * XXX - There should probably be a magic number associated 6561592Srgrimes * with a mutex so that destroy can be reasonably sure 6571592Srgrimes * the mutex is valid. 6581592Srgrimes * 6591592Srgrimes * pthread_mutex_destroy not tested for: 6601592Srgrimes */ 6611592Srgrimes log ("Testing pthread_mutex_destroy\n"); 6621592Srgrimes log ("-----------------------------\n"); 6631592Srgrimes 6641592Srgrimes assert (pthread_attr_init (&pattr) == 0); 6651592Srgrimes assert (pthread_attr_setdetachstate (&pattr, 6661592Srgrimes PTHREAD_CREATE_DETACHED) == 0); 6671592Srgrimes state.flags = 0; /* No flags yet. */ 6681592Srgrimes 6691592Srgrimes for (mproto = 0; mproto < NELEMENTS(protocols); mproto++) { 6701592Srgrimes for (mkind = M_POSIX; mkind <= M_SS2_RECURSIVE; mkind++) { 6711592Srgrimes /* Initialize the mutex attribute. */ 6721592Srgrimes assert (pthread_mutexattr_init (&mattr) == 0); 6731592Srgrimes assert (pthread_mutexattr_setprotocol (&mattr, 6741592Srgrimes protocols[mproto]) == 0); 6751592Srgrimes 6761592Srgrimes /* 6771592Srgrimes * Ensure that the first mutex type is a POSIX 6781592Srgrimes * compliant mutex. 6791592Srgrimes */ 6801592Srgrimes if (mkind != M_POSIX) { 6811592Srgrimes assert (pthread_mutexattr_settype (&mattr, 6821592Srgrimes mutex_types[mkind]) == 0); 6831592Srgrimes } 6841592Srgrimes 68517435Spst /* Create the mutex. */ 68617435Spst assert (pthread_mutex_init (&mutex, &mattr) == 0); 68717435Spst 6881592Srgrimes log (" Protocol %s, Type %s\n", 6891592Srgrimes protocol_strs[mproto], mutextype_strs[mkind]); 6901592Srgrimes 6911592Srgrimes log (" Destruction of unused mutex - "); 6921592Srgrimes assert (pthread_mutex_init (&mutex, &mattr) == 0); 6931592Srgrimes ret = pthread_mutex_destroy (&mutex); 6941592Srgrimes check_result (/* expected */ 0, ret); 6951592Srgrimes 6961592Srgrimes log (" Destruction of mutex locked by self - "); 6971592Srgrimes assert (pthread_mutex_init (&mutex, &mattr) == 0); 6981592Srgrimes assert (pthread_mutex_lock (&mutex) == 0); 6991592Srgrimes ret = pthread_mutex_destroy (&mutex); 7001592Srgrimes check_result (/* expected */ EBUSY, ret); 7011592Srgrimes assert (pthread_mutex_unlock (&mutex) == 0); 7021592Srgrimes assert (pthread_mutex_destroy (&mutex) == 0); 7031592Srgrimes 7041592Srgrimes log (" Destruction of mutex locked by another " 7051592Srgrimes "thread - "); 7061592Srgrimes assert (pthread_mutex_init (&mutex, &mattr) == 0); 7071592Srgrimes send_mutex_cmd (0, CMD_TAKE_MUTEX, &mutex); 7081592Srgrimes sleep (1); 7091592Srgrimes ret = pthread_mutex_destroy (&mutex); 7101592Srgrimes check_result (/* expected */ EBUSY, ret); 7111592Srgrimes send_cmd (0, CMD_RELEASE_ALL); 7121592Srgrimes sleep (1); 7131592Srgrimes assert (pthread_mutex_destroy (&mutex) == 0); 7141592Srgrimes 7151592Srgrimes log (" Destruction of mutex while being used in " 7161592Srgrimes "cond_wait - "); 7171592Srgrimes assert (pthread_mutex_init (&mutex, &mattr) == 0); 7181592Srgrimes assert (pthread_condattr_init (&cattr) == 0); 7191592Srgrimes assert (pthread_cond_init (&cv, &cattr) == 0); 7201592Srgrimes send_mutex_cv_cmd (0, CMD_WAIT_FOR_SIGNAL, &mutex, &cv); 7211592Srgrimes sleep (1); 7221592Srgrimes ret = pthread_mutex_destroy (&mutex); 7231592Srgrimes check_result (/* expected */ EBUSY, ret); 7241592Srgrimes pthread_cond_signal (&cv); 7251592Srgrimes sleep (1); 7261592Srgrimes assert (pthread_mutex_destroy (&mutex) == 0); 7271592Srgrimes } 7281592Srgrimes } 7291592Srgrimes} 7301592Srgrimes 7311592Srgrimes 7321592Srgrimesstatic void 7331592Srgrimesmutex_lock_test (void) 7341592Srgrimes{ 7351592Srgrimes pthread_mutexattr_t mattr; 7361592Srgrimes pthread_mutex_t mutex; 7371592Srgrimes pthread_attr_t pattr; 7381592Srgrimes int mproto, ret; 7391592Srgrimes mutex_kind_t mkind; 7401592Srgrimes thread_state_t state; 7411592Srgrimes 7421592Srgrimes /* 7431592Srgrimes * Lock a mutex. 7441592Srgrimes * 7451592Srgrimes * pthread_lock not tested for: 7461592Srgrimes */ 7471592Srgrimes log ("Testing pthread_mutex_lock\n"); 74856668Sshin log ("--------------------------\n"); 74956668Sshin 75056668Sshin assert (pthread_attr_init (&pattr) == 0); 75117435Spst assert (pthread_attr_setdetachstate (&pattr, 75256668Sshin PTHREAD_CREATE_DETACHED) == 0); 7531592Srgrimes state.flags = 0; /* No flags yet. */ 7541592Srgrimes 7551592Srgrimes for (mproto = 0; mproto < NELEMENTS(protocols); mproto++) { 7561592Srgrimes for (mkind = M_POSIX; mkind <= M_SS2_RECURSIVE; mkind++) { 75756668Sshin /* Initialize the mutex attribute. */ 75856668Sshin assert (pthread_mutexattr_init (&mattr) == 0); 75956668Sshin assert (pthread_mutexattr_setprotocol (&mattr, 76056668Sshin protocols[mproto]) == 0); 76156668Sshin 76256668Sshin /* 76356668Sshin * Ensure that the first mutex type is a POSIX 76456668Sshin * compliant mutex. 76556668Sshin */ 76656668Sshin if (mkind != M_POSIX) { 76756668Sshin assert (pthread_mutexattr_settype (&mattr, 76856668Sshin mutex_types[mkind]) == 0); 76956668Sshin } 77056668Sshin 77156668Sshin /* Create the mutex. */ 77256668Sshin assert (pthread_mutex_init (&mutex, &mattr) == 0); 77356668Sshin 77456668Sshin log (" Protocol %s, Type %s\n", 77556668Sshin protocol_strs[mproto], mutextype_strs[mkind]); 77656668Sshin 77756668Sshin log (" Lock on unlocked mutex - "); 77856668Sshin ret = pthread_mutex_lock (&mutex); 77956668Sshin check_result (/* expected */ 0, ret); 78056668Sshin pthread_mutex_unlock (&mutex); 78156668Sshin 78256668Sshin log (" Lock on invalid mutex - "); 78356668Sshin ret = pthread_mutex_lock (NULL); 78456668Sshin check_result (/* expected */ EINVAL, ret); 78556668Sshin 78656668Sshin log (" Lock on mutex held by self - "); 78756668Sshin assert (pthread_create (&state.tid, &pattr, lock_twice, 78856668Sshin (void *) &state) == 0); 78956668Sshin /* Let the thread start. */ 79056668Sshin sleep (1); 79156668Sshin state.cmd.mutex = &mutex; 79256668Sshin state.ret = 0xdeadbeef; 79356668Sshin assert (pthread_mutex_lock (&cond_mutex) == 0); 79456668Sshin assert (pthread_cond_signal (&cond_var) == 0); 79556668Sshin assert (pthread_mutex_unlock (&cond_mutex) == 0); 79656668Sshin /* Let the thread receive and process the command. */ 79756668Sshin sleep (1); 79856668Sshin 79956668Sshin switch (mkind) { 80056668Sshin case M_POSIX: 80156668Sshin check_result (/* expected */ EDEADLK, 80256668Sshin state.ret); 8031592Srgrimes break; 8041592Srgrimes case M_SS2_DEFAULT: 8051592Srgrimes check_result (/* expected */ EDEADLK, 8061592Srgrimes state.ret); 8071592Srgrimes break; 8081592Srgrimes case M_SS2_ERRORCHECK: 8091592Srgrimes check_result (/* expected */ EDEADLK, 8101592Srgrimes state.ret); 8111592Srgrimes break; 8121592Srgrimes case M_SS2_NORMAL: 8131592Srgrimes check_result (/* expected */ 0xdeadbeef, 8141592Srgrimes state.ret); 8151592Srgrimes break; 8161592Srgrimes case M_SS2_RECURSIVE: 8171592Srgrimes check_result (/* expected */ 0, state.ret); 8181592Srgrimes break; 8191592Srgrimes } 8201592Srgrimes pthread_mutex_destroy (&mutex); 8211592Srgrimes pthread_mutexattr_destroy (&mattr); 8221592Srgrimes } 8231592Srgrimes } 8241592Srgrimes} 8251592Srgrimes 8261592Srgrimes 8271592Srgrimesstatic void 8281592Srgrimesmutex_unlock_test (void) 8291592Srgrimes{ 8301592Srgrimes const int test_thread_id = 0; /* ID of test thread */ 8311592Srgrimes pthread_mutexattr_t mattr; 8321592Srgrimes pthread_mutex_t mutex; 8331592Srgrimes int mproto, ret; 8341592Srgrimes mutex_kind_t mkind; 8351592Srgrimes 8361592Srgrimes /* 8371592Srgrimes * Unlock a mutex. 8381592Srgrimes * 8391592Srgrimes * pthread_unlock not tested for: 8401592Srgrimes */ 8411592Srgrimes log ("Testing pthread_mutex_unlock\n"); 8421592Srgrimes log ("----------------------------\n"); 8431592Srgrimes 8441592Srgrimes for (mproto = 0; mproto < NELEMENTS(protocols); mproto++) { 8451592Srgrimes for (mkind = M_POSIX; mkind <= M_SS2_RECURSIVE; mkind++) { 8461592Srgrimes /* Initialize the mutex attribute. */ 8471592Srgrimes assert (pthread_mutexattr_init (&mattr) == 0); 8481592Srgrimes assert (pthread_mutexattr_setprotocol (&mattr, 8491592Srgrimes protocols[mproto]) == 0); 8501592Srgrimes 8511592Srgrimes /* 8521592Srgrimes * Ensure that the first mutex type is a POSIX 8531592Srgrimes * compliant mutex. 8541592Srgrimes */ 8551592Srgrimes if (mkind != M_POSIX) { 8561592Srgrimes assert (pthread_mutexattr_settype (&mattr, 8571592Srgrimes mutex_types[mkind]) == 0); 8581592Srgrimes } 8591592Srgrimes 8601592Srgrimes /* Create the mutex. */ 8611592Srgrimes assert (pthread_mutex_init (&mutex, &mattr) == 0); 8621592Srgrimes 8631592Srgrimes log (" Protocol %s, Type %s\n", 8641592Srgrimes protocol_strs[mproto], mutextype_strs[mkind]); 8651592Srgrimes 8661592Srgrimes log (" Unlock on mutex held by self - "); 8671592Srgrimes assert (pthread_mutex_lock (&mutex) == 0); 8681592Srgrimes ret = pthread_mutex_unlock (&mutex); 8691592Srgrimes check_result (/* expected */ 0, ret); 8701592Srgrimes 8711592Srgrimes log (" Unlock on invalid mutex - "); 8721592Srgrimes ret = pthread_mutex_unlock (NULL); 8731592Srgrimes check_result (/* expected */ EINVAL, ret); 8741592Srgrimes 8751592Srgrimes log (" Unlock on mutex locked by another thread - "); 8761592Srgrimes send_mutex_cmd (test_thread_id, CMD_TAKE_MUTEX, &mutex); 8771592Srgrimes sleep (1); 8781592Srgrimes ret = pthread_mutex_unlock (&mutex); 8791592Srgrimes switch (mkind) { 8801592Srgrimes case M_POSIX: 8811592Srgrimes check_result (/* expected */ EPERM, ret); 8821592Srgrimes break; 8831592Srgrimes case M_SS2_DEFAULT: 8841592Srgrimes check_result (/* expected */ EPERM, ret); 8851592Srgrimes break; 8861592Srgrimes case M_SS2_ERRORCHECK: 8871592Srgrimes check_result (/* expected */ EPERM, ret); 8881592Srgrimes break; 8891592Srgrimes case M_SS2_NORMAL: 8901592Srgrimes check_result (/* expected */ EPERM, ret); 8911592Srgrimes break; 8921592Srgrimes case M_SS2_RECURSIVE: 8931592Srgrimes check_result (/* expected */ EPERM, ret); 8941592Srgrimes break; 8951592Srgrimes } 8961592Srgrimes if (ret == 0) { 8971592Srgrimes /* 8981592Srgrimes * If for some reason we were able to unlock 8991592Srgrimes * the mutex, relock it so that the test 9001592Srgrimes * thread has no problems releasing the mutex. 9011592Srgrimes */ 9021592Srgrimes pthread_mutex_lock (&mutex); 9031592Srgrimes } 9041592Srgrimes send_cmd (test_thread_id, CMD_RELEASE_ALL); 9051592Srgrimes sleep (1); 9061592Srgrimes 9071592Srgrimes pthread_mutex_destroy (&mutex); 9081592Srgrimes pthread_mutexattr_destroy (&mattr); 9091592Srgrimes } 9101592Srgrimes } 9111592Srgrimes} 9121592Srgrimes 9131592Srgrimes 9141592Srgrimesstatic void 9151592Srgrimesqueueing_order_test (void) 9161592Srgrimes{ 9171592Srgrimes int i; 9181592Srgrimes 9191592Srgrimes log ("Testing queueing order\n"); 9201592Srgrimes log ("----------------------\n"); 9211592Srgrimes assert (pthread_mutex_lock (&waiter_mutex) == 0); 9221592Srgrimes /* 9231592Srgrimes * Tell the threads to report when they take the waiters mutex. 9241592Srgrimes */ 9251592Srgrimes assert (pthread_mutex_lock (&cond_mutex) == 0); 9261592Srgrimes for (i = 0; i < NUM_THREADS; i++) { 9271592Srgrimes states[i].flags = FLAGS_REPORT_WAITMUTEX; 9281592Srgrimes assert (pthread_cond_signal (&states[i].cond_var) == 0); 9291592Srgrimes } 9301592Srgrimes assert (pthread_mutex_unlock (&cond_mutex) == 0); 9311592Srgrimes 9321592Srgrimes /* Signal the threads to continue. */ 9331592Srgrimes sleep (1); 9341592Srgrimes 9351592Srgrimes /* Use the global condition variable next time. */ 9361592Srgrimes use_global_condvar = 1; 9371592Srgrimes 9381592Srgrimes /* Release the waiting threads and allow them to run again. */ 9391592Srgrimes assert (pthread_mutex_unlock (&waiter_mutex) == 0); 9401592Srgrimes sleep (1); 9411592Srgrimes 9421592Srgrimes log (" Queueing order on a mutex - "); 9431592Srgrimes check_run_order ("9,8,7,6,5,4,3,2,1,0"); 9441592Srgrimes for (i = 0; i < NUM_THREADS; i = i + 1) { 9451592Srgrimes /* Tell the threads to report when they've been signaled. */ 9461592Srgrimes states[i].flags = FLAGS_REPORT_WAITCONDVAR; 9471592Srgrimes } 9481592Srgrimes 9491592Srgrimes /* 9501592Srgrimes * Prevent the threads from continuing their loop after we 9511592Srgrimes * signal them. 9521592Srgrimes */ 9531592Srgrimes assert (pthread_mutex_lock (&waiter_mutex) == 0); 9541592Srgrimes 9551592Srgrimes 9561592Srgrimes log (" Queueing order on a condition variable - "); 9571592Srgrimes /* 9581592Srgrimes * Signal one thread to run and see that the highest priority 9591592Srgrimes * thread executes. 9601592Srgrimes */ 9611592Srgrimes assert (pthread_mutex_lock (&cond_mutex) == 0); 9621592Srgrimes assert (pthread_cond_signal (&cond_var) == 0); 9631592Srgrimes assert (pthread_mutex_unlock (&cond_mutex) == 0); 9641592Srgrimes sleep (1); 9651592Srgrimes if (states[NUM_THREADS - 1].status != STAT_WAITMUTEX) 9661592Srgrimes log_error ("highest priority thread does not run.\n"); 9671592Srgrimes 9681592Srgrimes /* Signal the remaining threads. */ 9691592Srgrimes assert (pthread_mutex_lock (&cond_mutex) == 0); 9701592Srgrimes assert (pthread_cond_broadcast (&cond_var) == 0); 9711592Srgrimes assert (pthread_mutex_unlock (&cond_mutex) == 0); 9721592Srgrimes sleep (1); 9731592Srgrimes 9741592Srgrimes check_run_order ("9,8,7,6,5,4,3,2,1,0"); 9751592Srgrimes for (i = 0; i < NUM_THREADS; i = i + 1) { 9761592Srgrimes /* Tell the threads not to report anything. */ 9771592Srgrimes states[i].flags = 0; 9781592Srgrimes } 9791592Srgrimes 9801592Srgrimes /* Use the thread unique condition variable next time. */ 9811592Srgrimes use_global_condvar = 0; 9821592Srgrimes 9831592Srgrimes /* Allow the threads to continue their loop. */ 9841592Srgrimes assert (pthread_mutex_unlock (&waiter_mutex) == 0); 9851592Srgrimes sleep (1); 9861592Srgrimes} 9871592Srgrimes 9881592Srgrimes 9891592Srgrimesstatic void 9901592Srgrimesmutex_prioceiling_test (void) 9911592Srgrimes{ 99256668Sshin const int test_thread_id = 0; /* ID of test thread */ 99356668Sshin pthread_mutexattr_t mattr; 9941592Srgrimes struct sched_param param; 99556668Sshin pthread_mutex_t m[3]; 99656668Sshin mutex_kind_t mkind; 9971592Srgrimes int i, ret, policy, my_prio, old_ceiling; 9981592Srgrimes 9991592Srgrimes log ("Testing priority ceilings\n"); 10001592Srgrimes log ("-------------------------\n"); 10011592Srgrimes for (mkind = M_POSIX; mkind <= M_SS2_RECURSIVE; mkind++) { 10021592Srgrimes 10031592Srgrimes log (" Protype PTHREAD_PRIO_PROTECT, Type %s\n", 10041592Srgrimes mutextype_strs[mkind]); 10051592Srgrimes 10061592Srgrimes /* 10071592Srgrimes * Initialize and create a mutex. 10081592Srgrimes */ 10091592Srgrimes assert (pthread_mutexattr_init (&mattr) == 0); 10101592Srgrimes 10111592Srgrimes /* Get this threads current priority. */ 10121592Srgrimes assert (pthread_getschedparam (pthread_self(), &policy, 10131592Srgrimes ¶m) == 0); 10141592Srgrimes my_prio = param.sched_priority; /* save for later use */ 10151592Srgrimes log_trace ("Current scheduling policy %d, priority %d\n", 10161592Srgrimes policy, my_prio); 10171592Srgrimes 10181592Srgrimes /* 10191592Srgrimes * Initialize and create 3 priority protection mutexes with 10201592Srgrimes * default (max priority) ceilings. 10211592Srgrimes */ 10221592Srgrimes assert (pthread_mutexattr_setprotocol(&mattr, 10231592Srgrimes PTHREAD_PRIO_PROTECT) == 0); 10241592Srgrimes 10251592Srgrimes /* 10261592Srgrimes * Ensure that the first mutex type is a POSIX 10271592Srgrimes * compliant mutex. 10281592Srgrimes */ 10291592Srgrimes if (mkind != M_POSIX) { 10301592Srgrimes assert (pthread_mutexattr_settype (&mattr, 10311592Srgrimes mutex_types[mkind]) == 0); 10321592Srgrimes } 10331592Srgrimes 10341592Srgrimes for (i = 0; i < 3; i++) 10351592Srgrimes assert (pthread_mutex_init (&m[i], &mattr) == 0); 10361592Srgrimes 10371592Srgrimes /* 10381592Srgrimes * Set the ceiling priorities for the 3 priority protection 10391592Srgrimes * mutexes to, 5 less than, equal to, and 5 greater than, 10401592Srgrimes * this threads current priority. 10411592Srgrimes */ 10421592Srgrimes for (i = 0; i < 3; i++) 10431592Srgrimes assert (pthread_mutex_setprioceiling (&m[i], 10441592Srgrimes my_prio - 5 + 5*i, &old_ceiling) == 0); 10451592Srgrimes 10461592Srgrimes /* 10471592Srgrimes * Check that if we attempt to take a mutex whose priority 10481592Srgrimes * ceiling is lower than our priority, we get an error. 10491592Srgrimes */ 10501592Srgrimes log (" Lock with ceiling priority < thread priority - "); 105156668Sshin ret = pthread_mutex_lock (&m[0]); 105256668Sshin check_result (/* expected */ EINVAL, ret); 10531592Srgrimes if (ret == 0) 10541592Srgrimes pthread_mutex_unlock (&m[0]); 105556668Sshin 10561592Srgrimes /* 10571592Srgrimes * Check that we can take a mutex whose priority ceiling 10581592Srgrimes * is equal to our priority. 10591592Srgrimes */ 10601592Srgrimes log (" Lock with ceiling priority = thread priority - "); 10611592Srgrimes ret = pthread_mutex_lock (&m[1]); 10621592Srgrimes check_result (/* expected */ 0, ret); 10631592Srgrimes if (ret == 0) 10641592Srgrimes pthread_mutex_unlock (&m[1]); 10651592Srgrimes 10661592Srgrimes /* 10671592Srgrimes * Check that we can take a mutex whose priority ceiling 10681592Srgrimes * is higher than our priority. 10691592Srgrimes */ 10701592Srgrimes log (" Lock with ceiling priority > thread priority - "); 10711592Srgrimes ret = pthread_mutex_lock (&m[2]); 10721592Srgrimes check_result (/* expected */ 0, ret); 10731592Srgrimes if (ret == 0) 10741592Srgrimes pthread_mutex_unlock (&m[2]); 10751592Srgrimes 10761592Srgrimes /* 10771592Srgrimes * Have the test thread go into a busy loop for 5 seconds 10781592Srgrimes * and see that it doesn't block this thread (since the 10791592Srgrimes * priority ceiling of mutex 0 and the priority of the test 10801592Srgrimes * thread are both less than the priority of this thread). 10811592Srgrimes */ 10821592Srgrimes log (" Preemption with ceiling priority < thread " 10831592Srgrimes "priority - "); 10841592Srgrimes /* Have the test thread take mutex 0. */ 10851592Srgrimes send_mutex_cmd (test_thread_id, CMD_TAKE_MUTEX, &m[0]); 10861592Srgrimes sleep (1); 10871592Srgrimes 10881592Srgrimes log_trace ("Sending busy command.\n"); 10891592Srgrimes send_cmd (test_thread_id, CMD_BUSY_LOOP); 10901592Srgrimes log_trace ("Busy sent, yielding\n"); 10911592Srgrimes pthread_yield (); 10921592Srgrimes log_trace ("Returned from yield.\n"); 10931592Srgrimes if (states[test_thread_id].flags & 10941592Srgrimes (FLAGS_IS_BUSY | FLAGS_WAS_BUSY)) 10951592Srgrimes log_error ("test thread inproperly preempted us.\n"); 10961592Srgrimes else { 10971592Srgrimes /* Let the thread finish its busy loop. */ 10981592Srgrimes sleep (6); 10991592Srgrimes if ((states[test_thread_id].flags & FLAGS_WAS_BUSY) == 0) 11001592Srgrimes log_error ("test thread never finished.\n"); 11011592Srgrimes else 11021592Srgrimes log_pass (); 11031592Srgrimes } 11041592Srgrimes states[test_thread_id].flags &= ~FLAGS_WAS_BUSY; 11051592Srgrimes 11061592Srgrimes /* Have the test thread release mutex 0. */ 11071592Srgrimes send_cmd (test_thread_id, CMD_RELEASE_ALL); 11081592Srgrimes sleep (1); 11091592Srgrimes 11101592Srgrimes /* 11111592Srgrimes * Have the test thread go into a busy loop for 5 seconds 11121592Srgrimes * and see that it preempts this thread (since the priority 11131592Srgrimes * ceiling of mutex 1 is the same as the priority of this 11141592Srgrimes * thread). The test thread should not run to completion 11151592Srgrimes * as its time quantum should expire before the 5 seconds 11161592Srgrimes * are up. 11171592Srgrimes */ 11181592Srgrimes log (" Preemption with ceiling priority = thread " 11191592Srgrimes "priority - "); 11201592Srgrimes 11211592Srgrimes /* Have the test thread take mutex 1. */ 11221592Srgrimes send_mutex_cmd (test_thread_id, CMD_TAKE_MUTEX, &m[1]); 11231592Srgrimes sleep (1); 11241592Srgrimes 11251592Srgrimes log_trace ("Sending busy\n"); 11261592Srgrimes send_cmd (test_thread_id, CMD_BUSY_LOOP); 11271592Srgrimes log_trace ("Busy sent, yielding\n"); 11281592Srgrimes pthread_yield (); 11291592Srgrimes log_trace ("Returned from yield.\n"); 11301592Srgrimes if ((states[test_thread_id].flags & FLAGS_IS_BUSY) == 0) 11311592Srgrimes log_error ("test thread did not switch in on yield.\n"); 11321592Srgrimes else if (states[test_thread_id].flags & FLAGS_WAS_BUSY) 11331592Srgrimes log_error ("test thread ran to completion.\n"); 11341592Srgrimes else { 11351592Srgrimes /* Let the thread finish its busy loop. */ 11361592Srgrimes sleep (6); 11371592Srgrimes if ((states[test_thread_id].flags & FLAGS_WAS_BUSY) == 0) 11381592Srgrimes log_error ("test thread never finished.\n"); 11391592Srgrimes else 11401592Srgrimes log_pass (); 11411592Srgrimes } 11421592Srgrimes states[test_thread_id].flags &= ~FLAGS_WAS_BUSY; 11431592Srgrimes 11441592Srgrimes /* Have the test thread release mutex 1. */ 11451592Srgrimes send_cmd (test_thread_id, CMD_RELEASE_ALL); 11461592Srgrimes sleep (1); 11471592Srgrimes 11481592Srgrimes /* 11491592Srgrimes * Set the scheduling policy of the test thread to SCHED_FIFO 11501592Srgrimes * and have it go into a busy loop for 5 seconds. This 11511592Srgrimes * thread is SCHED_RR, and since the priority ceiling of 11521592Srgrimes * mutex 1 is the same as the priority of this thread, the 11531592Srgrimes * test thread should run to completion once it is switched 11541592Srgrimes * in. 11551592Srgrimes */ 11561592Srgrimes log (" SCHED_FIFO scheduling and ceiling priority = " 11571592Srgrimes "thread priority - "); 11581592Srgrimes param.sched_priority = states[test_thread_id].priority; 11591592Srgrimes assert (pthread_setschedparam (states[test_thread_id].tid, 11601592Srgrimes SCHED_FIFO, ¶m) == 0); 11611592Srgrimes 11621592Srgrimes /* Have the test thread take mutex 1. */ 11631592Srgrimes send_mutex_cmd (test_thread_id, CMD_TAKE_MUTEX, &m[1]); 11641592Srgrimes sleep (1); 11651592Srgrimes 11661592Srgrimes log_trace ("Sending busy\n"); 11671592Srgrimes send_cmd (test_thread_id, CMD_BUSY_LOOP); 11681592Srgrimes log_trace ("Busy sent, yielding\n"); 11691592Srgrimes pthread_yield (); 11701592Srgrimes log_trace ("Returned from yield.\n"); 11711592Srgrimes if ((states[test_thread_id].flags & FLAGS_WAS_BUSY) == 0) { 11721592Srgrimes log_error ("test thread did not run to completion.\n"); 11731592Srgrimes /* Let the thread finish it's busy loop. */ 11741592Srgrimes sleep (6); 11751592Srgrimes } 11761592Srgrimes else 11771592Srgrimes log_pass (); 11781592Srgrimes states[test_thread_id].flags &= ~FLAGS_WAS_BUSY; 11791592Srgrimes 11801592Srgrimes /* Restore the test thread scheduling parameters. */ 11811592Srgrimes param.sched_priority = states[test_thread_id].priority; 11821592Srgrimes assert (pthread_setschedparam (states[test_thread_id].tid, 11831592Srgrimes SCHED_RR, ¶m) == 0); 11841592Srgrimes 118529574Sphk /* Have the test thread release mutex 1. */ 11861592Srgrimes send_cmd (test_thread_id, CMD_RELEASE_ALL); 11871592Srgrimes sleep (1); 11881592Srgrimes 11891592Srgrimes /* 11901592Srgrimes * Have the test thread go into a busy loop for 5 seconds 11911592Srgrimes * and see that it preempts this thread (since the priority 11921592Srgrimes * ceiling of mutex 2 is the greater than the priority of 11931592Srgrimes * this thread). The test thread should run to completion 11941592Srgrimes * and block this thread because its active priority is 11951592Srgrimes * higher. 11961592Srgrimes */ 11971592Srgrimes log (" SCHED_FIFO scheduling and ceiling priority > " 11981592Srgrimes "thread priority - "); 11991592Srgrimes /* Have the test thread take mutex 2. */ 12001592Srgrimes send_mutex_cmd (test_thread_id, CMD_TAKE_MUTEX, &m[2]); 12013776Spst sleep (1); 12021592Srgrimes 12031592Srgrimes log_trace ("Sending busy\n"); 12041592Srgrimes send_cmd (test_thread_id, CMD_BUSY_LOOP); 12051592Srgrimes log_trace ("Busy sent, yielding\n"); 12061592Srgrimes pthread_yield (); 12071592Srgrimes log_trace ("Returned from yield.\n"); 12081592Srgrimes if ((states[test_thread_id].flags & FLAGS_IS_BUSY) != 0) { 12091592Srgrimes log_error ("test thread did not run to completion.\n"); 12101592Srgrimes /* Let the thread finish it's busy loop. */ 12111592Srgrimes sleep (6); 12121592Srgrimes } 12131592Srgrimes else if ((states[test_thread_id].flags & FLAGS_WAS_BUSY) == 0) 12141592Srgrimes log_error ("test thread never finished.\n"); 12151592Srgrimes else 12161592Srgrimes log_pass (); 12171592Srgrimes states[test_thread_id].flags &= ~FLAGS_WAS_BUSY; 12181592Srgrimes 12191592Srgrimes /* Have the test thread release mutex 2. */ 12201592Srgrimes send_cmd (test_thread_id, CMD_RELEASE_ALL); 12211592Srgrimes sleep (1); 12221592Srgrimes 12231592Srgrimes /* Destroy the mutexes. */ 12241592Srgrimes for (i = 0; i < 3; i++) 12251592Srgrimes assert (pthread_mutex_destroy (&m[i]) == 0); 12263777Spst } 12271592Srgrimes} 12281592Srgrimes 12291592Srgrimes 12301592Srgrimesstatic void 12311592Srgrimesmutex_prioinherit_test (void) 12321592Srgrimes{ 12331592Srgrimes pthread_mutexattr_t mattr; 12341592Srgrimes struct sched_param param; 12351592Srgrimes pthread_mutex_t m[3]; 12361592Srgrimes mutex_kind_t mkind; 12371592Srgrimes int i, policy, my_prio; 12381592Srgrimes 12391592Srgrimes /* Get this threads current priority. */ 12401592Srgrimes assert (pthread_getschedparam (pthread_self(), &policy, 12411592Srgrimes ¶m) == 0); 12421592Srgrimes my_prio = param.sched_priority; /* save for later use */ 12431592Srgrimes log_trace ("Current scheduling policy %d, priority %d\n", 12441592Srgrimes policy, my_prio); 12451592Srgrimes 12461592Srgrimes log ("Testing priority inheritence\n"); 12471592Srgrimes log ("----------------------------\n"); 12481592Srgrimes for (mkind = M_POSIX; mkind <= M_SS2_RECURSIVE; mkind++) { 12491592Srgrimes 12501592Srgrimes log (" Protype PTHREAD_PRIO_INHERIT, Type %s\n", 12511592Srgrimes mutextype_strs[mkind]); 125251979Salfred 12531592Srgrimes /* 12541592Srgrimes * Initialize and create a mutex. 12551592Srgrimes */ 12561592Srgrimes assert (pthread_mutexattr_init (&mattr) == 0); 12571592Srgrimes 12581592Srgrimes /* 12591592Srgrimes * Initialize and create 3 priority inheritence mutexes with 12601592Srgrimes * default (max priority) ceilings. 12611592Srgrimes */ 12621592Srgrimes assert (pthread_mutexattr_setprotocol(&mattr, 12631592Srgrimes PTHREAD_PRIO_INHERIT) == 0); 12641592Srgrimes 12651592Srgrimes /* 12661592Srgrimes * Ensure that the first mutex type is a POSIX 12671592Srgrimes * compliant mutex. 12681592Srgrimes */ 12691592Srgrimes if (mkind != M_POSIX) { 12701592Srgrimes assert (pthread_mutexattr_settype (&mattr, 12711592Srgrimes mutex_types[mkind]) == 0); 12721592Srgrimes } 12731592Srgrimes 12741592Srgrimes for (i = 0; i < 3; i++) 12751592Srgrimes assert (pthread_mutex_init (&m[i], &mattr) == 0); 12761592Srgrimes 12771592Srgrimes /* 12781592Srgrimes * Test setup: 12791592Srgrimes * Thread 4 - take mutex 0, 1 12801592Srgrimes * Thread 2 - enter protected busy loop with mutex 0 12811592Srgrimes * Thread 3 - enter protected busy loop with mutex 1 12821592Srgrimes * Thread 4 - enter protected busy loop with mutex 2 12831592Srgrimes * Thread 5 - enter busy loop 12841592Srgrimes * Thread 6 - enter protected busy loop with mutex 0 12851592Srgrimes * Thread 4 - releases mutexes 1 and 0. 12861592Srgrimes * 12871592Srgrimes * Expected results: 12881592Srgrimes * Threads complete in order 4, 6, 5, 3, 2 12891592Srgrimes */ 12901592Srgrimes log (" Simple inheritence test - "); 12911592Srgrimes 12921592Srgrimes /* 12931592Srgrimes * Command thread 4 to take mutexes 0 and 1. 12941592Srgrimes */ 12951592Srgrimes send_mutex_cmd (4, CMD_TAKE_MUTEX, &m[0]); 12961592Srgrimes sleep (1); /* Allow command to be received. */ 12971592Srgrimes send_mutex_cmd (4, CMD_TAKE_MUTEX, &m[1]); 12981592Srgrimes sleep (1); 12991592Srgrimes 13001592Srgrimes /* 13011592Srgrimes * Tell the threads to report themselves when they are 13021592Srgrimes * at the bottom of their loop (waiting on wait_mutex). 13031592Srgrimes */ 13041592Srgrimes for (i = 0; i < NUM_THREADS; i++) 13051592Srgrimes states[i].flags |= FLAGS_REPORT_WAITMUTEX; 13061592Srgrimes 13071592Srgrimes /* 13081592Srgrimes * Command thread 2 to take mutex 0 and thread 3 to take 13091592Srgrimes * mutex 1, both via a protected operation command. Since 131056668Sshin * thread 4 owns mutexes 0 and 1, both threads 2 and 3 131156668Sshin * will block until the mutexes are released by thread 4. 131256668Sshin */ 131356668Sshin log_trace ("Commanding protected operation to thread 2.\n"); 131456668Sshin send_mutex_cmd (2, CMD_PROTECTED_OP, &m[0]); 13151592Srgrimes log_trace ("Commanding protected operation to thread 3.\n"); 13161592Srgrimes send_mutex_cmd (3, CMD_PROTECTED_OP, &m[1]); 13171592Srgrimes sleep (1); 13181592Srgrimes 13191592Srgrimes /* 13201592Srgrimes * Command thread 4 to take mutex 2 via a protected operation 13211592Srgrimes * and thread 5 to enter a busy loop for 5 seconds. Since 13221592Srgrimes * thread 5 has higher priority than thread 4, thread 5 will 13231592Srgrimes * enter the busy loop before thread 4 is activated. 13241592Srgrimes */ 13251592Srgrimes log_trace ("Commanding protected operation to thread 4.\n"); 13261592Srgrimes send_mutex_cmd (4, CMD_PROTECTED_OP, &m[2]); 13271592Srgrimes log_trace ("Commanding busy loop to thread 5.\n"); 13281592Srgrimes send_cmd (5, CMD_BUSY_LOOP); 13291592Srgrimes sleep (1); 13301592Srgrimes if ((states[5].flags & FLAGS_IS_BUSY) == 0) 13311592Srgrimes log_error ("thread 5 is not running.\n"); 13321592Srgrimes log_trace ("Commanding protected operation thread 6.\n"); 13331592Srgrimes send_mutex_cmd (6, CMD_PROTECTED_OP, &m[0]); 13341592Srgrimes sleep (1); 13351592Srgrimes if ((states[4].flags & FLAGS_WAS_BUSY) == 0) 13361592Srgrimes log_error ("thread 4 failed to inherit priority.\n"); 13371592Srgrimes states[4].flags = 0; 13381592Srgrimes send_cmd (4, CMD_RELEASE_ALL); 13391592Srgrimes sleep (5); 13401592Srgrimes check_run_order ("4,6,5,3,2"); 13411592Srgrimes 13421592Srgrimes /* 13431592Srgrimes * Clear the flags. 13441592Srgrimes */ 13451592Srgrimes for (i = 0; i < NUM_THREADS; i++) 13461592Srgrimes states[i].flags = 0; 13471592Srgrimes 13481592Srgrimes /* 13491592Srgrimes * Test setup: 13501592Srgrimes * Thread 2 - enter busy loop (SCHED_FIFO) 13511592Srgrimes * Thread 4 - take mutex 0 13521592Srgrimes * Thread 4 - priority change to same priority as thread 2 13531592Srgrimes * Thread 4 - release mutex 0 13541592Srgrimes * 13551592Srgrimes * Expected results: 13561592Srgrimes * Since thread 4 owns a priority mutex, it should be 13571592Srgrimes * placed at the front of the run queue (for its new 13581592Srgrimes * priority slot) when its priority is lowered to the 13591592Srgrimes * same priority as thread 2. If thread 4 did not own 13601592Srgrimes * a priority mutex, then it would have been added to 13611592Srgrimes * the end of the run queue and thread 2 would have 13621592Srgrimes * executed until it blocked (because it's scheduling 13631592Srgrimes * policy is SCHED_FIFO). 13641592Srgrimes * 13651592Srgrimes */ 13661592Srgrimes log (" Inheritence test with change of priority - "); 13671592Srgrimes 13681592Srgrimes /* 13691592Srgrimes * Change threads 2 and 4 scheduling policies to be 13701592Srgrimes * SCHED_FIFO. 13711592Srgrimes */ 13721592Srgrimes param.sched_priority = states[2].priority; 13731592Srgrimes assert (pthread_setschedparam (states[2].tid, SCHED_FIFO, 13741592Srgrimes ¶m) == 0); 13751592Srgrimes param.sched_priority = states[4].priority; 13761592Srgrimes assert (pthread_setschedparam (states[4].tid, SCHED_FIFO, 13771592Srgrimes ¶m) == 0); 13781592Srgrimes 13791592Srgrimes /* 13801592Srgrimes * Command thread 4 to take mutex 0. 13811592Srgrimes */ 13821592Srgrimes send_mutex_cmd (4, CMD_TAKE_MUTEX, &m[0]); 13831592Srgrimes sleep (1); 13841592Srgrimes 13851592Srgrimes /* 13861592Srgrimes * Command thread 2 to enter busy loop. 13871592Srgrimes */ 13881592Srgrimes send_cmd (2, CMD_BUSY_LOOP); 13891592Srgrimes sleep (1); /* Allow command to be received. */ 13901592Srgrimes 13911592Srgrimes /* 13921592Srgrimes * Command thread 4 to enter busy loop. 13931592Srgrimes */ 13941592Srgrimes send_cmd (4, CMD_BUSY_LOOP); 13951592Srgrimes sleep (1); /* Allow command to be received. */ 13961592Srgrimes 13971592Srgrimes /* Have threads 2 and 4 report themselves. */ 13981592Srgrimes states[2].flags = FLAGS_REPORT_WAITMUTEX; 13991592Srgrimes states[4].flags = FLAGS_REPORT_WAITMUTEX; 14001592Srgrimes 14011592Srgrimes /* Change the priority of thread 4. */ 14021592Srgrimes param.sched_priority = states[2].priority; 14031592Srgrimes assert (pthread_setschedparam (states[4].tid, SCHED_FIFO, 14041592Srgrimes ¶m) == 0); 14051592Srgrimes sleep (5); 14061592Srgrimes check_run_order ("4,2"); 14071592Srgrimes 14081592Srgrimes /* Clear the flags */ 14091592Srgrimes states[2].flags = 0; 14101592Srgrimes states[4].flags = 0; 14111592Srgrimes 14121592Srgrimes /* Reset the policies. */ 14131592Srgrimes param.sched_priority = states[2].priority; 14141592Srgrimes assert (pthread_setschedparam (states[2].tid, SCHED_RR, 14151592Srgrimes ¶m) == 0); 14161592Srgrimes param.sched_priority = states[4].priority; 14171592Srgrimes assert (pthread_setschedparam (states[4].tid, SCHED_RR, 14181592Srgrimes ¶m) == 0); 14191592Srgrimes 14201592Srgrimes send_cmd (4, CMD_RELEASE_MUTEX); 14211592Srgrimes sleep (1); 14221592Srgrimes 14231592Srgrimes /* Destroy the mutexes. */ 14241592Srgrimes for (i = 0; i < 3; i++) 14251592Srgrimes assert (pthread_mutex_destroy (&m[i]) == 0); 14261592Srgrimes } 14271592Srgrimes} 14281592Srgrimes 14291592Srgrimes 14301592Srgrimesint main (int argc, char *argv[]) 14311592Srgrimes{ 14321592Srgrimes pthread_mutexattr_t mattr; 14331592Srgrimes pthread_condattr_t cattr; 14341592Srgrimes pthread_attr_t pattr; 14351592Srgrimes int i, policy, main_prio; 14361592Srgrimes void * exit_status; 14371592Srgrimes sigset_t mask; 14381592Srgrimes struct sigaction act; 14391592Srgrimes struct sched_param param; 14401592Srgrimes 14411592Srgrimes logfile = stdout; 14421592Srgrimes 14431592Srgrimes assert (pthread_getschedparam (pthread_self (), &policy, ¶m) == 0); 14441592Srgrimes main_prio = param.sched_priority; 14451592Srgrimes 14461592Srgrimes /* Setupt our signal mask. */ 14471592Srgrimes sigfillset (&mask); 14481592Srgrimes sigdelset (&mask, SIGINT); 14491592Srgrimes sigprocmask (SIG_SETMASK, &mask, NULL); 14501592Srgrimes 14511592Srgrimes /* Install a signal handler for SIGINT */ 14521592Srgrimes sigemptyset (&act.sa_mask); 14531592Srgrimes sigaddset (&act.sa_mask, SIGINT); 14541592Srgrimes act.sa_handler = sighandler; 14551592Srgrimes act.sa_flags = SA_RESTART; 14561592Srgrimes sigaction (SIGINT, &act, NULL); 14571592Srgrimes 14581592Srgrimes /* 14591592Srgrimes * Initialize the thread attribute. 14601592Srgrimes */ 14611592Srgrimes assert (pthread_attr_init (&pattr) == 0); 14621592Srgrimes assert (pthread_attr_setdetachstate (&pattr, 14631592Srgrimes PTHREAD_CREATE_JOINABLE) == 0); 14641592Srgrimes 14651592Srgrimes /* 14661592Srgrimes * Initialize and create the waiter and condvar mutexes. 14671592Srgrimes */ 14681592Srgrimes assert (pthread_mutexattr_init (&mattr) == 0); 14691592Srgrimes assert (pthread_mutex_init (&waiter_mutex, &mattr) == 0); 14701592Srgrimes assert (pthread_mutex_init (&cond_mutex, &mattr) == 0); 14711592Srgrimes 14721592Srgrimes /* 14731592Srgrimes * Initialize and create a condition variable. 14741592Srgrimes */ 14751592Srgrimes assert (pthread_condattr_init (&cattr) == 0); 14761592Srgrimes assert (pthread_cond_init (&cond_var, &cattr) == 0); 14771592Srgrimes 14781592Srgrimes /* Create a pipe to catch the results of thread wakeups. */ 14791592Srgrimes assert (pipe (pipefd) == 0); 14801592Srgrimes 14811592Srgrimes#ifdef DEBUG 14821592Srgrimes assert (pthread_switch_add_np (kern_switch) == 0); 14831592Srgrimes#endif 148463350Sdes 148563350Sdes /* 148663350Sdes * Create the waiting threads. 14871592Srgrimes */ 14881592Srgrimes for (i = 0; i < NUM_THREADS; i++) { 14891592Srgrimes assert (pthread_cond_init (&states[i].cond_var, &cattr) == 0); 14901592Srgrimes states[i].id = (u_int8_t) i; /* NUM_THREADS must be <= 256 */ 14911592Srgrimes states[i].status = 0; 14921592Srgrimes states[i].cmd.cmd_id = CMD_NONE; 14931592Srgrimes states[i].flags = 0; /* No flags yet. */ 14941592Srgrimes assert (pthread_create (&states[i].tid, &pattr, waiter, 14951592Srgrimes (void *) &states[i]) == 0); 14961592Srgrimes param.sched_priority = main_prio - 10 + i; 14971592Srgrimes states[i].priority = param.sched_priority; 14981592Srgrimes assert (pthread_setschedparam (states[i].tid, SCHED_OTHER, 14991592Srgrimes ¶m) == 0); 15001592Srgrimes#if defined(_LIBC_R_) 150163350Sdes { 150263350Sdes char buf[30]; 150363350Sdes 150463350Sdes snprintf (buf, sizeof(buf), "waiter_%d", i); 150563350Sdes pthread_set_name_np (states[i].tid, buf); 15061592Srgrimes } 15071592Srgrimes#endif 15081592Srgrimes } 15091592Srgrimes 15101592Srgrimes /* Allow the threads to start. */ 15111592Srgrimes sleep (1); 15121592Srgrimes log_trace ("Done creating threads.\n"); 15131592Srgrimes 15141592Srgrimes log ("\n"); 15151592Srgrimes mutex_init_test (); 15161592Srgrimes log ("\n"); 15171592Srgrimes mutex_destroy_test (); 15181592Srgrimes log ("\n"); 15191592Srgrimes mutex_lock_test (); 15201592Srgrimes log ("\n"); 15211592Srgrimes mutex_unlock_test (); 15221592Srgrimes log ("\n"); 15231592Srgrimes queueing_order_test (); 15241592Srgrimes log ("\n"); 152556668Sshin mutex_prioinherit_test (); 152656668Sshin log ("\n"); 152756668Sshin mutex_prioceiling_test (); 152856668Sshin log ("\n"); 152956668Sshin 153056668Sshin log ("Total tests %d, passed %d, failed %d\n", 153156668Sshin total, pass_count, error_count); 153256668Sshin 153356668Sshin /* Set the done flag and signal the threads to exit. */ 153456668Sshin log_trace ("Setting done flag.\n"); 153556668Sshin done = 1; 153656668Sshin 153756668Sshin /* 153856668Sshin * Wait for the threads to finish. 153956668Sshin */ 154056668Sshin log_trace ("Trying to join threads.\n"); 154156668Sshin for (i = 0; i < NUM_THREADS; i++) { 154256668Sshin send_cmd (i, CMD_NONE); 154356668Sshin assert (pthread_join (states[i].tid, &exit_status) == 0); 154456668Sshin } 154556668Sshin 154656668Sshin /* Clean up after ourselves. */ 154756668Sshin close (pipefd[0]); 154856668Sshin close (pipefd[1]); 154956668Sshin 155056668Sshin if (error_count != 0) 155156668Sshin exit (EX_OSERR); /* any better ideas??? */ 155256668Sshin else 155356668Sshin exit (EX_OK); 155456668Sshin} 155556668Sshin