nsprpub/pr/tests/y2ktmo.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/nsprpub/pr/tests/y2ktmo.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,550 @@
     1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +/*
    1.10 + * Test: y2ktmo
    1.11 + *
    1.12 + * Description:
    1.13 + *   This test tests the interval time facilities in NSPR for Y2K
    1.14 + *   compliance.  All the functions that take a timeout argument
    1.15 + *   are tested: PR_Sleep, socket I/O (PR_Accept is taken as a
    1.16 + *   representative), PR_Poll, PR_WaitCondVar, PR_Wait, and
    1.17 + *   PR_CWait.  A thread of each thread scope (local, global, and
    1.18 + *   global bound) is created to call each of these functions.
    1.19 + *   The test should be started at the specified number of seconds
    1.20 + *   (called the lead time) before a Y2K rollover test date.  The
    1.21 + *   timeout values for these threads will span over the rollover
    1.22 + *   date by at least the specified number of seconds.  For
    1.23 + *   example, if the lead time is 5 seconds, the test should
    1.24 + *   be started at time (D - 5), where D is a rollover date, and
    1.25 + *   the threads will time out at or after time (D + 5).  The
    1.26 + *   timeout values for the threads are spaced one second apart.
    1.27 + *
    1.28 + *   When a thread times out, it calls PR_IntervalNow() to verify
    1.29 + *   that it did wait for the specified time.  In addition, it
    1.30 + *   calls a platform-native function to verify the actual elapsed
    1.31 + *   time again, to rule out the possibility that PR_IntervalNow()
    1.32 + *   is broken.  We allow the actual elapsed time to deviate from
    1.33 + *   the specified timeout by a certain tolerance (in milliseconds).
    1.34 + */ 
    1.35 +
    1.36 +#include "nspr.h"
    1.37 +#include "plgetopt.h"
    1.38 +
    1.39 +#include <stdio.h>
    1.40 +#include <stdlib.h>
    1.41 +#include <string.h>
    1.42 +#if defined(XP_UNIX)
    1.43 +#include <sys/time.h> /* for gettimeofday */
    1.44 +#endif
    1.45 +#if defined(WIN32)
    1.46 +#if defined(WINCE)
    1.47 +#include <windows.h>
    1.48 +#else
    1.49 +#include <sys/types.h>
    1.50 +#include <sys/timeb.h>  /* for _ftime */
    1.51 +#endif
    1.52 +#endif
    1.53 +
    1.54 +#define DEFAULT_LEAD_TIME_SECS 5
    1.55 +#define DEFAULT_TOLERANCE_MSECS 500
    1.56 +
    1.57 +static PRBool debug_mode = PR_FALSE;
    1.58 +static PRInt32 lead_time_secs = DEFAULT_LEAD_TIME_SECS;
    1.59 +static PRInt32 tolerance_msecs = DEFAULT_TOLERANCE_MSECS;
    1.60 +static PRIntervalTime start_time;
    1.61 +static PRIntervalTime tolerance;
    1.62 +
    1.63 +#if defined(XP_UNIX)
    1.64 +static struct timeval start_time_tv;
    1.65 +#endif
    1.66 +#if defined(WIN32)
    1.67 +#if defined(WINCE)
    1.68 +static DWORD start_time_tick;
    1.69 +#else
    1.70 +static struct _timeb start_time_tb;
    1.71 +#endif
    1.72 +#endif
    1.73 +
    1.74 +static void SleepThread(void *arg)
    1.75 +{
    1.76 +    PRIntervalTime timeout = (PRIntervalTime) arg;
    1.77 +    PRIntervalTime elapsed;
    1.78 +#if defined(XP_UNIX) || defined(WIN32)
    1.79 +    PRInt32 timeout_msecs = PR_IntervalToMilliseconds(timeout);
    1.80 +    PRInt32 elapsed_msecs;
    1.81 +#endif
    1.82 +#if defined(XP_UNIX)
    1.83 +    struct timeval end_time_tv;
    1.84 +#endif
    1.85 +#if defined(WIN32) && !defined(WINCE)
    1.86 +    struct _timeb end_time_tb;
    1.87 +#endif
    1.88 +
    1.89 +    if (PR_Sleep(timeout) == PR_FAILURE) {
    1.90 +        fprintf(stderr, "PR_Sleep failed\n");
    1.91 +        exit(1);
    1.92 +    }
    1.93 +    elapsed = (PRIntervalTime)(PR_IntervalNow() - start_time);
    1.94 +    if (elapsed + tolerance < timeout || elapsed > timeout + tolerance) {
    1.95 +        fprintf(stderr, "timeout wrong\n");
    1.96 +        exit(1);
    1.97 +    }
    1.98 +#if defined(XP_UNIX)
    1.99 +    gettimeofday(&end_time_tv, NULL);
   1.100 +    elapsed_msecs = 1000*(end_time_tv.tv_sec - start_time_tv.tv_sec)
   1.101 +            + (end_time_tv.tv_usec - start_time_tv.tv_usec)/1000;
   1.102 +#endif
   1.103 +#if defined(WIN32)
   1.104 +#if defined(WINCE)
   1.105 +    elapsed_msecs = GetTickCount() - start_time_tick;
   1.106 +#else
   1.107 +    _ftime(&end_time_tb);
   1.108 +    elapsed_msecs = 1000*(end_time_tb.time - start_time_tb.time)
   1.109 +            + (end_time_tb.millitm - start_time_tb.millitm);
   1.110 +#endif
   1.111 +#endif
   1.112 +#if defined(XP_UNIX) || defined(WIN32)
   1.113 +    if (elapsed_msecs + tolerance_msecs < timeout_msecs
   1.114 +            || elapsed_msecs > timeout_msecs + tolerance_msecs) {
   1.115 +        fprintf(stderr, "timeout wrong\n");
   1.116 +        exit(1);
   1.117 +    }
   1.118 +#endif
   1.119 +    if (debug_mode) {
   1.120 +        fprintf(stderr, "Sleep thread (scope %d) done\n",
   1.121 +                PR_GetThreadScope(PR_GetCurrentThread()));
   1.122 +    }
   1.123 +}
   1.124 +
   1.125 +static void AcceptThread(void *arg)
   1.126 +{
   1.127 +    PRIntervalTime timeout = (PRIntervalTime) arg;
   1.128 +    PRIntervalTime elapsed;
   1.129 +#if defined(XP_UNIX) || defined(WIN32)
   1.130 +    PRInt32 timeout_msecs = PR_IntervalToMilliseconds(timeout);
   1.131 +    PRInt32 elapsed_msecs;
   1.132 +#endif
   1.133 +#if defined(XP_UNIX)
   1.134 +    struct timeval end_time_tv;
   1.135 +#endif
   1.136 +#if defined(WIN32) && !defined(WINCE)
   1.137 +    struct _timeb end_time_tb;
   1.138 +#endif
   1.139 +    PRFileDesc *sock;
   1.140 +    PRNetAddr addr;
   1.141 +    PRFileDesc *accepted;
   1.142 +
   1.143 +    sock = PR_NewTCPSocket();
   1.144 +    if (sock == NULL) {
   1.145 +        fprintf(stderr, "PR_NewTCPSocket failed\n");
   1.146 +        exit(1);
   1.147 +    }
   1.148 +    memset(&addr, 0, sizeof(addr));
   1.149 +    addr.inet.family = PR_AF_INET;
   1.150 +    addr.inet.port = 0;
   1.151 +    addr.inet.ip = PR_htonl(PR_INADDR_ANY);
   1.152 +    if (PR_Bind(sock, &addr) == PR_FAILURE) {
   1.153 +        fprintf(stderr, "PR_Bind failed\n");
   1.154 +        exit(1);
   1.155 +    }
   1.156 +    if (PR_Listen(sock, 5) == PR_FAILURE) {
   1.157 +        fprintf(stderr, "PR_Listen failed\n");
   1.158 +        exit(1);
   1.159 +    }
   1.160 +    accepted = PR_Accept(sock, NULL, timeout);
   1.161 +    if (accepted != NULL || PR_GetError() != PR_IO_TIMEOUT_ERROR) {
   1.162 +        fprintf(stderr, "PR_Accept did not time out\n");
   1.163 +        exit(1);
   1.164 +    }
   1.165 +    elapsed = (PRIntervalTime)(PR_IntervalNow() - start_time);
   1.166 +    if (elapsed + tolerance < timeout || elapsed > timeout + tolerance) {
   1.167 +        fprintf(stderr, "timeout wrong\n");
   1.168 +        exit(1);
   1.169 +    }
   1.170 +#if defined(XP_UNIX)
   1.171 +    gettimeofday(&end_time_tv, NULL);
   1.172 +    elapsed_msecs = 1000*(end_time_tv.tv_sec - start_time_tv.tv_sec)
   1.173 +            + (end_time_tv.tv_usec - start_time_tv.tv_usec)/1000;
   1.174 +#endif
   1.175 +#if defined(WIN32)
   1.176 +#if defined(WINCE)
   1.177 +    elapsed_msecs = GetTickCount() - start_time_tick;
   1.178 +#else
   1.179 +    _ftime(&end_time_tb);
   1.180 +    elapsed_msecs = 1000*(end_time_tb.time - start_time_tb.time)
   1.181 +            + (end_time_tb.millitm - start_time_tb.millitm);
   1.182 +#endif
   1.183 +#endif
   1.184 +#if defined(XP_UNIX) || defined(WIN32)
   1.185 +    if (elapsed_msecs + tolerance_msecs < timeout_msecs
   1.186 +            || elapsed_msecs > timeout_msecs + tolerance_msecs) {
   1.187 +        fprintf(stderr, "timeout wrong\n");
   1.188 +        exit(1);
   1.189 +    }
   1.190 +#endif
   1.191 +    if (PR_Close(sock) == PR_FAILURE) {
   1.192 +        fprintf(stderr, "PR_Close failed\n");
   1.193 +        exit(1);
   1.194 +    }
   1.195 +    if (debug_mode) {
   1.196 +        fprintf(stderr, "Accept thread (scope %d) done\n",
   1.197 +                PR_GetThreadScope(PR_GetCurrentThread()));
   1.198 +    }
   1.199 +}
   1.200 +
   1.201 +static void PollThread(void *arg)
   1.202 +{
   1.203 +    PRIntervalTime timeout = (PRIntervalTime) arg;
   1.204 +    PRIntervalTime elapsed;
   1.205 +#if defined(XP_UNIX) || defined(WIN32)
   1.206 +    PRInt32 timeout_msecs = PR_IntervalToMilliseconds(timeout);
   1.207 +    PRInt32 elapsed_msecs;
   1.208 +#endif
   1.209 +#if defined(XP_UNIX)
   1.210 +    struct timeval end_time_tv;
   1.211 +#endif
   1.212 +#if defined(WIN32) && !defined(WINCE)
   1.213 +    struct _timeb end_time_tb;
   1.214 +#endif
   1.215 +    PRFileDesc *sock;
   1.216 +    PRNetAddr addr;
   1.217 +    PRPollDesc pd;
   1.218 +    PRIntn rv;
   1.219 +
   1.220 +    sock = PR_NewTCPSocket();
   1.221 +    if (sock == NULL) {
   1.222 +        fprintf(stderr, "PR_NewTCPSocket failed\n");
   1.223 +        exit(1);
   1.224 +    }
   1.225 +    memset(&addr, 0, sizeof(addr));
   1.226 +    addr.inet.family = PR_AF_INET;
   1.227 +    addr.inet.port = 0;
   1.228 +    addr.inet.ip = PR_htonl(PR_INADDR_ANY);
   1.229 +    if (PR_Bind(sock, &addr) == PR_FAILURE) {
   1.230 +        fprintf(stderr, "PR_Bind failed\n");
   1.231 +        exit(1);
   1.232 +    }
   1.233 +    if (PR_Listen(sock, 5) == PR_FAILURE) {
   1.234 +        fprintf(stderr, "PR_Listen failed\n");
   1.235 +        exit(1);
   1.236 +    }
   1.237 +    pd.fd = sock;
   1.238 +    pd.in_flags = PR_POLL_READ;
   1.239 +    rv = PR_Poll(&pd, 1, timeout);
   1.240 +    if (rv != 0) {
   1.241 +        fprintf(stderr, "PR_Poll did not time out\n");
   1.242 +        exit(1);
   1.243 +    }
   1.244 +    elapsed = (PRIntervalTime)(PR_IntervalNow() - start_time);
   1.245 +    if (elapsed + tolerance < timeout || elapsed > timeout + tolerance) {
   1.246 +        fprintf(stderr, "timeout wrong\n");
   1.247 +        exit(1);
   1.248 +    }
   1.249 +#if defined(XP_UNIX)
   1.250 +    gettimeofday(&end_time_tv, NULL);
   1.251 +    elapsed_msecs = 1000*(end_time_tv.tv_sec - start_time_tv.tv_sec)
   1.252 +            + (end_time_tv.tv_usec - start_time_tv.tv_usec)/1000;
   1.253 +#endif
   1.254 +#if defined(WIN32)
   1.255 +#if defined(WINCE)
   1.256 +    elapsed_msecs = GetTickCount() - start_time_tick;
   1.257 +#else
   1.258 +    _ftime(&end_time_tb);
   1.259 +    elapsed_msecs = 1000*(end_time_tb.time - start_time_tb.time)
   1.260 +            + (end_time_tb.millitm - start_time_tb.millitm);
   1.261 +#endif
   1.262 +#endif
   1.263 +#if defined(XP_UNIX) || defined(WIN32)
   1.264 +    if (elapsed_msecs + tolerance_msecs < timeout_msecs
   1.265 +            || elapsed_msecs > timeout_msecs + tolerance_msecs) {
   1.266 +        fprintf(stderr, "timeout wrong\n");
   1.267 +        exit(1);
   1.268 +    }
   1.269 +#endif
   1.270 +    if (PR_Close(sock) == PR_FAILURE) {
   1.271 +        fprintf(stderr, "PR_Close failed\n");
   1.272 +        exit(1);
   1.273 +    }
   1.274 +    if (debug_mode) {
   1.275 +        fprintf(stderr, "Poll thread (scope %d) done\n",
   1.276 +                PR_GetThreadScope(PR_GetCurrentThread()));
   1.277 +    }
   1.278 +}
   1.279 +
   1.280 +static void WaitCondVarThread(void *arg)
   1.281 +{
   1.282 +    PRIntervalTime timeout = (PRIntervalTime) arg;
   1.283 +    PRIntervalTime elapsed;
   1.284 +#if defined(XP_UNIX) || defined(WIN32)
   1.285 +    PRInt32 timeout_msecs = PR_IntervalToMilliseconds(timeout);
   1.286 +    PRInt32 elapsed_msecs;
   1.287 +#endif
   1.288 +#if defined(XP_UNIX)
   1.289 +    struct timeval end_time_tv;
   1.290 +#endif
   1.291 +#if defined(WIN32) && !defined(WINCE)
   1.292 +    struct _timeb end_time_tb;
   1.293 +#endif
   1.294 +    PRLock *ml;
   1.295 +    PRCondVar *cv;
   1.296 +
   1.297 +    ml = PR_NewLock();
   1.298 +    if (ml == NULL) {
   1.299 +        fprintf(stderr, "PR_NewLock failed\n");
   1.300 +        exit(1);
   1.301 +    }
   1.302 +    cv = PR_NewCondVar(ml);
   1.303 +    if (cv == NULL) {
   1.304 +        fprintf(stderr, "PR_NewCondVar failed\n");
   1.305 +        exit(1);
   1.306 +    }
   1.307 +    PR_Lock(ml);
   1.308 +    PR_WaitCondVar(cv, timeout);
   1.309 +    PR_Unlock(ml);
   1.310 +    elapsed = (PRIntervalTime)(PR_IntervalNow() - start_time);
   1.311 +    if (elapsed + tolerance < timeout || elapsed > timeout + tolerance) {
   1.312 +        fprintf(stderr, "timeout wrong\n");
   1.313 +        exit(1);
   1.314 +    }
   1.315 +#if defined(XP_UNIX)
   1.316 +    gettimeofday(&end_time_tv, NULL);
   1.317 +    elapsed_msecs = 1000*(end_time_tv.tv_sec - start_time_tv.tv_sec)
   1.318 +            + (end_time_tv.tv_usec - start_time_tv.tv_usec)/1000;
   1.319 +#endif
   1.320 +#if defined(WIN32)
   1.321 +#if defined(WINCE)
   1.322 +    elapsed_msecs = GetTickCount() - start_time_tick;
   1.323 +#else
   1.324 +    _ftime(&end_time_tb);
   1.325 +    elapsed_msecs = 1000*(end_time_tb.time - start_time_tb.time)
   1.326 +            + (end_time_tb.millitm - start_time_tb.millitm);
   1.327 +#endif
   1.328 +#endif
   1.329 +#if defined(XP_UNIX) || defined(WIN32)
   1.330 +    if (elapsed_msecs + tolerance_msecs < timeout_msecs
   1.331 +            || elapsed_msecs > timeout_msecs + tolerance_msecs) {
   1.332 +        fprintf(stderr, "timeout wrong\n");
   1.333 +        exit(1);
   1.334 +    }
   1.335 +#endif
   1.336 +    PR_DestroyCondVar(cv);
   1.337 +    PR_DestroyLock(ml);
   1.338 +    if (debug_mode) {
   1.339 +        fprintf(stderr, "wait cond var thread (scope %d) done\n",
   1.340 +                PR_GetThreadScope(PR_GetCurrentThread()));
   1.341 +    }
   1.342 +}
   1.343 +
   1.344 +static void WaitMonitorThread(void *arg)
   1.345 +{
   1.346 +    PRIntervalTime timeout = (PRIntervalTime) arg;
   1.347 +    PRIntervalTime elapsed;
   1.348 +#if defined(XP_UNIX) || defined(WIN32)
   1.349 +    PRInt32 timeout_msecs = PR_IntervalToMilliseconds(timeout);
   1.350 +    PRInt32 elapsed_msecs;
   1.351 +#endif
   1.352 +#if defined(XP_UNIX)
   1.353 +    struct timeval end_time_tv;
   1.354 +#endif
   1.355 +#if defined(WIN32) && !defined(WINCE)
   1.356 +    struct _timeb end_time_tb;
   1.357 +#endif
   1.358 +    PRMonitor *mon;
   1.359 +
   1.360 +    mon = PR_NewMonitor();
   1.361 +    if (mon == NULL) {
   1.362 +        fprintf(stderr, "PR_NewMonitor failed\n");
   1.363 +        exit(1);
   1.364 +    }
   1.365 +    PR_EnterMonitor(mon);
   1.366 +    PR_Wait(mon, timeout);
   1.367 +    PR_ExitMonitor(mon);
   1.368 +    elapsed = (PRIntervalTime)(PR_IntervalNow() - start_time);
   1.369 +    if (elapsed + tolerance < timeout || elapsed > timeout + tolerance) {
   1.370 +        fprintf(stderr, "timeout wrong\n");
   1.371 +        exit(1);
   1.372 +    }
   1.373 +#if defined(XP_UNIX)
   1.374 +    gettimeofday(&end_time_tv, NULL);
   1.375 +    elapsed_msecs = 1000*(end_time_tv.tv_sec - start_time_tv.tv_sec)
   1.376 +            + (end_time_tv.tv_usec - start_time_tv.tv_usec)/1000;
   1.377 +#endif
   1.378 +#if defined(WIN32)
   1.379 +#if defined(WINCE)
   1.380 +    elapsed_msecs = GetTickCount() - start_time_tick;
   1.381 +#else
   1.382 +    _ftime(&end_time_tb);
   1.383 +    elapsed_msecs = 1000*(end_time_tb.time - start_time_tb.time)
   1.384 +            + (end_time_tb.millitm - start_time_tb.millitm);
   1.385 +#endif
   1.386 +#endif
   1.387 +#if defined(XP_UNIX) || defined(WIN32)
   1.388 +    if (elapsed_msecs + tolerance_msecs < timeout_msecs
   1.389 +            || elapsed_msecs > timeout_msecs + tolerance_msecs) {
   1.390 +        fprintf(stderr, "timeout wrong\n");
   1.391 +        exit(1);
   1.392 +    }
   1.393 +#endif
   1.394 +    PR_DestroyMonitor(mon);
   1.395 +    if (debug_mode) {
   1.396 +        fprintf(stderr, "wait monitor thread (scope %d) done\n",
   1.397 +                PR_GetThreadScope(PR_GetCurrentThread()));
   1.398 +    }
   1.399 +}
   1.400 +
   1.401 +static void WaitCMonitorThread(void *arg)
   1.402 +{
   1.403 +    PRIntervalTime timeout = (PRIntervalTime) arg;
   1.404 +    PRIntervalTime elapsed;
   1.405 +#if defined(XP_UNIX) || defined(WIN32)
   1.406 +    PRInt32 timeout_msecs = PR_IntervalToMilliseconds(timeout);
   1.407 +    PRInt32 elapsed_msecs;
   1.408 +#endif
   1.409 +#if defined(XP_UNIX)
   1.410 +    struct timeval end_time_tv;
   1.411 +#endif
   1.412 +#if defined(WIN32) && !defined(WINCE)
   1.413 +    struct _timeb end_time_tb;
   1.414 +#endif
   1.415 +    int dummy;
   1.416 +
   1.417 +    PR_CEnterMonitor(&dummy);
   1.418 +    PR_CWait(&dummy, timeout);
   1.419 +    PR_CExitMonitor(&dummy);
   1.420 +    elapsed = (PRIntervalTime)(PR_IntervalNow() - start_time);
   1.421 +    if (elapsed + tolerance < timeout || elapsed > timeout + tolerance) {
   1.422 +        fprintf(stderr, "timeout wrong\n");
   1.423 +        exit(1);
   1.424 +    }
   1.425 +#if defined(XP_UNIX)
   1.426 +    gettimeofday(&end_time_tv, NULL);
   1.427 +    elapsed_msecs = 1000*(end_time_tv.tv_sec - start_time_tv.tv_sec)
   1.428 +            + (end_time_tv.tv_usec - start_time_tv.tv_usec)/1000;
   1.429 +#endif
   1.430 +#if defined(WIN32)
   1.431 +#if defined(WINCE)
   1.432 +    elapsed_msecs = GetTickCount() - start_time_tick;
   1.433 +#else
   1.434 +    _ftime(&end_time_tb);
   1.435 +    elapsed_msecs = 1000*(end_time_tb.time - start_time_tb.time)
   1.436 +            + (end_time_tb.millitm - start_time_tb.millitm);
   1.437 +#endif
   1.438 +#endif
   1.439 +#if defined(XP_UNIX) || defined(WIN32)
   1.440 +    if (elapsed_msecs + tolerance_msecs < timeout_msecs
   1.441 +            || elapsed_msecs > timeout_msecs + tolerance_msecs) {
   1.442 +        fprintf(stderr, "timeout wrong\n");
   1.443 +        exit(1);
   1.444 +    }
   1.445 +#endif
   1.446 +    if (debug_mode) {
   1.447 +        fprintf(stderr, "wait cached monitor thread (scope %d) done\n",
   1.448 +                PR_GetThreadScope(PR_GetCurrentThread()));
   1.449 +    }
   1.450 +}
   1.451 +
   1.452 +typedef void (*NSPRThreadFunc)(void*);
   1.453 +
   1.454 +static NSPRThreadFunc threadFuncs[] = {
   1.455 +    SleepThread, AcceptThread, PollThread,
   1.456 +    WaitCondVarThread, WaitMonitorThread, WaitCMonitorThread};
   1.457 +
   1.458 +static PRThreadScope threadScopes[] = {
   1.459 +    PR_LOCAL_THREAD, PR_GLOBAL_THREAD, PR_GLOBAL_BOUND_THREAD};
   1.460 +
   1.461 +static void Help(void)
   1.462 +{
   1.463 +    fprintf(stderr, "y2ktmo test program usage:\n");
   1.464 +    fprintf(stderr, "\t-d           debug mode         (FALSE)\n");
   1.465 +    fprintf(stderr, "\t-l <secs>    lead time          (%d)\n",
   1.466 +            DEFAULT_LEAD_TIME_SECS);
   1.467 +    fprintf(stderr, "\t-t <msecs>   tolerance          (%d)\n",
   1.468 +            DEFAULT_TOLERANCE_MSECS);
   1.469 +    fprintf(stderr, "\t-h           this message\n");
   1.470 +}  /* Help */
   1.471 +
   1.472 +int main(int argc, char **argv)
   1.473 +{
   1.474 +    PRThread **threads;
   1.475 +    int num_thread_funcs = sizeof(threadFuncs)/sizeof(NSPRThreadFunc);
   1.476 +    int num_thread_scopes = sizeof(threadScopes)/sizeof(PRThreadScope);
   1.477 +    int i, j;
   1.478 +    int idx;
   1.479 +    PRInt32 secs;
   1.480 +    PLOptStatus os;
   1.481 +    PLOptState *opt = PL_CreateOptState(argc, argv, "dl:t:h");
   1.482 +
   1.483 +    while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) {
   1.484 +        if (PL_OPT_BAD == os) continue;
   1.485 +        switch (opt->option) {
   1.486 +            case 'd':  /* debug mode */
   1.487 +                debug_mode = PR_TRUE;
   1.488 +                break;
   1.489 +            case 'l':  /* lead time */
   1.490 +                lead_time_secs = atoi(opt->value);
   1.491 +                break;
   1.492 +            case 't':  /* tolerance */
   1.493 +                tolerance_msecs = atoi(opt->value);
   1.494 +                break;
   1.495 +            case 'h':
   1.496 +            default:
   1.497 +                Help();
   1.498 +                return 2;
   1.499 +        }
   1.500 +    }
   1.501 +    PL_DestroyOptState(opt);
   1.502 +
   1.503 +    if (debug_mode) {
   1.504 +        fprintf(stderr, "lead time: %d secs\n", lead_time_secs);
   1.505 +        fprintf(stderr, "tolerance: %d msecs\n", tolerance_msecs);
   1.506 +    }
   1.507 +
   1.508 +    start_time = PR_IntervalNow();
   1.509 +#if defined(XP_UNIX)
   1.510 +    gettimeofday(&start_time_tv, NULL);
   1.511 +#endif
   1.512 +#if defined(WIN32)
   1.513 +#ifdef WINCE
   1.514 +    start_time_tick = GetTickCount();
   1.515 +#else
   1.516 +    _ftime(&start_time_tb);
   1.517 +#endif
   1.518 +#endif
   1.519 +    tolerance = PR_MillisecondsToInterval(tolerance_msecs);
   1.520 +
   1.521 +    threads = PR_Malloc(
   1.522 +            num_thread_scopes * num_thread_funcs * sizeof(PRThread*));
   1.523 +    if (threads == NULL) {
   1.524 +        fprintf(stderr, "PR_Malloc failed\n");
   1.525 +        exit(1);
   1.526 +    }
   1.527 +
   1.528 +    /* start to time out 5 seconds after a rollover date */
   1.529 +    secs = lead_time_secs + 5;
   1.530 +    idx = 0;
   1.531 +    for (i = 0; i < num_thread_scopes; i++) { 
   1.532 +        for (j = 0; j < num_thread_funcs; j++) {
   1.533 +            threads[idx] = PR_CreateThread(PR_USER_THREAD, threadFuncs[j],
   1.534 +                (void*)PR_SecondsToInterval(secs), PR_PRIORITY_NORMAL,
   1.535 +                threadScopes[i], PR_JOINABLE_THREAD, 0);
   1.536 +            if (threads[idx] == NULL) {
   1.537 +                fprintf(stderr, "PR_CreateThread failed\n");
   1.538 +                exit(1);
   1.539 +            }
   1.540 +            secs++;
   1.541 +            idx++;
   1.542 +        }
   1.543 +    }
   1.544 +    for (idx = 0; idx < num_thread_scopes*num_thread_funcs; idx++) {
   1.545 +        if (PR_JoinThread(threads[idx]) == PR_FAILURE) {
   1.546 +            fprintf(stderr, "PR_JoinThread failed\n");
   1.547 +            exit(1);
   1.548 +        }
   1.549 +    }
   1.550 +    PR_Free(threads);
   1.551 +    printf("PASS\n");
   1.552 +    return 0;
   1.553 +}

mercurial