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