1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/nsprpub/pr/tests/cvar2.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,960 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +/*********************************************************************** 1.10 +** 1996 - Netscape Communications Corporation 1.11 +** 1.12 +** Name: cvar2.c 1.13 +** 1.14 +** Description: Simple test creates several local and global threads; 1.15 +** half use a single,shared condvar, and the 1.16 +** other half have their own condvar. The main thread then loops 1.17 +** notifying them to wakeup. 1.18 +** 1.19 +** Modification History: 1.20 +** 14-May-97 AGarcia- Converted the test to accomodate the debug_mode flag. 1.21 +** The debug mode will print all of the printfs associated with this test. 1.22 +** The regress mode will be the default mode. Since the regress tool limits 1.23 +** the output to a one line status:PASS or FAIL,all of the printf statements 1.24 +** have been handled with an if (debug_mode) statement. 1.25 +***********************************************************************/ 1.26 + 1.27 +#include "nspr.h" 1.28 +#include "plerror.h" 1.29 +#include "plgetopt.h" 1.30 + 1.31 +#include <stdio.h> 1.32 +#include <stdlib.h> 1.33 +#include <string.h> 1.34 + 1.35 +int _debug_on = 0; 1.36 +#define DPRINTF(arg) if (_debug_on) printf arg 1.37 + 1.38 +#define DEFAULT_COUNT 100 1.39 +#define DEFAULT_THREADS 5 1.40 +PRInt32 count = DEFAULT_COUNT; 1.41 + 1.42 +typedef struct threadinfo { 1.43 + PRThread *thread; 1.44 + PRInt32 id; 1.45 + PRBool internal; 1.46 + PRInt32 *tcount; 1.47 + PRLock *lock; 1.48 + PRCondVar *cvar; 1.49 + PRIntervalTime timeout; 1.50 + PRInt32 loops; 1.51 + 1.52 + PRLock *exitlock; 1.53 + PRCondVar *exitcvar; 1.54 + PRInt32 *exitcount; 1.55 +} threadinfo; 1.56 + 1.57 +/* 1.58 +** Make exitcount, tcount static. for Win16. 1.59 +*/ 1.60 +static PRInt32 exitcount=0; 1.61 +static PRInt32 tcount=0; 1.62 + 1.63 + 1.64 +/* Thread that gets notified; many threads share the same condvar */ 1.65 +void PR_CALLBACK 1.66 +SharedCondVarThread(void *_info) 1.67 +{ 1.68 + threadinfo *info = (threadinfo *)_info; 1.69 + PRInt32 index; 1.70 + 1.71 + for (index=0; index<info->loops; index++) { 1.72 + PR_Lock(info->lock); 1.73 + if (*info->tcount == 0) 1.74 + PR_WaitCondVar(info->cvar, info->timeout); 1.75 +#if 0 1.76 + printf("shared thread %ld notified in loop %ld\n", info->id, index); 1.77 +#endif 1.78 + (*info->tcount)--; 1.79 + PR_Unlock(info->lock); 1.80 + 1.81 + PR_Lock(info->exitlock); 1.82 + (*info->exitcount)++; 1.83 + PR_NotifyCondVar(info->exitcvar); 1.84 + PR_Unlock(info->exitlock); 1.85 + } 1.86 +#if 0 1.87 + printf("shared thread %ld terminating\n", info->id); 1.88 +#endif 1.89 +} 1.90 + 1.91 +/* Thread that gets notified; no other threads use the same condvar */ 1.92 +void PR_CALLBACK 1.93 +PrivateCondVarThread(void *_info) 1.94 +{ 1.95 + threadinfo *info = (threadinfo *)_info; 1.96 + PRInt32 index; 1.97 + 1.98 + for (index=0; index<info->loops; index++) { 1.99 + PR_Lock(info->lock); 1.100 + if (*info->tcount == 0) { 1.101 + DPRINTF(("PrivateCondVarThread: thread 0x%lx waiting on cvar = 0x%lx\n", 1.102 + PR_GetCurrentThread(), info->cvar)); 1.103 + PR_WaitCondVar(info->cvar, info->timeout); 1.104 + } 1.105 +#if 0 1.106 + printf("solo thread %ld notified in loop %ld\n", info->id, index); 1.107 +#endif 1.108 + (*info->tcount)--; 1.109 + PR_Unlock(info->lock); 1.110 + 1.111 + PR_Lock(info->exitlock); 1.112 + (*info->exitcount)++; 1.113 + PR_NotifyCondVar(info->exitcvar); 1.114 +DPRINTF(("PrivateCondVarThread: thread 0x%lx notified exitcvar = 0x%lx cnt = %ld\n", 1.115 + PR_GetCurrentThread(), info->exitcvar,(*info->exitcount))); 1.116 + PR_Unlock(info->exitlock); 1.117 + } 1.118 +#if 0 1.119 + printf("solo thread %ld terminating\n", info->id); 1.120 +#endif 1.121 +} 1.122 + 1.123 +void 1.124 +CreateTestThread(threadinfo *info, 1.125 + PRInt32 id, 1.126 + PRLock *lock, 1.127 + PRCondVar *cvar, 1.128 + PRInt32 loops, 1.129 + PRIntervalTime timeout, 1.130 + PRInt32 *tcount, 1.131 + PRLock *exitlock, 1.132 + PRCondVar *exitcvar, 1.133 + PRInt32 *exitcount, 1.134 + PRBool shared, 1.135 + PRThreadScope scope) 1.136 +{ 1.137 + info->id = id; 1.138 + info->internal = (shared) ? PR_FALSE : PR_TRUE; 1.139 + info->lock = lock; 1.140 + info->cvar = cvar; 1.141 + info->loops = loops; 1.142 + info->timeout = timeout; 1.143 + info->tcount = tcount; 1.144 + info->exitlock = exitlock; 1.145 + info->exitcvar = exitcvar; 1.146 + info->exitcount = exitcount; 1.147 + info->thread = PR_CreateThread( 1.148 + PR_USER_THREAD, 1.149 + shared?SharedCondVarThread:PrivateCondVarThread, 1.150 + info, 1.151 + PR_PRIORITY_NORMAL, 1.152 + scope, 1.153 + PR_JOINABLE_THREAD, 1.154 + 0); 1.155 + if (!info->thread) 1.156 + PL_PrintError("error creating thread\n"); 1.157 +} 1.158 + 1.159 + 1.160 +void 1.161 +CondVarTestSUU(void *_arg) 1.162 +{ 1.163 + PRInt32 arg = (PRInt32)_arg; 1.164 + PRInt32 index, loops; 1.165 + threadinfo *list; 1.166 + PRLock *sharedlock; 1.167 + PRCondVar *sharedcvar; 1.168 + PRLock *exitlock; 1.169 + PRCondVar *exitcvar; 1.170 + 1.171 + exitcount=0; 1.172 + tcount=0; 1.173 + list = (threadinfo *)PR_MALLOC(sizeof(threadinfo) * (arg * 4)); 1.174 + 1.175 + sharedlock = PR_NewLock(); 1.176 + sharedcvar = PR_NewCondVar(sharedlock); 1.177 + exitlock = PR_NewLock(); 1.178 + exitcvar = PR_NewCondVar(exitlock); 1.179 + 1.180 + /* Create the threads */ 1.181 + for(index=0; index<arg; ) { 1.182 + CreateTestThread(&list[index], 1.183 + index, 1.184 + sharedlock, 1.185 + sharedcvar, 1.186 + count, 1.187 + PR_INTERVAL_NO_TIMEOUT, 1.188 + &tcount, 1.189 + exitlock, 1.190 + exitcvar, 1.191 + &exitcount, 1.192 + PR_TRUE, 1.193 + PR_LOCAL_THREAD); 1.194 + index++; 1.195 + DPRINTF(("CondVarTestSUU: created thread 0x%lx\n",list[index].thread)); 1.196 + } 1.197 + 1.198 + for (loops = 0; loops < count; loops++) { 1.199 + /* Notify the threads */ 1.200 + for(index=0; index<(arg); index++) { 1.201 + PR_Lock(list[index].lock); 1.202 + (*list[index].tcount)++; 1.203 + PR_NotifyCondVar(list[index].cvar); 1.204 + PR_Unlock(list[index].lock); 1.205 + DPRINTF(("PrivateCondVarThread: thread 0x%lx notified cvar = 0x%lx\n", 1.206 + PR_GetCurrentThread(), list[index].cvar)); 1.207 + } 1.208 + 1.209 + /* Wait for threads to finish */ 1.210 + PR_Lock(exitlock); 1.211 + while(exitcount < arg) 1.212 + PR_WaitCondVar(exitcvar, PR_SecondsToInterval(60)); 1.213 + PR_ASSERT(exitcount >= arg); 1.214 + exitcount -= arg; 1.215 + PR_Unlock(exitlock); 1.216 + } 1.217 + 1.218 + /* Join all the threads */ 1.219 + for(index=0; index<(arg); index++) 1.220 + PR_JoinThread(list[index].thread); 1.221 + 1.222 + PR_DestroyCondVar(sharedcvar); 1.223 + PR_DestroyLock(sharedlock); 1.224 + PR_DestroyCondVar(exitcvar); 1.225 + PR_DestroyLock(exitlock); 1.226 + 1.227 + PR_DELETE(list); 1.228 +} 1.229 + 1.230 +void 1.231 +CondVarTestSUK(void *_arg) 1.232 +{ 1.233 + PRInt32 arg = (PRInt32)_arg; 1.234 + PRInt32 index, loops; 1.235 + threadinfo *list; 1.236 + PRLock *sharedlock; 1.237 + PRCondVar *sharedcvar; 1.238 + PRLock *exitlock; 1.239 + PRCondVar *exitcvar; 1.240 + exitcount=0; 1.241 + tcount=0; 1.242 + 1.243 + list = (threadinfo *)PR_MALLOC(sizeof(threadinfo) * (arg * 4)); 1.244 + 1.245 + sharedlock = PR_NewLock(); 1.246 + sharedcvar = PR_NewCondVar(sharedlock); 1.247 + exitlock = PR_NewLock(); 1.248 + exitcvar = PR_NewCondVar(exitlock); 1.249 + 1.250 + /* Create the threads */ 1.251 + for(index=0; index<arg; ) { 1.252 + CreateTestThread(&list[index], 1.253 + index, 1.254 + sharedlock, 1.255 + sharedcvar, 1.256 + count, 1.257 + PR_INTERVAL_NO_TIMEOUT, 1.258 + &tcount, 1.259 + exitlock, 1.260 + exitcvar, 1.261 + &exitcount, 1.262 + PR_TRUE, 1.263 + PR_GLOBAL_THREAD); 1.264 + index++; 1.265 + } 1.266 + 1.267 + for (loops = 0; loops < count; loops++) { 1.268 + /* Notify the threads */ 1.269 + for(index=0; index<(arg); index++) { 1.270 + 1.271 + PR_Lock(list[index].lock); 1.272 + (*list[index].tcount)++; 1.273 + PR_NotifyCondVar(list[index].cvar); 1.274 + PR_Unlock(list[index].lock); 1.275 + } 1.276 + 1.277 +#if 0 1.278 + printf("wait for threads to be done\n"); 1.279 +#endif 1.280 + /* Wait for threads to finish */ 1.281 + PR_Lock(exitlock); 1.282 + while(exitcount < arg) 1.283 + PR_WaitCondVar(exitcvar, PR_SecondsToInterval(60)); 1.284 + PR_ASSERT(exitcount >= arg); 1.285 + exitcount -= arg; 1.286 + PR_Unlock(exitlock); 1.287 +#if 0 1.288 + printf("threads ready\n"); 1.289 +#endif 1.290 + } 1.291 + 1.292 + /* Join all the threads */ 1.293 + for(index=0; index<(arg); index++) 1.294 + PR_JoinThread(list[index].thread); 1.295 + 1.296 + PR_DestroyCondVar(sharedcvar); 1.297 + PR_DestroyLock(sharedlock); 1.298 + PR_DestroyCondVar(exitcvar); 1.299 + PR_DestroyLock(exitlock); 1.300 + 1.301 + PR_DELETE(list); 1.302 +} 1.303 + 1.304 +void 1.305 +CondVarTestPUU(void *_arg) 1.306 +{ 1.307 + PRInt32 arg = (PRInt32)_arg; 1.308 + PRInt32 index, loops; 1.309 + threadinfo *list; 1.310 + PRLock *sharedlock; 1.311 + PRCondVar *sharedcvar; 1.312 + PRLock *exitlock; 1.313 + PRCondVar *exitcvar; 1.314 + PRInt32 *tcount, *saved_tcount; 1.315 + 1.316 + exitcount=0; 1.317 + list = (threadinfo *)PR_MALLOC(sizeof(threadinfo) * (arg * 4)); 1.318 + saved_tcount = tcount = (PRInt32 *)PR_CALLOC(sizeof(*tcount) * (arg * 4)); 1.319 + 1.320 + sharedlock = PR_NewLock(); 1.321 + sharedcvar = PR_NewCondVar(sharedlock); 1.322 + exitlock = PR_NewLock(); 1.323 + exitcvar = PR_NewCondVar(exitlock); 1.324 + 1.325 + /* Create the threads */ 1.326 + for(index=0; index<arg; ) { 1.327 + list[index].lock = PR_NewLock(); 1.328 + list[index].cvar = PR_NewCondVar(list[index].lock); 1.329 + CreateTestThread(&list[index], 1.330 + index, 1.331 + list[index].lock, 1.332 + list[index].cvar, 1.333 + count, 1.334 + PR_INTERVAL_NO_TIMEOUT, 1.335 + tcount, 1.336 + exitlock, 1.337 + exitcvar, 1.338 + &exitcount, 1.339 + PR_FALSE, 1.340 + PR_LOCAL_THREAD); 1.341 + 1.342 + DPRINTF(("CondVarTestPUU: created thread 0x%lx\n",list[index].thread)); 1.343 + index++; 1.344 + tcount++; 1.345 + } 1.346 + 1.347 + for (loops = 0; loops < count; loops++) { 1.348 + /* Notify the threads */ 1.349 + for(index=0; index<(arg); index++) { 1.350 + 1.351 + PR_Lock(list[index].lock); 1.352 + (*list[index].tcount)++; 1.353 + PR_NotifyCondVar(list[index].cvar); 1.354 + PR_Unlock(list[index].lock); 1.355 + } 1.356 + 1.357 + PR_Lock(exitlock); 1.358 + /* Wait for threads to finish */ 1.359 + while(exitcount < arg) { 1.360 +DPRINTF(("CondVarTestPUU: thread 0x%lx waiting on exitcvar = 0x%lx cnt = %ld\n", 1.361 + PR_GetCurrentThread(), exitcvar, exitcount)); 1.362 + PR_WaitCondVar(exitcvar, PR_SecondsToInterval(60)); 1.363 + } 1.364 + PR_ASSERT(exitcount >= arg); 1.365 + exitcount -= arg; 1.366 + PR_Unlock(exitlock); 1.367 + } 1.368 + 1.369 + /* Join all the threads */ 1.370 + for(index=0; index<(arg); index++) { 1.371 + DPRINTF(("CondVarTestPUU: joining thread 0x%lx\n",list[index].thread)); 1.372 + PR_JoinThread(list[index].thread); 1.373 + if (list[index].internal) { 1.374 + PR_Lock(list[index].lock); 1.375 + PR_DestroyCondVar(list[index].cvar); 1.376 + PR_Unlock(list[index].lock); 1.377 + PR_DestroyLock(list[index].lock); 1.378 + } 1.379 + } 1.380 + 1.381 + PR_DestroyCondVar(sharedcvar); 1.382 + PR_DestroyLock(sharedlock); 1.383 + PR_DestroyCondVar(exitcvar); 1.384 + PR_DestroyLock(exitlock); 1.385 + 1.386 + PR_DELETE(list); 1.387 + PR_DELETE(saved_tcount); 1.388 +} 1.389 + 1.390 +void 1.391 +CondVarTestPUK(void *_arg) 1.392 +{ 1.393 + PRInt32 arg = (PRInt32)_arg; 1.394 + PRInt32 index, loops; 1.395 + threadinfo *list; 1.396 + PRLock *sharedlock; 1.397 + PRCondVar *sharedcvar; 1.398 + PRLock *exitlock; 1.399 + PRCondVar *exitcvar; 1.400 + PRInt32 *tcount, *saved_tcount; 1.401 + 1.402 + exitcount=0; 1.403 + list = (threadinfo *)PR_MALLOC(sizeof(threadinfo) * (arg * 4)); 1.404 + saved_tcount = tcount = (PRInt32 *)PR_CALLOC(sizeof(*tcount) * (arg * 4)); 1.405 + 1.406 + sharedlock = PR_NewLock(); 1.407 + sharedcvar = PR_NewCondVar(sharedlock); 1.408 + exitlock = PR_NewLock(); 1.409 + exitcvar = PR_NewCondVar(exitlock); 1.410 + 1.411 + /* Create the threads */ 1.412 + for(index=0; index<arg; ) { 1.413 + list[index].lock = PR_NewLock(); 1.414 + list[index].cvar = PR_NewCondVar(list[index].lock); 1.415 + CreateTestThread(&list[index], 1.416 + index, 1.417 + list[index].lock, 1.418 + list[index].cvar, 1.419 + count, 1.420 + PR_INTERVAL_NO_TIMEOUT, 1.421 + tcount, 1.422 + exitlock, 1.423 + exitcvar, 1.424 + &exitcount, 1.425 + PR_FALSE, 1.426 + PR_GLOBAL_THREAD); 1.427 + 1.428 + index++; 1.429 + tcount++; 1.430 + } 1.431 + 1.432 + for (loops = 0; loops < count; loops++) { 1.433 + /* Notify the threads */ 1.434 + for(index=0; index<(arg); index++) { 1.435 + 1.436 + PR_Lock(list[index].lock); 1.437 + (*list[index].tcount)++; 1.438 + PR_NotifyCondVar(list[index].cvar); 1.439 + PR_Unlock(list[index].lock); 1.440 + } 1.441 + 1.442 + /* Wait for threads to finish */ 1.443 + PR_Lock(exitlock); 1.444 + while(exitcount < arg) 1.445 + PR_WaitCondVar(exitcvar, PR_SecondsToInterval(60)); 1.446 + PR_ASSERT(exitcount >= arg); 1.447 + exitcount -= arg; 1.448 + PR_Unlock(exitlock); 1.449 + } 1.450 + 1.451 + /* Join all the threads */ 1.452 + for(index=0; index<(arg); index++) { 1.453 + PR_JoinThread(list[index].thread); 1.454 + if (list[index].internal) { 1.455 + PR_Lock(list[index].lock); 1.456 + PR_DestroyCondVar(list[index].cvar); 1.457 + PR_Unlock(list[index].lock); 1.458 + PR_DestroyLock(list[index].lock); 1.459 + } 1.460 + } 1.461 + 1.462 + PR_DestroyCondVar(sharedcvar); 1.463 + PR_DestroyLock(sharedlock); 1.464 + PR_DestroyCondVar(exitcvar); 1.465 + PR_DestroyLock(exitlock); 1.466 + 1.467 + PR_DELETE(list); 1.468 + PR_DELETE(saved_tcount); 1.469 +} 1.470 + 1.471 +void 1.472 +CondVarTest(void *_arg) 1.473 +{ 1.474 + PRInt32 arg = (PRInt32)_arg; 1.475 + PRInt32 index, loops; 1.476 + threadinfo *list; 1.477 + PRLock *sharedlock; 1.478 + PRCondVar *sharedcvar; 1.479 + PRLock *exitlock; 1.480 + PRCondVar *exitcvar; 1.481 + PRInt32 *ptcount, *saved_ptcount; 1.482 + 1.483 + exitcount=0; 1.484 + tcount=0; 1.485 + list = (threadinfo *)PR_MALLOC(sizeof(threadinfo) * (arg * 4)); 1.486 + saved_ptcount = ptcount = (PRInt32 *)PR_CALLOC(sizeof(*ptcount) * (arg * 4)); 1.487 + 1.488 + sharedlock = PR_NewLock(); 1.489 + sharedcvar = PR_NewCondVar(sharedlock); 1.490 + exitlock = PR_NewLock(); 1.491 + exitcvar = PR_NewCondVar(exitlock); 1.492 + 1.493 + /* Create the threads */ 1.494 + for(index=0; index<arg*4; ) { 1.495 + CreateTestThread(&list[index], 1.496 + index, 1.497 + sharedlock, 1.498 + sharedcvar, 1.499 + count, 1.500 + PR_INTERVAL_NO_TIMEOUT, 1.501 + &tcount, 1.502 + exitlock, 1.503 + exitcvar, 1.504 + &exitcount, 1.505 + PR_TRUE, 1.506 + PR_LOCAL_THREAD); 1.507 + 1.508 + index++; 1.509 + CreateTestThread(&list[index], 1.510 + index, 1.511 + sharedlock, 1.512 + sharedcvar, 1.513 + count, 1.514 + PR_INTERVAL_NO_TIMEOUT, 1.515 + &tcount, 1.516 + exitlock, 1.517 + exitcvar, 1.518 + &exitcount, 1.519 + PR_TRUE, 1.520 + PR_GLOBAL_THREAD); 1.521 + 1.522 + index++; 1.523 + list[index].lock = PR_NewLock(); 1.524 + list[index].cvar = PR_NewCondVar(list[index].lock); 1.525 + CreateTestThread(&list[index], 1.526 + index, 1.527 + list[index].lock, 1.528 + list[index].cvar, 1.529 + count, 1.530 + PR_INTERVAL_NO_TIMEOUT, 1.531 + ptcount, 1.532 + exitlock, 1.533 + exitcvar, 1.534 + &exitcount, 1.535 + PR_FALSE, 1.536 + PR_LOCAL_THREAD); 1.537 + index++; 1.538 + ptcount++; 1.539 + list[index].lock = PR_NewLock(); 1.540 + list[index].cvar = PR_NewCondVar(list[index].lock); 1.541 + CreateTestThread(&list[index], 1.542 + index, 1.543 + list[index].lock, 1.544 + list[index].cvar, 1.545 + count, 1.546 + PR_INTERVAL_NO_TIMEOUT, 1.547 + ptcount, 1.548 + exitlock, 1.549 + exitcvar, 1.550 + &exitcount, 1.551 + PR_FALSE, 1.552 + PR_GLOBAL_THREAD); 1.553 + 1.554 + index++; 1.555 + ptcount++; 1.556 + } 1.557 + 1.558 + for (loops = 0; loops < count; loops++) { 1.559 + 1.560 + /* Notify the threads */ 1.561 + for(index=0; index<(arg*4); index++) { 1.562 + PR_Lock(list[index].lock); 1.563 + (*list[index].tcount)++; 1.564 + PR_NotifyCondVar(list[index].cvar); 1.565 + PR_Unlock(list[index].lock); 1.566 + } 1.567 + 1.568 +#if 0 1.569 + printf("wait for threads done\n"); 1.570 +#endif 1.571 + 1.572 + /* Wait for threads to finish */ 1.573 + PR_Lock(exitlock); 1.574 + while(exitcount < arg*4) 1.575 + PR_WaitCondVar(exitcvar, PR_SecondsToInterval(60)); 1.576 + PR_ASSERT(exitcount >= arg*4); 1.577 + exitcount -= arg*4; 1.578 + PR_Unlock(exitlock); 1.579 +#if 0 1.580 + printf("threads ready\n"); 1.581 +#endif 1.582 + } 1.583 + 1.584 + /* Join all the threads */ 1.585 + for(index=0; index<(arg*4); index++) { 1.586 + PR_JoinThread(list[index].thread); 1.587 + if (list[index].internal) { 1.588 + PR_Lock(list[index].lock); 1.589 + PR_DestroyCondVar(list[index].cvar); 1.590 + PR_Unlock(list[index].lock); 1.591 + PR_DestroyLock(list[index].lock); 1.592 + } 1.593 + } 1.594 + 1.595 + PR_DestroyCondVar(sharedcvar); 1.596 + PR_DestroyLock(sharedlock); 1.597 + PR_DestroyCondVar(exitcvar); 1.598 + PR_DestroyLock(exitlock); 1.599 + 1.600 + PR_DELETE(list); 1.601 + PR_DELETE(saved_ptcount); 1.602 +} 1.603 + 1.604 +void 1.605 +CondVarTimeoutTest(void *_arg) 1.606 +{ 1.607 + PRInt32 arg = (PRInt32)_arg; 1.608 + PRInt32 index, loops; 1.609 + threadinfo *list; 1.610 + PRLock *sharedlock; 1.611 + PRCondVar *sharedcvar; 1.612 + PRLock *exitlock; 1.613 + PRCondVar *exitcvar; 1.614 + 1.615 + list = (threadinfo *)PR_MALLOC(sizeof(threadinfo) * (arg * 4)); 1.616 + 1.617 + sharedlock = PR_NewLock(); 1.618 + sharedcvar = PR_NewCondVar(sharedlock); 1.619 + exitlock = PR_NewLock(); 1.620 + exitcvar = PR_NewCondVar(exitlock); 1.621 + 1.622 + /* Create the threads */ 1.623 + for(index=0; index<arg*4; ) { 1.624 + CreateTestThread(&list[index], 1.625 + index, 1.626 + sharedlock, 1.627 + sharedcvar, 1.628 + count, 1.629 + PR_MillisecondsToInterval(50), 1.630 + &tcount, 1.631 + exitlock, 1.632 + exitcvar, 1.633 + &exitcount, 1.634 + PR_TRUE, 1.635 + PR_LOCAL_THREAD); 1.636 + index++; 1.637 + CreateTestThread(&list[index], 1.638 + index, 1.639 + sharedlock, 1.640 + sharedcvar, 1.641 + count, 1.642 + PR_MillisecondsToInterval(50), 1.643 + &tcount, 1.644 + exitlock, 1.645 + exitcvar, 1.646 + &exitcount, 1.647 + PR_TRUE, 1.648 + PR_GLOBAL_THREAD); 1.649 + index++; 1.650 + list[index].lock = PR_NewLock(); 1.651 + list[index].cvar = PR_NewCondVar(list[index].lock); 1.652 + CreateTestThread(&list[index], 1.653 + index, 1.654 + list[index].lock, 1.655 + list[index].cvar, 1.656 + count, 1.657 + PR_MillisecondsToInterval(50), 1.658 + &tcount, 1.659 + exitlock, 1.660 + exitcvar, 1.661 + &exitcount, 1.662 + PR_FALSE, 1.663 + PR_LOCAL_THREAD); 1.664 + index++; 1.665 + 1.666 + list[index].lock = PR_NewLock(); 1.667 + list[index].cvar = PR_NewCondVar(list[index].lock); 1.668 + CreateTestThread(&list[index], 1.669 + index, 1.670 + list[index].lock, 1.671 + list[index].cvar, 1.672 + count, 1.673 + PR_MillisecondsToInterval(50), 1.674 + &tcount, 1.675 + exitlock, 1.676 + exitcvar, 1.677 + &exitcount, 1.678 + PR_FALSE, 1.679 + PR_GLOBAL_THREAD); 1.680 + 1.681 + index++; 1.682 + } 1.683 + 1.684 + for (loops = 0; loops < count; loops++) { 1.685 + 1.686 + /* Wait for threads to finish */ 1.687 + PR_Lock(exitlock); 1.688 + while(exitcount < arg*4) 1.689 + PR_WaitCondVar(exitcvar, PR_SecondsToInterval(60)); 1.690 + PR_ASSERT(exitcount >= arg*4); 1.691 + exitcount -= arg*4; 1.692 + PR_Unlock(exitlock); 1.693 + } 1.694 + 1.695 + 1.696 + /* Join all the threads */ 1.697 + for(index=0; index<(arg*4); index++) { 1.698 + PR_JoinThread(list[index].thread); 1.699 + if (list[index].internal) { 1.700 + PR_Lock(list[index].lock); 1.701 + PR_DestroyCondVar(list[index].cvar); 1.702 + PR_Unlock(list[index].lock); 1.703 + PR_DestroyLock(list[index].lock); 1.704 + } 1.705 + } 1.706 + 1.707 + PR_DestroyCondVar(sharedcvar); 1.708 + PR_DestroyLock(sharedlock); 1.709 + PR_DestroyCondVar(exitcvar); 1.710 + PR_DestroyLock(exitlock); 1.711 + 1.712 + PR_DELETE(list); 1.713 +} 1.714 + 1.715 +void 1.716 +CondVarMixedTest(void *_arg) 1.717 +{ 1.718 + PRInt32 arg = (PRInt32)_arg; 1.719 + PRInt32 index, loops; 1.720 + threadinfo *list; 1.721 + PRLock *sharedlock; 1.722 + PRCondVar *sharedcvar; 1.723 + PRLock *exitlock; 1.724 + PRCondVar *exitcvar; 1.725 + PRInt32 *ptcount; 1.726 + 1.727 + exitcount=0; 1.728 + tcount=0; 1.729 + list = (threadinfo *)PR_MALLOC(sizeof(threadinfo) * (arg * 4)); 1.730 + ptcount = (PRInt32 *)PR_CALLOC(sizeof(*ptcount) * (arg * 4)); 1.731 + 1.732 + sharedlock = PR_NewLock(); 1.733 + sharedcvar = PR_NewCondVar(sharedlock); 1.734 + exitlock = PR_NewLock(); 1.735 + exitcvar = PR_NewCondVar(exitlock); 1.736 + 1.737 + /* Create the threads */ 1.738 + for(index=0; index<arg*4; ) { 1.739 + CreateTestThread(&list[index], 1.740 + index, 1.741 + sharedlock, 1.742 + sharedcvar, 1.743 + count, 1.744 + PR_MillisecondsToInterval(50), 1.745 + &tcount, 1.746 + exitlock, 1.747 + exitcvar, 1.748 + &exitcount, 1.749 + PR_TRUE, 1.750 + PR_LOCAL_THREAD); 1.751 + index++; 1.752 + CreateTestThread(&list[index], 1.753 + index, 1.754 + sharedlock, 1.755 + sharedcvar, 1.756 + count, 1.757 + PR_MillisecondsToInterval(50), 1.758 + &tcount, 1.759 + exitlock, 1.760 + exitcvar, 1.761 + &exitcount, 1.762 + PR_TRUE, 1.763 + PR_GLOBAL_THREAD); 1.764 + index++; 1.765 + list[index].lock = PR_NewLock(); 1.766 + list[index].cvar = PR_NewCondVar(list[index].lock); 1.767 + CreateTestThread(&list[index], 1.768 + index, 1.769 + list[index].lock, 1.770 + list[index].cvar, 1.771 + count, 1.772 + PR_MillisecondsToInterval(50), 1.773 + ptcount, 1.774 + exitlock, 1.775 + exitcvar, 1.776 + &exitcount, 1.777 + PR_FALSE, 1.778 + PR_LOCAL_THREAD); 1.779 + index++; 1.780 + ptcount++; 1.781 + 1.782 + list[index].lock = PR_NewLock(); 1.783 + list[index].cvar = PR_NewCondVar(list[index].lock); 1.784 + CreateTestThread(&list[index], 1.785 + index, 1.786 + list[index].lock, 1.787 + list[index].cvar, 1.788 + count, 1.789 + PR_MillisecondsToInterval(50), 1.790 + ptcount, 1.791 + exitlock, 1.792 + exitcvar, 1.793 + &exitcount, 1.794 + PR_FALSE, 1.795 + PR_GLOBAL_THREAD); 1.796 + index++; 1.797 + ptcount++; 1.798 + } 1.799 + 1.800 + 1.801 + /* Notify every 3rd thread */ 1.802 + for (loops = 0; loops < count; loops++) { 1.803 + 1.804 + /* Notify the threads */ 1.805 + for(index=0; index<(arg*4); index+=3) { 1.806 + 1.807 + PR_Lock(list[index].lock); 1.808 + *list[index].tcount++; 1.809 + PR_NotifyCondVar(list[index].cvar); 1.810 + PR_Unlock(list[index].lock); 1.811 + 1.812 + } 1.813 + /* Wait for threads to finish */ 1.814 + PR_Lock(exitlock); 1.815 + while(exitcount < arg*4) 1.816 + PR_WaitCondVar(exitcvar, PR_SecondsToInterval(60)); 1.817 + PR_ASSERT(exitcount >= arg*4); 1.818 + exitcount -= arg*4; 1.819 + PR_Unlock(exitlock); 1.820 + } 1.821 + 1.822 + /* Join all the threads */ 1.823 + for(index=0; index<(arg*4); index++) { 1.824 + PR_JoinThread(list[index].thread); 1.825 + if (list[index].internal) { 1.826 + PR_Lock(list[index].lock); 1.827 + PR_DestroyCondVar(list[index].cvar); 1.828 + PR_Unlock(list[index].lock); 1.829 + PR_DestroyLock(list[index].lock); 1.830 + } 1.831 + } 1.832 + 1.833 + PR_DestroyCondVar(sharedcvar); 1.834 + PR_DestroyLock(sharedlock); 1.835 + 1.836 + PR_DELETE(list); 1.837 +} 1.838 + 1.839 +void 1.840 +CondVarCombinedTest(void *arg) 1.841 +{ 1.842 + PRThread *threads[3]; 1.843 + 1.844 + threads[0] = PR_CreateThread(PR_USER_THREAD, 1.845 + CondVarTest, 1.846 + (void *)arg, 1.847 + PR_PRIORITY_NORMAL, 1.848 + PR_GLOBAL_THREAD, 1.849 + PR_JOINABLE_THREAD, 1.850 + 0); 1.851 + threads[1] = PR_CreateThread(PR_USER_THREAD, 1.852 + CondVarTimeoutTest, 1.853 + (void *)arg, 1.854 + PR_PRIORITY_NORMAL, 1.855 + PR_GLOBAL_THREAD, 1.856 + PR_JOINABLE_THREAD, 1.857 + 0); 1.858 + threads[2] = PR_CreateThread(PR_USER_THREAD, 1.859 + CondVarMixedTest, 1.860 + (void *)arg, 1.861 + PR_PRIORITY_NORMAL, 1.862 + PR_GLOBAL_THREAD, 1.863 + PR_JOINABLE_THREAD, 1.864 + 0); 1.865 + 1.866 + PR_JoinThread(threads[0]); 1.867 + PR_JoinThread(threads[1]); 1.868 + PR_JoinThread(threads[2]); 1.869 +} 1.870 + 1.871 +/************************************************************************/ 1.872 + 1.873 +static void Measure(void (*func)(void *), PRInt32 arg, const char *msg) 1.874 +{ 1.875 + PRIntervalTime start, stop; 1.876 + double d; 1.877 + 1.878 + start = PR_IntervalNow(); 1.879 + (*func)((void *)arg); 1.880 + stop = PR_IntervalNow(); 1.881 + 1.882 + d = (double)PR_IntervalToMicroseconds(stop - start); 1.883 + 1.884 + printf("%40s: %6.2f usec\n", msg, d / count); 1.885 +} 1.886 + 1.887 +static PRIntn PR_CALLBACK RealMain(int argc, char **argv) 1.888 +{ 1.889 + PRInt32 threads, default_threads = DEFAULT_THREADS; 1.890 + PLOptStatus os; 1.891 + PLOptState *opt = PL_CreateOptState(argc, argv, "vc:t:"); 1.892 + while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) 1.893 + { 1.894 + if (PL_OPT_BAD == os) continue; 1.895 + switch (opt->option) 1.896 + { 1.897 + case 'v': /* debug mode */ 1.898 + _debug_on = 1; 1.899 + break; 1.900 + case 'c': /* loop counter */ 1.901 + count = atoi(opt->value); 1.902 + break; 1.903 + case 't': /* number of threads involved */ 1.904 + default_threads = atoi(opt->value); 1.905 + break; 1.906 + default: 1.907 + break; 1.908 + } 1.909 + } 1.910 + PL_DestroyOptState(opt); 1.911 + 1.912 + if (0 == count) count = DEFAULT_COUNT; 1.913 + if (0 == default_threads) default_threads = DEFAULT_THREADS; 1.914 + 1.915 + printf("\n\ 1.916 +CondVar Test: \n\ 1.917 + \n\ 1.918 +Simple test creates several local and global threads; half use a single,\n\ 1.919 +shared condvar, and the other half have their own condvar. The main \n\ 1.920 +thread then loops notifying them to wakeup. \n\ 1.921 + \n\ 1.922 +The timeout test is very similar except that the threads are not \n\ 1.923 +notified. They will all wakeup on a 1 second timeout. \n\ 1.924 + \n\ 1.925 +The mixed test combines the simple test and the timeout test; every \n\ 1.926 +third thread is notified, the other threads are expected to timeout \n\ 1.927 +correctly. \n\ 1.928 + \n\ 1.929 +Lastly, the combined test creates a thread for each of the above three \n\ 1.930 +cases and they all run simultaneously. \n\ 1.931 + \n\ 1.932 +This test is run with %d, %d, %d, and %d threads of each type.\n\n", 1.933 +default_threads, default_threads*2, default_threads*3, default_threads*4); 1.934 + 1.935 + PR_SetConcurrency(2); 1.936 + 1.937 + for (threads = default_threads; threads < default_threads*5; threads+=default_threads) { 1.938 + printf("\n%ld Thread tests\n", threads); 1.939 + Measure(CondVarTestSUU, threads, "Condvar simple test shared UU"); 1.940 + Measure(CondVarTestSUK, threads, "Condvar simple test shared UK"); 1.941 + Measure(CondVarTestPUU, threads, "Condvar simple test priv UU"); 1.942 + Measure(CondVarTestPUK, threads, "Condvar simple test priv UK"); 1.943 + Measure(CondVarTest, threads, "Condvar simple test All"); 1.944 + Measure(CondVarTimeoutTest, threads, "Condvar timeout test"); 1.945 +#if 0 1.946 + Measure(CondVarMixedTest, threads, "Condvar mixed timeout test"); 1.947 + Measure(CondVarCombinedTest, threads, "Combined condvar test"); 1.948 +#endif 1.949 + } 1.950 + 1.951 + printf("PASS\n"); 1.952 + 1.953 + return 0; 1.954 +} 1.955 + 1.956 +int main(int argc, char **argv) 1.957 +{ 1.958 + PRIntn rv; 1.959 + 1.960 + PR_STDIO_INIT(); 1.961 + rv = PR_Initialize(RealMain, argc, argv, 0); 1.962 + return rv; 1.963 +} /* main */