nsprpub/pr/tests/cvar2.c

Fri, 16 Jan 2015 04:50:19 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 04:50:19 +0100
branch
TOR_BUG_9701
changeset 13
44a2da4a2ab2
permissions
-rw-r--r--

Replace accessor implementation with direct member state manipulation, by
request https://trac.torproject.org/projects/tor/ticket/9701#comment:32

michael@0 1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 /***********************************************************************
michael@0 7 ** 1996 - Netscape Communications Corporation
michael@0 8 **
michael@0 9 ** Name: cvar2.c
michael@0 10 **
michael@0 11 ** Description: Simple test creates several local and global threads;
michael@0 12 ** half use a single,shared condvar, and the
michael@0 13 ** other half have their own condvar. The main thread then loops
michael@0 14 ** notifying them to wakeup.
michael@0 15 **
michael@0 16 ** Modification History:
michael@0 17 ** 14-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
michael@0 18 ** The debug mode will print all of the printfs associated with this test.
michael@0 19 ** The regress mode will be the default mode. Since the regress tool limits
michael@0 20 ** the output to a one line status:PASS or FAIL,all of the printf statements
michael@0 21 ** have been handled with an if (debug_mode) statement.
michael@0 22 ***********************************************************************/
michael@0 23
michael@0 24 #include "nspr.h"
michael@0 25 #include "plerror.h"
michael@0 26 #include "plgetopt.h"
michael@0 27
michael@0 28 #include <stdio.h>
michael@0 29 #include <stdlib.h>
michael@0 30 #include <string.h>
michael@0 31
michael@0 32 int _debug_on = 0;
michael@0 33 #define DPRINTF(arg) if (_debug_on) printf arg
michael@0 34
michael@0 35 #define DEFAULT_COUNT 100
michael@0 36 #define DEFAULT_THREADS 5
michael@0 37 PRInt32 count = DEFAULT_COUNT;
michael@0 38
michael@0 39 typedef struct threadinfo {
michael@0 40 PRThread *thread;
michael@0 41 PRInt32 id;
michael@0 42 PRBool internal;
michael@0 43 PRInt32 *tcount;
michael@0 44 PRLock *lock;
michael@0 45 PRCondVar *cvar;
michael@0 46 PRIntervalTime timeout;
michael@0 47 PRInt32 loops;
michael@0 48
michael@0 49 PRLock *exitlock;
michael@0 50 PRCondVar *exitcvar;
michael@0 51 PRInt32 *exitcount;
michael@0 52 } threadinfo;
michael@0 53
michael@0 54 /*
michael@0 55 ** Make exitcount, tcount static. for Win16.
michael@0 56 */
michael@0 57 static PRInt32 exitcount=0;
michael@0 58 static PRInt32 tcount=0;
michael@0 59
michael@0 60
michael@0 61 /* Thread that gets notified; many threads share the same condvar */
michael@0 62 void PR_CALLBACK
michael@0 63 SharedCondVarThread(void *_info)
michael@0 64 {
michael@0 65 threadinfo *info = (threadinfo *)_info;
michael@0 66 PRInt32 index;
michael@0 67
michael@0 68 for (index=0; index<info->loops; index++) {
michael@0 69 PR_Lock(info->lock);
michael@0 70 if (*info->tcount == 0)
michael@0 71 PR_WaitCondVar(info->cvar, info->timeout);
michael@0 72 #if 0
michael@0 73 printf("shared thread %ld notified in loop %ld\n", info->id, index);
michael@0 74 #endif
michael@0 75 (*info->tcount)--;
michael@0 76 PR_Unlock(info->lock);
michael@0 77
michael@0 78 PR_Lock(info->exitlock);
michael@0 79 (*info->exitcount)++;
michael@0 80 PR_NotifyCondVar(info->exitcvar);
michael@0 81 PR_Unlock(info->exitlock);
michael@0 82 }
michael@0 83 #if 0
michael@0 84 printf("shared thread %ld terminating\n", info->id);
michael@0 85 #endif
michael@0 86 }
michael@0 87
michael@0 88 /* Thread that gets notified; no other threads use the same condvar */
michael@0 89 void PR_CALLBACK
michael@0 90 PrivateCondVarThread(void *_info)
michael@0 91 {
michael@0 92 threadinfo *info = (threadinfo *)_info;
michael@0 93 PRInt32 index;
michael@0 94
michael@0 95 for (index=0; index<info->loops; index++) {
michael@0 96 PR_Lock(info->lock);
michael@0 97 if (*info->tcount == 0) {
michael@0 98 DPRINTF(("PrivateCondVarThread: thread 0x%lx waiting on cvar = 0x%lx\n",
michael@0 99 PR_GetCurrentThread(), info->cvar));
michael@0 100 PR_WaitCondVar(info->cvar, info->timeout);
michael@0 101 }
michael@0 102 #if 0
michael@0 103 printf("solo thread %ld notified in loop %ld\n", info->id, index);
michael@0 104 #endif
michael@0 105 (*info->tcount)--;
michael@0 106 PR_Unlock(info->lock);
michael@0 107
michael@0 108 PR_Lock(info->exitlock);
michael@0 109 (*info->exitcount)++;
michael@0 110 PR_NotifyCondVar(info->exitcvar);
michael@0 111 DPRINTF(("PrivateCondVarThread: thread 0x%lx notified exitcvar = 0x%lx cnt = %ld\n",
michael@0 112 PR_GetCurrentThread(), info->exitcvar,(*info->exitcount)));
michael@0 113 PR_Unlock(info->exitlock);
michael@0 114 }
michael@0 115 #if 0
michael@0 116 printf("solo thread %ld terminating\n", info->id);
michael@0 117 #endif
michael@0 118 }
michael@0 119
michael@0 120 void
michael@0 121 CreateTestThread(threadinfo *info,
michael@0 122 PRInt32 id,
michael@0 123 PRLock *lock,
michael@0 124 PRCondVar *cvar,
michael@0 125 PRInt32 loops,
michael@0 126 PRIntervalTime timeout,
michael@0 127 PRInt32 *tcount,
michael@0 128 PRLock *exitlock,
michael@0 129 PRCondVar *exitcvar,
michael@0 130 PRInt32 *exitcount,
michael@0 131 PRBool shared,
michael@0 132 PRThreadScope scope)
michael@0 133 {
michael@0 134 info->id = id;
michael@0 135 info->internal = (shared) ? PR_FALSE : PR_TRUE;
michael@0 136 info->lock = lock;
michael@0 137 info->cvar = cvar;
michael@0 138 info->loops = loops;
michael@0 139 info->timeout = timeout;
michael@0 140 info->tcount = tcount;
michael@0 141 info->exitlock = exitlock;
michael@0 142 info->exitcvar = exitcvar;
michael@0 143 info->exitcount = exitcount;
michael@0 144 info->thread = PR_CreateThread(
michael@0 145 PR_USER_THREAD,
michael@0 146 shared?SharedCondVarThread:PrivateCondVarThread,
michael@0 147 info,
michael@0 148 PR_PRIORITY_NORMAL,
michael@0 149 scope,
michael@0 150 PR_JOINABLE_THREAD,
michael@0 151 0);
michael@0 152 if (!info->thread)
michael@0 153 PL_PrintError("error creating thread\n");
michael@0 154 }
michael@0 155
michael@0 156
michael@0 157 void
michael@0 158 CondVarTestSUU(void *_arg)
michael@0 159 {
michael@0 160 PRInt32 arg = (PRInt32)_arg;
michael@0 161 PRInt32 index, loops;
michael@0 162 threadinfo *list;
michael@0 163 PRLock *sharedlock;
michael@0 164 PRCondVar *sharedcvar;
michael@0 165 PRLock *exitlock;
michael@0 166 PRCondVar *exitcvar;
michael@0 167
michael@0 168 exitcount=0;
michael@0 169 tcount=0;
michael@0 170 list = (threadinfo *)PR_MALLOC(sizeof(threadinfo) * (arg * 4));
michael@0 171
michael@0 172 sharedlock = PR_NewLock();
michael@0 173 sharedcvar = PR_NewCondVar(sharedlock);
michael@0 174 exitlock = PR_NewLock();
michael@0 175 exitcvar = PR_NewCondVar(exitlock);
michael@0 176
michael@0 177 /* Create the threads */
michael@0 178 for(index=0; index<arg; ) {
michael@0 179 CreateTestThread(&list[index],
michael@0 180 index,
michael@0 181 sharedlock,
michael@0 182 sharedcvar,
michael@0 183 count,
michael@0 184 PR_INTERVAL_NO_TIMEOUT,
michael@0 185 &tcount,
michael@0 186 exitlock,
michael@0 187 exitcvar,
michael@0 188 &exitcount,
michael@0 189 PR_TRUE,
michael@0 190 PR_LOCAL_THREAD);
michael@0 191 index++;
michael@0 192 DPRINTF(("CondVarTestSUU: created thread 0x%lx\n",list[index].thread));
michael@0 193 }
michael@0 194
michael@0 195 for (loops = 0; loops < count; loops++) {
michael@0 196 /* Notify the threads */
michael@0 197 for(index=0; index<(arg); index++) {
michael@0 198 PR_Lock(list[index].lock);
michael@0 199 (*list[index].tcount)++;
michael@0 200 PR_NotifyCondVar(list[index].cvar);
michael@0 201 PR_Unlock(list[index].lock);
michael@0 202 DPRINTF(("PrivateCondVarThread: thread 0x%lx notified cvar = 0x%lx\n",
michael@0 203 PR_GetCurrentThread(), list[index].cvar));
michael@0 204 }
michael@0 205
michael@0 206 /* Wait for threads to finish */
michael@0 207 PR_Lock(exitlock);
michael@0 208 while(exitcount < arg)
michael@0 209 PR_WaitCondVar(exitcvar, PR_SecondsToInterval(60));
michael@0 210 PR_ASSERT(exitcount >= arg);
michael@0 211 exitcount -= arg;
michael@0 212 PR_Unlock(exitlock);
michael@0 213 }
michael@0 214
michael@0 215 /* Join all the threads */
michael@0 216 for(index=0; index<(arg); index++)
michael@0 217 PR_JoinThread(list[index].thread);
michael@0 218
michael@0 219 PR_DestroyCondVar(sharedcvar);
michael@0 220 PR_DestroyLock(sharedlock);
michael@0 221 PR_DestroyCondVar(exitcvar);
michael@0 222 PR_DestroyLock(exitlock);
michael@0 223
michael@0 224 PR_DELETE(list);
michael@0 225 }
michael@0 226
michael@0 227 void
michael@0 228 CondVarTestSUK(void *_arg)
michael@0 229 {
michael@0 230 PRInt32 arg = (PRInt32)_arg;
michael@0 231 PRInt32 index, loops;
michael@0 232 threadinfo *list;
michael@0 233 PRLock *sharedlock;
michael@0 234 PRCondVar *sharedcvar;
michael@0 235 PRLock *exitlock;
michael@0 236 PRCondVar *exitcvar;
michael@0 237 exitcount=0;
michael@0 238 tcount=0;
michael@0 239
michael@0 240 list = (threadinfo *)PR_MALLOC(sizeof(threadinfo) * (arg * 4));
michael@0 241
michael@0 242 sharedlock = PR_NewLock();
michael@0 243 sharedcvar = PR_NewCondVar(sharedlock);
michael@0 244 exitlock = PR_NewLock();
michael@0 245 exitcvar = PR_NewCondVar(exitlock);
michael@0 246
michael@0 247 /* Create the threads */
michael@0 248 for(index=0; index<arg; ) {
michael@0 249 CreateTestThread(&list[index],
michael@0 250 index,
michael@0 251 sharedlock,
michael@0 252 sharedcvar,
michael@0 253 count,
michael@0 254 PR_INTERVAL_NO_TIMEOUT,
michael@0 255 &tcount,
michael@0 256 exitlock,
michael@0 257 exitcvar,
michael@0 258 &exitcount,
michael@0 259 PR_TRUE,
michael@0 260 PR_GLOBAL_THREAD);
michael@0 261 index++;
michael@0 262 }
michael@0 263
michael@0 264 for (loops = 0; loops < count; loops++) {
michael@0 265 /* Notify the threads */
michael@0 266 for(index=0; index<(arg); index++) {
michael@0 267
michael@0 268 PR_Lock(list[index].lock);
michael@0 269 (*list[index].tcount)++;
michael@0 270 PR_NotifyCondVar(list[index].cvar);
michael@0 271 PR_Unlock(list[index].lock);
michael@0 272 }
michael@0 273
michael@0 274 #if 0
michael@0 275 printf("wait for threads to be done\n");
michael@0 276 #endif
michael@0 277 /* Wait for threads to finish */
michael@0 278 PR_Lock(exitlock);
michael@0 279 while(exitcount < arg)
michael@0 280 PR_WaitCondVar(exitcvar, PR_SecondsToInterval(60));
michael@0 281 PR_ASSERT(exitcount >= arg);
michael@0 282 exitcount -= arg;
michael@0 283 PR_Unlock(exitlock);
michael@0 284 #if 0
michael@0 285 printf("threads ready\n");
michael@0 286 #endif
michael@0 287 }
michael@0 288
michael@0 289 /* Join all the threads */
michael@0 290 for(index=0; index<(arg); index++)
michael@0 291 PR_JoinThread(list[index].thread);
michael@0 292
michael@0 293 PR_DestroyCondVar(sharedcvar);
michael@0 294 PR_DestroyLock(sharedlock);
michael@0 295 PR_DestroyCondVar(exitcvar);
michael@0 296 PR_DestroyLock(exitlock);
michael@0 297
michael@0 298 PR_DELETE(list);
michael@0 299 }
michael@0 300
michael@0 301 void
michael@0 302 CondVarTestPUU(void *_arg)
michael@0 303 {
michael@0 304 PRInt32 arg = (PRInt32)_arg;
michael@0 305 PRInt32 index, loops;
michael@0 306 threadinfo *list;
michael@0 307 PRLock *sharedlock;
michael@0 308 PRCondVar *sharedcvar;
michael@0 309 PRLock *exitlock;
michael@0 310 PRCondVar *exitcvar;
michael@0 311 PRInt32 *tcount, *saved_tcount;
michael@0 312
michael@0 313 exitcount=0;
michael@0 314 list = (threadinfo *)PR_MALLOC(sizeof(threadinfo) * (arg * 4));
michael@0 315 saved_tcount = tcount = (PRInt32 *)PR_CALLOC(sizeof(*tcount) * (arg * 4));
michael@0 316
michael@0 317 sharedlock = PR_NewLock();
michael@0 318 sharedcvar = PR_NewCondVar(sharedlock);
michael@0 319 exitlock = PR_NewLock();
michael@0 320 exitcvar = PR_NewCondVar(exitlock);
michael@0 321
michael@0 322 /* Create the threads */
michael@0 323 for(index=0; index<arg; ) {
michael@0 324 list[index].lock = PR_NewLock();
michael@0 325 list[index].cvar = PR_NewCondVar(list[index].lock);
michael@0 326 CreateTestThread(&list[index],
michael@0 327 index,
michael@0 328 list[index].lock,
michael@0 329 list[index].cvar,
michael@0 330 count,
michael@0 331 PR_INTERVAL_NO_TIMEOUT,
michael@0 332 tcount,
michael@0 333 exitlock,
michael@0 334 exitcvar,
michael@0 335 &exitcount,
michael@0 336 PR_FALSE,
michael@0 337 PR_LOCAL_THREAD);
michael@0 338
michael@0 339 DPRINTF(("CondVarTestPUU: created thread 0x%lx\n",list[index].thread));
michael@0 340 index++;
michael@0 341 tcount++;
michael@0 342 }
michael@0 343
michael@0 344 for (loops = 0; loops < count; loops++) {
michael@0 345 /* Notify the threads */
michael@0 346 for(index=0; index<(arg); index++) {
michael@0 347
michael@0 348 PR_Lock(list[index].lock);
michael@0 349 (*list[index].tcount)++;
michael@0 350 PR_NotifyCondVar(list[index].cvar);
michael@0 351 PR_Unlock(list[index].lock);
michael@0 352 }
michael@0 353
michael@0 354 PR_Lock(exitlock);
michael@0 355 /* Wait for threads to finish */
michael@0 356 while(exitcount < arg) {
michael@0 357 DPRINTF(("CondVarTestPUU: thread 0x%lx waiting on exitcvar = 0x%lx cnt = %ld\n",
michael@0 358 PR_GetCurrentThread(), exitcvar, exitcount));
michael@0 359 PR_WaitCondVar(exitcvar, PR_SecondsToInterval(60));
michael@0 360 }
michael@0 361 PR_ASSERT(exitcount >= arg);
michael@0 362 exitcount -= arg;
michael@0 363 PR_Unlock(exitlock);
michael@0 364 }
michael@0 365
michael@0 366 /* Join all the threads */
michael@0 367 for(index=0; index<(arg); index++) {
michael@0 368 DPRINTF(("CondVarTestPUU: joining thread 0x%lx\n",list[index].thread));
michael@0 369 PR_JoinThread(list[index].thread);
michael@0 370 if (list[index].internal) {
michael@0 371 PR_Lock(list[index].lock);
michael@0 372 PR_DestroyCondVar(list[index].cvar);
michael@0 373 PR_Unlock(list[index].lock);
michael@0 374 PR_DestroyLock(list[index].lock);
michael@0 375 }
michael@0 376 }
michael@0 377
michael@0 378 PR_DestroyCondVar(sharedcvar);
michael@0 379 PR_DestroyLock(sharedlock);
michael@0 380 PR_DestroyCondVar(exitcvar);
michael@0 381 PR_DestroyLock(exitlock);
michael@0 382
michael@0 383 PR_DELETE(list);
michael@0 384 PR_DELETE(saved_tcount);
michael@0 385 }
michael@0 386
michael@0 387 void
michael@0 388 CondVarTestPUK(void *_arg)
michael@0 389 {
michael@0 390 PRInt32 arg = (PRInt32)_arg;
michael@0 391 PRInt32 index, loops;
michael@0 392 threadinfo *list;
michael@0 393 PRLock *sharedlock;
michael@0 394 PRCondVar *sharedcvar;
michael@0 395 PRLock *exitlock;
michael@0 396 PRCondVar *exitcvar;
michael@0 397 PRInt32 *tcount, *saved_tcount;
michael@0 398
michael@0 399 exitcount=0;
michael@0 400 list = (threadinfo *)PR_MALLOC(sizeof(threadinfo) * (arg * 4));
michael@0 401 saved_tcount = tcount = (PRInt32 *)PR_CALLOC(sizeof(*tcount) * (arg * 4));
michael@0 402
michael@0 403 sharedlock = PR_NewLock();
michael@0 404 sharedcvar = PR_NewCondVar(sharedlock);
michael@0 405 exitlock = PR_NewLock();
michael@0 406 exitcvar = PR_NewCondVar(exitlock);
michael@0 407
michael@0 408 /* Create the threads */
michael@0 409 for(index=0; index<arg; ) {
michael@0 410 list[index].lock = PR_NewLock();
michael@0 411 list[index].cvar = PR_NewCondVar(list[index].lock);
michael@0 412 CreateTestThread(&list[index],
michael@0 413 index,
michael@0 414 list[index].lock,
michael@0 415 list[index].cvar,
michael@0 416 count,
michael@0 417 PR_INTERVAL_NO_TIMEOUT,
michael@0 418 tcount,
michael@0 419 exitlock,
michael@0 420 exitcvar,
michael@0 421 &exitcount,
michael@0 422 PR_FALSE,
michael@0 423 PR_GLOBAL_THREAD);
michael@0 424
michael@0 425 index++;
michael@0 426 tcount++;
michael@0 427 }
michael@0 428
michael@0 429 for (loops = 0; loops < count; loops++) {
michael@0 430 /* Notify the threads */
michael@0 431 for(index=0; index<(arg); index++) {
michael@0 432
michael@0 433 PR_Lock(list[index].lock);
michael@0 434 (*list[index].tcount)++;
michael@0 435 PR_NotifyCondVar(list[index].cvar);
michael@0 436 PR_Unlock(list[index].lock);
michael@0 437 }
michael@0 438
michael@0 439 /* Wait for threads to finish */
michael@0 440 PR_Lock(exitlock);
michael@0 441 while(exitcount < arg)
michael@0 442 PR_WaitCondVar(exitcvar, PR_SecondsToInterval(60));
michael@0 443 PR_ASSERT(exitcount >= arg);
michael@0 444 exitcount -= arg;
michael@0 445 PR_Unlock(exitlock);
michael@0 446 }
michael@0 447
michael@0 448 /* Join all the threads */
michael@0 449 for(index=0; index<(arg); index++) {
michael@0 450 PR_JoinThread(list[index].thread);
michael@0 451 if (list[index].internal) {
michael@0 452 PR_Lock(list[index].lock);
michael@0 453 PR_DestroyCondVar(list[index].cvar);
michael@0 454 PR_Unlock(list[index].lock);
michael@0 455 PR_DestroyLock(list[index].lock);
michael@0 456 }
michael@0 457 }
michael@0 458
michael@0 459 PR_DestroyCondVar(sharedcvar);
michael@0 460 PR_DestroyLock(sharedlock);
michael@0 461 PR_DestroyCondVar(exitcvar);
michael@0 462 PR_DestroyLock(exitlock);
michael@0 463
michael@0 464 PR_DELETE(list);
michael@0 465 PR_DELETE(saved_tcount);
michael@0 466 }
michael@0 467
michael@0 468 void
michael@0 469 CondVarTest(void *_arg)
michael@0 470 {
michael@0 471 PRInt32 arg = (PRInt32)_arg;
michael@0 472 PRInt32 index, loops;
michael@0 473 threadinfo *list;
michael@0 474 PRLock *sharedlock;
michael@0 475 PRCondVar *sharedcvar;
michael@0 476 PRLock *exitlock;
michael@0 477 PRCondVar *exitcvar;
michael@0 478 PRInt32 *ptcount, *saved_ptcount;
michael@0 479
michael@0 480 exitcount=0;
michael@0 481 tcount=0;
michael@0 482 list = (threadinfo *)PR_MALLOC(sizeof(threadinfo) * (arg * 4));
michael@0 483 saved_ptcount = ptcount = (PRInt32 *)PR_CALLOC(sizeof(*ptcount) * (arg * 4));
michael@0 484
michael@0 485 sharedlock = PR_NewLock();
michael@0 486 sharedcvar = PR_NewCondVar(sharedlock);
michael@0 487 exitlock = PR_NewLock();
michael@0 488 exitcvar = PR_NewCondVar(exitlock);
michael@0 489
michael@0 490 /* Create the threads */
michael@0 491 for(index=0; index<arg*4; ) {
michael@0 492 CreateTestThread(&list[index],
michael@0 493 index,
michael@0 494 sharedlock,
michael@0 495 sharedcvar,
michael@0 496 count,
michael@0 497 PR_INTERVAL_NO_TIMEOUT,
michael@0 498 &tcount,
michael@0 499 exitlock,
michael@0 500 exitcvar,
michael@0 501 &exitcount,
michael@0 502 PR_TRUE,
michael@0 503 PR_LOCAL_THREAD);
michael@0 504
michael@0 505 index++;
michael@0 506 CreateTestThread(&list[index],
michael@0 507 index,
michael@0 508 sharedlock,
michael@0 509 sharedcvar,
michael@0 510 count,
michael@0 511 PR_INTERVAL_NO_TIMEOUT,
michael@0 512 &tcount,
michael@0 513 exitlock,
michael@0 514 exitcvar,
michael@0 515 &exitcount,
michael@0 516 PR_TRUE,
michael@0 517 PR_GLOBAL_THREAD);
michael@0 518
michael@0 519 index++;
michael@0 520 list[index].lock = PR_NewLock();
michael@0 521 list[index].cvar = PR_NewCondVar(list[index].lock);
michael@0 522 CreateTestThread(&list[index],
michael@0 523 index,
michael@0 524 list[index].lock,
michael@0 525 list[index].cvar,
michael@0 526 count,
michael@0 527 PR_INTERVAL_NO_TIMEOUT,
michael@0 528 ptcount,
michael@0 529 exitlock,
michael@0 530 exitcvar,
michael@0 531 &exitcount,
michael@0 532 PR_FALSE,
michael@0 533 PR_LOCAL_THREAD);
michael@0 534 index++;
michael@0 535 ptcount++;
michael@0 536 list[index].lock = PR_NewLock();
michael@0 537 list[index].cvar = PR_NewCondVar(list[index].lock);
michael@0 538 CreateTestThread(&list[index],
michael@0 539 index,
michael@0 540 list[index].lock,
michael@0 541 list[index].cvar,
michael@0 542 count,
michael@0 543 PR_INTERVAL_NO_TIMEOUT,
michael@0 544 ptcount,
michael@0 545 exitlock,
michael@0 546 exitcvar,
michael@0 547 &exitcount,
michael@0 548 PR_FALSE,
michael@0 549 PR_GLOBAL_THREAD);
michael@0 550
michael@0 551 index++;
michael@0 552 ptcount++;
michael@0 553 }
michael@0 554
michael@0 555 for (loops = 0; loops < count; loops++) {
michael@0 556
michael@0 557 /* Notify the threads */
michael@0 558 for(index=0; index<(arg*4); index++) {
michael@0 559 PR_Lock(list[index].lock);
michael@0 560 (*list[index].tcount)++;
michael@0 561 PR_NotifyCondVar(list[index].cvar);
michael@0 562 PR_Unlock(list[index].lock);
michael@0 563 }
michael@0 564
michael@0 565 #if 0
michael@0 566 printf("wait for threads done\n");
michael@0 567 #endif
michael@0 568
michael@0 569 /* Wait for threads to finish */
michael@0 570 PR_Lock(exitlock);
michael@0 571 while(exitcount < arg*4)
michael@0 572 PR_WaitCondVar(exitcvar, PR_SecondsToInterval(60));
michael@0 573 PR_ASSERT(exitcount >= arg*4);
michael@0 574 exitcount -= arg*4;
michael@0 575 PR_Unlock(exitlock);
michael@0 576 #if 0
michael@0 577 printf("threads ready\n");
michael@0 578 #endif
michael@0 579 }
michael@0 580
michael@0 581 /* Join all the threads */
michael@0 582 for(index=0; index<(arg*4); index++) {
michael@0 583 PR_JoinThread(list[index].thread);
michael@0 584 if (list[index].internal) {
michael@0 585 PR_Lock(list[index].lock);
michael@0 586 PR_DestroyCondVar(list[index].cvar);
michael@0 587 PR_Unlock(list[index].lock);
michael@0 588 PR_DestroyLock(list[index].lock);
michael@0 589 }
michael@0 590 }
michael@0 591
michael@0 592 PR_DestroyCondVar(sharedcvar);
michael@0 593 PR_DestroyLock(sharedlock);
michael@0 594 PR_DestroyCondVar(exitcvar);
michael@0 595 PR_DestroyLock(exitlock);
michael@0 596
michael@0 597 PR_DELETE(list);
michael@0 598 PR_DELETE(saved_ptcount);
michael@0 599 }
michael@0 600
michael@0 601 void
michael@0 602 CondVarTimeoutTest(void *_arg)
michael@0 603 {
michael@0 604 PRInt32 arg = (PRInt32)_arg;
michael@0 605 PRInt32 index, loops;
michael@0 606 threadinfo *list;
michael@0 607 PRLock *sharedlock;
michael@0 608 PRCondVar *sharedcvar;
michael@0 609 PRLock *exitlock;
michael@0 610 PRCondVar *exitcvar;
michael@0 611
michael@0 612 list = (threadinfo *)PR_MALLOC(sizeof(threadinfo) * (arg * 4));
michael@0 613
michael@0 614 sharedlock = PR_NewLock();
michael@0 615 sharedcvar = PR_NewCondVar(sharedlock);
michael@0 616 exitlock = PR_NewLock();
michael@0 617 exitcvar = PR_NewCondVar(exitlock);
michael@0 618
michael@0 619 /* Create the threads */
michael@0 620 for(index=0; index<arg*4; ) {
michael@0 621 CreateTestThread(&list[index],
michael@0 622 index,
michael@0 623 sharedlock,
michael@0 624 sharedcvar,
michael@0 625 count,
michael@0 626 PR_MillisecondsToInterval(50),
michael@0 627 &tcount,
michael@0 628 exitlock,
michael@0 629 exitcvar,
michael@0 630 &exitcount,
michael@0 631 PR_TRUE,
michael@0 632 PR_LOCAL_THREAD);
michael@0 633 index++;
michael@0 634 CreateTestThread(&list[index],
michael@0 635 index,
michael@0 636 sharedlock,
michael@0 637 sharedcvar,
michael@0 638 count,
michael@0 639 PR_MillisecondsToInterval(50),
michael@0 640 &tcount,
michael@0 641 exitlock,
michael@0 642 exitcvar,
michael@0 643 &exitcount,
michael@0 644 PR_TRUE,
michael@0 645 PR_GLOBAL_THREAD);
michael@0 646 index++;
michael@0 647 list[index].lock = PR_NewLock();
michael@0 648 list[index].cvar = PR_NewCondVar(list[index].lock);
michael@0 649 CreateTestThread(&list[index],
michael@0 650 index,
michael@0 651 list[index].lock,
michael@0 652 list[index].cvar,
michael@0 653 count,
michael@0 654 PR_MillisecondsToInterval(50),
michael@0 655 &tcount,
michael@0 656 exitlock,
michael@0 657 exitcvar,
michael@0 658 &exitcount,
michael@0 659 PR_FALSE,
michael@0 660 PR_LOCAL_THREAD);
michael@0 661 index++;
michael@0 662
michael@0 663 list[index].lock = PR_NewLock();
michael@0 664 list[index].cvar = PR_NewCondVar(list[index].lock);
michael@0 665 CreateTestThread(&list[index],
michael@0 666 index,
michael@0 667 list[index].lock,
michael@0 668 list[index].cvar,
michael@0 669 count,
michael@0 670 PR_MillisecondsToInterval(50),
michael@0 671 &tcount,
michael@0 672 exitlock,
michael@0 673 exitcvar,
michael@0 674 &exitcount,
michael@0 675 PR_FALSE,
michael@0 676 PR_GLOBAL_THREAD);
michael@0 677
michael@0 678 index++;
michael@0 679 }
michael@0 680
michael@0 681 for (loops = 0; loops < count; loops++) {
michael@0 682
michael@0 683 /* Wait for threads to finish */
michael@0 684 PR_Lock(exitlock);
michael@0 685 while(exitcount < arg*4)
michael@0 686 PR_WaitCondVar(exitcvar, PR_SecondsToInterval(60));
michael@0 687 PR_ASSERT(exitcount >= arg*4);
michael@0 688 exitcount -= arg*4;
michael@0 689 PR_Unlock(exitlock);
michael@0 690 }
michael@0 691
michael@0 692
michael@0 693 /* Join all the threads */
michael@0 694 for(index=0; index<(arg*4); index++) {
michael@0 695 PR_JoinThread(list[index].thread);
michael@0 696 if (list[index].internal) {
michael@0 697 PR_Lock(list[index].lock);
michael@0 698 PR_DestroyCondVar(list[index].cvar);
michael@0 699 PR_Unlock(list[index].lock);
michael@0 700 PR_DestroyLock(list[index].lock);
michael@0 701 }
michael@0 702 }
michael@0 703
michael@0 704 PR_DestroyCondVar(sharedcvar);
michael@0 705 PR_DestroyLock(sharedlock);
michael@0 706 PR_DestroyCondVar(exitcvar);
michael@0 707 PR_DestroyLock(exitlock);
michael@0 708
michael@0 709 PR_DELETE(list);
michael@0 710 }
michael@0 711
michael@0 712 void
michael@0 713 CondVarMixedTest(void *_arg)
michael@0 714 {
michael@0 715 PRInt32 arg = (PRInt32)_arg;
michael@0 716 PRInt32 index, loops;
michael@0 717 threadinfo *list;
michael@0 718 PRLock *sharedlock;
michael@0 719 PRCondVar *sharedcvar;
michael@0 720 PRLock *exitlock;
michael@0 721 PRCondVar *exitcvar;
michael@0 722 PRInt32 *ptcount;
michael@0 723
michael@0 724 exitcount=0;
michael@0 725 tcount=0;
michael@0 726 list = (threadinfo *)PR_MALLOC(sizeof(threadinfo) * (arg * 4));
michael@0 727 ptcount = (PRInt32 *)PR_CALLOC(sizeof(*ptcount) * (arg * 4));
michael@0 728
michael@0 729 sharedlock = PR_NewLock();
michael@0 730 sharedcvar = PR_NewCondVar(sharedlock);
michael@0 731 exitlock = PR_NewLock();
michael@0 732 exitcvar = PR_NewCondVar(exitlock);
michael@0 733
michael@0 734 /* Create the threads */
michael@0 735 for(index=0; index<arg*4; ) {
michael@0 736 CreateTestThread(&list[index],
michael@0 737 index,
michael@0 738 sharedlock,
michael@0 739 sharedcvar,
michael@0 740 count,
michael@0 741 PR_MillisecondsToInterval(50),
michael@0 742 &tcount,
michael@0 743 exitlock,
michael@0 744 exitcvar,
michael@0 745 &exitcount,
michael@0 746 PR_TRUE,
michael@0 747 PR_LOCAL_THREAD);
michael@0 748 index++;
michael@0 749 CreateTestThread(&list[index],
michael@0 750 index,
michael@0 751 sharedlock,
michael@0 752 sharedcvar,
michael@0 753 count,
michael@0 754 PR_MillisecondsToInterval(50),
michael@0 755 &tcount,
michael@0 756 exitlock,
michael@0 757 exitcvar,
michael@0 758 &exitcount,
michael@0 759 PR_TRUE,
michael@0 760 PR_GLOBAL_THREAD);
michael@0 761 index++;
michael@0 762 list[index].lock = PR_NewLock();
michael@0 763 list[index].cvar = PR_NewCondVar(list[index].lock);
michael@0 764 CreateTestThread(&list[index],
michael@0 765 index,
michael@0 766 list[index].lock,
michael@0 767 list[index].cvar,
michael@0 768 count,
michael@0 769 PR_MillisecondsToInterval(50),
michael@0 770 ptcount,
michael@0 771 exitlock,
michael@0 772 exitcvar,
michael@0 773 &exitcount,
michael@0 774 PR_FALSE,
michael@0 775 PR_LOCAL_THREAD);
michael@0 776 index++;
michael@0 777 ptcount++;
michael@0 778
michael@0 779 list[index].lock = PR_NewLock();
michael@0 780 list[index].cvar = PR_NewCondVar(list[index].lock);
michael@0 781 CreateTestThread(&list[index],
michael@0 782 index,
michael@0 783 list[index].lock,
michael@0 784 list[index].cvar,
michael@0 785 count,
michael@0 786 PR_MillisecondsToInterval(50),
michael@0 787 ptcount,
michael@0 788 exitlock,
michael@0 789 exitcvar,
michael@0 790 &exitcount,
michael@0 791 PR_FALSE,
michael@0 792 PR_GLOBAL_THREAD);
michael@0 793 index++;
michael@0 794 ptcount++;
michael@0 795 }
michael@0 796
michael@0 797
michael@0 798 /* Notify every 3rd thread */
michael@0 799 for (loops = 0; loops < count; loops++) {
michael@0 800
michael@0 801 /* Notify the threads */
michael@0 802 for(index=0; index<(arg*4); index+=3) {
michael@0 803
michael@0 804 PR_Lock(list[index].lock);
michael@0 805 *list[index].tcount++;
michael@0 806 PR_NotifyCondVar(list[index].cvar);
michael@0 807 PR_Unlock(list[index].lock);
michael@0 808
michael@0 809 }
michael@0 810 /* Wait for threads to finish */
michael@0 811 PR_Lock(exitlock);
michael@0 812 while(exitcount < arg*4)
michael@0 813 PR_WaitCondVar(exitcvar, PR_SecondsToInterval(60));
michael@0 814 PR_ASSERT(exitcount >= arg*4);
michael@0 815 exitcount -= arg*4;
michael@0 816 PR_Unlock(exitlock);
michael@0 817 }
michael@0 818
michael@0 819 /* Join all the threads */
michael@0 820 for(index=0; index<(arg*4); index++) {
michael@0 821 PR_JoinThread(list[index].thread);
michael@0 822 if (list[index].internal) {
michael@0 823 PR_Lock(list[index].lock);
michael@0 824 PR_DestroyCondVar(list[index].cvar);
michael@0 825 PR_Unlock(list[index].lock);
michael@0 826 PR_DestroyLock(list[index].lock);
michael@0 827 }
michael@0 828 }
michael@0 829
michael@0 830 PR_DestroyCondVar(sharedcvar);
michael@0 831 PR_DestroyLock(sharedlock);
michael@0 832
michael@0 833 PR_DELETE(list);
michael@0 834 }
michael@0 835
michael@0 836 void
michael@0 837 CondVarCombinedTest(void *arg)
michael@0 838 {
michael@0 839 PRThread *threads[3];
michael@0 840
michael@0 841 threads[0] = PR_CreateThread(PR_USER_THREAD,
michael@0 842 CondVarTest,
michael@0 843 (void *)arg,
michael@0 844 PR_PRIORITY_NORMAL,
michael@0 845 PR_GLOBAL_THREAD,
michael@0 846 PR_JOINABLE_THREAD,
michael@0 847 0);
michael@0 848 threads[1] = PR_CreateThread(PR_USER_THREAD,
michael@0 849 CondVarTimeoutTest,
michael@0 850 (void *)arg,
michael@0 851 PR_PRIORITY_NORMAL,
michael@0 852 PR_GLOBAL_THREAD,
michael@0 853 PR_JOINABLE_THREAD,
michael@0 854 0);
michael@0 855 threads[2] = PR_CreateThread(PR_USER_THREAD,
michael@0 856 CondVarMixedTest,
michael@0 857 (void *)arg,
michael@0 858 PR_PRIORITY_NORMAL,
michael@0 859 PR_GLOBAL_THREAD,
michael@0 860 PR_JOINABLE_THREAD,
michael@0 861 0);
michael@0 862
michael@0 863 PR_JoinThread(threads[0]);
michael@0 864 PR_JoinThread(threads[1]);
michael@0 865 PR_JoinThread(threads[2]);
michael@0 866 }
michael@0 867
michael@0 868 /************************************************************************/
michael@0 869
michael@0 870 static void Measure(void (*func)(void *), PRInt32 arg, const char *msg)
michael@0 871 {
michael@0 872 PRIntervalTime start, stop;
michael@0 873 double d;
michael@0 874
michael@0 875 start = PR_IntervalNow();
michael@0 876 (*func)((void *)arg);
michael@0 877 stop = PR_IntervalNow();
michael@0 878
michael@0 879 d = (double)PR_IntervalToMicroseconds(stop - start);
michael@0 880
michael@0 881 printf("%40s: %6.2f usec\n", msg, d / count);
michael@0 882 }
michael@0 883
michael@0 884 static PRIntn PR_CALLBACK RealMain(int argc, char **argv)
michael@0 885 {
michael@0 886 PRInt32 threads, default_threads = DEFAULT_THREADS;
michael@0 887 PLOptStatus os;
michael@0 888 PLOptState *opt = PL_CreateOptState(argc, argv, "vc:t:");
michael@0 889 while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
michael@0 890 {
michael@0 891 if (PL_OPT_BAD == os) continue;
michael@0 892 switch (opt->option)
michael@0 893 {
michael@0 894 case 'v': /* debug mode */
michael@0 895 _debug_on = 1;
michael@0 896 break;
michael@0 897 case 'c': /* loop counter */
michael@0 898 count = atoi(opt->value);
michael@0 899 break;
michael@0 900 case 't': /* number of threads involved */
michael@0 901 default_threads = atoi(opt->value);
michael@0 902 break;
michael@0 903 default:
michael@0 904 break;
michael@0 905 }
michael@0 906 }
michael@0 907 PL_DestroyOptState(opt);
michael@0 908
michael@0 909 if (0 == count) count = DEFAULT_COUNT;
michael@0 910 if (0 == default_threads) default_threads = DEFAULT_THREADS;
michael@0 911
michael@0 912 printf("\n\
michael@0 913 CondVar Test: \n\
michael@0 914 \n\
michael@0 915 Simple test creates several local and global threads; half use a single,\n\
michael@0 916 shared condvar, and the other half have their own condvar. The main \n\
michael@0 917 thread then loops notifying them to wakeup. \n\
michael@0 918 \n\
michael@0 919 The timeout test is very similar except that the threads are not \n\
michael@0 920 notified. They will all wakeup on a 1 second timeout. \n\
michael@0 921 \n\
michael@0 922 The mixed test combines the simple test and the timeout test; every \n\
michael@0 923 third thread is notified, the other threads are expected to timeout \n\
michael@0 924 correctly. \n\
michael@0 925 \n\
michael@0 926 Lastly, the combined test creates a thread for each of the above three \n\
michael@0 927 cases and they all run simultaneously. \n\
michael@0 928 \n\
michael@0 929 This test is run with %d, %d, %d, and %d threads of each type.\n\n",
michael@0 930 default_threads, default_threads*2, default_threads*3, default_threads*4);
michael@0 931
michael@0 932 PR_SetConcurrency(2);
michael@0 933
michael@0 934 for (threads = default_threads; threads < default_threads*5; threads+=default_threads) {
michael@0 935 printf("\n%ld Thread tests\n", threads);
michael@0 936 Measure(CondVarTestSUU, threads, "Condvar simple test shared UU");
michael@0 937 Measure(CondVarTestSUK, threads, "Condvar simple test shared UK");
michael@0 938 Measure(CondVarTestPUU, threads, "Condvar simple test priv UU");
michael@0 939 Measure(CondVarTestPUK, threads, "Condvar simple test priv UK");
michael@0 940 Measure(CondVarTest, threads, "Condvar simple test All");
michael@0 941 Measure(CondVarTimeoutTest, threads, "Condvar timeout test");
michael@0 942 #if 0
michael@0 943 Measure(CondVarMixedTest, threads, "Condvar mixed timeout test");
michael@0 944 Measure(CondVarCombinedTest, threads, "Combined condvar test");
michael@0 945 #endif
michael@0 946 }
michael@0 947
michael@0 948 printf("PASS\n");
michael@0 949
michael@0 950 return 0;
michael@0 951 }
michael@0 952
michael@0 953 int main(int argc, char **argv)
michael@0 954 {
michael@0 955 PRIntn rv;
michael@0 956
michael@0 957 PR_STDIO_INIT();
michael@0 958 rv = PR_Initialize(RealMain, argc, argv, 0);
michael@0 959 return rv;
michael@0 960 } /* main */

mercurial