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 +}