mutex_d.c revision 81975
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 81975 2001-08-20 12:53:36Z kris $
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
16859612Sjasonestatic FILE *logfile = stdout;
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));
35759612Sjasone			log_trace ("Thread %d: wrote %d 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		    &param) == 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, &param) == 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, &param) == 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	    &param) == 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		    &param) == 0);
137559612Sjasone		param.sched_priority = states[4].priority;
137659612Sjasone		assert (pthread_setschedparam (states[4].tid, SCHED_FIFO,
137759612Sjasone		    &param) == 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		    &param) == 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		    &param) == 0);
141659612Sjasone		param.sched_priority = states[4].priority;
141759612Sjasone		assert (pthread_setschedparam (states[4].tid, SCHED_RR,
141859612Sjasone		    &param) == 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
144159612Sjasone	assert (pthread_getschedparam (pthread_self (), &policy, &param) == 0);
144259612Sjasone	main_prio = param.sched_priority;
144359612Sjasone
144459612Sjasone	/* Setupt our signal mask. */
144559612Sjasone	sigfillset (&mask);
144659612Sjasone	sigdelset (&mask, SIGINT);
144759612Sjasone	sigprocmask (SIG_SETMASK, &mask, NULL);
144859612Sjasone
144959612Sjasone	/* Install a signal handler for SIGINT */
145059612Sjasone	sigemptyset (&act.sa_mask);
145159612Sjasone	sigaddset (&act.sa_mask, SIGINT);
145259612Sjasone	act.sa_handler = sighandler;
145359612Sjasone	act.sa_flags = SA_RESTART;
145459612Sjasone	sigaction (SIGINT, &act, NULL);
145559612Sjasone
145659612Sjasone	/*
145759612Sjasone	 * Initialize the thread attribute.
145859612Sjasone	 */
145959612Sjasone	assert (pthread_attr_init (&pattr) == 0);
146059612Sjasone	assert (pthread_attr_setdetachstate (&pattr,
146159612Sjasone	    PTHREAD_CREATE_JOINABLE) == 0);
146259612Sjasone
146359612Sjasone	/*
146459612Sjasone	 * Initialize and create the waiter and condvar mutexes.
146559612Sjasone	 */
146659612Sjasone	assert (pthread_mutexattr_init (&mattr) == 0);
146759612Sjasone	assert (pthread_mutex_init (&waiter_mutex, &mattr) == 0);
146859612Sjasone	assert (pthread_mutex_init (&cond_mutex, &mattr) == 0);
146959612Sjasone
147059612Sjasone	/*
147159612Sjasone	 * Initialize and create a condition variable.
147259612Sjasone	 */
147359612Sjasone	assert (pthread_condattr_init (&cattr) == 0);
147459612Sjasone	assert (pthread_cond_init (&cond_var, &cattr) == 0);
147559612Sjasone
147659612Sjasone	/* Create a pipe to catch the results of thread wakeups. */
147759612Sjasone	assert (pipe (pipefd) == 0);
147859612Sjasone
147959612Sjasone#ifdef DEBUG
148059612Sjasone	assert (pthread_switch_add_np (kern_switch) == 0);
148159612Sjasone#endif
148259612Sjasone
148359612Sjasone	/*
148459612Sjasone	 * Create the waiting threads.
148559612Sjasone	 */
148659612Sjasone	for (i = 0; i < NUM_THREADS; i++) {
148759612Sjasone		assert (pthread_cond_init (&states[i].cond_var, &cattr) == 0);
148859612Sjasone		states[i].id = (u_int8_t) i;  /* NUM_THREADS must be <= 256 */
148959612Sjasone		states[i].status = 0;
149059612Sjasone		states[i].cmd.cmd_id = CMD_NONE;
149159612Sjasone		states[i].flags = 0;	/* No flags yet. */
149259612Sjasone		assert (pthread_create (&states[i].tid, &pattr, waiter,
149359612Sjasone		    (void *) &states[i]) == 0);
149459612Sjasone		param.sched_priority = main_prio - 10 + i;
149559612Sjasone		states[i].priority = param.sched_priority;
149659612Sjasone		assert (pthread_setschedparam (states[i].tid, SCHED_OTHER,
149759612Sjasone		    &param) == 0);
149859612Sjasone#if defined(_LIBC_R_)
149959612Sjasone		{
150059612Sjasone			char buf[30];
150159612Sjasone
150259612Sjasone			snprintf (buf, sizeof(buf), "waiter_%d", i);
150359612Sjasone			pthread_set_name_np (states[i].tid, buf);
150459612Sjasone		}
150559612Sjasone#endif
150659612Sjasone	}
150759612Sjasone
150859612Sjasone	/* Allow the threads to start. */
150959612Sjasone	sleep (1);
151059612Sjasone	log_trace ("Done creating threads.\n");
151159612Sjasone
151259612Sjasone	log ("\n");
151359612Sjasone	mutex_init_test ();
151459612Sjasone	log ("\n");
151559612Sjasone	mutex_destroy_test ();
151659612Sjasone	log ("\n");
151759612Sjasone	mutex_lock_test ();
151859612Sjasone	log ("\n");
151959612Sjasone	mutex_unlock_test ();
152059612Sjasone	log ("\n");
152159612Sjasone	queueing_order_test ();
152259612Sjasone	log ("\n");
152359612Sjasone	mutex_prioinherit_test ();
152459612Sjasone	log ("\n");
152559612Sjasone	mutex_prioceiling_test ();
152659612Sjasone	log ("\n");
152759612Sjasone
152859612Sjasone	log ("Total tests %d, passed %d, failed %d\n",
152959612Sjasone	    total, pass_count, error_count);
153059612Sjasone
153159612Sjasone	/* Set the done flag and signal the threads to exit. */
153259612Sjasone	log_trace ("Setting done flag.\n");
153359612Sjasone	done = 1;
153459612Sjasone
153559612Sjasone	/*
153659612Sjasone	 * Wait for the threads to finish.
153759612Sjasone	 */
153859612Sjasone	log_trace ("Trying to join threads.\n");
153959612Sjasone	for (i = 0; i < NUM_THREADS; i++) {
154059612Sjasone		send_cmd (i, CMD_NONE);
154159612Sjasone		assert (pthread_join (states[i].tid, &exit_status) == 0);
154259612Sjasone	}
154359612Sjasone
154459612Sjasone	/* Clean up after ourselves. */
154559612Sjasone	close (pipefd[0]);
154659612Sjasone	close (pipefd[1]);
154759612Sjasone
154859612Sjasone	if (error_count != 0)
154959612Sjasone		exit (EX_OSERR);	/* any better ideas??? */
155059612Sjasone	else
155159612Sjasone		exit (EX_OK);
155259612Sjasone}
1553