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