~ubuntu-branches/ubuntu/gutsy/virtualbox-ose/gutsy

« back to all changes in this revision

Viewing changes to src/libs/xpcom18a4/nsprpub/pr/tests/y2ktmo.c

  • Committer: Bazaar Package Importer
  • Author(s): Steve Kowalik
  • Date: 2007-09-08 16:44:58 UTC
  • Revision ID: james.westby@ubuntu.com-20070908164458-wao29470vqtr8ksy
Tags: upstream-1.5.0-dfsg2
ImportĀ upstreamĀ versionĀ 1.5.0-dfsg2

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
/* ***** 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) 1999-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
 * Test: y2ktmo
 
40
 *
 
41
 * Description:
 
42
 *   This test tests the interval time facilities in NSPR for Y2K
 
43
 *   compliance.  All the functions that take a timeout argument
 
44
 *   are tested: PR_Sleep, socket I/O (PR_Accept is taken as a
 
45
 *   representative), PR_Poll, PR_WaitCondVar, PR_Wait, and
 
46
 *   PR_CWait.  A thread of each thread scope (local, global, and
 
47
 *   global bound) is created to call each of these functions.
 
48
 *   The test should be started at the specified number of seconds
 
49
 *   (called the lead time) before a Y2K rollover test date.  The
 
50
 *   timeout values for these threads will span over the rollover
 
51
 *   date by at least the specified number of seconds.  For
 
52
 *   example, if the lead time is 5 seconds, the test should
 
53
 *   be started at time (D - 5), where D is a rollover date, and
 
54
 *   the threads will time out at or after time (D + 5).  The
 
55
 *   timeout values for the threads are spaced one second apart.
 
56
 *
 
57
 *   When a thread times out, it calls PR_IntervalNow() to verify
 
58
 *   that it did wait for the specified time.  In addition, it
 
59
 *   calls a platform-native function to verify the actual elapsed
 
60
 *   time again, to rule out the possibility that PR_IntervalNow()
 
61
 *   is broken.  We allow the actual elapsed time to deviate from
 
62
 *   the specified timeout by a certain tolerance (in milliseconds).
 
63
 */ 
 
64
 
 
65
#include "nspr.h"
 
66
#include "plgetopt.h"
 
67
 
 
68
#include <stdio.h>
 
69
#include <stdlib.h>
 
70
#include <string.h>
 
71
#if defined(XP_UNIX)
 
72
#include <sys/time.h> /* for gettimeofday */
 
73
#endif
 
74
#if defined(WIN32)
 
75
#include <sys/types.h>
 
76
#include <sys/timeb.h>  /* for _ftime */
 
77
#endif
 
78
 
 
79
#define DEFAULT_LEAD_TIME_SECS 5
 
80
#define DEFAULT_TOLERANCE_MSECS 500
 
81
 
 
82
static PRBool debug_mode = PR_FALSE;
 
83
static PRInt32 lead_time_secs = DEFAULT_LEAD_TIME_SECS;
 
84
static PRInt32 tolerance_msecs = DEFAULT_TOLERANCE_MSECS;
 
85
static PRIntervalTime start_time;
 
86
static PRIntervalTime tolerance;
 
87
 
 
88
#if defined(XP_UNIX)
 
89
static struct timeval start_time_tv;
 
90
#endif
 
91
#if defined(WIN32)
 
92
static struct _timeb start_time_tb;
 
93
#endif
 
94
 
 
95
static void SleepThread(void *arg)
 
96
{
 
97
    PRIntervalTime timeout = (PRIntervalTime) arg;
 
98
    PRIntervalTime elapsed;
 
99
#if defined(XP_UNIX) || defined(WIN32)
 
100
    PRInt32 timeout_msecs = PR_IntervalToMilliseconds(timeout);
 
101
    PRInt32 elapsed_msecs;
 
102
#endif
 
103
#if defined(XP_UNIX)
 
104
    struct timeval end_time_tv;
 
105
#endif
 
106
#if defined(WIN32)
 
107
    struct _timeb end_time_tb;
 
108
#endif
 
109
 
 
110
    if (PR_Sleep(timeout) == PR_FAILURE) {
 
111
        fprintf(stderr, "PR_Sleep failed\n");
 
112
        exit(1);
 
113
    }
 
114
    elapsed = (PRIntervalTime)(PR_IntervalNow() - start_time);
 
115
    if (elapsed + tolerance < timeout || elapsed > timeout + tolerance) {
 
116
        fprintf(stderr, "timeout wrong\n");
 
117
        exit(1);
 
118
    }
 
119
#if defined(XP_UNIX)
 
120
    gettimeofday(&end_time_tv, NULL);
 
121
    elapsed_msecs = 1000*(end_time_tv.tv_sec - start_time_tv.tv_sec)
 
122
            + (end_time_tv.tv_usec - start_time_tv.tv_usec)/1000;
 
123
#endif
 
124
#if defined(WIN32)
 
125
    _ftime(&end_time_tb);
 
126
    elapsed_msecs = 1000*(end_time_tb.time - start_time_tb.time)
 
127
            + (end_time_tb.millitm - start_time_tb.millitm);
 
128
#endif
 
129
#if defined(XP_UNIX) || defined(WIN32)
 
130
    if (elapsed_msecs + tolerance_msecs < timeout_msecs
 
131
            || elapsed_msecs > timeout_msecs + tolerance_msecs) {
 
132
        fprintf(stderr, "timeout wrong\n");
 
133
        exit(1);
 
134
    }
 
135
#endif
 
136
    if (debug_mode) {
 
137
        fprintf(stderr, "Sleep thread (scope %d) done\n",
 
138
                PR_GetThreadScope(PR_GetCurrentThread()));
 
139
    }
 
140
}
 
141
 
 
142
static void AcceptThread(void *arg)
 
143
{
 
144
    PRIntervalTime timeout = (PRIntervalTime) arg;
 
145
    PRIntervalTime elapsed;
 
146
#if defined(XP_UNIX) || defined(WIN32)
 
147
    PRInt32 timeout_msecs = PR_IntervalToMilliseconds(timeout);
 
148
    PRInt32 elapsed_msecs;
 
149
#endif
 
150
#if defined(XP_UNIX)
 
151
    struct timeval end_time_tv;
 
152
#endif
 
153
#if defined(WIN32)
 
154
    struct _timeb end_time_tb;
 
155
#endif
 
156
    PRFileDesc *sock;
 
157
    PRNetAddr addr;
 
158
    PRFileDesc *accepted;
 
159
 
 
160
    sock = PR_NewTCPSocket();
 
161
    if (sock == NULL) {
 
162
        fprintf(stderr, "PR_NewTCPSocket failed\n");
 
163
        exit(1);
 
164
    }
 
165
    memset(&addr, 0, sizeof(addr));
 
166
    addr.inet.family = PR_AF_INET;
 
167
    addr.inet.port = 0;
 
168
    addr.inet.ip = PR_htonl(PR_INADDR_ANY);
 
169
    if (PR_Bind(sock, &addr) == PR_FAILURE) {
 
170
        fprintf(stderr, "PR_Bind failed\n");
 
171
        exit(1);
 
172
    }
 
173
    if (PR_Listen(sock, 5) == PR_FAILURE) {
 
174
        fprintf(stderr, "PR_Listen failed\n");
 
175
        exit(1);
 
176
    }
 
177
    accepted = PR_Accept(sock, NULL, timeout);
 
178
    if (accepted != NULL || PR_GetError() != PR_IO_TIMEOUT_ERROR) {
 
179
        fprintf(stderr, "PR_Accept did not time out\n");
 
180
        exit(1);
 
181
    }
 
182
    elapsed = (PRIntervalTime)(PR_IntervalNow() - start_time);
 
183
    if (elapsed + tolerance < timeout || elapsed > timeout + tolerance) {
 
184
        fprintf(stderr, "timeout wrong\n");
 
185
        exit(1);
 
186
    }
 
187
#if defined(XP_UNIX)
 
188
    gettimeofday(&end_time_tv, NULL);
 
189
    elapsed_msecs = 1000*(end_time_tv.tv_sec - start_time_tv.tv_sec)
 
190
            + (end_time_tv.tv_usec - start_time_tv.tv_usec)/1000;
 
191
#endif
 
192
#if defined(WIN32)
 
193
    _ftime(&end_time_tb);
 
194
    elapsed_msecs = 1000*(end_time_tb.time - start_time_tb.time)
 
195
            + (end_time_tb.millitm - start_time_tb.millitm);
 
196
#endif
 
197
#if defined(XP_UNIX) || defined(WIN32)
 
198
    if (elapsed_msecs + tolerance_msecs < timeout_msecs
 
199
            || elapsed_msecs > timeout_msecs + tolerance_msecs) {
 
200
        fprintf(stderr, "timeout wrong\n");
 
201
        exit(1);
 
202
    }
 
203
#endif
 
204
    if (PR_Close(sock) == PR_FAILURE) {
 
205
        fprintf(stderr, "PR_Close failed\n");
 
206
        exit(1);
 
207
    }
 
208
    if (debug_mode) {
 
209
        fprintf(stderr, "Accept thread (scope %d) done\n",
 
210
                PR_GetThreadScope(PR_GetCurrentThread()));
 
211
    }
 
212
}
 
213
 
 
214
static void PollThread(void *arg)
 
215
{
 
216
    PRIntervalTime timeout = (PRIntervalTime) arg;
 
217
    PRIntervalTime elapsed;
 
218
#if defined(XP_UNIX) || defined(WIN32)
 
219
    PRInt32 timeout_msecs = PR_IntervalToMilliseconds(timeout);
 
220
    PRInt32 elapsed_msecs;
 
221
#endif
 
222
#if defined(XP_UNIX)
 
223
    struct timeval end_time_tv;
 
224
#endif
 
225
#if defined(WIN32)
 
226
    struct _timeb end_time_tb;
 
227
#endif
 
228
    PRFileDesc *sock;
 
229
    PRNetAddr addr;
 
230
    PRPollDesc pd;
 
231
    PRIntn rv;
 
232
 
 
233
    sock = PR_NewTCPSocket();
 
234
    if (sock == NULL) {
 
235
        fprintf(stderr, "PR_NewTCPSocket failed\n");
 
236
        exit(1);
 
237
    }
 
238
    memset(&addr, 0, sizeof(addr));
 
239
    addr.inet.family = PR_AF_INET;
 
240
    addr.inet.port = 0;
 
241
    addr.inet.ip = PR_htonl(PR_INADDR_ANY);
 
242
    if (PR_Bind(sock, &addr) == PR_FAILURE) {
 
243
        fprintf(stderr, "PR_Bind failed\n");
 
244
        exit(1);
 
245
    }
 
246
    if (PR_Listen(sock, 5) == PR_FAILURE) {
 
247
        fprintf(stderr, "PR_Listen failed\n");
 
248
        exit(1);
 
249
    }
 
250
    pd.fd = sock;
 
251
    pd.in_flags = PR_POLL_READ;
 
252
    rv = PR_Poll(&pd, 1, timeout);
 
253
    if (rv != 0) {
 
254
        fprintf(stderr, "PR_Poll did not time out\n");
 
255
        exit(1);
 
256
    }
 
257
    elapsed = (PRIntervalTime)(PR_IntervalNow() - start_time);
 
258
    if (elapsed + tolerance < timeout || elapsed > timeout + tolerance) {
 
259
        fprintf(stderr, "timeout wrong\n");
 
260
        exit(1);
 
261
    }
 
262
#if defined(XP_UNIX)
 
263
    gettimeofday(&end_time_tv, NULL);
 
264
    elapsed_msecs = 1000*(end_time_tv.tv_sec - start_time_tv.tv_sec)
 
265
            + (end_time_tv.tv_usec - start_time_tv.tv_usec)/1000;
 
266
#endif
 
267
#if defined(WIN32)
 
268
    _ftime(&end_time_tb);
 
269
    elapsed_msecs = 1000*(end_time_tb.time - start_time_tb.time)
 
270
            + (end_time_tb.millitm - start_time_tb.millitm);
 
271
#endif
 
272
#if defined(XP_UNIX) || defined(WIN32)
 
273
    if (elapsed_msecs + tolerance_msecs < timeout_msecs
 
274
            || elapsed_msecs > timeout_msecs + tolerance_msecs) {
 
275
        fprintf(stderr, "timeout wrong\n");
 
276
        exit(1);
 
277
    }
 
278
#endif
 
279
    if (PR_Close(sock) == PR_FAILURE) {
 
280
        fprintf(stderr, "PR_Close failed\n");
 
281
        exit(1);
 
282
    }
 
283
    if (debug_mode) {
 
284
        fprintf(stderr, "Poll thread (scope %d) done\n",
 
285
                PR_GetThreadScope(PR_GetCurrentThread()));
 
286
    }
 
287
}
 
288
 
 
289
static void WaitCondVarThread(void *arg)
 
290
{
 
291
    PRIntervalTime timeout = (PRIntervalTime) arg;
 
292
    PRIntervalTime elapsed;
 
293
#if defined(XP_UNIX) || defined(WIN32)
 
294
    PRInt32 timeout_msecs = PR_IntervalToMilliseconds(timeout);
 
295
    PRInt32 elapsed_msecs;
 
296
#endif
 
297
#if defined(XP_UNIX)
 
298
    struct timeval end_time_tv;
 
299
#endif
 
300
#if defined(WIN32)
 
301
    struct _timeb end_time_tb;
 
302
#endif
 
303
    PRLock *ml;
 
304
    PRCondVar *cv;
 
305
 
 
306
    ml = PR_NewLock();
 
307
    if (ml == NULL) {
 
308
        fprintf(stderr, "PR_NewLock failed\n");
 
309
        exit(1);
 
310
    }
 
311
    cv = PR_NewCondVar(ml);
 
312
    if (cv == NULL) {
 
313
        fprintf(stderr, "PR_NewCondVar failed\n");
 
314
        exit(1);
 
315
    }
 
316
    PR_Lock(ml);
 
317
    PR_WaitCondVar(cv, timeout);
 
318
    PR_Unlock(ml);
 
319
    elapsed = (PRIntervalTime)(PR_IntervalNow() - start_time);
 
320
    if (elapsed + tolerance < timeout || elapsed > timeout + tolerance) {
 
321
        fprintf(stderr, "timeout wrong\n");
 
322
        exit(1);
 
323
    }
 
324
#if defined(XP_UNIX)
 
325
    gettimeofday(&end_time_tv, NULL);
 
326
    elapsed_msecs = 1000*(end_time_tv.tv_sec - start_time_tv.tv_sec)
 
327
            + (end_time_tv.tv_usec - start_time_tv.tv_usec)/1000;
 
328
#endif
 
329
#if defined(WIN32)
 
330
    _ftime(&end_time_tb);
 
331
    elapsed_msecs = 1000*(end_time_tb.time - start_time_tb.time)
 
332
            + (end_time_tb.millitm - start_time_tb.millitm);
 
333
#endif
 
334
#if defined(XP_UNIX) || defined(WIN32)
 
335
    if (elapsed_msecs + tolerance_msecs < timeout_msecs
 
336
            || elapsed_msecs > timeout_msecs + tolerance_msecs) {
 
337
        fprintf(stderr, "timeout wrong\n");
 
338
        exit(1);
 
339
    }
 
340
#endif
 
341
    PR_DestroyCondVar(cv);
 
342
    PR_DestroyLock(ml);
 
343
    if (debug_mode) {
 
344
        fprintf(stderr, "wait cond var thread (scope %d) done\n",
 
345
                PR_GetThreadScope(PR_GetCurrentThread()));
 
346
    }
 
347
}
 
348
 
 
349
static void WaitMonitorThread(void *arg)
 
350
{
 
351
    PRIntervalTime timeout = (PRIntervalTime) arg;
 
352
    PRIntervalTime elapsed;
 
353
#if defined(XP_UNIX) || defined(WIN32)
 
354
    PRInt32 timeout_msecs = PR_IntervalToMilliseconds(timeout);
 
355
    PRInt32 elapsed_msecs;
 
356
#endif
 
357
#if defined(XP_UNIX)
 
358
    struct timeval end_time_tv;
 
359
#endif
 
360
#if defined(WIN32)
 
361
    struct _timeb end_time_tb;
 
362
#endif
 
363
    PRMonitor *mon;
 
364
 
 
365
    mon = PR_NewMonitor();
 
366
    if (mon == NULL) {
 
367
        fprintf(stderr, "PR_NewMonitor failed\n");
 
368
        exit(1);
 
369
    }
 
370
    PR_EnterMonitor(mon);
 
371
    PR_Wait(mon, timeout);
 
372
    PR_ExitMonitor(mon);
 
373
    elapsed = (PRIntervalTime)(PR_IntervalNow() - start_time);
 
374
    if (elapsed + tolerance < timeout || elapsed > timeout + tolerance) {
 
375
        fprintf(stderr, "timeout wrong\n");
 
376
        exit(1);
 
377
    }
 
378
#if defined(XP_UNIX)
 
379
    gettimeofday(&end_time_tv, NULL);
 
380
    elapsed_msecs = 1000*(end_time_tv.tv_sec - start_time_tv.tv_sec)
 
381
            + (end_time_tv.tv_usec - start_time_tv.tv_usec)/1000;
 
382
#endif
 
383
#if defined(WIN32)
 
384
    _ftime(&end_time_tb);
 
385
    elapsed_msecs = 1000*(end_time_tb.time - start_time_tb.time)
 
386
            + (end_time_tb.millitm - start_time_tb.millitm);
 
387
#endif
 
388
#if defined(XP_UNIX) || defined(WIN32)
 
389
    if (elapsed_msecs + tolerance_msecs < timeout_msecs
 
390
            || elapsed_msecs > timeout_msecs + tolerance_msecs) {
 
391
        fprintf(stderr, "timeout wrong\n");
 
392
        exit(1);
 
393
    }
 
394
#endif
 
395
    PR_DestroyMonitor(mon);
 
396
    if (debug_mode) {
 
397
        fprintf(stderr, "wait monitor thread (scope %d) done\n",
 
398
                PR_GetThreadScope(PR_GetCurrentThread()));
 
399
    }
 
400
}
 
401
 
 
402
static void WaitCMonitorThread(void *arg)
 
403
{
 
404
    PRIntervalTime timeout = (PRIntervalTime) arg;
 
405
    PRIntervalTime elapsed;
 
406
#if defined(XP_UNIX) || defined(WIN32)
 
407
    PRInt32 timeout_msecs = PR_IntervalToMilliseconds(timeout);
 
408
    PRInt32 elapsed_msecs;
 
409
#endif
 
410
#if defined(XP_UNIX)
 
411
    struct timeval end_time_tv;
 
412
#endif
 
413
#if defined(WIN32)
 
414
    struct _timeb end_time_tb;
 
415
#endif
 
416
    int dummy;
 
417
 
 
418
    PR_CEnterMonitor(&dummy);
 
419
    PR_CWait(&dummy, timeout);
 
420
    PR_CExitMonitor(&dummy);
 
421
    elapsed = (PRIntervalTime)(PR_IntervalNow() - start_time);
 
422
    if (elapsed + tolerance < timeout || elapsed > timeout + tolerance) {
 
423
        fprintf(stderr, "timeout wrong\n");
 
424
        exit(1);
 
425
    }
 
426
#if defined(XP_UNIX)
 
427
    gettimeofday(&end_time_tv, NULL);
 
428
    elapsed_msecs = 1000*(end_time_tv.tv_sec - start_time_tv.tv_sec)
 
429
            + (end_time_tv.tv_usec - start_time_tv.tv_usec)/1000;
 
430
#endif
 
431
#if defined(WIN32)
 
432
    _ftime(&end_time_tb);
 
433
    elapsed_msecs = 1000*(end_time_tb.time - start_time_tb.time)
 
434
            + (end_time_tb.millitm - start_time_tb.millitm);
 
435
#endif
 
436
#if defined(XP_UNIX) || defined(WIN32)
 
437
    if (elapsed_msecs + tolerance_msecs < timeout_msecs
 
438
            || elapsed_msecs > timeout_msecs + tolerance_msecs) {
 
439
        fprintf(stderr, "timeout wrong\n");
 
440
        exit(1);
 
441
    }
 
442
#endif
 
443
    if (debug_mode) {
 
444
        fprintf(stderr, "wait cached monitor thread (scope %d) done\n",
 
445
                PR_GetThreadScope(PR_GetCurrentThread()));
 
446
    }
 
447
}
 
448
 
 
449
typedef void (*NSPRThreadFunc)(void*);
 
450
 
 
451
static NSPRThreadFunc threadFuncs[] = {
 
452
    SleepThread, AcceptThread, PollThread,
 
453
    WaitCondVarThread, WaitMonitorThread, WaitCMonitorThread};
 
454
 
 
455
static PRThreadScope threadScopes[] = {
 
456
    PR_LOCAL_THREAD, PR_GLOBAL_THREAD, PR_GLOBAL_BOUND_THREAD};
 
457
 
 
458
static void Help(void)
 
459
{
 
460
    fprintf(stderr, "y2ktmo test program usage:\n");
 
461
    fprintf(stderr, "\t-d           debug mode         (FALSE)\n");
 
462
    fprintf(stderr, "\t-l <secs>    lead time          (%d)\n",
 
463
            DEFAULT_LEAD_TIME_SECS);
 
464
    fprintf(stderr, "\t-t <msecs>   tolerance          (%d)\n",
 
465
            DEFAULT_TOLERANCE_MSECS);
 
466
    fprintf(stderr, "\t-h           this message\n");
 
467
}  /* Help */
 
468
 
 
469
int main(int argc, char **argv)
 
470
{
 
471
    PRThread **threads;
 
472
    int num_thread_funcs = sizeof(threadFuncs)/sizeof(NSPRThreadFunc);
 
473
    int num_thread_scopes = sizeof(threadScopes)/sizeof(PRThreadScope);
 
474
    int i, j;
 
475
    int idx;
 
476
    PRInt32 secs;
 
477
    PLOptStatus os;
 
478
    PLOptState *opt = PL_CreateOptState(argc, argv, "dl:t:h");
 
479
 
 
480
    while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) {
 
481
        if (PL_OPT_BAD == os) continue;
 
482
        switch (opt->option) {
 
483
            case 'd':  /* debug mode */
 
484
                debug_mode = PR_TRUE;
 
485
                break;
 
486
            case 'l':  /* lead time */
 
487
                lead_time_secs = atoi(opt->value);
 
488
                break;
 
489
            case 't':  /* tolerance */
 
490
                tolerance_msecs = atoi(opt->value);
 
491
                break;
 
492
            case 'h':
 
493
            default:
 
494
                Help();
 
495
                return 2;
 
496
        }
 
497
    }
 
498
    PL_DestroyOptState(opt);
 
499
 
 
500
    if (debug_mode) {
 
501
        fprintf(stderr, "lead time: %d secs\n", lead_time_secs);
 
502
        fprintf(stderr, "tolerance: %d msecs\n", tolerance_msecs);
 
503
    }
 
504
 
 
505
    start_time = PR_IntervalNow();
 
506
#if defined(XP_UNIX)
 
507
    gettimeofday(&start_time_tv, NULL);
 
508
#endif
 
509
#if defined(WIN32)
 
510
    _ftime(&start_time_tb);
 
511
#endif
 
512
    tolerance = PR_MillisecondsToInterval(tolerance_msecs);
 
513
 
 
514
    threads = PR_Malloc(
 
515
            num_thread_scopes * num_thread_funcs * sizeof(PRThread*));
 
516
    if (threads == NULL) {
 
517
        fprintf(stderr, "PR_Malloc failed\n");
 
518
        exit(1);
 
519
    }
 
520
 
 
521
    /* start to time out 5 seconds after a rollover date */
 
522
    secs = lead_time_secs + 5;
 
523
    idx = 0;
 
524
    for (i = 0; i < num_thread_scopes; i++) { 
 
525
        for (j = 0; j < num_thread_funcs; j++) {
 
526
            threads[idx] = PR_CreateThread(PR_USER_THREAD, threadFuncs[j],
 
527
                (void*)PR_SecondsToInterval(secs), PR_PRIORITY_NORMAL,
 
528
                threadScopes[i], PR_JOINABLE_THREAD, 0);
 
529
            if (threads[idx] == NULL) {
 
530
                fprintf(stderr, "PR_CreateThread failed\n");
 
531
                exit(1);
 
532
            }
 
533
            secs++;
 
534
            idx++;
 
535
        }
 
536
    }
 
537
    for (idx = 0; idx < num_thread_scopes*num_thread_funcs; idx++) {
 
538
        if (PR_JoinThread(threads[idx]) == PR_FAILURE) {
 
539
            fprintf(stderr, "PR_JoinThread failed\n");
 
540
            exit(1);
 
541
        }
 
542
    }
 
543
    PR_Free(threads);
 
544
    printf("PASS\n");
 
545
    return 0;
 
546
}