mutex_d.c revision 59612
159612Sjasone/* 259612Sjasone * Copyright (c) 1998 Daniel M. Eischen <eischen@vigrid.com> 359612Sjasone * All rights reserved. 459612Sjasone * 559612Sjasone * Redistribution and use in source and binary forms, with or without 659612Sjasone * modification, are permitted provided that the following conditions 759612Sjasone * are met: 859612Sjasone * 1. Redistributions of source code must retain the above copyright 959612Sjasone * notice, this list of conditions and the following disclaimer. 1059612Sjasone * 2. Redistributions in binary form must reproduce the above copyright 1159612Sjasone * notice, this list of conditions and the following disclaimer in the 1259612Sjasone * documentation and/or other materials provided with the distribution. 1359612Sjasone * 3. All advertising materials mentioning features or use of this software 1459612Sjasone * must display the following acknowledgement: 1559612Sjasone * This product includes software developed by Daniel M. Eischen. 1659612Sjasone * 4. Neither the name of the author nor the names of any co-contributors 1759612Sjasone * may be used to endorse or promote products derived from this software 1859612Sjasone * without specific prior written permission. 1959612Sjasone * 2059612Sjasone * THIS SOFTWARE IS PROVIDED BY DANIEL M. EISCHEN AND CONTRIBUTORS ``AS IS'' 2159612Sjasone * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2259612Sjasone * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2359612Sjasone * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2459612Sjasone * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2559612Sjasone * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2659612Sjasone * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2759612Sjasone * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2859612Sjasone * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2959612Sjasone * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3059612Sjasone * SUCH DAMAGE. 3159612Sjasone * 3259612Sjasone * $FreeBSD: head/lib/libkse/test/mutex_d.c 59612 2000-04-24 21:07:45Z jasone $ 3359612Sjasone */ 3459612Sjasone#include <stdlib.h> 3559612Sjasone#include <unistd.h> 3659612Sjasone 3759612Sjasone#include <sys/ioctl.h> 3859612Sjasone#include <assert.h> 3959612Sjasone#include <errno.h> 4059612Sjasone#include "pthread.h" 4159612Sjasone#include <sched.h> 4259612Sjasone#include <signal.h> 4359612Sjasone#include <stdarg.h> 4459612Sjasone#include <stdio.h> 4559612Sjasone#include <string.h> 4659612Sjasone#include <sysexits.h> 4759612Sjasone 4859612Sjasone#if defined(_LIBC_R_) 4959612Sjasone#include <pthread_np.h> 5059612Sjasone#endif 5159612Sjasone 5259612Sjasone#ifndef NELEMENTS 5359612Sjasone#define NELEMENTS(arr) (sizeof (arr) / sizeof (arr[0])) 5459612Sjasone#endif 5559612Sjasone 5659612Sjasone#ifndef NUM_THREADS 5759612Sjasone#define NUM_THREADS 10 5859612Sjasone#endif 5959612Sjasone 6059612Sjasone#define MAX_THREAD_CMDS 10 6159612Sjasone 6259612Sjasone 6359612Sjasone/*------------------------------------------------------------ 6459612Sjasone * Types 6559612Sjasone *----------------------------------------------------------*/ 6659612Sjasone 6759612Sjasonetypedef enum { 6859612Sjasone STAT_INITIAL, /* initial state */ 6959612Sjasone STAT_WAITCONDVAR, /* waiting for condition variable signal */ 7059612Sjasone STAT_WAITMUTEX /* waiting for mutex lock */ 7159612Sjasone} thread_status_t; 7259612Sjasone 7359612Sjasonetypedef enum { 7459612Sjasone FLAGS_REPORT_WAITCONDMUTEX = 0x01, 7559612Sjasone FLAGS_REPORT_WAITCONDVAR = 0x02, 7659612Sjasone FLAGS_REPORT_WAITMUTEX = 0x04, 7759612Sjasone FLAGS_REPORT_BUSY_LOOP = 0x08, 7859612Sjasone FLAGS_IS_BUSY = 0x10, 7959612Sjasone FLAGS_WAS_BUSY = 0x20 8059612Sjasone} thread_flags_t; 8159612Sjasone 8259612Sjasonetypedef enum { 8359612Sjasone CMD_NONE, 8459612Sjasone CMD_TAKE_MUTEX, 8559612Sjasone CMD_RELEASE_MUTEX, 8659612Sjasone CMD_WAIT_FOR_SIGNAL, 8759612Sjasone CMD_BUSY_LOOP, 8859612Sjasone CMD_PROTECTED_OP, 8959612Sjasone CMD_RELEASE_ALL 9059612Sjasone} thread_cmd_id_t; 9159612Sjasone 9259612Sjasonetypedef struct { 9359612Sjasone thread_cmd_id_t cmd_id; 9459612Sjasone pthread_mutex_t *mutex; 9559612Sjasone pthread_cond_t *cond; 9659612Sjasone} thread_cmd_t; 9759612Sjasone 9859612Sjasonetypedef struct { 9959612Sjasone pthread_cond_t cond_var; 10059612Sjasone thread_status_t status; 10159612Sjasone thread_cmd_t cmd; 10259612Sjasone int flags; 10359612Sjasone int priority; 10459612Sjasone int ret; 10559612Sjasone pthread_t tid; 10659612Sjasone u_int8_t id; 10759612Sjasone} thread_state_t; 10859612Sjasone 10959612Sjasonetypedef enum { 11059612Sjasone M_POSIX, 11159612Sjasone M_SS2_DEFAULT, 11259612Sjasone M_SS2_ERRORCHECK, 11359612Sjasone M_SS2_NORMAL, 11459612Sjasone M_SS2_RECURSIVE 11559612Sjasone} mutex_kind_t; 11659612Sjasone 11759612Sjasone 11859612Sjasone/*------------------------------------------------------------ 11959612Sjasone * Constants 12059612Sjasone *----------------------------------------------------------*/ 12159612Sjasone 12259612Sjasoneconst char *protocol_strs[] = { 12359612Sjasone "PTHREAD_PRIO_NONE", 12459612Sjasone "PTHREAD_PRIO_INHERIT", 12559612Sjasone "PTHREAD_PRIO_PROTECT" 12659612Sjasone}; 12759612Sjasone 12859612Sjasoneconst int protocols[] = { 12959612Sjasone PTHREAD_PRIO_NONE, 13059612Sjasone PTHREAD_PRIO_INHERIT, 13159612Sjasone PTHREAD_PRIO_PROTECT 13259612Sjasone}; 13359612Sjasone 13459612Sjasoneconst char *mutextype_strs[] = { 13559612Sjasone "POSIX (type not specified)", 13659612Sjasone "SS2 PTHREAD_MUTEX_DEFAULT", 13759612Sjasone "SS2 PTHREAD_MUTEX_ERRORCHECK", 13859612Sjasone "SS2 PTHREAD_MUTEX_NORMAL", 13959612Sjasone "SS2 PTHREAD_MUTEX_RECURSIVE" 14059612Sjasone}; 14159612Sjasone 14259612Sjasoneconst int mutex_types[] = { 14359612Sjasone 0, /* M_POSIX */ 14459612Sjasone PTHREAD_MUTEX_DEFAULT, /* M_SS2_DEFAULT */ 14559612Sjasone PTHREAD_MUTEX_ERRORCHECK, /* M_SS2_ERRORCHECK */ 14659612Sjasone PTHREAD_MUTEX_NORMAL, /* M_SS2_NORMAL */ 14759612Sjasone PTHREAD_MUTEX_RECURSIVE /* M_SS2_RECURSIVE */ 14859612Sjasone}; 14959612Sjasone 15059612Sjasone 15159612Sjasone/*------------------------------------------------------------ 15259612Sjasone * Objects 15359612Sjasone *----------------------------------------------------------*/ 15459612Sjasone 15559612Sjasonestatic int done = 0; 15659612Sjasonestatic int trace_enabled = 0; 15759612Sjasonestatic int use_global_condvar = 0; 15859612Sjasonestatic thread_state_t states[NUM_THREADS]; 15959612Sjasonestatic int pipefd[2]; 16059612Sjasone 16159612Sjasonestatic pthread_mutex_t waiter_mutex; 16259612Sjasonestatic pthread_mutex_t cond_mutex; 16359612Sjasonestatic pthread_cond_t cond_var; 16459612Sjasone 16559612Sjasonestatic FILE *logfile = stdout; 16659612Sjasonestatic int error_count = 0, pass_count = 0, total = 0; 16759612Sjasone 16859612Sjasone 16959612Sjasone/*------------------------------------------------------------ 17059612Sjasone * Prototypes 17159612Sjasone *----------------------------------------------------------*/ 17259612Sjasoneextern char *strtok_r(char *str, const char *sep, char **last); 17359612Sjasone 17459612Sjasone 17559612Sjasone/*------------------------------------------------------------ 17659612Sjasone * Functions 17759612Sjasone *----------------------------------------------------------*/ 17859612Sjasone 17959612Sjasone#ifdef DEBUG 18059612Sjasonestatic void 18159612Sjasonekern_switch (pthread_t pthread_out, pthread_t pthread_in) 18259612Sjasone{ 18359612Sjasone if (pthread_out != NULL) 18459612Sjasone printf ("Swapping out thread 0x%x, ", (int) pthread_out); 18559612Sjasone else 18659612Sjasone printf ("Swapping out kernel thread, "); 18759612Sjasone 18859612Sjasone if (pthread_in != NULL) 18959612Sjasone printf ("swapping in thread 0x%x\n", (int) pthread_in); 19059612Sjasone else 19159612Sjasone printf ("swapping in kernel thread.\n"); 19259612Sjasone} 19359612Sjasone#endif 19459612Sjasone 19559612Sjasone 19659612Sjasonestatic void 19759612Sjasonelog_error (const char *fmt, ...) 19859612Sjasone{ 19959612Sjasone va_list ap; 20059612Sjasone 20159612Sjasone va_start (ap, fmt); 20259612Sjasone fprintf (logfile, "FAIL: "); 20359612Sjasone vfprintf (logfile, fmt, ap); 20459612Sjasone error_count = error_count + 1; 20559612Sjasone total = total + 1; 20659612Sjasone} 20759612Sjasone 20859612Sjasone 20959612Sjasonestatic void 21059612Sjasonelog_pass (void) 21159612Sjasone{ 21259612Sjasone fprintf (logfile, "PASS\n"); 21359612Sjasone pass_count = pass_count + 1; 21459612Sjasone total = total + 1; 21559612Sjasone} 21659612Sjasone 21759612Sjasone 21859612Sjasonestatic void 21959612Sjasonelog_trace (const char *fmt, ...) 22059612Sjasone{ 22159612Sjasone va_list ap; 22259612Sjasone 22359612Sjasone if (trace_enabled) { 22459612Sjasone va_start (ap, fmt); 22559612Sjasone vfprintf (logfile, fmt, ap); 22659612Sjasone } 22759612Sjasone} 22859612Sjasone 22959612Sjasone 23059612Sjasonestatic void 23159612Sjasonelog (const char *fmt, ...) 23259612Sjasone{ 23359612Sjasone va_list ap; 23459612Sjasone 23559612Sjasone va_start (ap, fmt); 23659612Sjasone vfprintf (logfile, fmt, ap); 23759612Sjasone} 23859612Sjasone 23959612Sjasone 24059612Sjasonestatic void 24159612Sjasonecheck_result (int expected, int actual) 24259612Sjasone{ 24359612Sjasone if (expected != actual) 24459612Sjasone log_error ("expected %d, returned %d\n", expected, actual); 24559612Sjasone else 24659612Sjasone log_pass (); 24759612Sjasone} 24859612Sjasone 24959612Sjasone 25059612Sjasone/* 25159612Sjasone * Check to see that the threads ran in the specified order. 25259612Sjasone */ 25359612Sjasonestatic void 25459612Sjasonecheck_run_order (char *order) 25559612Sjasone{ 25659612Sjasone const char *sep = ":,"; 25759612Sjasone char *tok, *last, *idstr, *endptr; 25859612Sjasone int expected_id, bytes, count = 0, errors = 0; 25959612Sjasone u_int8_t id; 26059612Sjasone 26159612Sjasone assert ((tok = (char *) malloc (strlen(order) + 1)) != NULL); 26259612Sjasone strcpy (tok, order); /* tok has to be larger than order */ 26359612Sjasone assert (ioctl (pipefd[0], FIONREAD, &bytes) == 0); 26459612Sjasone log_trace ("%d bytes read from FIFO.\n", bytes); 26559612Sjasone 26659612Sjasone for (idstr = strtok_r (tok, sep, &last); 26759612Sjasone (idstr != NULL) && (count < bytes); 26859612Sjasone idstr = strtok_r (NULL, sep, &last)) { 26959612Sjasone 27059612Sjasone /* Get the expected id: */ 27159612Sjasone expected_id = (int) strtol (idstr, &endptr, 10); 27259612Sjasone assert ((endptr != NULL) && (*endptr == '\0')); 27359612Sjasone 27459612Sjasone /* Read the actual id from the pipe: */ 27559612Sjasone assert (read (pipefd[0], &id, sizeof (id)) == sizeof (id)); 27659612Sjasone count = count + sizeof (id); 27759612Sjasone 27859612Sjasone if (id != expected_id) { 27959612Sjasone log_trace ("Thread %d ran out of order.\n", id); 28059612Sjasone errors = errors + 1; 28159612Sjasone } 28259612Sjasone else { 28359612Sjasone log_trace ("Thread %d at priority %d reporting.\n", 28459612Sjasone (int) id, states[id].priority); 28559612Sjasone } 28659612Sjasone } 28759612Sjasone 28859612Sjasone if (count < bytes) { 28959612Sjasone /* Clear the pipe: */ 29059612Sjasone while (count < bytes) { 29159612Sjasone read (pipefd[0], &id, sizeof (id)); 29259612Sjasone count = count + 1; 29359612Sjasone errors = errors + 1; 29459612Sjasone } 29559612Sjasone } 29659612Sjasone else if (bytes < count) 29759612Sjasone errors = errors + count - bytes; 29859612Sjasone 29959612Sjasone if (errors == 0) 30059612Sjasone log_pass (); 30159612Sjasone else 30259612Sjasone log_error ("%d threads ran out of order", errors); 30359612Sjasone} 30459612Sjasone 30559612Sjasone 30659612Sjasonestatic void * 30759612Sjasonewaiter (void *arg) 30859612Sjasone{ 30959612Sjasone thread_state_t *statep = (thread_state_t *) arg; 31059612Sjasone pthread_mutex_t *held_mutex[MAX_THREAD_CMDS]; 31159612Sjasone int held_mutex_owned[MAX_THREAD_CMDS]; 31259612Sjasone sigset_t mask; 31359612Sjasone struct timeval tv1, tv2; 31459612Sjasone thread_cmd_t cmd; 31559612Sjasone int i, mutex_count = 0; 31659612Sjasone 31759612Sjasone statep->status = STAT_INITIAL; 31859612Sjasone 31959612Sjasone /* Block all signals except for interrupt.*/ 32059612Sjasone sigfillset (&mask); 32159612Sjasone sigdelset (&mask, SIGINT); 32259612Sjasone sigprocmask (SIG_BLOCK, &mask, NULL); 32359612Sjasone 32459612Sjasone while (done == 0) { 32559612Sjasone /* Wait for signal from the main thread to continue. */ 32659612Sjasone statep->status = STAT_WAITMUTEX; 32759612Sjasone log_trace ("Thread %d: locking cond_mutex.\n", 32859612Sjasone (int) statep->id); 32959612Sjasone pthread_mutex_lock (&cond_mutex); 33059612Sjasone 33159612Sjasone /* Do we report our status. */ 33259612Sjasone if (statep->flags & FLAGS_REPORT_WAITCONDMUTEX) 33359612Sjasone write (pipefd[1], &statep->id, sizeof (statep->id)); 33459612Sjasone log_trace ("Thread %d: waiting for cond_var.\n", 33559612Sjasone (int) statep->id); 33659612Sjasone 33759612Sjasone /* Wait for a command. */ 33859612Sjasone statep->status = STAT_WAITCONDVAR; 33959612Sjasone 34059612Sjasone /* 34159612Sjasone * The threads are allowed commanded to wait either on 34259612Sjasone * their own unique condition variable (so they may be 34359612Sjasone * separately signaled) or on one global condition variable 34459612Sjasone * (so they may be signaled together). 34559612Sjasone */ 34659612Sjasone if (use_global_condvar != 0) 34759612Sjasone pthread_cond_wait (&cond_var, &cond_mutex); 34859612Sjasone else 34959612Sjasone pthread_cond_wait (&statep->cond_var, &cond_mutex); 35059612Sjasone 35159612Sjasone /* Do we report our status? */ 35259612Sjasone if (statep->flags & FLAGS_REPORT_WAITCONDVAR) { 35359612Sjasone write (pipefd[1], &statep->id, sizeof (statep->id)); 35459612Sjasone log_trace ("Thread %d: wrote %d to pipe.\n", 35559612Sjasone (int) statep->id); 35659612Sjasone } 35759612Sjasone log_trace ("Thread %d: received cond_var signal.\n", 35859612Sjasone (int) statep->id); 35959612Sjasone 36059612Sjasone /* Get a copy of the command before releasing the mutex. */ 36159612Sjasone cmd = statep->cmd; 36259612Sjasone 36359612Sjasone /* Clear the command after copying it. */ 36459612Sjasone statep->cmd.cmd_id = CMD_NONE; 36559612Sjasone 36659612Sjasone /* Unlock the condition variable mutex. */ 36759612Sjasone assert (pthread_mutex_unlock (&cond_mutex) == 0); 36859612Sjasone 36959612Sjasone /* Peform the command.*/ 37059612Sjasone switch (cmd.cmd_id) { 37159612Sjasone case CMD_TAKE_MUTEX: 37259612Sjasone statep->ret = pthread_mutex_lock (cmd.mutex); 37359612Sjasone if (statep->ret == 0) { 37459612Sjasone assert (mutex_count < sizeof (held_mutex)); 37559612Sjasone held_mutex[mutex_count] = cmd.mutex; 37659612Sjasone held_mutex_owned[mutex_count] = 1; 37759612Sjasone mutex_count++; 37859612Sjasone } 37959612Sjasone else { 38059612Sjasone held_mutex_owned[mutex_count] = 0; 38159612Sjasone log_trace ("Thread id %d unable to lock mutex, " 38259612Sjasone "error = %d\n", (int) statep->id, 38359612Sjasone statep->ret); 38459612Sjasone } 38559612Sjasone break; 38659612Sjasone 38759612Sjasone case CMD_RELEASE_MUTEX: 38859612Sjasone assert ((mutex_count <= sizeof (held_mutex)) && 38959612Sjasone (mutex_count > 0)); 39059612Sjasone mutex_count--; 39159612Sjasone if (held_mutex_owned[mutex_count] != 0) 39259612Sjasone assert (pthread_mutex_unlock 39359612Sjasone (held_mutex[mutex_count]) == 0); 39459612Sjasone break; 39559612Sjasone 39659612Sjasone case CMD_WAIT_FOR_SIGNAL: 39759612Sjasone assert (pthread_mutex_lock (cmd.mutex) == 0); 39859612Sjasone assert (pthread_cond_wait (cmd.cond, cmd.mutex) == 0); 39959612Sjasone assert (pthread_mutex_unlock (cmd.mutex) == 0); 40059612Sjasone break; 40159612Sjasone 40259612Sjasone case CMD_BUSY_LOOP: 40359612Sjasone log_trace ("Thread %d: Entering busy loop.\n", 40459612Sjasone (int) statep->id); 40559612Sjasone /* Spin for 15 seconds. */ 40659612Sjasone assert (gettimeofday (&tv2, NULL) == 0); 40759612Sjasone tv1.tv_sec = tv2.tv_sec + 5; 40859612Sjasone tv1.tv_usec = tv2.tv_usec; 40959612Sjasone statep->flags |= FLAGS_IS_BUSY; 41059612Sjasone while (timercmp (&tv2, &tv1,<)) { 41159612Sjasone assert (gettimeofday (&tv2, NULL) == 0); 41259612Sjasone } 41359612Sjasone statep->flags &= ~FLAGS_IS_BUSY; 41459612Sjasone statep->flags |= FLAGS_WAS_BUSY; 41559612Sjasone 41659612Sjasone /* Do we report our status? */ 41759612Sjasone if (statep->flags & FLAGS_REPORT_BUSY_LOOP) 41859612Sjasone write (pipefd[1], &statep->id, 41959612Sjasone sizeof (statep->id)); 42059612Sjasone 42159612Sjasone log_trace ("Thread %d: Leaving busy loop.\n", 42259612Sjasone (int) statep->id); 42359612Sjasone break; 42459612Sjasone 42559612Sjasone case CMD_PROTECTED_OP: 42659612Sjasone assert (pthread_mutex_lock (cmd.mutex) == 0); 42759612Sjasone statep->flags |= FLAGS_WAS_BUSY; 42859612Sjasone /* Do we report our status? */ 42959612Sjasone if (statep->flags & FLAGS_REPORT_BUSY_LOOP) 43059612Sjasone write (pipefd[1], &statep->id, 43159612Sjasone sizeof (statep->id)); 43259612Sjasone 43359612Sjasone assert (pthread_mutex_unlock (cmd.mutex) == 0); 43459612Sjasone break; 43559612Sjasone 43659612Sjasone case CMD_RELEASE_ALL: 43759612Sjasone assert ((mutex_count <= sizeof (held_mutex)) && 43859612Sjasone (mutex_count > 0)); 43959612Sjasone for (i = mutex_count - 1; i >= 0; i--) { 44059612Sjasone if (held_mutex_owned[i] != 0) 44159612Sjasone assert (pthread_mutex_unlock 44259612Sjasone (held_mutex[i]) == 0); 44359612Sjasone } 44459612Sjasone mutex_count = 0; 44559612Sjasone break; 44659612Sjasone 44759612Sjasone case CMD_NONE: 44859612Sjasone default: 44959612Sjasone break; 45059612Sjasone } 45159612Sjasone 45259612Sjasone /* Wait for the big giant waiter lock. */ 45359612Sjasone statep->status = STAT_WAITMUTEX; 45459612Sjasone log_trace ("Thread %d: waiting for big giant lock.\n", 45559612Sjasone (int) statep->id); 45659612Sjasone pthread_mutex_lock (&waiter_mutex); 45759612Sjasone if (statep->flags & FLAGS_REPORT_WAITMUTEX) 45859612Sjasone write (pipefd[1], &statep->id, sizeof (statep->id)); 45959612Sjasone log_trace ("Thread %d: got big giant lock.\n", 46059612Sjasone (int) statep->id); 46159612Sjasone statep->status = STAT_INITIAL; 46259612Sjasone pthread_mutex_unlock (&waiter_mutex); 46359612Sjasone } 46459612Sjasone 46559612Sjasone log_trace ("Thread %d: Exiting thread 0x%x\n", (int) statep->id, 46659612Sjasone (int) pthread_self()); 46759612Sjasone pthread_exit (arg); 46859612Sjasone return (NULL); 46959612Sjasone} 47059612Sjasone 47159612Sjasone 47259612Sjasonestatic void * 47359612Sjasonelock_twice (void *arg) 47459612Sjasone{ 47559612Sjasone thread_state_t *statep = (thread_state_t *) arg; 47659612Sjasone sigset_t mask; 47759612Sjasone 47859612Sjasone statep->status = STAT_INITIAL; 47959612Sjasone 48059612Sjasone /* Block all signals except for interrupt.*/ 48159612Sjasone sigfillset (&mask); 48259612Sjasone sigdelset (&mask, SIGINT); 48359612Sjasone sigprocmask (SIG_BLOCK, &mask, NULL); 48459612Sjasone 48559612Sjasone /* Wait for a signal to continue. */ 48659612Sjasone log_trace ("Thread %d: locking cond_mutex.\n", (int) statep->id); 48759612Sjasone pthread_mutex_lock (&cond_mutex); 48859612Sjasone 48959612Sjasone log_trace ("Thread %d: waiting for cond_var.\n", (int) statep->id); 49059612Sjasone statep->status = STAT_WAITCONDVAR; 49159612Sjasone pthread_cond_wait (&cond_var, &cond_mutex); 49259612Sjasone 49359612Sjasone log_trace ("Thread %d: received cond_var signal.\n", (int) statep->id); 49459612Sjasone 49559612Sjasone /* Unlock the condition variable mutex. */ 49659612Sjasone assert (pthread_mutex_unlock (&cond_mutex) == 0); 49759612Sjasone 49859612Sjasone statep->status = STAT_WAITMUTEX; 49959612Sjasone /* Lock the mutex once. */ 50059612Sjasone assert (pthread_mutex_lock (statep->cmd.mutex) == 0); 50159612Sjasone 50259612Sjasone /* Lock it again and capture the error. */ 50359612Sjasone statep->ret = pthread_mutex_lock (statep->cmd.mutex); 50459612Sjasone statep->status = 0; 50559612Sjasone 50659612Sjasone assert (pthread_mutex_unlock (statep->cmd.mutex) == 0); 50759612Sjasone 50859612Sjasone /* Unlock it again if it is locked recursively. */ 50959612Sjasone if (statep->ret == 0) 51059612Sjasone pthread_mutex_unlock (statep->cmd.mutex); 51159612Sjasone 51259612Sjasone log_trace ("Thread %d: Exiting thread 0x%x\n", (int) statep->id, 51359612Sjasone (int) pthread_self()); 51459612Sjasone pthread_exit (arg); 51559612Sjasone return (NULL); 51659612Sjasone} 51759612Sjasone 51859612Sjasone 51959612Sjasonestatic void 52059612Sjasonesighandler (int signo) 52159612Sjasone{ 52259612Sjasone log ("Signal handler caught signal %d, thread id 0x%x\n", 52359612Sjasone signo, (int) pthread_self()); 52459612Sjasone 52559612Sjasone if (signo == SIGINT) 52659612Sjasone done = 1; 52759612Sjasone} 52859612Sjasone 52959612Sjasone 53059612Sjasonestatic void 53159612Sjasonesend_cmd (int id, thread_cmd_id_t cmd) 53259612Sjasone{ 53359612Sjasone assert (pthread_mutex_lock (&cond_mutex) == 0); 53459612Sjasone assert (states[id].status == STAT_WAITCONDVAR); 53559612Sjasone states[id].cmd.cmd_id = cmd; 53659612Sjasone states[id].cmd.mutex = NULL; 53759612Sjasone states[id].cmd.cond = NULL; 53859612Sjasone /* Clear the busy flags. */ 53959612Sjasone states[id].flags &= ~(FLAGS_WAS_BUSY | FLAGS_IS_BUSY); 54059612Sjasone assert (pthread_cond_signal (&states[id].cond_var) == 0); 54159612Sjasone assert (pthread_mutex_unlock (&cond_mutex) == 0); 54259612Sjasone} 54359612Sjasone 54459612Sjasone 54559612Sjasonestatic void 54659612Sjasonesend_mutex_cmd (int id, thread_cmd_id_t cmd, pthread_mutex_t *m) 54759612Sjasone{ 54859612Sjasone assert (pthread_mutex_lock (&cond_mutex) == 0); 54959612Sjasone assert (states[id].status == STAT_WAITCONDVAR); 55059612Sjasone states[id].cmd.cmd_id = cmd; 55159612Sjasone states[id].cmd.mutex = m; 55259612Sjasone states[id].cmd.cond = NULL; 55359612Sjasone /* Clear the busy flags. */ 55459612Sjasone states[id].flags &= ~(FLAGS_WAS_BUSY | FLAGS_IS_BUSY); 55559612Sjasone assert (pthread_cond_signal (&states[id].cond_var) == 0); 55659612Sjasone assert (pthread_mutex_unlock (&cond_mutex) == 0); 55759612Sjasone} 55859612Sjasone 55959612Sjasone 56059612Sjasonestatic void 56159612Sjasonesend_mutex_cv_cmd (int id, thread_cmd_id_t cmd, pthread_mutex_t *m, 56259612Sjasone pthread_cond_t *cv) 56359612Sjasone{ 56459612Sjasone assert (pthread_mutex_lock (&cond_mutex) == 0); 56559612Sjasone assert (states[id].status == STAT_WAITCONDVAR); 56659612Sjasone states[id].cmd.cmd_id = cmd; 56759612Sjasone states[id].cmd.mutex = m; 56859612Sjasone states[id].cmd.cond = cv; 56959612Sjasone /* Clear the busy flags. */ 57059612Sjasone states[id].flags &= ~(FLAGS_WAS_BUSY | FLAGS_IS_BUSY); 57159612Sjasone assert (pthread_cond_signal (&states[id].cond_var) == 0); 57259612Sjasone assert (pthread_mutex_unlock (&cond_mutex) == 0); 57359612Sjasone} 57459612Sjasone 57559612Sjasone 57659612Sjasonestatic void 57759612Sjasonemutex_init_test (void) 57859612Sjasone{ 57959612Sjasone pthread_mutexattr_t mattr; 58059612Sjasone pthread_mutex_t mutex; 58159612Sjasone mutex_kind_t mkind; 58259612Sjasone int mproto, ret; 58359612Sjasone 58459612Sjasone /* 58559612Sjasone * Initialize a mutex attribute. 58659612Sjasone * 58759612Sjasone * pthread_mutexattr_init not tested for: ENOMEM 58859612Sjasone */ 58959612Sjasone assert (pthread_mutexattr_init (&mattr) == 0); 59059612Sjasone 59159612Sjasone /* 59259612Sjasone * Initialize a mutex. 59359612Sjasone * 59459612Sjasone * pthread_mutex_init not tested for: EAGAIN ENOMEM EPERM EBUSY 59559612Sjasone */ 59659612Sjasone log ("Testing pthread_mutex_init\n"); 59759612Sjasone log ("--------------------------\n"); 59859612Sjasone 59959612Sjasone for (mproto = 0; mproto < NELEMENTS(protocols); mproto++) { 60059612Sjasone for (mkind = M_POSIX; mkind <= M_SS2_RECURSIVE; mkind++) { 60159612Sjasone /* Initialize the mutex attribute. */ 60259612Sjasone assert (pthread_mutexattr_init (&mattr) == 0); 60359612Sjasone assert (pthread_mutexattr_setprotocol (&mattr, 60459612Sjasone protocols[mproto]) == 0); 60559612Sjasone 60659612Sjasone /* 60759612Sjasone * Ensure that the first mutex type is a POSIX 60859612Sjasone * compliant mutex. 60959612Sjasone */ 61059612Sjasone if (mkind != M_POSIX) { 61159612Sjasone assert (pthread_mutexattr_settype (&mattr, 61259612Sjasone mutex_types[mkind]) == 0); 61359612Sjasone } 61459612Sjasone 61559612Sjasone log (" Protocol %s, Type %s - ", 61659612Sjasone protocol_strs[mproto], mutextype_strs[mkind]); 61759612Sjasone ret = pthread_mutex_init (&mutex, &mattr); 61859612Sjasone check_result (/* expected */ 0, ret); 61959612Sjasone assert (pthread_mutex_destroy (&mutex) == 0); 62059612Sjasone 62159612Sjasone /* 62259612Sjasone * Destroy a mutex attribute. 62359612Sjasone * 62459612Sjasone * XXX - There should probably be a magic number 62559612Sjasone * associated with a mutex attribute so that 62659612Sjasone * destroy can be reasonably sure the attribute 62759612Sjasone * is valid. 62859612Sjasone * 62959612Sjasone * pthread_mutexattr_destroy not tested for: EINVAL 63059612Sjasone */ 63159612Sjasone assert (pthread_mutexattr_destroy (&mattr) == 0); 63259612Sjasone } 63359612Sjasone } 63459612Sjasone} 63559612Sjasone 63659612Sjasone 63759612Sjasonestatic void 63859612Sjasonemutex_destroy_test (void) 63959612Sjasone{ 64059612Sjasone pthread_mutexattr_t mattr; 64159612Sjasone pthread_mutex_t mutex; 64259612Sjasone pthread_condattr_t cattr; 64359612Sjasone pthread_cond_t cv; 64459612Sjasone pthread_attr_t pattr; 64559612Sjasone int mproto, ret; 64659612Sjasone mutex_kind_t mkind; 64759612Sjasone thread_state_t state; 64859612Sjasone 64959612Sjasone /* 65059612Sjasone * Destroy a mutex. 65159612Sjasone * 65259612Sjasone * XXX - There should probably be a magic number associated 65359612Sjasone * with a mutex so that destroy can be reasonably sure 65459612Sjasone * the mutex is valid. 65559612Sjasone * 65659612Sjasone * pthread_mutex_destroy not tested for: 65759612Sjasone */ 65859612Sjasone log ("Testing pthread_mutex_destroy\n"); 65959612Sjasone log ("-----------------------------\n"); 66059612Sjasone 66159612Sjasone assert (pthread_attr_init (&pattr) == 0); 66259612Sjasone assert (pthread_attr_setdetachstate (&pattr, 66359612Sjasone PTHREAD_CREATE_DETACHED) == 0); 66459612Sjasone state.flags = 0; /* No flags yet. */ 66559612Sjasone 66659612Sjasone for (mproto = 0; mproto < NELEMENTS(protocols); mproto++) { 66759612Sjasone for (mkind = M_POSIX; mkind <= M_SS2_RECURSIVE; mkind++) { 66859612Sjasone /* Initialize the mutex attribute. */ 66959612Sjasone assert (pthread_mutexattr_init (&mattr) == 0); 67059612Sjasone assert (pthread_mutexattr_setprotocol (&mattr, 67159612Sjasone protocols[mproto]) == 0); 67259612Sjasone 67359612Sjasone /* 67459612Sjasone * Ensure that the first mutex type is a POSIX 67559612Sjasone * compliant mutex. 67659612Sjasone */ 67759612Sjasone if (mkind != M_POSIX) { 67859612Sjasone assert (pthread_mutexattr_settype (&mattr, 67959612Sjasone mutex_types[mkind]) == 0); 68059612Sjasone } 68159612Sjasone 68259612Sjasone /* Create the mutex. */ 68359612Sjasone assert (pthread_mutex_init (&mutex, &mattr) == 0); 68459612Sjasone 68559612Sjasone log (" Protocol %s, Type %s\n", 68659612Sjasone protocol_strs[mproto], mutextype_strs[mkind]); 68759612Sjasone 68859612Sjasone log (" Destruction of unused mutex - "); 68959612Sjasone assert (pthread_mutex_init (&mutex, &mattr) == 0); 69059612Sjasone ret = pthread_mutex_destroy (&mutex); 69159612Sjasone check_result (/* expected */ 0, ret); 69259612Sjasone 69359612Sjasone log (" Destruction of mutex locked by self - "); 69459612Sjasone assert (pthread_mutex_init (&mutex, &mattr) == 0); 69559612Sjasone assert (pthread_mutex_lock (&mutex) == 0); 69659612Sjasone ret = pthread_mutex_destroy (&mutex); 69759612Sjasone check_result (/* expected */ EBUSY, ret); 69859612Sjasone assert (pthread_mutex_unlock (&mutex) == 0); 69959612Sjasone assert (pthread_mutex_destroy (&mutex) == 0); 70059612Sjasone 70159612Sjasone log (" Destruction of mutex locked by another " 70259612Sjasone "thread - "); 70359612Sjasone assert (pthread_mutex_init (&mutex, &mattr) == 0); 70459612Sjasone send_mutex_cmd (0, CMD_TAKE_MUTEX, &mutex); 70559612Sjasone sleep (1); 70659612Sjasone ret = pthread_mutex_destroy (&mutex); 70759612Sjasone check_result (/* expected */ EBUSY, ret); 70859612Sjasone send_cmd (0, CMD_RELEASE_ALL); 70959612Sjasone sleep (1); 71059612Sjasone assert (pthread_mutex_destroy (&mutex) == 0); 71159612Sjasone 71259612Sjasone log (" Destruction of mutex while being used in " 71359612Sjasone "cond_wait - "); 71459612Sjasone assert (pthread_mutex_init (&mutex, &mattr) == 0); 71559612Sjasone assert (pthread_condattr_init (&cattr) == 0); 71659612Sjasone assert (pthread_cond_init (&cv, &cattr) == 0); 71759612Sjasone send_mutex_cv_cmd (0, CMD_WAIT_FOR_SIGNAL, &mutex, &cv); 71859612Sjasone sleep (1); 71959612Sjasone ret = pthread_mutex_destroy (&mutex); 72059612Sjasone check_result (/* expected */ EBUSY, ret); 72159612Sjasone pthread_cond_signal (&cv); 72259612Sjasone sleep (1); 72359612Sjasone assert (pthread_mutex_destroy (&mutex) == 0); 72459612Sjasone } 72559612Sjasone } 72659612Sjasone} 72759612Sjasone 72859612Sjasone 72959612Sjasonestatic void 73059612Sjasonemutex_lock_test (void) 73159612Sjasone{ 73259612Sjasone pthread_mutexattr_t mattr; 73359612Sjasone pthread_mutex_t mutex; 73459612Sjasone pthread_attr_t pattr; 73559612Sjasone int mproto, ret; 73659612Sjasone mutex_kind_t mkind; 73759612Sjasone thread_state_t state; 73859612Sjasone 73959612Sjasone /* 74059612Sjasone * Lock a mutex. 74159612Sjasone * 74259612Sjasone * pthread_lock not tested for: 74359612Sjasone */ 74459612Sjasone log ("Testing pthread_mutex_lock\n"); 74559612Sjasone log ("--------------------------\n"); 74659612Sjasone 74759612Sjasone assert (pthread_attr_init (&pattr) == 0); 74859612Sjasone assert (pthread_attr_setdetachstate (&pattr, 74959612Sjasone PTHREAD_CREATE_DETACHED) == 0); 75059612Sjasone state.flags = 0; /* No flags yet. */ 75159612Sjasone 75259612Sjasone for (mproto = 0; mproto < NELEMENTS(protocols); mproto++) { 75359612Sjasone for (mkind = M_POSIX; mkind <= M_SS2_RECURSIVE; mkind++) { 75459612Sjasone /* Initialize the mutex attribute. */ 75559612Sjasone assert (pthread_mutexattr_init (&mattr) == 0); 75659612Sjasone assert (pthread_mutexattr_setprotocol (&mattr, 75759612Sjasone protocols[mproto]) == 0); 75859612Sjasone 75959612Sjasone /* 76059612Sjasone * Ensure that the first mutex type is a POSIX 76159612Sjasone * compliant mutex. 76259612Sjasone */ 76359612Sjasone if (mkind != M_POSIX) { 76459612Sjasone assert (pthread_mutexattr_settype (&mattr, 76559612Sjasone mutex_types[mkind]) == 0); 76659612Sjasone } 76759612Sjasone 76859612Sjasone /* Create the mutex. */ 76959612Sjasone assert (pthread_mutex_init (&mutex, &mattr) == 0); 77059612Sjasone 77159612Sjasone log (" Protocol %s, Type %s\n", 77259612Sjasone protocol_strs[mproto], mutextype_strs[mkind]); 77359612Sjasone 77459612Sjasone log (" Lock on unlocked mutex - "); 77559612Sjasone ret = pthread_mutex_lock (&mutex); 77659612Sjasone check_result (/* expected */ 0, ret); 77759612Sjasone pthread_mutex_unlock (&mutex); 77859612Sjasone 77959612Sjasone log (" Lock on invalid mutex - "); 78059612Sjasone ret = pthread_mutex_lock (NULL); 78159612Sjasone check_result (/* expected */ EINVAL, ret); 78259612Sjasone 78359612Sjasone log (" Lock on mutex held by self - "); 78459612Sjasone assert (pthread_create (&state.tid, &pattr, lock_twice, 78559612Sjasone (void *) &state) == 0); 78659612Sjasone /* Let the thread start. */ 78759612Sjasone sleep (1); 78859612Sjasone state.cmd.mutex = &mutex; 78959612Sjasone state.ret = 0xdeadbeef; 79059612Sjasone assert (pthread_mutex_lock (&cond_mutex) == 0); 79159612Sjasone assert (pthread_cond_signal (&cond_var) == 0); 79259612Sjasone assert (pthread_mutex_unlock (&cond_mutex) == 0); 79359612Sjasone /* Let the thread receive and process the command. */ 79459612Sjasone sleep (1); 79559612Sjasone 79659612Sjasone switch (mkind) { 79759612Sjasone case M_POSIX: 79859612Sjasone check_result (/* expected */ EDEADLK, 79959612Sjasone state.ret); 80059612Sjasone break; 80159612Sjasone case M_SS2_DEFAULT: 80259612Sjasone check_result (/* expected */ EDEADLK, 80359612Sjasone state.ret); 80459612Sjasone break; 80559612Sjasone case M_SS2_ERRORCHECK: 80659612Sjasone check_result (/* expected */ EDEADLK, 80759612Sjasone state.ret); 80859612Sjasone break; 80959612Sjasone case M_SS2_NORMAL: 81059612Sjasone check_result (/* expected */ 0xdeadbeef, 81159612Sjasone state.ret); 81259612Sjasone break; 81359612Sjasone case M_SS2_RECURSIVE: 81459612Sjasone check_result (/* expected */ 0, state.ret); 81559612Sjasone break; 81659612Sjasone } 81759612Sjasone pthread_mutex_destroy (&mutex); 81859612Sjasone pthread_mutexattr_destroy (&mattr); 81959612Sjasone } 82059612Sjasone } 82159612Sjasone} 82259612Sjasone 82359612Sjasone 82459612Sjasonestatic void 82559612Sjasonemutex_unlock_test (void) 82659612Sjasone{ 82759612Sjasone const int test_thread_id = 0; /* ID of test thread */ 82859612Sjasone pthread_mutexattr_t mattr; 82959612Sjasone pthread_mutex_t mutex; 83059612Sjasone int mproto, ret; 83159612Sjasone mutex_kind_t mkind; 83259612Sjasone 83359612Sjasone /* 83459612Sjasone * Unlock a mutex. 83559612Sjasone * 83659612Sjasone * pthread_unlock not tested for: 83759612Sjasone */ 83859612Sjasone log ("Testing pthread_mutex_unlock\n"); 83959612Sjasone log ("----------------------------\n"); 84059612Sjasone 84159612Sjasone for (mproto = 0; mproto < NELEMENTS(protocols); mproto++) { 84259612Sjasone for (mkind = M_POSIX; mkind <= M_SS2_RECURSIVE; mkind++) { 84359612Sjasone /* Initialize the mutex attribute. */ 84459612Sjasone assert (pthread_mutexattr_init (&mattr) == 0); 84559612Sjasone assert (pthread_mutexattr_setprotocol (&mattr, 84659612Sjasone protocols[mproto]) == 0); 84759612Sjasone 84859612Sjasone /* 84959612Sjasone * Ensure that the first mutex type is a POSIX 85059612Sjasone * compliant mutex. 85159612Sjasone */ 85259612Sjasone if (mkind != M_POSIX) { 85359612Sjasone assert (pthread_mutexattr_settype (&mattr, 85459612Sjasone mutex_types[mkind]) == 0); 85559612Sjasone } 85659612Sjasone 85759612Sjasone /* Create the mutex. */ 85859612Sjasone assert (pthread_mutex_init (&mutex, &mattr) == 0); 85959612Sjasone 86059612Sjasone log (" Protocol %s, Type %s\n", 86159612Sjasone protocol_strs[mproto], mutextype_strs[mkind]); 86259612Sjasone 86359612Sjasone log (" Unlock on mutex held by self - "); 86459612Sjasone assert (pthread_mutex_lock (&mutex) == 0); 86559612Sjasone ret = pthread_mutex_unlock (&mutex); 86659612Sjasone check_result (/* expected */ 0, ret); 86759612Sjasone 86859612Sjasone log (" Unlock on invalid mutex - "); 86959612Sjasone ret = pthread_mutex_unlock (NULL); 87059612Sjasone check_result (/* expected */ EINVAL, ret); 87159612Sjasone 87259612Sjasone log (" Unlock on mutex locked by another thread - "); 87359612Sjasone send_mutex_cmd (test_thread_id, CMD_TAKE_MUTEX, &mutex); 87459612Sjasone sleep (1); 87559612Sjasone ret = pthread_mutex_unlock (&mutex); 87659612Sjasone switch (mkind) { 87759612Sjasone case M_POSIX: 87859612Sjasone check_result (/* expected */ EPERM, ret); 87959612Sjasone break; 88059612Sjasone case M_SS2_DEFAULT: 88159612Sjasone check_result (/* expected */ EPERM, ret); 88259612Sjasone break; 88359612Sjasone case M_SS2_ERRORCHECK: 88459612Sjasone check_result (/* expected */ EPERM, ret); 88559612Sjasone break; 88659612Sjasone case M_SS2_NORMAL: 88759612Sjasone check_result (/* expected */ EPERM, ret); 88859612Sjasone break; 88959612Sjasone case M_SS2_RECURSIVE: 89059612Sjasone check_result (/* expected */ EPERM, ret); 89159612Sjasone break; 89259612Sjasone } 89359612Sjasone if (ret == 0) { 89459612Sjasone /* 89559612Sjasone * If for some reason we were able to unlock 89659612Sjasone * the mutex, relock it so that the test 89759612Sjasone * thread has no problems releasing the mutex. 89859612Sjasone */ 89959612Sjasone pthread_mutex_lock (&mutex); 90059612Sjasone } 90159612Sjasone send_cmd (test_thread_id, CMD_RELEASE_ALL); 90259612Sjasone sleep (1); 90359612Sjasone 90459612Sjasone pthread_mutex_destroy (&mutex); 90559612Sjasone pthread_mutexattr_destroy (&mattr); 90659612Sjasone } 90759612Sjasone } 90859612Sjasone} 90959612Sjasone 91059612Sjasone 91159612Sjasonestatic void 91259612Sjasonequeueing_order_test (void) 91359612Sjasone{ 91459612Sjasone int i; 91559612Sjasone 91659612Sjasone log ("Testing queueing order\n"); 91759612Sjasone log ("----------------------\n"); 91859612Sjasone assert (pthread_mutex_lock (&waiter_mutex) == 0); 91959612Sjasone /* 92059612Sjasone * Tell the threads to report when they take the waiters mutex. 92159612Sjasone */ 92259612Sjasone assert (pthread_mutex_lock (&cond_mutex) == 0); 92359612Sjasone for (i = 0; i < NUM_THREADS; i++) { 92459612Sjasone states[i].flags = FLAGS_REPORT_WAITMUTEX; 92559612Sjasone assert (pthread_cond_signal (&states[i].cond_var) == 0); 92659612Sjasone } 92759612Sjasone assert (pthread_mutex_unlock (&cond_mutex) == 0); 92859612Sjasone 92959612Sjasone /* Signal the threads to continue. */ 93059612Sjasone sleep (1); 93159612Sjasone 93259612Sjasone /* Use the global condition variable next time. */ 93359612Sjasone use_global_condvar = 1; 93459612Sjasone 93559612Sjasone /* Release the waiting threads and allow them to run again. */ 93659612Sjasone assert (pthread_mutex_unlock (&waiter_mutex) == 0); 93759612Sjasone sleep (1); 93859612Sjasone 93959612Sjasone log (" Queueing order on a mutex - "); 94059612Sjasone check_run_order ("9,8,7,6,5,4,3,2,1,0"); 94159612Sjasone for (i = 0; i < NUM_THREADS; i = i + 1) { 94259612Sjasone /* Tell the threads to report when they've been signaled. */ 94359612Sjasone states[i].flags = FLAGS_REPORT_WAITCONDVAR; 94459612Sjasone } 94559612Sjasone 94659612Sjasone /* 94759612Sjasone * Prevent the threads from continuing their loop after we 94859612Sjasone * signal them. 94959612Sjasone */ 95059612Sjasone assert (pthread_mutex_lock (&waiter_mutex) == 0); 95159612Sjasone 95259612Sjasone 95359612Sjasone log (" Queueing order on a condition variable - "); 95459612Sjasone /* 95559612Sjasone * Signal one thread to run and see that the highest priority 95659612Sjasone * thread executes. 95759612Sjasone */ 95859612Sjasone assert (pthread_mutex_lock (&cond_mutex) == 0); 95959612Sjasone assert (pthread_cond_signal (&cond_var) == 0); 96059612Sjasone assert (pthread_mutex_unlock (&cond_mutex) == 0); 96159612Sjasone sleep (1); 96259612Sjasone if (states[NUM_THREADS - 1].status != STAT_WAITMUTEX) 96359612Sjasone log_error ("highest priority thread does not run.\n"); 96459612Sjasone 96559612Sjasone /* Signal the remaining threads. */ 96659612Sjasone assert (pthread_mutex_lock (&cond_mutex) == 0); 96759612Sjasone assert (pthread_cond_broadcast (&cond_var) == 0); 96859612Sjasone assert (pthread_mutex_unlock (&cond_mutex) == 0); 96959612Sjasone sleep (1); 97059612Sjasone 97159612Sjasone check_run_order ("9,8,7,6,5,4,3,2,1,0"); 97259612Sjasone for (i = 0; i < NUM_THREADS; i = i + 1) { 97359612Sjasone /* Tell the threads not to report anything. */ 97459612Sjasone states[i].flags = 0; 97559612Sjasone } 97659612Sjasone 97759612Sjasone /* Use the thread unique condition variable next time. */ 97859612Sjasone use_global_condvar = 0; 97959612Sjasone 98059612Sjasone /* Allow the threads to continue their loop. */ 98159612Sjasone assert (pthread_mutex_unlock (&waiter_mutex) == 0); 98259612Sjasone sleep (1); 98359612Sjasone} 98459612Sjasone 98559612Sjasone 98659612Sjasonestatic void 98759612Sjasonemutex_prioceiling_test (void) 98859612Sjasone{ 98959612Sjasone const int test_thread_id = 0; /* ID of test thread */ 99059612Sjasone pthread_mutexattr_t mattr; 99159612Sjasone struct sched_param param; 99259612Sjasone pthread_mutex_t m[3]; 99359612Sjasone mutex_kind_t mkind; 99459612Sjasone int i, ret, policy, my_prio, old_ceiling; 99559612Sjasone 99659612Sjasone log ("Testing priority ceilings\n"); 99759612Sjasone log ("-------------------------\n"); 99859612Sjasone for (mkind = M_POSIX; mkind <= M_SS2_RECURSIVE; mkind++) { 99959612Sjasone 100059612Sjasone log (" Protype PTHREAD_PRIO_PROTECT, Type %s\n", 100159612Sjasone mutextype_strs[mkind]); 100259612Sjasone 100359612Sjasone /* 100459612Sjasone * Initialize and create a mutex. 100559612Sjasone */ 100659612Sjasone assert (pthread_mutexattr_init (&mattr) == 0); 100759612Sjasone 100859612Sjasone /* Get this threads current priority. */ 100959612Sjasone assert (pthread_getschedparam (pthread_self(), &policy, 101059612Sjasone ¶m) == 0); 101159612Sjasone my_prio = param.sched_priority; /* save for later use */ 101259612Sjasone log_trace ("Current scheduling policy %d, priority %d\n", 101359612Sjasone policy, my_prio); 101459612Sjasone 101559612Sjasone /* 101659612Sjasone * Initialize and create 3 priority protection mutexes with 101759612Sjasone * default (max priority) ceilings. 101859612Sjasone */ 101959612Sjasone assert (pthread_mutexattr_setprotocol(&mattr, 102059612Sjasone PTHREAD_PRIO_PROTECT) == 0); 102159612Sjasone 102259612Sjasone /* 102359612Sjasone * Ensure that the first mutex type is a POSIX 102459612Sjasone * compliant mutex. 102559612Sjasone */ 102659612Sjasone if (mkind != M_POSIX) { 102759612Sjasone assert (pthread_mutexattr_settype (&mattr, 102859612Sjasone mutex_types[mkind]) == 0); 102959612Sjasone } 103059612Sjasone 103159612Sjasone for (i = 0; i < 3; i++) 103259612Sjasone assert (pthread_mutex_init (&m[i], &mattr) == 0); 103359612Sjasone 103459612Sjasone /* 103559612Sjasone * Set the ceiling priorities for the 3 priority protection 103659612Sjasone * mutexes to, 5 less than, equal to, and 5 greater than, 103759612Sjasone * this threads current priority. 103859612Sjasone */ 103959612Sjasone for (i = 0; i < 3; i++) 104059612Sjasone assert (pthread_mutex_setprioceiling (&m[i], 104159612Sjasone my_prio - 5 + 5*i, &old_ceiling) == 0); 104259612Sjasone 104359612Sjasone /* 104459612Sjasone * Check that if we attempt to take a mutex whose priority 104559612Sjasone * ceiling is lower than our priority, we get an error. 104659612Sjasone */ 104759612Sjasone log (" Lock with ceiling priority < thread priority - "); 104859612Sjasone ret = pthread_mutex_lock (&m[0]); 104959612Sjasone check_result (/* expected */ EINVAL, ret); 105059612Sjasone if (ret == 0) 105159612Sjasone pthread_mutex_unlock (&m[0]); 105259612Sjasone 105359612Sjasone /* 105459612Sjasone * Check that we can take a mutex whose priority ceiling 105559612Sjasone * is equal to our priority. 105659612Sjasone */ 105759612Sjasone log (" Lock with ceiling priority = thread priority - "); 105859612Sjasone ret = pthread_mutex_lock (&m[1]); 105959612Sjasone check_result (/* expected */ 0, ret); 106059612Sjasone if (ret == 0) 106159612Sjasone pthread_mutex_unlock (&m[1]); 106259612Sjasone 106359612Sjasone /* 106459612Sjasone * Check that we can take a mutex whose priority ceiling 106559612Sjasone * is higher than our priority. 106659612Sjasone */ 106759612Sjasone log (" Lock with ceiling priority > thread priority - "); 106859612Sjasone ret = pthread_mutex_lock (&m[2]); 106959612Sjasone check_result (/* expected */ 0, ret); 107059612Sjasone if (ret == 0) 107159612Sjasone pthread_mutex_unlock (&m[2]); 107259612Sjasone 107359612Sjasone /* 107459612Sjasone * Have the test thread go into a busy loop for 5 seconds 107559612Sjasone * and see that it doesn't block this thread (since the 107659612Sjasone * priority ceiling of mutex 0 and the priority of the test 107759612Sjasone * thread are both less than the priority of this thread). 107859612Sjasone */ 107959612Sjasone log (" Preemption with ceiling priority < thread " 108059612Sjasone "priority - "); 108159612Sjasone /* Have the test thread take mutex 0. */ 108259612Sjasone send_mutex_cmd (test_thread_id, CMD_TAKE_MUTEX, &m[0]); 108359612Sjasone sleep (1); 108459612Sjasone 108559612Sjasone log_trace ("Sending busy command.\n"); 108659612Sjasone send_cmd (test_thread_id, CMD_BUSY_LOOP); 108759612Sjasone log_trace ("Busy sent, yielding\n"); 108859612Sjasone pthread_yield (); 108959612Sjasone log_trace ("Returned from yield.\n"); 109059612Sjasone if (states[test_thread_id].flags & 109159612Sjasone (FLAGS_IS_BUSY | FLAGS_WAS_BUSY)) 109259612Sjasone log_error ("test thread inproperly preempted us.\n"); 109359612Sjasone else { 109459612Sjasone /* Let the thread finish its busy loop. */ 109559612Sjasone sleep (6); 109659612Sjasone if ((states[test_thread_id].flags & FLAGS_WAS_BUSY) == 0) 109759612Sjasone log_error ("test thread never finished.\n"); 109859612Sjasone else 109959612Sjasone log_pass (); 110059612Sjasone } 110159612Sjasone states[test_thread_id].flags &= ~FLAGS_WAS_BUSY; 110259612Sjasone 110359612Sjasone /* Have the test thread release mutex 0. */ 110459612Sjasone send_cmd (test_thread_id, CMD_RELEASE_ALL); 110559612Sjasone sleep (1); 110659612Sjasone 110759612Sjasone /* 110859612Sjasone * Have the test thread go into a busy loop for 5 seconds 110959612Sjasone * and see that it preempts this thread (since the priority 111059612Sjasone * ceiling of mutex 1 is the same as the priority of this 111159612Sjasone * thread). The test thread should not run to completion 111259612Sjasone * as its time quantum should expire before the 5 seconds 111359612Sjasone * are up. 111459612Sjasone */ 111559612Sjasone log (" Preemption with ceiling priority = thread " 111659612Sjasone "priority - "); 111759612Sjasone 111859612Sjasone /* Have the test thread take mutex 1. */ 111959612Sjasone send_mutex_cmd (test_thread_id, CMD_TAKE_MUTEX, &m[1]); 112059612Sjasone sleep (1); 112159612Sjasone 112259612Sjasone log_trace ("Sending busy\n"); 112359612Sjasone send_cmd (test_thread_id, CMD_BUSY_LOOP); 112459612Sjasone log_trace ("Busy sent, yielding\n"); 112559612Sjasone pthread_yield (); 112659612Sjasone log_trace ("Returned from yield.\n"); 112759612Sjasone if ((states[test_thread_id].flags & FLAGS_IS_BUSY) == 0) 112859612Sjasone log_error ("test thread did not switch in on yield.\n"); 112959612Sjasone else if (states[test_thread_id].flags & FLAGS_WAS_BUSY) 113059612Sjasone log_error ("test thread ran to completion.\n"); 113159612Sjasone else { 113259612Sjasone /* Let the thread finish its busy loop. */ 113359612Sjasone sleep (6); 113459612Sjasone if ((states[test_thread_id].flags & FLAGS_WAS_BUSY) == 0) 113559612Sjasone log_error ("test thread never finished.\n"); 113659612Sjasone else 113759612Sjasone log_pass (); 113859612Sjasone } 113959612Sjasone states[test_thread_id].flags &= ~FLAGS_WAS_BUSY; 114059612Sjasone 114159612Sjasone /* Have the test thread release mutex 1. */ 114259612Sjasone send_cmd (test_thread_id, CMD_RELEASE_ALL); 114359612Sjasone sleep (1); 114459612Sjasone 114559612Sjasone /* 114659612Sjasone * Set the scheduling policy of the test thread to SCHED_FIFO 114759612Sjasone * and have it go into a busy loop for 5 seconds. This 114859612Sjasone * thread is SCHED_RR, and since the priority ceiling of 114959612Sjasone * mutex 1 is the same as the priority of this thread, the 115059612Sjasone * test thread should run to completion once it is switched 115159612Sjasone * in. 115259612Sjasone */ 115359612Sjasone log (" SCHED_FIFO scheduling and ceiling priority = " 115459612Sjasone "thread priority - "); 115559612Sjasone param.sched_priority = states[test_thread_id].priority; 115659612Sjasone assert (pthread_setschedparam (states[test_thread_id].tid, 115759612Sjasone SCHED_FIFO, ¶m) == 0); 115859612Sjasone 115959612Sjasone /* Have the test thread take mutex 1. */ 116059612Sjasone send_mutex_cmd (test_thread_id, CMD_TAKE_MUTEX, &m[1]); 116159612Sjasone sleep (1); 116259612Sjasone 116359612Sjasone log_trace ("Sending busy\n"); 116459612Sjasone send_cmd (test_thread_id, CMD_BUSY_LOOP); 116559612Sjasone log_trace ("Busy sent, yielding\n"); 116659612Sjasone pthread_yield (); 116759612Sjasone log_trace ("Returned from yield.\n"); 116859612Sjasone if ((states[test_thread_id].flags & FLAGS_WAS_BUSY) == 0) { 116959612Sjasone log_error ("test thread did not run to completion.\n"); 117059612Sjasone /* Let the thread finish it's busy loop. */ 117159612Sjasone sleep (6); 117259612Sjasone } 117359612Sjasone else 117459612Sjasone log_pass (); 117559612Sjasone states[test_thread_id].flags &= ~FLAGS_WAS_BUSY; 117659612Sjasone 117759612Sjasone /* Restore the test thread scheduling parameters. */ 117859612Sjasone param.sched_priority = states[test_thread_id].priority; 117959612Sjasone assert (pthread_setschedparam (states[test_thread_id].tid, 118059612Sjasone SCHED_RR, ¶m) == 0); 118159612Sjasone 118259612Sjasone /* Have the test thread release mutex 1. */ 118359612Sjasone send_cmd (test_thread_id, CMD_RELEASE_ALL); 118459612Sjasone sleep (1); 118559612Sjasone 118659612Sjasone /* 118759612Sjasone * Have the test thread go into a busy loop for 5 seconds 118859612Sjasone * and see that it preempts this thread (since the priority 118959612Sjasone * ceiling of mutex 2 is the greater than the priority of 119059612Sjasone * this thread). The test thread should run to completion 119159612Sjasone * and block this thread because its active priority is 119259612Sjasone * higher. 119359612Sjasone */ 119459612Sjasone log (" SCHED_FIFO scheduling and ceiling priority > " 119559612Sjasone "thread priority - "); 119659612Sjasone /* Have the test thread take mutex 2. */ 119759612Sjasone send_mutex_cmd (test_thread_id, CMD_TAKE_MUTEX, &m[2]); 119859612Sjasone sleep (1); 119959612Sjasone 120059612Sjasone log_trace ("Sending busy\n"); 120159612Sjasone send_cmd (test_thread_id, CMD_BUSY_LOOP); 120259612Sjasone log_trace ("Busy sent, yielding\n"); 120359612Sjasone pthread_yield (); 120459612Sjasone log_trace ("Returned from yield.\n"); 120559612Sjasone if ((states[test_thread_id].flags & FLAGS_IS_BUSY) != 0) { 120659612Sjasone log_error ("test thread did not run to completion.\n"); 120759612Sjasone /* Let the thread finish it's busy loop. */ 120859612Sjasone sleep (6); 120959612Sjasone } 121059612Sjasone else if ((states[test_thread_id].flags & FLAGS_WAS_BUSY) == 0) 121159612Sjasone log_error ("test thread never finished.\n"); 121259612Sjasone else 121359612Sjasone log_pass (); 121459612Sjasone states[test_thread_id].flags &= ~FLAGS_WAS_BUSY; 121559612Sjasone 121659612Sjasone /* Have the test thread release mutex 2. */ 121759612Sjasone send_cmd (test_thread_id, CMD_RELEASE_ALL); 121859612Sjasone sleep (1); 121959612Sjasone 122059612Sjasone /* Destroy the mutexes. */ 122159612Sjasone for (i = 0; i < 3; i++) 122259612Sjasone assert (pthread_mutex_destroy (&m[i]) == 0); 122359612Sjasone } 122459612Sjasone} 122559612Sjasone 122659612Sjasone 122759612Sjasonestatic void 122859612Sjasonemutex_prioinherit_test (void) 122959612Sjasone{ 123059612Sjasone pthread_mutexattr_t mattr; 123159612Sjasone struct sched_param param; 123259612Sjasone pthread_mutex_t m[3]; 123359612Sjasone mutex_kind_t mkind; 123459612Sjasone int i, policy, my_prio; 123559612Sjasone 123659612Sjasone /* Get this threads current priority. */ 123759612Sjasone assert (pthread_getschedparam (pthread_self(), &policy, 123859612Sjasone ¶m) == 0); 123959612Sjasone my_prio = param.sched_priority; /* save for later use */ 124059612Sjasone log_trace ("Current scheduling policy %d, priority %d\n", 124159612Sjasone policy, my_prio); 124259612Sjasone 124359612Sjasone log ("Testing priority inheritence\n"); 124459612Sjasone log ("----------------------------\n"); 124559612Sjasone for (mkind = M_POSIX; mkind <= M_SS2_RECURSIVE; mkind++) { 124659612Sjasone 124759612Sjasone log (" Protype PTHREAD_PRIO_INHERIT, Type %s\n", 124859612Sjasone mutextype_strs[mkind]); 124959612Sjasone 125059612Sjasone /* 125159612Sjasone * Initialize and create a mutex. 125259612Sjasone */ 125359612Sjasone assert (pthread_mutexattr_init (&mattr) == 0); 125459612Sjasone 125559612Sjasone /* 125659612Sjasone * Initialize and create 3 priority inheritence mutexes with 125759612Sjasone * default (max priority) ceilings. 125859612Sjasone */ 125959612Sjasone assert (pthread_mutexattr_setprotocol(&mattr, 126059612Sjasone PTHREAD_PRIO_INHERIT) == 0); 126159612Sjasone 126259612Sjasone /* 126359612Sjasone * Ensure that the first mutex type is a POSIX 126459612Sjasone * compliant mutex. 126559612Sjasone */ 126659612Sjasone if (mkind != M_POSIX) { 126759612Sjasone assert (pthread_mutexattr_settype (&mattr, 126859612Sjasone mutex_types[mkind]) == 0); 126959612Sjasone } 127059612Sjasone 127159612Sjasone for (i = 0; i < 3; i++) 127259612Sjasone assert (pthread_mutex_init (&m[i], &mattr) == 0); 127359612Sjasone 127459612Sjasone /* 127559612Sjasone * Test setup: 127659612Sjasone * Thread 4 - take mutex 0, 1 127759612Sjasone * Thread 2 - enter protected busy loop with mutex 0 127859612Sjasone * Thread 3 - enter protected busy loop with mutex 1 127959612Sjasone * Thread 4 - enter protected busy loop with mutex 2 128059612Sjasone * Thread 5 - enter busy loop 128159612Sjasone * Thread 6 - enter protected busy loop with mutex 0 128259612Sjasone * Thread 4 - releases mutexes 1 and 0. 128359612Sjasone * 128459612Sjasone * Expected results: 128559612Sjasone * Threads complete in order 4, 6, 5, 3, 2 128659612Sjasone */ 128759612Sjasone log (" Simple inheritence test - "); 128859612Sjasone 128959612Sjasone /* 129059612Sjasone * Command thread 4 to take mutexes 0 and 1. 129159612Sjasone */ 129259612Sjasone send_mutex_cmd (4, CMD_TAKE_MUTEX, &m[0]); 129359612Sjasone sleep (1); /* Allow command to be received. */ 129459612Sjasone send_mutex_cmd (4, CMD_TAKE_MUTEX, &m[1]); 129559612Sjasone sleep (1); 129659612Sjasone 129759612Sjasone /* 129859612Sjasone * Tell the threads to report themselves when they are 129959612Sjasone * at the bottom of their loop (waiting on wait_mutex). 130059612Sjasone */ 130159612Sjasone for (i = 0; i < NUM_THREADS; i++) 130259612Sjasone states[i].flags |= FLAGS_REPORT_WAITMUTEX; 130359612Sjasone 130459612Sjasone /* 130559612Sjasone * Command thread 2 to take mutex 0 and thread 3 to take 130659612Sjasone * mutex 1, both via a protected operation command. Since 130759612Sjasone * thread 4 owns mutexes 0 and 1, both threads 2 and 3 130859612Sjasone * will block until the mutexes are released by thread 4. 130959612Sjasone */ 131059612Sjasone log_trace ("Commanding protected operation to thread 2.\n"); 131159612Sjasone send_mutex_cmd (2, CMD_PROTECTED_OP, &m[0]); 131259612Sjasone log_trace ("Commanding protected operation to thread 3.\n"); 131359612Sjasone send_mutex_cmd (3, CMD_PROTECTED_OP, &m[1]); 131459612Sjasone sleep (1); 131559612Sjasone 131659612Sjasone /* 131759612Sjasone * Command thread 4 to take mutex 2 via a protected operation 131859612Sjasone * and thread 5 to enter a busy loop for 5 seconds. Since 131959612Sjasone * thread 5 has higher priority than thread 4, thread 5 will 132059612Sjasone * enter the busy loop before thread 4 is activated. 132159612Sjasone */ 132259612Sjasone log_trace ("Commanding protected operation to thread 4.\n"); 132359612Sjasone send_mutex_cmd (4, CMD_PROTECTED_OP, &m[2]); 132459612Sjasone log_trace ("Commanding busy loop to thread 5.\n"); 132559612Sjasone send_cmd (5, CMD_BUSY_LOOP); 132659612Sjasone sleep (1); 132759612Sjasone if ((states[5].flags & FLAGS_IS_BUSY) == 0) 132859612Sjasone log_error ("thread 5 is not running.\n"); 132959612Sjasone log_trace ("Commanding protected operation thread 6.\n"); 133059612Sjasone send_mutex_cmd (6, CMD_PROTECTED_OP, &m[0]); 133159612Sjasone sleep (1); 133259612Sjasone if ((states[4].flags & FLAGS_WAS_BUSY) == 0) 133359612Sjasone log_error ("thread 4 failed to inherit priority.\n"); 133459612Sjasone states[4].flags = 0; 133559612Sjasone send_cmd (4, CMD_RELEASE_ALL); 133659612Sjasone sleep (5); 133759612Sjasone check_run_order ("4,6,5,3,2"); 133859612Sjasone 133959612Sjasone /* 134059612Sjasone * Clear the flags. 134159612Sjasone */ 134259612Sjasone for (i = 0; i < NUM_THREADS; i++) 134359612Sjasone states[i].flags = 0; 134459612Sjasone 134559612Sjasone /* 134659612Sjasone * Test setup: 134759612Sjasone * Thread 2 - enter busy loop (SCHED_FIFO) 134859612Sjasone * Thread 4 - take mutex 0 134959612Sjasone * Thread 4 - priority change to same priority as thread 2 135059612Sjasone * Thread 4 - release mutex 0 135159612Sjasone * 135259612Sjasone * Expected results: 135359612Sjasone * Since thread 4 owns a priority mutex, it should be 135459612Sjasone * placed at the front of the run queue (for its new 135559612Sjasone * priority slot) when its priority is lowered to the 135659612Sjasone * same priority as thread 2. If thread 4 did not own 135759612Sjasone * a priority mutex, then it would have been added to 135859612Sjasone * the end of the run queue and thread 2 would have 135959612Sjasone * executed until it blocked (because it's scheduling 136059612Sjasone * policy is SCHED_FIFO). 136159612Sjasone * 136259612Sjasone */ 136359612Sjasone log (" Inheritence test with change of priority - "); 136459612Sjasone 136559612Sjasone /* 136659612Sjasone * Change threads 2 and 4 scheduling policies to be 136759612Sjasone * SCHED_FIFO. 136859612Sjasone */ 136959612Sjasone param.sched_priority = states[2].priority; 137059612Sjasone assert (pthread_setschedparam (states[2].tid, SCHED_FIFO, 137159612Sjasone ¶m) == 0); 137259612Sjasone param.sched_priority = states[4].priority; 137359612Sjasone assert (pthread_setschedparam (states[4].tid, SCHED_FIFO, 137459612Sjasone ¶m) == 0); 137559612Sjasone 137659612Sjasone /* 137759612Sjasone * Command thread 4 to take mutex 0. 137859612Sjasone */ 137959612Sjasone send_mutex_cmd (4, CMD_TAKE_MUTEX, &m[0]); 138059612Sjasone sleep (1); 138159612Sjasone 138259612Sjasone /* 138359612Sjasone * Command thread 2 to enter busy loop. 138459612Sjasone */ 138559612Sjasone send_cmd (2, CMD_BUSY_LOOP); 138659612Sjasone sleep (1); /* Allow command to be received. */ 138759612Sjasone 138859612Sjasone /* 138959612Sjasone * Command thread 4 to enter busy loop. 139059612Sjasone */ 139159612Sjasone send_cmd (4, CMD_BUSY_LOOP); 139259612Sjasone sleep (1); /* Allow command to be received. */ 139359612Sjasone 139459612Sjasone /* Have threads 2 and 4 report themselves. */ 139559612Sjasone states[2].flags = FLAGS_REPORT_WAITMUTEX; 139659612Sjasone states[4].flags = FLAGS_REPORT_WAITMUTEX; 139759612Sjasone 139859612Sjasone /* Change the priority of thread 4. */ 139959612Sjasone param.sched_priority = states[2].priority; 140059612Sjasone assert (pthread_setschedparam (states[4].tid, SCHED_FIFO, 140159612Sjasone ¶m) == 0); 140259612Sjasone sleep (5); 140359612Sjasone check_run_order ("4,2"); 140459612Sjasone 140559612Sjasone /* Clear the flags */ 140659612Sjasone states[2].flags = 0; 140759612Sjasone states[4].flags = 0; 140859612Sjasone 140959612Sjasone /* Reset the policies. */ 141059612Sjasone param.sched_priority = states[2].priority; 141159612Sjasone assert (pthread_setschedparam (states[2].tid, SCHED_RR, 141259612Sjasone ¶m) == 0); 141359612Sjasone param.sched_priority = states[4].priority; 141459612Sjasone assert (pthread_setschedparam (states[4].tid, SCHED_RR, 141559612Sjasone ¶m) == 0); 141659612Sjasone 141759612Sjasone send_cmd (4, CMD_RELEASE_MUTEX); 141859612Sjasone sleep (1); 141959612Sjasone 142059612Sjasone /* Destroy the mutexes. */ 142159612Sjasone for (i = 0; i < 3; i++) 142259612Sjasone assert (pthread_mutex_destroy (&m[i]) == 0); 142359612Sjasone } 142459612Sjasone} 142559612Sjasone 142659612Sjasone 142759612Sjasoneint main (int argc, char *argv[]) 142859612Sjasone{ 142959612Sjasone pthread_mutexattr_t mattr; 143059612Sjasone pthread_condattr_t cattr; 143159612Sjasone pthread_attr_t pattr; 143259612Sjasone int i, policy, main_prio; 143359612Sjasone void * exit_status; 143459612Sjasone sigset_t mask; 143559612Sjasone struct sigaction act; 143659612Sjasone struct sched_param param; 143759612Sjasone 143859612Sjasone assert (pthread_getschedparam (pthread_self (), &policy, ¶m) == 0); 143959612Sjasone main_prio = param.sched_priority; 144059612Sjasone 144159612Sjasone /* Setupt our signal mask. */ 144259612Sjasone sigfillset (&mask); 144359612Sjasone sigdelset (&mask, SIGINT); 144459612Sjasone sigprocmask (SIG_SETMASK, &mask, NULL); 144559612Sjasone 144659612Sjasone /* Install a signal handler for SIGINT */ 144759612Sjasone sigemptyset (&act.sa_mask); 144859612Sjasone sigaddset (&act.sa_mask, SIGINT); 144959612Sjasone act.sa_handler = sighandler; 145059612Sjasone act.sa_flags = SA_RESTART; 145159612Sjasone sigaction (SIGINT, &act, NULL); 145259612Sjasone 145359612Sjasone /* 145459612Sjasone * Initialize the thread attribute. 145559612Sjasone */ 145659612Sjasone assert (pthread_attr_init (&pattr) == 0); 145759612Sjasone assert (pthread_attr_setdetachstate (&pattr, 145859612Sjasone PTHREAD_CREATE_JOINABLE) == 0); 145959612Sjasone 146059612Sjasone /* 146159612Sjasone * Initialize and create the waiter and condvar mutexes. 146259612Sjasone */ 146359612Sjasone assert (pthread_mutexattr_init (&mattr) == 0); 146459612Sjasone assert (pthread_mutex_init (&waiter_mutex, &mattr) == 0); 146559612Sjasone assert (pthread_mutex_init (&cond_mutex, &mattr) == 0); 146659612Sjasone 146759612Sjasone /* 146859612Sjasone * Initialize and create a condition variable. 146959612Sjasone */ 147059612Sjasone assert (pthread_condattr_init (&cattr) == 0); 147159612Sjasone assert (pthread_cond_init (&cond_var, &cattr) == 0); 147259612Sjasone 147359612Sjasone /* Create a pipe to catch the results of thread wakeups. */ 147459612Sjasone assert (pipe (pipefd) == 0); 147559612Sjasone 147659612Sjasone#ifdef DEBUG 147759612Sjasone assert (pthread_switch_add_np (kern_switch) == 0); 147859612Sjasone#endif 147959612Sjasone 148059612Sjasone /* 148159612Sjasone * Create the waiting threads. 148259612Sjasone */ 148359612Sjasone for (i = 0; i < NUM_THREADS; i++) { 148459612Sjasone assert (pthread_cond_init (&states[i].cond_var, &cattr) == 0); 148559612Sjasone states[i].id = (u_int8_t) i; /* NUM_THREADS must be <= 256 */ 148659612Sjasone states[i].status = 0; 148759612Sjasone states[i].cmd.cmd_id = CMD_NONE; 148859612Sjasone states[i].flags = 0; /* No flags yet. */ 148959612Sjasone assert (pthread_create (&states[i].tid, &pattr, waiter, 149059612Sjasone (void *) &states[i]) == 0); 149159612Sjasone param.sched_priority = main_prio - 10 + i; 149259612Sjasone states[i].priority = param.sched_priority; 149359612Sjasone assert (pthread_setschedparam (states[i].tid, SCHED_OTHER, 149459612Sjasone ¶m) == 0); 149559612Sjasone#if defined(_LIBC_R_) 149659612Sjasone { 149759612Sjasone char buf[30]; 149859612Sjasone 149959612Sjasone snprintf (buf, sizeof(buf), "waiter_%d", i); 150059612Sjasone pthread_set_name_np (states[i].tid, buf); 150159612Sjasone } 150259612Sjasone#endif 150359612Sjasone } 150459612Sjasone 150559612Sjasone /* Allow the threads to start. */ 150659612Sjasone sleep (1); 150759612Sjasone log_trace ("Done creating threads.\n"); 150859612Sjasone 150959612Sjasone log ("\n"); 151059612Sjasone mutex_init_test (); 151159612Sjasone log ("\n"); 151259612Sjasone mutex_destroy_test (); 151359612Sjasone log ("\n"); 151459612Sjasone mutex_lock_test (); 151559612Sjasone log ("\n"); 151659612Sjasone mutex_unlock_test (); 151759612Sjasone log ("\n"); 151859612Sjasone queueing_order_test (); 151959612Sjasone log ("\n"); 152059612Sjasone mutex_prioinherit_test (); 152159612Sjasone log ("\n"); 152259612Sjasone mutex_prioceiling_test (); 152359612Sjasone log ("\n"); 152459612Sjasone 152559612Sjasone log ("Total tests %d, passed %d, failed %d\n", 152659612Sjasone total, pass_count, error_count); 152759612Sjasone 152859612Sjasone /* Set the done flag and signal the threads to exit. */ 152959612Sjasone log_trace ("Setting done flag.\n"); 153059612Sjasone done = 1; 153159612Sjasone 153259612Sjasone /* 153359612Sjasone * Wait for the threads to finish. 153459612Sjasone */ 153559612Sjasone log_trace ("Trying to join threads.\n"); 153659612Sjasone for (i = 0; i < NUM_THREADS; i++) { 153759612Sjasone send_cmd (i, CMD_NONE); 153859612Sjasone assert (pthread_join (states[i].tid, &exit_status) == 0); 153959612Sjasone } 154059612Sjasone 154159612Sjasone /* Clean up after ourselves. */ 154259612Sjasone close (pipefd[0]); 154359612Sjasone close (pipefd[1]); 154459612Sjasone 154559612Sjasone if (error_count != 0) 154659612Sjasone exit (EX_OSERR); /* any better ideas??? */ 154759612Sjasone else 154859612Sjasone exit (EX_OK); 154959612Sjasone} 1550