• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2004, Bull S.A..  All rights reserved.
3  * Created by: Sebastien Decugis
4 
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it would be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12  *
13  * You should have received a copy of the GNU General Public License along
14  * with this program; if not, write the Free Software Foundation, Inc.,
15  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16  *
17 
18  * This file is a scalability test for the pthread_mutex_lock function.
19  * The goal is to test if there is a limit on the number
20  *  of threads waiting on the same mutex.
21 
22  * The steps are:
23  * -> Create 5 mutex with different attributes.
24  * -> lock the 5 mutex in the main thread
25  * -> Create the maximum amount of threads allowed on the system.
26  * -> each thread, for each mutex:
27  *       - locks the mutex
28  *       - increments a counter
29  *       - unlocks the mutex
30  *       - if the counter equals the amount of threads,
31  */
32 
33  /* We are testing conformance to IEEE Std 1003.1, 2003 Edition */
34 #define _POSIX_C_SOURCE 200112L
35 
36  /* We enable the following line to have mutex attributes defined */
37 #ifndef WITHOUT_XOPEN
38 #define _XOPEN_SOURCE	600
39 #endif
40 
41 /********************************************************************************************/
42 /****************************** standard includes *****************************************/
43 /********************************************************************************************/
44 #include <pthread.h>
45 #include <errno.h>
46 #include <unistd.h>
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <stdarg.h>
50 
51 /********************************************************************************************/
52 /******************************   Test framework   *****************************************/
53 /********************************************************************************************/
54 #include "testfrmw.h"
55 #include "testfrmw.c"
56  /* This header is responsible for defining the following macros:
57   * UNRESOLVED(ret, descr);
58   *    where descr is a description of the error and ret is an int (error code for example)
59   * FAILED(descr);
60   *    where descr is a short text saying why the test has failed.
61   * PASSED();
62   *    No parameter.
63   *
64   * Both three macros shall terminate the calling process.
65   * The testcase shall not terminate in any other maneer.
66   *
67   * The other file defines the functions
68   * void output_init()
69   * void output(char * string, ...)
70   *
71   * Those may be used to output information.
72   */
73 
74 /********************************************************************************************/
75 /********************************** Configuration ******************************************/
76 /********************************************************************************************/
77 #ifndef SCALABILITY_FACTOR
78 #define SCALABILITY_FACTOR 1	/* This is not used in this testcase */
79 #endif
80 #ifndef VERBOSE
81 #define VERBOSE 2
82 #endif
83 
84 /********************************************************************************************/
85 /***********************************    Test case   *****************************************/
86 /********************************************************************************************/
87 
88 #ifndef WITHOUT_XOPEN
89 int types[] = {
90 	PTHREAD_MUTEX_NORMAL,
91 	PTHREAD_MUTEX_ERRORCHECK,
92 	PTHREAD_MUTEX_RECURSIVE,
93 	PTHREAD_MUTEX_DEFAULT
94 };
95 #endif
96 
97 /* The mutex the threads will block on */
98 pthread_mutex_t mtx[5];
99 
100 /* The condition used to signal the main thread to go to the next step */
101 pthread_cond_t cnd;
102 pthread_mutex_t m;
103 
104 /* The shared data used to control the results of the test */
105 unsigned long nbthOK[5];
106 unsigned long nbthNOK[5];
107 unsigned long nbthTOT;
108 
109 /*****
110  *
111  */
threaded(void * arg)112 void *threaded(void *arg)
113 {
114 	int ret;
115 	int i;
116 	int bool;
117 
118 	for (i = 0; i < 5; i++) {
119 		ret = pthread_mutex_lock(&mtx[i]);
120 		if (ret == 0) {	/* The thread was blocked successfuly */
121 			/* We increment nbth[i] */
122 			ret = pthread_mutex_lock(&m);
123 			if (ret != 0) {
124 				UNRESOLVED(ret, "Unable to lock 'm'");
125 			}
126 			nbthOK[i]++;
127 			bool = ((nbthOK[i] + nbthNOK[i]) >= nbthTOT);
128 			ret = pthread_mutex_unlock(&m);
129 			if (ret != 0) {
130 				UNRESOLVED(ret, "Unable to unlock 'm'");
131 			}
132 
133 			/* We can unlock the test mutex */
134 			ret = pthread_mutex_unlock(&mtx[i]);
135 			if (ret != 0) {
136 				FAILED("Unlocking a test mutex failed");
137 			}
138 		} else {	/* Locking the test mutex failed */
139 
140 			/* We increment nbth[i] */
141 			ret = pthread_mutex_lock(&m);
142 			if (ret != 0) {
143 				UNRESOLVED(ret, "Unable to lock 'm'");
144 			}
145 			nbthNOK[i]++;
146 			bool = ((nbthOK[i] + nbthNOK[i]) >= nbthTOT);
147 			ret = pthread_mutex_unlock(&m);
148 			if (ret != 0) {
149 				UNRESOLVED(ret, "Unable to unlock 'm'");
150 			}
151 		}
152 
153 		/* When every thread has passed the lock call, bool is true.
154 		   we signal the main thread to release the next mutex. */
155 
156 		if (bool) {
157 			ret = pthread_cond_signal(&cnd);
158 			if (ret != 0) {
159 				UNRESOLVED(ret,
160 					   "Signaling the condition failed");
161 			}
162 		}
163 	}
164 
165 	/* The test is terminated, the thread can die */
166 	ret = pthread_detach(pthread_self());
167 	if (ret != 0) {
168 		UNRESOLVED(ret, "Thread detach failed");
169 	}
170 
171 	return NULL;
172 }
173 
main(int argc,char * argv[])174 int main(int argc, char *argv[])
175 {
176 	pthread_t th;
177 	pthread_attr_t tha;
178 	pthread_mutexattr_t ma;
179 	int ret;
180 	int i;
181 
182 	output_init();
183 
184 #if VERBOSE > 1
185 	output("Test starting, initializing data\n");
186 #endif
187 
188 	/* Init the shared data */
189 	for (i = 0; i < 4; i++) {
190 		nbthOK[i] = 0;
191 		nbthNOK[i] = 0;
192 	}
193 	nbthTOT = 0;
194 
195 	/* Init the cnd */
196 	ret = pthread_mutex_init(&m, NULL);
197 	if (ret != 0) {
198 		UNRESOLVED(ret, "Unable to initialize 'm'");
199 	}
200 	ret = pthread_cond_init(&cnd, NULL);
201 	if (ret != 0) {
202 		UNRESOLVED(ret, "Unable to initialize 'cnd'");
203 	}
204 
205 	/* Init the 5 mutexes */
206 	ret = pthread_mutexattr_init(&ma);
207 	if (ret != 0) {
208 		UNRESOLVED(ret, "Unable to initialize 'ma'");
209 	}
210 
211 	for (i = 0; i < 5; i++) {
212 #ifndef WITHOUT_XOPEN
213 		if (i > 0) {
214 			ret = pthread_mutexattr_settype(&ma, types[i - 1]);
215 			if (ret != 0) {
216 				UNRESOLVED(ret,
217 					   "Unable to set mutex attribute type");
218 			}
219 		}
220 #endif
221 		ret = pthread_mutex_init(&mtx[i], &ma);
222 		if (ret != 0) {
223 			UNRESOLVED(ret, "A mutex init failed");
224 		}
225 	}
226 
227 	ret = pthread_mutexattr_destroy(&ma);
228 	if (ret != 0) {
229 		UNRESOLVED(ret, "Unable to destroy the mutex attribute object");
230 	}
231 
232 	/* Lock the mutexes */
233 	for (i = 0; i < 5; i++) {
234 		ret = pthread_mutex_lock(&mtx[i]);
235 		if (ret != 0) {
236 			UNRESOLVED(ret,
237 				   "Unable to lock a mutex for the first time");
238 		}
239 	}
240 
241 	/* Init the threads attribute */
242 	ret = pthread_attr_init(&tha);
243 	if (ret != 0) {
244 		UNRESOLVED(ret, "Thread attribute init failed");
245 	}
246 
247 	ret = pthread_attr_setstacksize(&tha, sysconf(_SC_THREAD_STACK_MIN));
248 	if (ret != 0) {
249 		UNRESOLVED(ret, "Unable to set stack size to minimum value");
250 	}
251 
252 	/* Create as many threads as possible */
253 #if VERBOSE > 1
254 	output("Creating threads...\n");
255 #endif
256 	do {
257 		ret = pthread_create(&th, &tha, threaded, NULL);
258 		if (ret == 0)
259 			nbthTOT++;
260 	} while (ret == 0);
261 
262 #if VERBOSE > 1
263 	output("Created %d threads.\n", nbthTOT);
264 #endif
265 
266 	/* lock m */
267 	ret = pthread_mutex_lock(&m);
268 	if (ret != 0) {
269 		UNRESOLVED(ret, "Unable to lock 'm' in main thread");
270 	}
271 
272 	/* For each mutex */
273 	for (i = 0; i < 5; i++) {
274 		/* Yield to let other threads enter the lock function */
275 		sched_yield();
276 
277 		/* unlock the test mutex */
278 		ret = pthread_mutex_unlock(&mtx[i]);
279 		if (ret != 0) {
280 			UNRESOLVED(ret,
281 				   "Unable to unlock a test mutex in main thread");
282 		}
283 
284 		/* wait for cnd */
285 		do {
286 			ret = pthread_cond_wait(&cnd, &m);
287 		}
288 		while ((ret == 0) && ((nbthOK[i] + nbthNOK[i]) < nbthTOT));
289 		if (ret != 0) {
290 			UNRESOLVED(ret, "Unable to wait for 'cnd'");
291 		}
292 	}
293 
294 	/* unlock m */
295 	ret = pthread_mutex_unlock(&m);
296 	if (ret != 0) {
297 		UNRESOLVED(ret, "Final 'm' unlock failed");
298 	}
299 
300 	/* Destroy everything */
301 	ret = pthread_attr_destroy(&tha);
302 	if (ret != 0) {
303 		UNRESOLVED(ret, "Final thread attribute destroy failed");
304 	}
305 
306 	for (i = 0; i < 5; i++) {
307 		ret = pthread_mutex_destroy(&mtx[i]);
308 		if (ret != 0) {
309 			UNRESOLVED(ret, "Unable to destroy a test mutex");
310 		}
311 	}
312 
313 	ret = pthread_cond_destroy(&cnd);
314 	if (ret != 0) {
315 		UNRESOLVED(ret, "Final cond destroy failed");
316 	}
317 
318 	ret = pthread_mutex_destroy(&m);
319 	if (ret != 0) {
320 		UNRESOLVED(ret, "Final mutex destroy failed");
321 	}
322 
323 	/* Output the results */
324 	output("Sample results:\n");
325 	output(" %lu threads were created\n", nbthTOT);
326 	for (i = 0; i < 5; i++) {
327 		output(" %lu threads have waited on mutex %i\n", nbthOK[i],
328 		       i + 1);
329 		output("  (and %lu threads could not wait)\n", nbthNOK[i]);
330 		ret += nbthNOK[i];
331 	}
332 
333 	/* Exit */
334 	if (ret == 0) {
335 		PASSED;
336 	} else {
337 		FAILED("There may be an issue in scalability");
338 	}
339 }
340