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