~ubuntu-branches/ubuntu/precise/kompozer/precise

« back to all changes in this revision

Viewing changes to mozilla/nsprpub/pr/tests/cvar2.c

  • Committer: Bazaar Package Importer
  • Author(s): Anthony Yarusso
  • Date: 2007-08-27 01:11:03 UTC
  • Revision ID: james.westby@ubuntu.com-20070827011103-2jgf4s6532gqu2ka
Tags: upstream-0.7.10
ImportĀ upstreamĀ versionĀ 0.7.10

Show diffs side-by-side

added added

removed removed

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