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