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 stress test for the pthread_mutex_init function.
192c28215423293e443469a07ae7011135d058b671Garrett Cooper
202c28215423293e443469a07ae7011135d058b671Garrett Cooper * The steps are:
212c28215423293e443469a07ae7011135d058b671Garrett Cooper * -> Create some threads
222c28215423293e443469a07ae7011135d058b671Garrett Cooper * -> each thread loops on initializing and destroying a mutex
232c28215423293e443469a07ae7011135d058b671Garrett Cooper * -> the whole process stop when receiving signal SIGUSR1
242c28215423293e443469a07ae7011135d058b671Garrett Cooper */
252c28215423293e443469a07ae7011135d058b671Garrett Cooper
262c28215423293e443469a07ae7011135d058b671Garrett Cooper /* We are testing conformance to IEEE Std 1003.1, 2003 Edition */
27354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#define _POSIX_C_SOURCE 200112L
282c28215423293e443469a07ae7011135d058b671Garrett Cooper
292c28215423293e443469a07ae7011135d058b671Garrett Cooper /* We enable the following line to have mutex attributes defined */
302c28215423293e443469a07ae7011135d058b671Garrett Cooper#ifndef WITHOUT_XOPEN
31354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#define _XOPEN_SOURCE	600
322c28215423293e443469a07ae7011135d058b671Garrett Cooper#endif
332c28215423293e443469a07ae7011135d058b671Garrett Cooper
342c28215423293e443469a07ae7011135d058b671Garrett Cooper/********************************************************************************************/
352c28215423293e443469a07ae7011135d058b671Garrett Cooper/****************************** standard includes *****************************************/
362c28215423293e443469a07ae7011135d058b671Garrett Cooper/********************************************************************************************/
37354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#include <pthread.h>
38354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#include <errno.h>
39354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#include <signal.h>
40354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#include <unistd.h>
41354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#include <stdio.h>
42354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#include <stdlib.h>
43354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#include <stdarg.h>
442c28215423293e443469a07ae7011135d058b671Garrett Cooper
452c28215423293e443469a07ae7011135d058b671Garrett Cooper/********************************************************************************************/
462c28215423293e443469a07ae7011135d058b671Garrett Cooper/******************************   Test framework   *****************************************/
472c28215423293e443469a07ae7011135d058b671Garrett Cooper/********************************************************************************************/
48354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#include "testfrmw.h"
49354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#include "testfrmw.c"
502c28215423293e443469a07ae7011135d058b671Garrett Cooper /* This header is responsible for defining the following macros:
512c28215423293e443469a07ae7011135d058b671Garrett Cooper  * UNRESOLVED(ret, descr);
522c28215423293e443469a07ae7011135d058b671Garrett Cooper  *    where descr is a description of the error and ret is an int (error code for example)
532c28215423293e443469a07ae7011135d058b671Garrett Cooper  * FAILED(descr);
542c28215423293e443469a07ae7011135d058b671Garrett Cooper  *    where descr is a short text saying why the test has failed.
552c28215423293e443469a07ae7011135d058b671Garrett Cooper  * PASSED();
562c28215423293e443469a07ae7011135d058b671Garrett Cooper  *    No parameter.
572c28215423293e443469a07ae7011135d058b671Garrett Cooper  *
582c28215423293e443469a07ae7011135d058b671Garrett Cooper  * Both three macros shall terminate the calling process.
592c28215423293e443469a07ae7011135d058b671Garrett Cooper  * The testcase shall not terminate in any other maneer.
602c28215423293e443469a07ae7011135d058b671Garrett Cooper  *
612c28215423293e443469a07ae7011135d058b671Garrett Cooper  * The other file defines the functions
622c28215423293e443469a07ae7011135d058b671Garrett Cooper  * void output_init()
632c28215423293e443469a07ae7011135d058b671Garrett Cooper  * void output(char * string, ...)
642c28215423293e443469a07ae7011135d058b671Garrett Cooper  *
652c28215423293e443469a07ae7011135d058b671Garrett Cooper  * Those may be used to output information.
662c28215423293e443469a07ae7011135d058b671Garrett Cooper  */
672c28215423293e443469a07ae7011135d058b671Garrett Cooper
682c28215423293e443469a07ae7011135d058b671Garrett Cooper/********************************************************************************************/
692c28215423293e443469a07ae7011135d058b671Garrett Cooper/********************************** Configuration ******************************************/
702c28215423293e443469a07ae7011135d058b671Garrett Cooper/********************************************************************************************/
712c28215423293e443469a07ae7011135d058b671Garrett Cooper#ifndef SCALABILITY_FACTOR
722c28215423293e443469a07ae7011135d058b671Garrett Cooper#define SCALABILITY_FACTOR 1
732c28215423293e443469a07ae7011135d058b671Garrett Cooper#endif
742c28215423293e443469a07ae7011135d058b671Garrett Cooper#ifndef VERBOSE
752c28215423293e443469a07ae7011135d058b671Garrett Cooper#define VERBOSE 2
762c28215423293e443469a07ae7011135d058b671Garrett Cooper#endif
772c28215423293e443469a07ae7011135d058b671Garrett Cooper#define N 20
782c28215423293e443469a07ae7011135d058b671Garrett Cooper
792c28215423293e443469a07ae7011135d058b671Garrett Cooper/********************************************************************************************/
802c28215423293e443469a07ae7011135d058b671Garrett Cooper/***********************************    Test case   *****************************************/
812c28215423293e443469a07ae7011135d058b671Garrett Cooper/********************************************************************************************/
82354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaochar do_it = 1;
832c28215423293e443469a07ae7011135d058b671Garrett Cooper#ifndef WITHOUT_XOPEN
84354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaoint types[] = { PTHREAD_MUTEX_NORMAL,
85354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	PTHREAD_MUTEX_ERRORCHECK,
86354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	PTHREAD_MUTEX_RECURSIVE,
87354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	PTHREAD_MUTEX_DEFAULT
88354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao};
892c28215423293e443469a07ae7011135d058b671Garrett Cooper#endif
902c28215423293e443469a07ae7011135d058b671Garrett Cooper
912c28215423293e443469a07ae7011135d058b671Garrett Cooper/******** Threads function *********/
92354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid *threaded(void *arg)
932c28215423293e443469a07ae7011135d058b671Garrett Cooper{
94354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int me = (int)arg;
952c28215423293e443469a07ae7011135d058b671Garrett Cooper	pthread_mutex_t mtx;
96354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	pthread_mutex_t *pmtx;
972c28215423293e443469a07ae7011135d058b671Garrett Cooper	pthread_mutexattr_t ma;
98354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	pthread_mutexattr_t *pma;
992c28215423293e443469a07ae7011135d058b671Garrett Cooper	int ret;
1002c28215423293e443469a07ae7011135d058b671Garrett Cooper#ifndef WITHOUT_XOPEN
1012c28215423293e443469a07ae7011135d058b671Garrett Cooper	int sz = 2 + (sizeof(types) / sizeof(int));
1022c28215423293e443469a07ae7011135d058b671Garrett Cooper#else
1032c28215423293e443469a07ae7011135d058b671Garrett Cooper	int sz = 2;
1042c28215423293e443469a07ae7011135d058b671Garrett Cooper#endif
1052c28215423293e443469a07ae7011135d058b671Garrett Cooper	/* We will use mutex from the stack or from malloc'ed memory */
106354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	char loc = ((me % 5) % 2);
1072c28215423293e443469a07ae7011135d058b671Garrett Cooper
108354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (loc) {
1092c28215423293e443469a07ae7011135d058b671Garrett Cooper		pmtx = &mtx;
110354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	} else {
111d218f348c12b42a78fa0306d9a033bfa4f67238bCyril Hrubis		pmtx = malloc(sizeof(pthread_mutex_t));
112354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (pmtx == NULL) {
113354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			UNRESOLVED(errno, "Memory allocation for mutex failed");
114354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
1152c28215423293e443469a07ae7011135d058b671Garrett Cooper	}
1162c28215423293e443469a07ae7011135d058b671Garrett Cooper
1172c28215423293e443469a07ae7011135d058b671Garrett Cooper	me %= sz;
1182c28215423293e443469a07ae7011135d058b671Garrett Cooper
119354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	switch (me) {
120354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	case 0:		/* We will initialize the mutex with NULL pointer */
121354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		pma = NULL;
122354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		break;
1232c28215423293e443469a07ae7011135d058b671Garrett Cooper
124354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	default:		/* We will initialize the mutex with an attribute object */
125354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if ((ret = pthread_mutexattr_init(&ma))) {
126354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			UNRESOLVED(ret, "Mutex attribute init failed");
127354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
128354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		pma = &ma;
1292c28215423293e443469a07ae7011135d058b671Garrett Cooper
130354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (me == 1)
131354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			break;
1322c28215423293e443469a07ae7011135d058b671Garrett Cooper
133354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if ((ret = pthread_mutexattr_settype(&ma, types[me - 2]))) {
134354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			UNRESOLVED(ret, "Mutex attribute settype failed");
135354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
1362c28215423293e443469a07ae7011135d058b671Garrett Cooper	}
1372c28215423293e443469a07ae7011135d058b671Garrett Cooper
138354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	while (do_it) {
1392c28215423293e443469a07ae7011135d058b671Garrett Cooper		ret = pthread_mutex_init(pmtx, pma);
140354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (ret != 0) {
141354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			FAILED("Mutex init failed");
142354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
1432c28215423293e443469a07ae7011135d058b671Garrett Cooper		/* We use the mutex to check everything is OK */
1442c28215423293e443469a07ae7011135d058b671Garrett Cooper		ret = pthread_mutex_lock(pmtx);
145354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (ret != 0) {
146354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			FAILED("Mutex lock failed");
147354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
1482c28215423293e443469a07ae7011135d058b671Garrett Cooper		ret = pthread_mutex_unlock(pmtx);
149354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (ret != 0) {
150354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			FAILED("Mutex unlock failed");
151354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
1522c28215423293e443469a07ae7011135d058b671Garrett Cooper		ret = pthread_mutex_destroy(pmtx);
153354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (ret != 0) {
154354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			FAILED("Mutex destroy failed");
155354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
1562c28215423293e443469a07ae7011135d058b671Garrett Cooper	}
1572c28215423293e443469a07ae7011135d058b671Garrett Cooper
158354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (!loc)		/* mutex was malloc'ed */
1592c28215423293e443469a07ae7011135d058b671Garrett Cooper		free(pmtx);
1602c28215423293e443469a07ae7011135d058b671Garrett Cooper
1612c28215423293e443469a07ae7011135d058b671Garrett Cooper	if (me)
162354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if ((ret = pthread_mutexattr_destroy(pma))) {
163354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			FAILED("Mutex attribute destroy failed at the end");
164354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
1652c28215423293e443469a07ae7011135d058b671Garrett Cooper
1662c28215423293e443469a07ae7011135d058b671Garrett Cooper	return NULL;
1672c28215423293e443469a07ae7011135d058b671Garrett Cooper}
1682c28215423293e443469a07ae7011135d058b671Garrett Cooper
1692c28215423293e443469a07ae7011135d058b671Garrett Cooper/******** Signal handler ************/
1702c28215423293e443469a07ae7011135d058b671Garrett Coopervoid sighdl(int sig)
1712c28215423293e443469a07ae7011135d058b671Garrett Cooper{
172354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	do {
173354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		do_it = 0;
174354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
1752c28215423293e443469a07ae7011135d058b671Garrett Cooper	while (do_it);
1762c28215423293e443469a07ae7011135d058b671Garrett Cooper}
1772c28215423293e443469a07ae7011135d058b671Garrett Cooper
1782c28215423293e443469a07ae7011135d058b671Garrett Cooper/******** Parent thread *************/
179354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaoint main(int argc, char *argv[])
1802c28215423293e443469a07ae7011135d058b671Garrett Cooper{
1812c28215423293e443469a07ae7011135d058b671Garrett Cooper	struct sigaction sa;
1822c28215423293e443469a07ae7011135d058b671Garrett Cooper	pthread_t threads[N * SCALABILITY_FACTOR];
1832c28215423293e443469a07ae7011135d058b671Garrett Cooper	int i;
1842c28215423293e443469a07ae7011135d058b671Garrett Cooper	int ret;
1852c28215423293e443469a07ae7011135d058b671Garrett Cooper
1862c28215423293e443469a07ae7011135d058b671Garrett Cooper	output_init();
1872c28215423293e443469a07ae7011135d058b671Garrett Cooper
188354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	sigemptyset(&sa.sa_mask);
1892c28215423293e443469a07ae7011135d058b671Garrett Cooper	sa.sa_flags = 0;
1902c28215423293e443469a07ae7011135d058b671Garrett Cooper	sa.sa_handler = sighdl;
191354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if ((ret = sigaction(SIGUSR1, &sa, NULL))) {
192354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		UNRESOLVED(ret, "Unable to register signal handler");
193354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
1942c28215423293e443469a07ae7011135d058b671Garrett Cooper
195354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	for (i = 0; (i < (N * SCALABILITY_FACTOR) && (ret == 0)); i++) {
196354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		ret = pthread_create(&threads[i], NULL, threaded, (void *)i);
1972c28215423293e443469a07ae7011135d058b671Garrett Cooper	}
198354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (ret != 0) {		/* A thread creation failed */
199354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		/* Stop the started threads */
200354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		do {
201354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			do_it = 0;
202354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
2032c28215423293e443469a07ae7011135d058b671Garrett Cooper		while (do_it);
204354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		for (; i > 0; i--)
205354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			pthread_join(threads[i - 1], NULL);
2062c28215423293e443469a07ae7011135d058b671Garrett Cooper
2072c28215423293e443469a07ae7011135d058b671Garrett Cooper		UNRESOLVED(ret, "Unable to create enough threads");
2082c28215423293e443469a07ae7011135d058b671Garrett Cooper	}
2092c28215423293e443469a07ae7011135d058b671Garrett Cooper
2102c28215423293e443469a07ae7011135d058b671Garrett Cooper	/* Every threads were created; we now just wait */
211354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	for (i = 0; i < (N * SCALABILITY_FACTOR); i++) {
212354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if ((ret = pthread_join(threads[i], NULL))) {
213354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			FAILED("Unable to join a thread");
214354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
2152c28215423293e443469a07ae7011135d058b671Garrett Cooper	}
216354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#if VERBOSE > 0
2172c28215423293e443469a07ae7011135d058b671Garrett Cooper	output("pthread_mutex_init stress test passed\n");
218354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#endif
2192c28215423293e443469a07ae7011135d058b671Garrett Cooper
2202c28215423293e443469a07ae7011135d058b671Garrett Cooper	/* Everything went OK */
2212c28215423293e443469a07ae7011135d058b671Garrett Cooper	PASSED;
222ec6edca7aa42b6affd989ef91b5897f96795e40fChris Dearman}
223