10dc076565f772bb1953209fb69ea150b494aaa40robbiew/*
20dc076565f772bb1953209fb69ea150b494aaa40robbiew * Copyright (c) 2004, Bull S.A..  All rights reserved.
30dc076565f772bb1953209fb69ea150b494aaa40robbiew * Created by: Sebastien Decugis
40dc076565f772bb1953209fb69ea150b494aaa40robbiew
50dc076565f772bb1953209fb69ea150b494aaa40robbiew * This program is free software; you can redistribute it and/or modify it
60dc076565f772bb1953209fb69ea150b494aaa40robbiew * under the terms of version 2 of the GNU General Public License as
70dc076565f772bb1953209fb69ea150b494aaa40robbiew * published by the Free Software Foundation.
80dc076565f772bb1953209fb69ea150b494aaa40robbiew *
90dc076565f772bb1953209fb69ea150b494aaa40robbiew * This program is distributed in the hope that it would be useful, but
100dc076565f772bb1953209fb69ea150b494aaa40robbiew * WITHOUT ANY WARRANTY; without even the implied warranty of
110dc076565f772bb1953209fb69ea150b494aaa40robbiew * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
120dc076565f772bb1953209fb69ea150b494aaa40robbiew *
130dc076565f772bb1953209fb69ea150b494aaa40robbiew * You should have received a copy of the GNU General Public License along
14fed9641096e27f79a0f2d9adfe9839dd8d11dc0fWanlong Gao * with this program; if not, write the Free Software Foundation, Inc.,
15fed9641096e27f79a0f2d9adfe9839dd8d11dc0fWanlong Gao * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
160dc076565f772bb1953209fb69ea150b494aaa40robbiew
170dc076565f772bb1953209fb69ea150b494aaa40robbiew * This sample test aims to check the following assertion:
180dc076565f772bb1953209fb69ea150b494aaa40robbiew *
192c28215423293e443469a07ae7011135d058b671Garrett Cooper * If the mutex is of type PTHREAD_MUTEX_RECURSIVE,
202c28215423293e443469a07ae7011135d058b671Garrett Cooper * and the calling thread already owns the mutex,
210dc076565f772bb1953209fb69ea150b494aaa40robbiew * the call is successful (the lock count is incremented).
220dc076565f772bb1953209fb69ea150b494aaa40robbiew
230dc076565f772bb1953209fb69ea150b494aaa40robbiew * The steps are:
240dc076565f772bb1953209fb69ea150b494aaa40robbiew *
250dc076565f772bb1953209fb69ea150b494aaa40robbiew *   -> trylock the mutex. It shall suceed.
260dc076565f772bb1953209fb69ea150b494aaa40robbiew *   -> trylock the mutex again. It shall suceed again
270dc076565f772bb1953209fb69ea150b494aaa40robbiew *   -> unlock once
280dc076565f772bb1953209fb69ea150b494aaa40robbiew *   -> create a new child (either thread or process)
290dc076565f772bb1953209fb69ea150b494aaa40robbiew *      -> the new child trylock the mutex. It shall fail.
300dc076565f772bb1953209fb69ea150b494aaa40robbiew *   -> Unlock. It shall succeed.
310dc076565f772bb1953209fb69ea150b494aaa40robbiew *   -> Unlock again. It shall fail.
320dc076565f772bb1953209fb69ea150b494aaa40robbiew *   -> undo everything.
330dc076565f772bb1953209fb69ea150b494aaa40robbiew */
342c28215423293e443469a07ae7011135d058b671Garrett Cooper
350dc076565f772bb1953209fb69ea150b494aaa40robbiew /* We are testing conformance to IEEE Std 1003.1, 2003 Edition */
36354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#define _POSIX_C_SOURCE 200112L
372c28215423293e443469a07ae7011135d058b671Garrett Cooper
380dc076565f772bb1953209fb69ea150b494aaa40robbiew /* We need the XSI extention for the mutex attributes
39354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao    and the mkstemp() routine */
400dc076565f772bb1953209fb69ea150b494aaa40robbiew#ifndef WITHOUT_XOPEN
41354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#define _XOPEN_SOURCE	600
420dc076565f772bb1953209fb69ea150b494aaa40robbiew#endif
430dc076565f772bb1953209fb69ea150b494aaa40robbiew /********************************************************************************************/
440dc076565f772bb1953209fb69ea150b494aaa40robbiew/****************************** standard includes *****************************************/
450dc076565f772bb1953209fb69ea150b494aaa40robbiew/********************************************************************************************/
46354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#include <pthread.h>
47354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#include <stdarg.h>
48354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#include <stdio.h>
49354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#include <stdlib.h>
50354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#include <unistd.h>
510dc076565f772bb1953209fb69ea150b494aaa40robbiew
52354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#include <errno.h>
53354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#include <sys/wait.h>
54354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#include <sys/mman.h>
55354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#include <string.h>
562c28215423293e443469a07ae7011135d058b671Garrett Cooper
570dc076565f772bb1953209fb69ea150b494aaa40robbiew/********************************************************************************************/
580dc076565f772bb1953209fb69ea150b494aaa40robbiew/******************************   Test framework   *****************************************/
590dc076565f772bb1953209fb69ea150b494aaa40robbiew/********************************************************************************************/
60354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#include "../testfrmw/testfrmw.h"
61354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#include "../testfrmw/testfrmw.c"
620dc076565f772bb1953209fb69ea150b494aaa40robbiew /* This header is responsible for defining the following macros:
632c28215423293e443469a07ae7011135d058b671Garrett Cooper  * UNRESOLVED(ret, descr);
640dc076565f772bb1953209fb69ea150b494aaa40robbiew  *    where descr is a description of the error and ret is an int (error code for example)
650dc076565f772bb1953209fb69ea150b494aaa40robbiew  * FAILED(descr);
660dc076565f772bb1953209fb69ea150b494aaa40robbiew  *    where descr is a short text saying why the test has failed.
670dc076565f772bb1953209fb69ea150b494aaa40robbiew  * PASSED();
680dc076565f772bb1953209fb69ea150b494aaa40robbiew  *    No parameter.
692c28215423293e443469a07ae7011135d058b671Garrett Cooper  *
700dc076565f772bb1953209fb69ea150b494aaa40robbiew  * Both three macros shall terminate the calling process.
710dc076565f772bb1953209fb69ea150b494aaa40robbiew  * The testcase shall not terminate in any other maneer.
722c28215423293e443469a07ae7011135d058b671Garrett Cooper  *
730dc076565f772bb1953209fb69ea150b494aaa40robbiew  * The other file defines the functions
740dc076565f772bb1953209fb69ea150b494aaa40robbiew  * void output_init()
750dc076565f772bb1953209fb69ea150b494aaa40robbiew  * void output(char * string, ...)
762c28215423293e443469a07ae7011135d058b671Garrett Cooper  *
770dc076565f772bb1953209fb69ea150b494aaa40robbiew  * Those may be used to output information.
780dc076565f772bb1953209fb69ea150b494aaa40robbiew  */
790dc076565f772bb1953209fb69ea150b494aaa40robbiew
800dc076565f772bb1953209fb69ea150b494aaa40robbiew/********************************************************************************************/
810dc076565f772bb1953209fb69ea150b494aaa40robbiew/********************************** Configuration ******************************************/
820dc076565f772bb1953209fb69ea150b494aaa40robbiew/********************************************************************************************/
830dc076565f772bb1953209fb69ea150b494aaa40robbiew#ifndef VERBOSE
840dc076565f772bb1953209fb69ea150b494aaa40robbiew#define VERBOSE 1
850dc076565f772bb1953209fb69ea150b494aaa40robbiew#endif
860dc076565f772bb1953209fb69ea150b494aaa40robbiew
870dc076565f772bb1953209fb69ea150b494aaa40robbiew/********************************************************************************************/
880dc076565f772bb1953209fb69ea150b494aaa40robbiew/***********************************    Test case   *****************************************/
890dc076565f772bb1953209fb69ea150b494aaa40robbiew/********************************************************************************************/
900dc076565f772bb1953209fb69ea150b494aaa40robbiew#ifndef WITHOUT_XOPEN
910dc076565f772bb1953209fb69ea150b494aaa40robbiew
92354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaotypedef struct {
930dc076565f772bb1953209fb69ea150b494aaa40robbiew	pthread_mutex_t mtx;
94354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int status;		/* error code */
950dc076565f772bb1953209fb69ea150b494aaa40robbiew} testdata_t;
960dc076565f772bb1953209fb69ea150b494aaa40robbiew
97354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaostruct _scenar {
98354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int m_type;		/* Mutex type to use */
99354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int m_pshared;		/* 0: mutex is process-private (default) ~ !0: mutex is process-shared, if supported */
100354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int fork;		/* 0: Test between threads. ~ !0: Test across processes, if supported (mmap) */
101354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	char *descr;		/* Case description */
102354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao} scenarii[] = {
103354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	{
104354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	PTHREAD_MUTEX_RECURSIVE, 0, 0, "Recursive mutex"}
105354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	, {
106354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	PTHREAD_MUTEX_RECURSIVE, 1, 0, "Pshared Recursive mutex"}
107354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	, {
108354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	PTHREAD_MUTEX_RECURSIVE, 1, 1,
109354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		    "Pshared Recursive mutex across processes"}
1100dc076565f772bb1953209fb69ea150b494aaa40robbiew};
111354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
1120dc076565f772bb1953209fb69ea150b494aaa40robbiew#define NSCENAR (sizeof(scenarii)/sizeof(scenarii[0]))
1130dc076565f772bb1953209fb69ea150b494aaa40robbiew
1140dc076565f772bb1953209fb69ea150b494aaa40robbiew/* The test function will only perform a trylock operation then return. */
115354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid *tf(void *arg)
1160dc076565f772bb1953209fb69ea150b494aaa40robbiew{
117354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	testdata_t *td = (testdata_t *) arg;
1182c28215423293e443469a07ae7011135d058b671Garrett Cooper
1190dc076565f772bb1953209fb69ea150b494aaa40robbiew	td->status = pthread_mutex_trylock(&(td->mtx));
1202c28215423293e443469a07ae7011135d058b671Garrett Cooper
121354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (td->status == 0) {
1220dc076565f772bb1953209fb69ea150b494aaa40robbiew		int ret;
1232c28215423293e443469a07ae7011135d058b671Garrett Cooper
1240dc076565f772bb1953209fb69ea150b494aaa40robbiew		ret = pthread_mutex_unlock(&(td->mtx));
125354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (ret != 0) {
126354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			UNRESOLVED(ret, "Failed to unlock a locked semaphore");
127354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
1280dc076565f772bb1953209fb69ea150b494aaa40robbiew	}
1292c28215423293e443469a07ae7011135d058b671Garrett Cooper
1300dc076565f772bb1953209fb69ea150b494aaa40robbiew	return NULL;
1310dc076565f772bb1953209fb69ea150b494aaa40robbiew}
1320dc076565f772bb1953209fb69ea150b494aaa40robbiew
1330dc076565f772bb1953209fb69ea150b494aaa40robbiew/* Main entry point. */
1344ca2bbdcd3003f3c8df4e6129e9c7b2bd1514f87Cyril Hrubisint main(void)
1350dc076565f772bb1953209fb69ea150b494aaa40robbiew{
1360dc076565f772bb1953209fb69ea150b494aaa40robbiew	int ret;
1370dc076565f772bb1953209fb69ea150b494aaa40robbiew	int sc;
1380dc076565f772bb1953209fb69ea150b494aaa40robbiew	pthread_mutexattr_t ma;
1392c28215423293e443469a07ae7011135d058b671Garrett Cooper
140354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	testdata_t *td;
1410dc076565f772bb1953209fb69ea150b494aaa40robbiew	testdata_t alternativ;
1422c28215423293e443469a07ae7011135d058b671Garrett Cooper
1430dc076565f772bb1953209fb69ea150b494aaa40robbiew	int do_fork;
1442c28215423293e443469a07ae7011135d058b671Garrett Cooper
145354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	pid_t child_pr = 0, chkpid;
1460dc076565f772bb1953209fb69ea150b494aaa40robbiew	int status;
1470dc076565f772bb1953209fb69ea150b494aaa40robbiew	pthread_t child_th;
1482c28215423293e443469a07ae7011135d058b671Garrett Cooper
1490dc076565f772bb1953209fb69ea150b494aaa40robbiew	long pshared, mf;
1502c28215423293e443469a07ae7011135d058b671Garrett Cooper
1510dc076565f772bb1953209fb69ea150b494aaa40robbiew	/* Initialize output */
1520dc076565f772bb1953209fb69ea150b494aaa40robbiew	output_init();
1532c28215423293e443469a07ae7011135d058b671Garrett Cooper
1540dc076565f772bb1953209fb69ea150b494aaa40robbiew	/* Test system abilities */
1550dc076565f772bb1953209fb69ea150b494aaa40robbiew	pshared = sysconf(_SC_THREAD_PROCESS_SHARED);
156354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	mf = sysconf(_SC_MAPPED_FILES);
1572c28215423293e443469a07ae7011135d058b671Garrett Cooper
158354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#if VERBOSE > 0
1590dc076565f772bb1953209fb69ea150b494aaa40robbiew	output("Test starting\n");
1600dc076565f772bb1953209fb69ea150b494aaa40robbiew	output("System abilities:\n");
1610dc076565f772bb1953209fb69ea150b494aaa40robbiew	output(" TSH : %li\n", pshared);
1620dc076565f772bb1953209fb69ea150b494aaa40robbiew	output(" MF  : %li\n", mf);
1630dc076565f772bb1953209fb69ea150b494aaa40robbiew	if ((mf < 0) || (pshared < 0))
1640dc076565f772bb1953209fb69ea150b494aaa40robbiew		output("Process-shared attributes won't be tested\n");
165354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#endif
1660dc076565f772bb1953209fb69ea150b494aaa40robbiew
1670dc076565f772bb1953209fb69ea150b494aaa40robbiew/**********
1680dc076565f772bb1953209fb69ea150b494aaa40robbiew * Allocate space for the testdata structure
1690dc076565f772bb1953209fb69ea150b494aaa40robbiew */
170354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (mf < 0) {
1710dc076565f772bb1953209fb69ea150b494aaa40robbiew		/* Cannot mmap a file (or not interested in this), we use an alternative method */
1720dc076565f772bb1953209fb69ea150b494aaa40robbiew		td = &alternativ;
173354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		pshared = -1;	/* We won't do this testing anyway */
174354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#if VERBOSE > 0
1750dc076565f772bb1953209fb69ea150b494aaa40robbiew		output("Testdata allocated in the process memory.\n");
176354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#endif
177354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	} else {
1780dc076565f772bb1953209fb69ea150b494aaa40robbiew		/* We will place the test data in a mmaped file */
1790dc076565f772bb1953209fb69ea150b494aaa40robbiew		char filename[] = "/tmp/mutex_trylock_2-1-XXXXXX";
1800dc076565f772bb1953209fb69ea150b494aaa40robbiew		size_t sz;
181354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		void *mmaped;
1820dc076565f772bb1953209fb69ea150b494aaa40robbiew		int fd;
183354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		char *tmp;
1842c28215423293e443469a07ae7011135d058b671Garrett Cooper
1850dc076565f772bb1953209fb69ea150b494aaa40robbiew		/* We now create the temp files */
1860dc076565f772bb1953209fb69ea150b494aaa40robbiew		fd = mkstemp(filename);
187354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (fd == -1) {
188354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			UNRESOLVED(errno,
189354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				   "Temporary file could not be created");
190354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
1912c28215423293e443469a07ae7011135d058b671Garrett Cooper
1920dc076565f772bb1953209fb69ea150b494aaa40robbiew		/* and make sure the file will be deleted when closed */
1930dc076565f772bb1953209fb69ea150b494aaa40robbiew		unlink(filename);
1942c28215423293e443469a07ae7011135d058b671Garrett Cooper
195354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#if VERBOSE > 1
1960dc076565f772bb1953209fb69ea150b494aaa40robbiew		output("Temp file created (%s).\n", filename);
197354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#endif
1982c28215423293e443469a07ae7011135d058b671Garrett Cooper
199354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		sz = (size_t) sysconf(_SC_PAGESIZE);
2002c28215423293e443469a07ae7011135d058b671Garrett Cooper
2010dc076565f772bb1953209fb69ea150b494aaa40robbiew		tmp = calloc(1, sz);
202354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (tmp == NULL) {
203354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			UNRESOLVED(errno, "Memory allocation failed");
204354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
2052c28215423293e443469a07ae7011135d058b671Garrett Cooper
2060dc076565f772bb1953209fb69ea150b494aaa40robbiew		/* Write the data to the file.  */
207354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (write(fd, tmp, sz) != (ssize_t) sz) {
208354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			UNRESOLVED(sz, "Writting to the file failed");
209354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
2102c28215423293e443469a07ae7011135d058b671Garrett Cooper
2110dc076565f772bb1953209fb69ea150b494aaa40robbiew		free(tmp);
2122c28215423293e443469a07ae7011135d058b671Garrett Cooper
2130dc076565f772bb1953209fb69ea150b494aaa40robbiew		/* Now we can map the file in memory */
214354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		mmaped =
215354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		    mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
216354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (mmaped == MAP_FAILED) {
217354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			UNRESOLVED(errno, "mmap failed");
218354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
2192c28215423293e443469a07ae7011135d058b671Garrett Cooper
2200dc076565f772bb1953209fb69ea150b494aaa40robbiew		td = (testdata_t *) mmaped;
2212c28215423293e443469a07ae7011135d058b671Garrett Cooper
2220dc076565f772bb1953209fb69ea150b494aaa40robbiew		/* Our datatest structure is now in shared memory */
223354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#if VERBOSE > 1
2240dc076565f772bb1953209fb69ea150b494aaa40robbiew		output("Testdata allocated in shared memory.\n");
225354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#endif
2260dc076565f772bb1953209fb69ea150b494aaa40robbiew	}
2272c28215423293e443469a07ae7011135d058b671Garrett Cooper
2280dc076565f772bb1953209fb69ea150b494aaa40robbiew/**********
2290dc076565f772bb1953209fb69ea150b494aaa40robbiew * For each test scenario, initialize the attributes and other variables.
2300dc076565f772bb1953209fb69ea150b494aaa40robbiew * Do the whole thing for each time to test.
2310dc076565f772bb1953209fb69ea150b494aaa40robbiew */
232354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	for (sc = 0; sc < NSCENAR; sc++) {
233354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#if VERBOSE > 1
234354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		output("[parent] Preparing attributes for: %s\n",
235354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		       scenarii[sc].descr);
236354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#endif
2370dc076565f772bb1953209fb69ea150b494aaa40robbiew		/* set / reset everything */
238354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		do_fork = 0;
2390dc076565f772bb1953209fb69ea150b494aaa40robbiew		ret = pthread_mutexattr_init(&ma);
240354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (ret != 0) {
241354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			UNRESOLVED(ret,
242354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				   "[parent] Unable to initialize the mutex attribute object");
243354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
2442c28215423293e443469a07ae7011135d058b671Garrett Cooper
2450dc076565f772bb1953209fb69ea150b494aaa40robbiew		/* Set the mutex type */
2460dc076565f772bb1953209fb69ea150b494aaa40robbiew		ret = pthread_mutexattr_settype(&ma, scenarii[sc].m_type);
247354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (ret != 0) {
248354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			UNRESOLVED(ret, "[parent] Unable to set mutex type");
249354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
250354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#if VERBOSE > 1
2510dc076565f772bb1953209fb69ea150b494aaa40robbiew		output("[parent] Mutex type : %i\n", scenarii[sc].m_type);
252354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#endif
2532c28215423293e443469a07ae7011135d058b671Garrett Cooper
2540dc076565f772bb1953209fb69ea150b494aaa40robbiew		/* Set the pshared attributes, if supported */
255354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if ((pshared > 0) && (scenarii[sc].m_pshared != 0)) {
256354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			ret =
257354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			    pthread_mutexattr_setpshared(&ma,
258354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao							 PTHREAD_PROCESS_SHARED);
259354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			if (ret != 0) {
260354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				UNRESOLVED(ret,
261354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao					   "[parent] Unable to set the mutex process-shared");
262354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			}
263354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#if VERBOSE > 1
2640dc076565f772bb1953209fb69ea150b494aaa40robbiew			output("[parent] Mutex is process-shared\n");
265354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#endif
2660dc076565f772bb1953209fb69ea150b494aaa40robbiew		}
267354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#if VERBOSE > 1
2680dc076565f772bb1953209fb69ea150b494aaa40robbiew		else {
2690dc076565f772bb1953209fb69ea150b494aaa40robbiew			output("[parent] Mutex is process-private\n");
2700dc076565f772bb1953209fb69ea150b494aaa40robbiew		}
271354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#endif
2722c28215423293e443469a07ae7011135d058b671Garrett Cooper
2730dc076565f772bb1953209fb69ea150b494aaa40robbiew		/* Tell whether the test will be across processes */
274354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if ((pshared > 0) && (scenarii[sc].fork != 0)) {
2750dc076565f772bb1953209fb69ea150b494aaa40robbiew			do_fork = 1;
276354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#if VERBOSE > 1
2770dc076565f772bb1953209fb69ea150b494aaa40robbiew			output("[parent] Child will be a new process\n");
278354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#endif
2790dc076565f772bb1953209fb69ea150b494aaa40robbiew		}
280354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#if VERBOSE > 1
2810dc076565f772bb1953209fb69ea150b494aaa40robbiew		else {
2820dc076565f772bb1953209fb69ea150b494aaa40robbiew			output("[parent] Child will be a new thread\n");
2830dc076565f772bb1953209fb69ea150b494aaa40robbiew		}
284354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#endif
2852c28215423293e443469a07ae7011135d058b671Garrett Cooper
2860dc076565f772bb1953209fb69ea150b494aaa40robbiew/**********
2872c28215423293e443469a07ae7011135d058b671Garrett Cooper * Initialize the testdata_t structure with the previously defined attributes
2880dc076565f772bb1953209fb69ea150b494aaa40robbiew */
2890dc076565f772bb1953209fb69ea150b494aaa40robbiew		/* Initialize the mutex */
2900dc076565f772bb1953209fb69ea150b494aaa40robbiew		ret = pthread_mutex_init(&(td->mtx), &ma);
291354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (ret != 0) {
292354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			UNRESOLVED(ret, "[parent] Mutex init failed");
293354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
2942c28215423293e443469a07ae7011135d058b671Garrett Cooper
2950dc076565f772bb1953209fb69ea150b494aaa40robbiew		/* Initialize the other datas from the test structure */
296354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		td->status = 0;
2972c28215423293e443469a07ae7011135d058b671Garrett Cooper
2980dc076565f772bb1953209fb69ea150b494aaa40robbiew/**********
2992c28215423293e443469a07ae7011135d058b671Garrett Cooper * Proceed to the actual testing
3000dc076565f772bb1953209fb69ea150b494aaa40robbiew */
3010dc076565f772bb1953209fb69ea150b494aaa40robbiew		/* Trylock the mutex twice before creating children */
3020dc076565f772bb1953209fb69ea150b494aaa40robbiew		ret = pthread_mutex_trylock(&(td->mtx));
303354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (ret != 0) {
304354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			UNRESOLVED(ret, "[parent] Unable to trylock the mutex");
305354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
3060dc076565f772bb1953209fb69ea150b494aaa40robbiew		ret = pthread_mutex_trylock(&(td->mtx));
3070dc076565f772bb1953209fb69ea150b494aaa40robbiew
308354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (scenarii[sc].m_type == PTHREAD_MUTEX_RECURSIVE) {
309354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			if (ret != 0) {
310354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				FAILED
311354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				    ("Failed to pthread_mutex_trylock() twice a recursive mutex");
312354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			}
3132c28215423293e443469a07ae7011135d058b671Garrett Cooper
3140dc076565f772bb1953209fb69ea150b494aaa40robbiew			/* Unlock once so the count is "1" */
3150dc076565f772bb1953209fb69ea150b494aaa40robbiew			ret = pthread_mutex_unlock(&(td->mtx));
316354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			if (ret != 0) {
317354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				UNRESOLVED(ret, "Failed to unlock the mutex");
318354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			}
319354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		} else if (ret == 0) {
320354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			UNRESOLVED(-1,
321354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				   "Main was able to pthread_mutex_trylock() twice without error");
3220dc076565f772bb1953209fb69ea150b494aaa40robbiew		}
3232c28215423293e443469a07ae7011135d058b671Garrett Cooper
3240dc076565f772bb1953209fb69ea150b494aaa40robbiew		/* Create the children */
325354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (do_fork != 0) {
3260dc076565f772bb1953209fb69ea150b494aaa40robbiew			/* We are testing across processes */
3270dc076565f772bb1953209fb69ea150b494aaa40robbiew			child_pr = fork();
328354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			if (child_pr == -1) {
329354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				UNRESOLVED(errno, "[parent] Fork failed");
330354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			}
331354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
332354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			if (child_pr == 0) {
333354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#if VERBOSE > 3
334354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				output
335354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				    ("[child] Child process is starting...\n");
336354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#endif
337354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
338354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				if (tf((void *)td) != NULL) {
339354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao					UNRESOLVED(-1,
340354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao						   "[child] Got an unexpected return value from test function");
341354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				} else {
3420dc076565f772bb1953209fb69ea150b494aaa40robbiew					/* We cannot use the PASSED macro here since it would terminate the output */
343354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao					exit(0);
3440dc076565f772bb1953209fb69ea150b494aaa40robbiew				}
3450dc076565f772bb1953209fb69ea150b494aaa40robbiew			}
3460dc076565f772bb1953209fb69ea150b494aaa40robbiew			/* Only the parent process goes further */
347354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		} else {	/* do_fork == 0 */
348354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
3490dc076565f772bb1953209fb69ea150b494aaa40robbiew			/* We are testing across two threads */
3500dc076565f772bb1953209fb69ea150b494aaa40robbiew			ret = pthread_create(&child_th, NULL, tf, td);
351354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			if (ret != 0) {
352354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				UNRESOLVED(ret,
353354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao					   "[parent] Unable to create the child thread.");
354354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			}
3550dc076565f772bb1953209fb69ea150b494aaa40robbiew		}
3562c28215423293e443469a07ae7011135d058b671Garrett Cooper
3570dc076565f772bb1953209fb69ea150b494aaa40robbiew		/* Wait for the child to terminate */
358354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (do_fork != 0) {
3590dc076565f772bb1953209fb69ea150b494aaa40robbiew			/* We were testing across processes */
3600dc076565f772bb1953209fb69ea150b494aaa40robbiew			ret = 0;
3610dc076565f772bb1953209fb69ea150b494aaa40robbiew			chkpid = waitpid(child_pr, &status, 0);
362354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			if (chkpid != child_pr) {
363354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				output("Expected pid: %i. Got %i\n",
364354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				       (int)child_pr, (int)chkpid);
3652c28215423293e443469a07ae7011135d058b671Garrett Cooper				UNRESOLVED(errno, "Waitpid failed");
3660dc076565f772bb1953209fb69ea150b494aaa40robbiew			}
367354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			if (WIFSIGNALED(status)) {
368354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				output("Child process killed with signal %d\n",
369354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				       WTERMSIG(status));
370354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				UNRESOLVED(-1, "Child process was killed");
3710dc076565f772bb1953209fb69ea150b494aaa40robbiew			}
3722c28215423293e443469a07ae7011135d058b671Garrett Cooper
373354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			if (WIFEXITED(status)) {
3740dc076565f772bb1953209fb69ea150b494aaa40robbiew				ret = WEXITSTATUS(status);
375354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			} else {
376354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				UNRESOLVED(-1,
377354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao					   "Child process was neither killed nor exited");
3780dc076565f772bb1953209fb69ea150b494aaa40robbiew			}
3792c28215423293e443469a07ae7011135d058b671Garrett Cooper
380354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			if (ret != 0) {
381354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				exit(ret);	/* Output has already been closed in child */
3820dc076565f772bb1953209fb69ea150b494aaa40robbiew			}
3832c28215423293e443469a07ae7011135d058b671Garrett Cooper
384354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		} else {	/* child was a thread */
385354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
3860dc076565f772bb1953209fb69ea150b494aaa40robbiew			ret = pthread_join(child_th, NULL);
387354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			if (ret != 0) {
388354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				UNRESOLVED(ret,
389354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao					   "[parent] Unable to join the thread");
390354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			}
3910dc076565f772bb1953209fb69ea150b494aaa40robbiew		}
3922c28215423293e443469a07ae7011135d058b671Garrett Cooper
3930dc076565f772bb1953209fb69ea150b494aaa40robbiew		/* Check the child status */
394354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (td->status != EBUSY) {
395354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			output("Unexpected return value: %d (%s)\n", td->status,
396354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			       strerror(td->status));
397354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			FAILED
398354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			    ("pthread_mutex_trylock() did not return EBUSY in the child");
3990dc076565f772bb1953209fb69ea150b494aaa40robbiew		}
4002c28215423293e443469a07ae7011135d058b671Garrett Cooper
4010dc076565f772bb1953209fb69ea150b494aaa40robbiew		/* Unlock the mutex */
402354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		ret = pthread_mutex_unlock(&(td->mtx));
403354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (ret != 0) {
404354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			FAILED
405354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			    ("Failed to unlock the mutex -- count is broken?");
406354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
4072c28215423293e443469a07ae7011135d058b671Garrett Cooper
408354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		ret = pthread_mutex_unlock(&(td->mtx));
409354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (ret == 0) {
410354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			FAILED
411354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			    ("Was able to unlock once more the mutex -- count is broken?");
412354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
4132c28215423293e443469a07ae7011135d058b671Garrett Cooper
4140dc076565f772bb1953209fb69ea150b494aaa40robbiew/**********
4152c28215423293e443469a07ae7011135d058b671Garrett Cooper * Destroy the data
4160dc076565f772bb1953209fb69ea150b494aaa40robbiew */
4170dc076565f772bb1953209fb69ea150b494aaa40robbiew		ret = pthread_mutex_destroy(&(td->mtx));
418354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (ret != 0) {
419354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			UNRESOLVED(ret, "Failed to destroy the mutex");
420354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
4212c28215423293e443469a07ae7011135d058b671Garrett Cooper
4220dc076565f772bb1953209fb69ea150b494aaa40robbiew		ret = pthread_mutexattr_destroy(&ma);
423354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (ret != 0) {
424354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			UNRESOLVED(ret,
425354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				   "Failed to destroy the mutex attribute object");
426354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
4272c28215423293e443469a07ae7011135d058b671Garrett Cooper
428354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}			/* Proceed to the next scenario */
4292c28215423293e443469a07ae7011135d058b671Garrett Cooper
430354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#if VERBOSE > 0
4310dc076565f772bb1953209fb69ea150b494aaa40robbiew	output("Test passed\n");
432354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#endif
4330dc076565f772bb1953209fb69ea150b494aaa40robbiew
4340dc076565f772bb1953209fb69ea150b494aaa40robbiew	PASSED;
4350dc076565f772bb1953209fb69ea150b494aaa40robbiew}
4360dc076565f772bb1953209fb69ea150b494aaa40robbiew
4370dc076565f772bb1953209fb69ea150b494aaa40robbiew#else /* WITHOUT_XOPEN */
4384ca2bbdcd3003f3c8df4e6129e9c7b2bd1514f87Cyril Hrubisint main(void)
4390dc076565f772bb1953209fb69ea150b494aaa40robbiew{
4400dc076565f772bb1953209fb69ea150b494aaa40robbiew	output_init();
4410dc076565f772bb1953209fb69ea150b494aaa40robbiew	UNTESTED("This test requires XSI features");
4420dc076565f772bb1953209fb69ea150b494aaa40robbiew}
443ec6edca7aa42b6affd989ef91b5897f96795e40fChris Dearman#endif
444