12c28215423293e443469a07ae7011135d058b671Garrett Cooper/*
22c28215423293e443469a07ae7011135d058b671Garrett Cooper * Copyright (c) 2004, Bull S.A..  All rights reserved.
32c28215423293e443469a07ae7011135d058b671Garrett Cooper * Created by: Sebastien Decugis
42c28215423293e443469a07ae7011135d058b671Garrett Cooper
52c28215423293e443469a07ae7011135d058b671Garrett Cooper * This program is free software; you can redistribute it and/or modify it
62c28215423293e443469a07ae7011135d058b671Garrett Cooper * under the terms of version 2 of the GNU General Public License as
72c28215423293e443469a07ae7011135d058b671Garrett Cooper * published by the Free Software Foundation.
82c28215423293e443469a07ae7011135d058b671Garrett Cooper *
92c28215423293e443469a07ae7011135d058b671Garrett Cooper * This program is distributed in the hope that it would be useful, but
102c28215423293e443469a07ae7011135d058b671Garrett Cooper * WITHOUT ANY WARRANTY; without even the implied warranty of
112c28215423293e443469a07ae7011135d058b671Garrett Cooper * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
122c28215423293e443469a07ae7011135d058b671Garrett Cooper *
132c28215423293e443469a07ae7011135d058b671Garrett Cooper * 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.
162c28215423293e443469a07ae7011135d058b671Garrett Cooper *
172c28215423293e443469a07ae7011135d058b671Garrett Cooper
182c28215423293e443469a07ae7011135d058b671Garrett Cooper * This file is a scalability test for the pthread_mutex_lock function.
192c28215423293e443469a07ae7011135d058b671Garrett Cooper * The goal is to test if there is a limit on the number
202c28215423293e443469a07ae7011135d058b671Garrett Cooper *  of concurrent mutex having threads pending.
212c28215423293e443469a07ae7011135d058b671Garrett Cooper
222c28215423293e443469a07ae7011135d058b671Garrett Cooper * The steps are:
232c28215423293e443469a07ae7011135d058b671Garrett Cooper * -> create some mutex attributes objects
242c28215423293e443469a07ae7011135d058b671Garrett Cooper * -> As long as nothing fails, do
252c28215423293e443469a07ae7011135d058b671Garrett Cooper *    - create a thread.
262c28215423293e443469a07ae7011135d058b671Garrett Cooper *       - this thread initializes a mutex with one of the mutex attributes
272c28215423293e443469a07ae7011135d058b671Garrett Cooper *       - lock this mutex
282c28215423293e443469a07ae7011135d058b671Garrett Cooper *       - create another thread which waits on the mutex (and hangs) then returns
292c28215423293e443469a07ae7011135d058b671Garrett Cooper *       - wait for a condition
302c28215423293e443469a07ae7011135d058b671Garrett Cooper *       - unlock the mutex.
312c28215423293e443469a07ae7011135d058b671Garrett Cooper *       - join the thread
322c28215423293e443469a07ae7011135d058b671Garrett Cooper * -> When a create operation fails, broadcast the condition then join every threads.
332c28215423293e443469a07ae7011135d058b671Garrett Cooper *
342c28215423293e443469a07ae7011135d058b671Garrett Cooper * Additional note:
352c28215423293e443469a07ae7011135d058b671Garrett Cooper *    This test will test only N/2 parallel mutex, where N is the max number of threads.
362c28215423293e443469a07ae7011135d058b671Garrett Cooper *    It would be possible to create N parallel mutex with a slightly different algorithme:
372c28215423293e443469a07ae7011135d058b671Garrett Cooper *     the main thread owns each mutex, then creates a thread which will block.
382c28215423293e443469a07ae7011135d058b671Garrett Cooper *    This test could be written too. The current algorithm will give more stress to
392c28215423293e443469a07ae7011135d058b671Garrett Cooper *     the mutex threads queues mechanism, as the threads are always different.
402c28215423293e443469a07ae7011135d058b671Garrett Cooper */
412c28215423293e443469a07ae7011135d058b671Garrett Cooper
422c28215423293e443469a07ae7011135d058b671Garrett Cooper /* We are testing conformance to IEEE Std 1003.1, 2003 Edition */
43354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#define _POSIX_C_SOURCE 200112L
442c28215423293e443469a07ae7011135d058b671Garrett Cooper
452c28215423293e443469a07ae7011135d058b671Garrett Cooper /* We enable the following line to have mutex attributes defined */
462c28215423293e443469a07ae7011135d058b671Garrett Cooper#ifndef WITHOUT_XOPEN
47354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#define _XOPEN_SOURCE	600
482c28215423293e443469a07ae7011135d058b671Garrett Cooper#endif
492c28215423293e443469a07ae7011135d058b671Garrett Cooper
502c28215423293e443469a07ae7011135d058b671Garrett Cooper/********************************************************************************************/
512c28215423293e443469a07ae7011135d058b671Garrett Cooper/****************************** standard includes *****************************************/
522c28215423293e443469a07ae7011135d058b671Garrett Cooper/********************************************************************************************/
53354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#include <pthread.h>
54354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#include <errno.h>
55354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#include <unistd.h>
56354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#include <stdio.h>
57354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#include <stdlib.h>
58354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#include <stdarg.h>
592c28215423293e443469a07ae7011135d058b671Garrett Cooper
602c28215423293e443469a07ae7011135d058b671Garrett Cooper/********************************************************************************************/
612c28215423293e443469a07ae7011135d058b671Garrett Cooper/******************************   Test framework   *****************************************/
622c28215423293e443469a07ae7011135d058b671Garrett Cooper/********************************************************************************************/
63354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#include "testfrmw.h"
64354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#include "testfrmw.c"
652c28215423293e443469a07ae7011135d058b671Garrett Cooper /* This header is responsible for defining the following macros:
662c28215423293e443469a07ae7011135d058b671Garrett Cooper  * UNRESOLVED(ret, descr);
672c28215423293e443469a07ae7011135d058b671Garrett Cooper  *    where descr is a description of the error and ret is an int (error code for example)
682c28215423293e443469a07ae7011135d058b671Garrett Cooper  * FAILED(descr);
692c28215423293e443469a07ae7011135d058b671Garrett Cooper  *    where descr is a short text saying why the test has failed.
702c28215423293e443469a07ae7011135d058b671Garrett Cooper  * PASSED();
712c28215423293e443469a07ae7011135d058b671Garrett Cooper  *    No parameter.
722c28215423293e443469a07ae7011135d058b671Garrett Cooper  *
732c28215423293e443469a07ae7011135d058b671Garrett Cooper  * Both three macros shall terminate the calling process.
742c28215423293e443469a07ae7011135d058b671Garrett Cooper  * The testcase shall not terminate in any other maneer.
752c28215423293e443469a07ae7011135d058b671Garrett Cooper  *
762c28215423293e443469a07ae7011135d058b671Garrett Cooper  * The other file defines the functions
772c28215423293e443469a07ae7011135d058b671Garrett Cooper  * void output_init()
782c28215423293e443469a07ae7011135d058b671Garrett Cooper  * void output(char * string, ...)
792c28215423293e443469a07ae7011135d058b671Garrett Cooper  *
802c28215423293e443469a07ae7011135d058b671Garrett Cooper  * Those may be used to output information.
812c28215423293e443469a07ae7011135d058b671Garrett Cooper  */
822c28215423293e443469a07ae7011135d058b671Garrett Cooper
832c28215423293e443469a07ae7011135d058b671Garrett Cooper/********************************************************************************************/
842c28215423293e443469a07ae7011135d058b671Garrett Cooper/********************************** Configuration ******************************************/
852c28215423293e443469a07ae7011135d058b671Garrett Cooper/********************************************************************************************/
862c28215423293e443469a07ae7011135d058b671Garrett Cooper#ifndef SCALABILITY_FACTOR
87354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#define SCALABILITY_FACTOR 1	/* This is not used in this testcase */
882c28215423293e443469a07ae7011135d058b671Garrett Cooper#endif
892c28215423293e443469a07ae7011135d058b671Garrett Cooper#ifndef VERBOSE
902c28215423293e443469a07ae7011135d058b671Garrett Cooper#define VERBOSE 2
912c28215423293e443469a07ae7011135d058b671Garrett Cooper#endif
922c28215423293e443469a07ae7011135d058b671Garrett Cooper
932c28215423293e443469a07ae7011135d058b671Garrett Cooper/********************************************************************************************/
942c28215423293e443469a07ae7011135d058b671Garrett Cooper/***********************************    Test case   *****************************************/
952c28215423293e443469a07ae7011135d058b671Garrett Cooper/********************************************************************************************/
962c28215423293e443469a07ae7011135d058b671Garrett Cooper
972c28215423293e443469a07ae7011135d058b671Garrett Cooper#ifndef WITHOUT_XOPEN
98354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaoint types[] = {
992c28215423293e443469a07ae7011135d058b671Garrett Cooper	PTHREAD_MUTEX_NORMAL,
1002c28215423293e443469a07ae7011135d058b671Garrett Cooper	PTHREAD_MUTEX_ERRORCHECK,
1012c28215423293e443469a07ae7011135d058b671Garrett Cooper	PTHREAD_MUTEX_RECURSIVE,
1022c28215423293e443469a07ae7011135d058b671Garrett Cooper	PTHREAD_MUTEX_DEFAULT
103354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao};
1042c28215423293e443469a07ae7011135d058b671Garrett Cooper#endif
1052c28215423293e443469a07ae7011135d058b671Garrett Cooper
1062c28215423293e443469a07ae7011135d058b671Garrett Cooper/* The condition used to signal the main thread to go to the next step */
1072c28215423293e443469a07ae7011135d058b671Garrett Cooperpthread_cond_t cnd;
108354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaopthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
1092c28215423293e443469a07ae7011135d058b671Garrett Cooperchar do_it;
1102c28215423293e443469a07ae7011135d058b671Garrett Cooperunsigned long counter;
1112c28215423293e443469a07ae7011135d058b671Garrett Cooper
1122c28215423293e443469a07ae7011135d058b671Garrett Cooper/* Mutex attribute objects and pointers */
113354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaopthread_mutexattr_t *pma[6];
1142c28215423293e443469a07ae7011135d058b671Garrett Cooper#ifdef WITHOUT_XOPEN
1152c28215423293e443469a07ae7011135d058b671Garrett Cooperpthread_mutexattr_t ma[1];
1162c28215423293e443469a07ae7011135d058b671Garrett Cooper#else
1172c28215423293e443469a07ae7011135d058b671Garrett Cooperpthread_mutexattr_t ma[5];
1182c28215423293e443469a07ae7011135d058b671Garrett Cooper#endif
1192c28215423293e443469a07ae7011135d058b671Garrett Cooper
1202c28215423293e443469a07ae7011135d058b671Garrett Cooper/* Test data type */
121354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaotypedef struct _td {
1222c28215423293e443469a07ae7011135d058b671Garrett Cooper	pthread_t child;
1232c28215423293e443469a07ae7011135d058b671Garrett Cooper	int id;
1242c28215423293e443469a07ae7011135d058b671Garrett Cooper	pthread_mutex_t mtx;
1252c28215423293e443469a07ae7011135d058b671Garrett Cooper	int error;
126354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	struct _td *next;	/* It is a chained list */
1272c28215423293e443469a07ae7011135d058b671Garrett Cooper} testdata_t;
1282c28215423293e443469a07ae7011135d058b671Garrett Cooper
1292c28215423293e443469a07ae7011135d058b671Garrett Cooper/* Thread attribute object */
1302c28215423293e443469a07ae7011135d058b671Garrett Cooperpthread_attr_t ta;
1312c28215423293e443469a07ae7011135d058b671Garrett Cooper
1322c28215423293e443469a07ae7011135d058b671Garrett Cooper/*****
1332c28215423293e443469a07ae7011135d058b671Garrett Cooper * Level 2 - grandchild function
1342c28215423293e443469a07ae7011135d058b671Garrett Cooper */
135354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid *sub(void *arg)
1362c28215423293e443469a07ae7011135d058b671Garrett Cooper{
137354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	testdata_t *td = (testdata_t *) arg;
1382c28215423293e443469a07ae7011135d058b671Garrett Cooper	td->error = pthread_mutex_lock(&(td->mtx));
139354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (td->error != 0) {
1402c28215423293e443469a07ae7011135d058b671Garrett Cooper		/* Print out the error */
141354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		output("PROBLEM: Unable to lock the mutex in thread %i\n",
142354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		       td->id);
143354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	} else {
1442c28215423293e443469a07ae7011135d058b671Garrett Cooper		td->error = pthread_mutex_unlock(&(td->mtx));
145354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (td->error != 0) {
146354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			UNRESOLVED(td->error,
147354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				   "Mutex unlock failed. Mutex data was corrupted?");
148354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
1492c28215423293e443469a07ae7011135d058b671Garrett Cooper	}
1502c28215423293e443469a07ae7011135d058b671Garrett Cooper
1512c28215423293e443469a07ae7011135d058b671Garrett Cooper	return NULL;
1522c28215423293e443469a07ae7011135d058b671Garrett Cooper}
1532c28215423293e443469a07ae7011135d058b671Garrett Cooper
1542c28215423293e443469a07ae7011135d058b671Garrett Cooper/*****
1552c28215423293e443469a07ae7011135d058b671Garrett Cooper * Level 1 - child function
1562c28215423293e443469a07ae7011135d058b671Garrett Cooper */
157354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid *threaded(void *arg)
1582c28215423293e443469a07ae7011135d058b671Garrett Cooper{
159354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	testdata_t *td = (testdata_t *) arg;
1602c28215423293e443469a07ae7011135d058b671Garrett Cooper	int ret;
1612c28215423293e443469a07ae7011135d058b671Garrett Cooper	int ret_create;
1622c28215423293e443469a07ae7011135d058b671Garrett Cooper	pthread_t ch;
1632c28215423293e443469a07ae7011135d058b671Garrett Cooper
1642c28215423293e443469a07ae7011135d058b671Garrett Cooper	ret = pthread_mutex_lock(&m);
165354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (ret != 0) {
166354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		UNRESOLVED(ret, "Unable to lock 'm' in child");
167354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
1682c28215423293e443469a07ae7011135d058b671Garrett Cooper	/* Mark this thread as started */
1692c28215423293e443469a07ae7011135d058b671Garrett Cooper	counter++;
1702c28215423293e443469a07ae7011135d058b671Garrett Cooper
1712c28215423293e443469a07ae7011135d058b671Garrett Cooper	/* Initialize the mutex with the mutex attribute */
1722c28215423293e443469a07ae7011135d058b671Garrett Cooper	ret = pthread_mutex_init(&(td->mtx), pma[td->id % 6]);
173354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (ret != 0) {
174354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		UNRESOLVED(ret, "Unable to initialize a mutex");
175354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
1762c28215423293e443469a07ae7011135d058b671Garrett Cooper
1772c28215423293e443469a07ae7011135d058b671Garrett Cooper	/* Lock the mutex */
1782c28215423293e443469a07ae7011135d058b671Garrett Cooper	td->error = pthread_mutex_lock(&(td->mtx));
179354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (td->error != 0) {
1802c28215423293e443469a07ae7011135d058b671Garrett Cooper		/* If the lock failed, we stop now */
1812c28215423293e443469a07ae7011135d058b671Garrett Cooper		ret = pthread_mutex_unlock(&m);
182354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (ret != 0) {
183354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			UNRESOLVED(ret, "Unable to unlock 'm' in child");
184354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
1852c28215423293e443469a07ae7011135d058b671Garrett Cooper		return NULL;
1862c28215423293e443469a07ae7011135d058b671Garrett Cooper	}
1872c28215423293e443469a07ae7011135d058b671Garrett Cooper
1882c28215423293e443469a07ae7011135d058b671Garrett Cooper	/* Create the child thread */
1892c28215423293e443469a07ae7011135d058b671Garrett Cooper	ret_create = pthread_create(&ch, &ta, sub, arg);
1902c28215423293e443469a07ae7011135d058b671Garrett Cooper
1912c28215423293e443469a07ae7011135d058b671Garrett Cooper	/* Wait for the condition */
192354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	while (do_it) {
1932c28215423293e443469a07ae7011135d058b671Garrett Cooper		ret = pthread_cond_wait(&cnd, &m);
194354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (ret != 0) {
195354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			UNRESOLVED(ret, "Unable to wait for condvar");
196354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
1972c28215423293e443469a07ae7011135d058b671Garrett Cooper	}
1982c28215423293e443469a07ae7011135d058b671Garrett Cooper	ret = pthread_mutex_unlock(&m);
199354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (ret != 0) {
200354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		UNRESOLVED(ret, "Unable to unlock 'm' in child");
201354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
2022c28215423293e443469a07ae7011135d058b671Garrett Cooper
2032c28215423293e443469a07ae7011135d058b671Garrett Cooper	/* Unlock the mutex and release the child */
2042c28215423293e443469a07ae7011135d058b671Garrett Cooper	ret = pthread_mutex_unlock(&(td->mtx));
205354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (ret != 0) {
206354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		UNRESOLVED(ret,
207354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			   "Mutex unlock failed. Mutex data was corrupted?");
208354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
2092c28215423293e443469a07ae7011135d058b671Garrett Cooper
2102c28215423293e443469a07ae7011135d058b671Garrett Cooper	/* If the child exists, join it now */
211354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (ret_create == 0) {
2122c28215423293e443469a07ae7011135d058b671Garrett Cooper		ret = pthread_join(ch, NULL);
213354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (ret != 0) {
214354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			UNRESOLVED(ret, "Grandchild join failed");
215354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
2162c28215423293e443469a07ae7011135d058b671Garrett Cooper	}
2172c28215423293e443469a07ae7011135d058b671Garrett Cooper
2182c28215423293e443469a07ae7011135d058b671Garrett Cooper	/* Destroy the test mutex */
2192c28215423293e443469a07ae7011135d058b671Garrett Cooper	ret = pthread_mutex_destroy(&(td->mtx));
220354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (ret != 0) {
221354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		UNRESOLVED(ret, "Test mutex destroy failed. Corrupted data?");
222354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
2232c28215423293e443469a07ae7011135d058b671Garrett Cooper
2242c28215423293e443469a07ae7011135d058b671Garrett Cooper	/* We're done */
2252c28215423293e443469a07ae7011135d058b671Garrett Cooper	return NULL;
2262c28215423293e443469a07ae7011135d058b671Garrett Cooper}
2272c28215423293e443469a07ae7011135d058b671Garrett Cooper
2282c28215423293e443469a07ae7011135d058b671Garrett Cooper/*****
2292c28215423293e443469a07ae7011135d058b671Garrett Cooper * Level 0 - main function
2302c28215423293e443469a07ae7011135d058b671Garrett Cooper */
231354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaoint main(int argc, char *argv[])
2322c28215423293e443469a07ae7011135d058b671Garrett Cooper{
2332c28215423293e443469a07ae7011135d058b671Garrett Cooper	int ret;
2342c28215423293e443469a07ae7011135d058b671Garrett Cooper	int i;
2352c28215423293e443469a07ae7011135d058b671Garrett Cooper	int errors;
2362c28215423293e443469a07ae7011135d058b671Garrett Cooper	testdata_t sentinel;
2372c28215423293e443469a07ae7011135d058b671Garrett Cooper	testdata_t *cur, *tmp;
2382c28215423293e443469a07ae7011135d058b671Garrett Cooper
2392c28215423293e443469a07ae7011135d058b671Garrett Cooper	output_init();
2402c28215423293e443469a07ae7011135d058b671Garrett Cooper
241354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#if VERBOSE > 1
2422c28215423293e443469a07ae7011135d058b671Garrett Cooper	output("Test starting, initializing data\n");
243354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#endif
2442c28215423293e443469a07ae7011135d058b671Garrett Cooper
2452c28215423293e443469a07ae7011135d058b671Garrett Cooper	do_it = 1;
246354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	errors = 0;
2472c28215423293e443469a07ae7011135d058b671Garrett Cooper	counter = 0;
248354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	sentinel.next = NULL;
2492c28215423293e443469a07ae7011135d058b671Garrett Cooper	sentinel.id = 0;
2502c28215423293e443469a07ae7011135d058b671Garrett Cooper	cur = &sentinel;
2512c28215423293e443469a07ae7011135d058b671Garrett Cooper
2522c28215423293e443469a07ae7011135d058b671Garrett Cooper	/* Initialize the 6 pma objects */
253354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	pma[0] = NULL;
254354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	pma[1] = &ma[0];
2552c28215423293e443469a07ae7011135d058b671Garrett Cooper	ret = pthread_mutexattr_init(pma[1]);
256354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (ret != 0) {
257354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		UNRESOLVED(ret, "Mutex attribute init failed");
258354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
259354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#ifdef WITHOUT_XOPEN
2602c28215423293e443469a07ae7011135d058b671Garrett Cooper	/* We only have default attributes objects */
261354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	pma[2] = pma[0];
262354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	pma[4] = pma[0];
263354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	pma[3] = pma[1];
264354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	pma[5] = pma[1];
265354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#if VERBOSE > 1
2662c28215423293e443469a07ae7011135d058b671Garrett Cooper	output("Default mutex attribute object was initialized\n");
267354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#endif
268354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#else
2692c28215423293e443469a07ae7011135d058b671Garrett Cooper	/* We can use the different mutex types */
270354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	for (i = 0; i < 4; i++) {
271354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		pma[i + 2] = &ma[i + 1];
272354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		ret = pthread_mutexattr_init(pma[i + 2]);
273354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (ret != 0) {
274354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			UNRESOLVED(ret, "Mutex attribute init failed");
275354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
276354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		ret = pthread_mutexattr_settype(pma[i + 2], types[i]);
277354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (ret != 0) {
278354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			UNRESOLVED(ret, "Mutex attribute settype failed");
279354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
2802c28215423293e443469a07ae7011135d058b671Garrett Cooper	}
281354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#if VERBOSE > 1
282354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	output("%d types of mutex attribute objects were initialized\n",
283354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	       sizeof(types) / sizeof(types[0]));
284354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#endif
285354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#endif
2862c28215423293e443469a07ae7011135d058b671Garrett Cooper
2872c28215423293e443469a07ae7011135d058b671Garrett Cooper	/* Initialize the thread attribute object */
2882c28215423293e443469a07ae7011135d058b671Garrett Cooper	ret = pthread_attr_init(&ta);
289354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (ret != 0) {
290354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		UNRESOLVED(ret, "Thread attribute init failed");
291354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
2922c28215423293e443469a07ae7011135d058b671Garrett Cooper	ret = pthread_attr_setstacksize(&ta, sysconf(_SC_THREAD_STACK_MIN));
293354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (ret != 0) {
294354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		UNRESOLVED(ret, "Unable to set stack size to minimum value");
295354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
2962c28215423293e443469a07ae7011135d058b671Garrett Cooper
2972c28215423293e443469a07ae7011135d058b671Garrett Cooper	/* Lock m */
2982c28215423293e443469a07ae7011135d058b671Garrett Cooper	ret = pthread_mutex_lock(&m);
299354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (ret != 0) {
300354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		UNRESOLVED(ret, "Unable to lock 'm' in main");
301354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
302354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#if VERBOSE > 1
3032c28215423293e443469a07ae7011135d058b671Garrett Cooper	output("Ready to create the threads, processing...\n");
304354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#endif
3052c28215423293e443469a07ae7011135d058b671Garrett Cooper
3062c28215423293e443469a07ae7011135d058b671Garrett Cooper	/* create the threads */
307354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	while (1) {
308d218f348c12b42a78fa0306d9a033bfa4f67238bCyril Hrubis		tmp = malloc(sizeof(testdata_t));
309354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (tmp == NULL) {
3102c28215423293e443469a07ae7011135d058b671Garrett Cooper			/* We cannot create anymore testdata */
3112c28215423293e443469a07ae7011135d058b671Garrett Cooper			break;
3122c28215423293e443469a07ae7011135d058b671Garrett Cooper		}
3132c28215423293e443469a07ae7011135d058b671Garrett Cooper
3142c28215423293e443469a07ae7011135d058b671Garrett Cooper		/* We have a new test data structure */
3152c28215423293e443469a07ae7011135d058b671Garrett Cooper		ret = pthread_create(&(tmp->child), &ta, threaded, tmp);
316354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (ret != 0) {
3172c28215423293e443469a07ae7011135d058b671Garrett Cooper			/* We cannot create more threads */
3182c28215423293e443469a07ae7011135d058b671Garrett Cooper			free((void *)tmp);
3192c28215423293e443469a07ae7011135d058b671Garrett Cooper			break;
3202c28215423293e443469a07ae7011135d058b671Garrett Cooper		}
3212c28215423293e443469a07ae7011135d058b671Garrett Cooper
3222c28215423293e443469a07ae7011135d058b671Garrett Cooper		cur->next = tmp;
3232c28215423293e443469a07ae7011135d058b671Garrett Cooper		tmp->id = cur->id + 1;
3242c28215423293e443469a07ae7011135d058b671Garrett Cooper		tmp->error = 0;
3252c28215423293e443469a07ae7011135d058b671Garrett Cooper		cur = tmp;
3262c28215423293e443469a07ae7011135d058b671Garrett Cooper
327354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		/* The new thread was created, let's start it */
328354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		do {
3292c28215423293e443469a07ae7011135d058b671Garrett Cooper			/* Unlock m so the thread can acquire it */
3302c28215423293e443469a07ae7011135d058b671Garrett Cooper			ret = pthread_mutex_unlock(&m);
331354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			if (ret != 0) {
332354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				UNRESOLVED(ret,
333354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao					   "Unlock 'm' failed in main loop");
334354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			}
3352c28215423293e443469a07ae7011135d058b671Garrett Cooper			/* Make sure the thread has a chance to run */
3362c28215423293e443469a07ae7011135d058b671Garrett Cooper			sched_yield();
3372c28215423293e443469a07ae7011135d058b671Garrett Cooper			/* Get m back */
3382c28215423293e443469a07ae7011135d058b671Garrett Cooper			ret = pthread_mutex_lock(&m);
339354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			if (ret != 0) {
340354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				UNRESOLVED(ret, "Lock 'm' failed in main loop");
341354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			}
342354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			/* If the counter has been incremented, this means this child is in the cond wait loop */
3432c28215423293e443469a07ae7011135d058b671Garrett Cooper		} while (counter != cur->id);
3442c28215423293e443469a07ae7011135d058b671Garrett Cooper	}
3452c28215423293e443469a07ae7011135d058b671Garrett Cooper
3462c28215423293e443469a07ae7011135d058b671Garrett Cooper	/* Unable to create more threads, let's signal the cond and join the threads */
347354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#if VERBOSE > 1
348354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (tmp == NULL) {
3492c28215423293e443469a07ae7011135d058b671Garrett Cooper		output("Cannot malloc more memory for the test data.\n");
350354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	} else {
351354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		output("Cannot create another thread (error: %d).\n", ret);
3522c28215423293e443469a07ae7011135d058b671Garrett Cooper	}
3532c28215423293e443469a07ae7011135d058b671Garrett Cooper	output("The children will now be signaled.\n");
354354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#endif
355354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	do_it = 0;
3562c28215423293e443469a07ae7011135d058b671Garrett Cooper	ret = pthread_cond_broadcast(&cnd);
357354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (ret != 0) {
358354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		UNRESOLVED(ret, "Cond broadcast failed");
359354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
3602c28215423293e443469a07ae7011135d058b671Garrett Cooper
3612c28215423293e443469a07ae7011135d058b671Garrett Cooper	ret = pthread_mutex_unlock(&m);
362354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (ret != 0) {
363354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		UNRESOLVED(ret, "Unable to unlock m after broadcast");
364354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
365354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#if VERBOSE > 1
3662c28215423293e443469a07ae7011135d058b671Garrett Cooper	output("The children are terminating. We will join them.\n");
367354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#endif
3682c28215423293e443469a07ae7011135d058b671Garrett Cooper
3692c28215423293e443469a07ae7011135d058b671Garrett Cooper	/* All the threads are terminating, we can join the children and destroy the testdata */
3702c28215423293e443469a07ae7011135d058b671Garrett Cooper	cur = &sentinel;
371354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	while (cur->next != NULL) {
3722c28215423293e443469a07ae7011135d058b671Garrett Cooper		/* Remove the first item from the list */
3732c28215423293e443469a07ae7011135d058b671Garrett Cooper		tmp = cur->next;
3742c28215423293e443469a07ae7011135d058b671Garrett Cooper		cur->next = tmp->next;
3752c28215423293e443469a07ae7011135d058b671Garrett Cooper
3762c28215423293e443469a07ae7011135d058b671Garrett Cooper		/* Join the thread from the current item */
3772c28215423293e443469a07ae7011135d058b671Garrett Cooper		ret = pthread_join(tmp->child, NULL);
378354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (ret != 0) {
379354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			UNRESOLVED(ret, "Unable to join a child");
380354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
3812c28215423293e443469a07ae7011135d058b671Garrett Cooper
3822c28215423293e443469a07ae7011135d058b671Garrett Cooper		/* get the useful data */
3832c28215423293e443469a07ae7011135d058b671Garrett Cooper		if (tmp->error != 0)
3842c28215423293e443469a07ae7011135d058b671Garrett Cooper			errors++;
3852c28215423293e443469a07ae7011135d058b671Garrett Cooper
3862c28215423293e443469a07ae7011135d058b671Garrett Cooper		/* Free the memory */
3872c28215423293e443469a07ae7011135d058b671Garrett Cooper		free((void *)tmp);
3882c28215423293e443469a07ae7011135d058b671Garrett Cooper	}
3892c28215423293e443469a07ae7011135d058b671Garrett Cooper
3902c28215423293e443469a07ae7011135d058b671Garrett Cooper	/* We are done */
3912c28215423293e443469a07ae7011135d058b671Garrett Cooper
3922c28215423293e443469a07ae7011135d058b671Garrett Cooper	/* Exit */
393354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (errors == 0) {
394354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#if VERBOSE > 1
3952c28215423293e443469a07ae7011135d058b671Garrett Cooper		output("The test passed successfully.\n");
3962c28215423293e443469a07ae7011135d058b671Garrett Cooper		output("  %i mutex were created and locked.\n", counter);
3972c28215423293e443469a07ae7011135d058b671Garrett Cooper		output("  No error was encountered\n");
398354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#endif
3992c28215423293e443469a07ae7011135d058b671Garrett Cooper		PASSED;
400354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	} else {
401354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#if VERBOSE > 0
4022c28215423293e443469a07ae7011135d058b671Garrett Cooper		output("The test failed.\n");
4032c28215423293e443469a07ae7011135d058b671Garrett Cooper		output("  %i mutex were created.\n", counter);
4042c28215423293e443469a07ae7011135d058b671Garrett Cooper		output("  %i lock operation failed.\n", errors);
405354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#endif
4062c28215423293e443469a07ae7011135d058b671Garrett Cooper		FAILED("There may be an issue in scalability");
4072c28215423293e443469a07ae7011135d058b671Garrett Cooper	}
408ec6edca7aa42b6affd989ef91b5897f96795e40fChris Dearman}
409