VirtualBox

source: vbox/trunk/src/libs/xpcom18a4/nsprpub/pr/tests/cvar2.c@ 1

Last change on this file since 1 was 1, checked in by vboxsync, 55 years ago

import

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette