VirtualBox

source: vbox/trunk/src/libs/xpcom18a4/nsprpub/pr/tests/alarm.c@ 89890

最後變更 在這個檔案從89890是 1,由 vboxsync 提交於 55 年 前

import

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 14.8 KB
 
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2/* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 *
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
9 *
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
14 *
15 * The Original Code is the Netscape Portable Runtime (NSPR).
16 *
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998-2000
20 * the Initial Developer. All Rights Reserved.
21 *
22 * Contributor(s):
23 *
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
35 *
36 * ***** END LICENSE BLOCK ***** */
37
38/***********************************************************************
39** 1996 - Netscape Communications Corporation
40**
41** Name: alarmtst.c
42**
43** Description: Test alarms
44**
45** Modification History:
46** 13-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** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
52** recognize the return code from tha main program.
53***********************************************************************/
54
55/***********************************************************************
56** Includes
57***********************************************************************/
58
59#include "prlog.h"
60#include "prinit.h"
61#ifdef XP_MAC
62#include "pralarm.h"
63#else
64#include "obsolete/pralarm.h"
65#endif
66#include "prlock.h"
67#include "prlong.h"
68#include "prcvar.h"
69#include "prinrval.h"
70#include "prtime.h"
71
72/* Used to get the command line option */
73#include "plgetopt.h"
74#include <stdio.h>
75#include <stdlib.h>
76
77#if defined(XP_UNIX)
78#include <sys/time.h>
79#endif
80
81#ifdef XP_MAC
82#include "prlog.h"
83#define printf PR_LogPrint
84extern void SetupMacPrintfLog(char *logFile);
85#endif
86
87static PRIntn debug_mode;
88static PRIntn failed_already=0;
89static PRThreadScope thread_scope = PR_LOCAL_THREAD;
90
91typedef struct notifyData {
92 PRLock *ml;
93 PRCondVar *child;
94 PRCondVar *parent;
95 PRBool pending;
96 PRUint32 counter;
97} NotifyData;
98
99static void Notifier(void *arg)
100{
101 NotifyData *notifyData = (NotifyData*)arg;
102 PR_Lock(notifyData->ml);
103 while (notifyData->counter > 0)
104 {
105 while (!notifyData->pending)
106 PR_WaitCondVar(notifyData->child, PR_INTERVAL_NO_TIMEOUT);
107 notifyData->counter -= 1;
108 notifyData->pending = PR_FALSE;
109 PR_NotifyCondVar(notifyData->parent);
110 }
111 PR_Unlock(notifyData->ml);
112} /* Notifier */
113/***********************************************************************
114** PRIVATE FUNCTION: ConditionNotify
115** DESCRIPTION:
116**
117** INPUTS: loops
118** OUTPUTS: None
119** RETURN: overhead
120** SIDE EFFECTS:
121**
122** RESTRICTIONS:
123** None
124** MEMORY: NA
125** ALGORITHM:
126**
127***********************************************************************/
128
129
130static PRIntervalTime ConditionNotify(PRUint32 loops)
131{
132 PRThread *thread;
133 NotifyData notifyData;
134 PRIntervalTime timein, overhead;
135
136 timein = PR_IntervalNow();
137
138 notifyData.counter = loops;
139 notifyData.ml = PR_NewLock();
140 notifyData.child = PR_NewCondVar(notifyData.ml);
141 notifyData.parent = PR_NewCondVar(notifyData.ml);
142 thread = PR_CreateThread(
143 PR_USER_THREAD, Notifier, &notifyData,
144 PR_GetThreadPriority(PR_GetCurrentThread()),
145 thread_scope, PR_JOINABLE_THREAD, 0);
146
147 overhead = PR_IntervalNow() - timein; /* elapsed so far */
148
149 PR_Lock(notifyData.ml);
150 while (notifyData.counter > 0)
151 {
152 notifyData.pending = PR_TRUE;
153 PR_NotifyCondVar(notifyData.child);
154 while (notifyData.pending)
155 PR_WaitCondVar(notifyData.parent, PR_INTERVAL_NO_TIMEOUT);
156 }
157 PR_Unlock(notifyData.ml);
158
159 timein = PR_IntervalNow();
160
161 (void)PR_JoinThread(thread);
162 PR_DestroyCondVar(notifyData.child);
163 PR_DestroyCondVar(notifyData.parent);
164 PR_DestroyLock(notifyData.ml);
165
166 overhead += (PR_IntervalNow() - timein); /* more overhead */
167
168 return overhead;
169} /* ConditionNotify */
170
171static PRIntervalTime ConditionTimeout(PRUint32 loops)
172{
173 PRUintn count;
174 PRIntervalTime overhead, timein = PR_IntervalNow();
175
176 PRLock *ml = PR_NewLock();
177 PRCondVar *cv = PR_NewCondVar(ml);
178 PRIntervalTime interval = PR_MillisecondsToInterval(50);
179
180 overhead = PR_IntervalNow() - timein;
181
182 PR_Lock(ml);
183 for (count = 0; count < loops; ++count)
184 {
185 overhead += interval;
186 PR_ASSERT(PR_WaitCondVar(cv, interval) == PR_SUCCESS);
187 }
188 PR_Unlock(ml);
189
190 timein = PR_IntervalNow();
191 PR_DestroyCondVar(cv);
192 PR_DestroyLock(ml);
193 overhead += (PR_IntervalNow() - timein);
194
195 return overhead;
196} /* ConditionTimeout */
197
198typedef struct AlarmData {
199 PRLock *ml;
200 PRCondVar *cv;
201 PRUint32 rate, late, times;
202 PRIntervalTime duration, timein, period;
203} AlarmData;
204
205static PRBool AlarmFn1(PRAlarmID *id, void *clientData, PRUint32 late)
206{
207 PRStatus rv = PR_SUCCESS;
208 PRBool keepGoing, resetAlarm;
209 PRIntervalTime interval, now = PR_IntervalNow();
210 AlarmData *ad = (AlarmData*)clientData;
211
212 PR_Lock(ad->ml);
213 ad->late += late;
214 ad->times += 1;
215 keepGoing = ((PRIntervalTime)(now - ad->timein) < ad->duration) ?
216 PR_TRUE : PR_FALSE;
217 if (!keepGoing)
218 rv = PR_NotifyCondVar(ad->cv);
219 resetAlarm = ((ad->times % 31) == 0) ? PR_TRUE : PR_FALSE;
220
221 interval = (ad->period + ad->rate - 1) / ad->rate;
222 if (!late && (interval > 10))
223 {
224 interval &= (now & 0x03) + 1;
225 PR_WaitCondVar(ad->cv, interval);
226 }
227
228 PR_Unlock(ad->ml);
229
230 if (rv != PR_SUCCESS)
231 {
232 if (!debug_mode) failed_already=1;
233 else
234 printf("AlarmFn: notify status: FAIL\n");
235
236 }
237
238 if (resetAlarm)
239 {
240 ad->rate += 3;
241 ad->late = ad->times = 0;
242 if (PR_ResetAlarm(id, ad->period, ad->rate) != PR_SUCCESS)
243 {
244 if (!debug_mode)
245 failed_already=1;
246 else
247 printf("AlarmFn: Resetting alarm status: FAIL\n");
248
249 keepGoing = PR_FALSE;
250 }
251
252 }
253
254 return keepGoing;
255} /* AlarmFn1 */
256
257static PRIntervalTime Alarms1(PRUint32 loops)
258{
259 PRAlarm *alarm;
260 AlarmData ad;
261 PRIntervalTime overhead, timein = PR_IntervalNow();
262 PRIntervalTime duration = PR_SecondsToInterval(3);
263
264 PRLock *ml = PR_NewLock();
265 PRCondVar *cv = PR_NewCondVar(ml);
266
267 ad.ml = ml;
268 ad.cv = cv;
269 ad.rate = 1;
270 ad.times = loops;
271 ad.late = ad.times = 0;
272 ad.duration = duration;
273 ad.timein = PR_IntervalNow();
274 ad.period = PR_SecondsToInterval(1);
275
276 alarm = PR_CreateAlarm();
277
278 (void)PR_SetAlarm(
279 alarm, ad.period, ad.rate, AlarmFn1, &ad);
280
281 overhead = PR_IntervalNow() - timein;
282
283 PR_Lock(ml);
284 while ((PRIntervalTime)(PR_IntervalNow() - ad.timein) < duration)
285 PR_WaitCondVar(cv, PR_INTERVAL_NO_TIMEOUT);
286 PR_Unlock(ml);
287
288 timein = PR_IntervalNow();
289 (void)PR_DestroyAlarm(alarm);
290 PR_DestroyCondVar(cv);
291 PR_DestroyLock(ml);
292 overhead += (PR_IntervalNow() - timein);
293
294 return duration + overhead;
295} /* Alarms1 */
296
297static PRBool AlarmFn2(PRAlarmID *id, void *clientData, PRUint32 late)
298{
299#if defined(XP_MAC)
300#pragma unused (id)
301#endif
302
303 PRBool keepGoing;
304 PRStatus rv = PR_SUCCESS;
305 AlarmData *ad = (AlarmData*)clientData;
306 PRIntervalTime interval, now = PR_IntervalNow();
307
308 PR_Lock(ad->ml);
309 ad->times += 1;
310 keepGoing = ((PRIntervalTime)(now - ad->timein) < ad->duration) ?
311 PR_TRUE : PR_FALSE;
312 interval = (ad->period + ad->rate - 1) / ad->rate;
313
314 if (!late && (interval > 10))
315 {
316 interval &= (now & 0x03) + 1;
317 PR_WaitCondVar(ad->cv, interval);
318 }
319
320 if (!keepGoing) rv = PR_NotifyCondVar(ad->cv);
321
322 PR_Unlock(ad->ml);
323
324
325 if (rv != PR_SUCCESS)
326 failed_already=1;;
327
328 return keepGoing;
329} /* AlarmFn2 */
330
331static PRIntervalTime Alarms2(PRUint32 loops)
332{
333 PRStatus rv;
334 PRAlarm *alarm;
335 PRIntervalTime overhead, timein = PR_IntervalNow();
336 AlarmData ad;
337 PRIntervalTime duration = PR_SecondsToInterval(30);
338
339 PRLock *ml = PR_NewLock();
340 PRCondVar *cv = PR_NewCondVar(ml);
341
342 ad.ml = ml;
343 ad.cv = cv;
344 ad.rate = 1;
345 ad.times = loops;
346 ad.late = ad.times = 0;
347 ad.duration = duration;
348 ad.timein = PR_IntervalNow();
349 ad.period = PR_SecondsToInterval(1);
350
351 alarm = PR_CreateAlarm();
352
353 (void)PR_SetAlarm(
354 alarm, ad.period, ad.rate, AlarmFn2, &ad);
355
356 overhead = PR_IntervalNow() - timein;
357
358 PR_Lock(ml);
359 while ((PRIntervalTime)(PR_IntervalNow() - ad.timein) < duration)
360 PR_WaitCondVar(cv, PR_INTERVAL_NO_TIMEOUT);
361 PR_Unlock(ml);
362
363 timein = PR_IntervalNow();
364
365 rv = PR_DestroyAlarm(alarm);
366 if (rv != PR_SUCCESS)
367 {
368 if (!debug_mode)
369 failed_already=1;
370 else
371 printf("***Destroying alarm status: FAIL\n");
372 }
373
374
375 PR_DestroyCondVar(cv);
376 PR_DestroyLock(ml);
377
378 overhead += (PR_IntervalNow() - timein);
379
380 return duration + overhead;
381} /* Alarms2 */
382
383static PRIntervalTime Alarms3(PRUint32 loops)
384{
385 PRIntn i;
386 PRStatus rv;
387 PRAlarm *alarm;
388 AlarmData ad[3];
389 PRIntervalTime duration = PR_SecondsToInterval(30);
390 PRIntervalTime overhead, timein = PR_IntervalNow();
391
392 PRLock *ml = PR_NewLock();
393 PRCondVar *cv = PR_NewCondVar(ml);
394
395 for (i = 0; i < 3; ++i)
396 {
397 ad[i].ml = ml;
398 ad[i].cv = cv;
399 ad[i].rate = 1;
400 ad[i].times = loops;
401 ad[i].duration = duration;
402 ad[i].late = ad[i].times = 0;
403 ad[i].timein = PR_IntervalNow();
404 ad[i].period = PR_SecondsToInterval(1);
405
406 /* more loops, faster rate => same elapsed time */
407 ad[i].times = (i + 1) * loops;
408 ad[i].rate = (i + 1) * 10;
409 }
410
411 alarm = PR_CreateAlarm();
412
413 for (i = 0; i < 3; ++i)
414 {
415 (void)PR_SetAlarm(
416 alarm, ad[i].period, ad[i].rate,
417 AlarmFn2, &ad[i]);
418 }
419
420 overhead = PR_IntervalNow() - timein;
421
422 PR_Lock(ml);
423 for (i = 0; i < 3; ++i)
424 {
425 while ((PRIntervalTime)(PR_IntervalNow() - ad[i].timein) < duration)
426 PR_WaitCondVar(cv, PR_INTERVAL_NO_TIMEOUT);
427 }
428 PR_Unlock(ml);
429
430 timein = PR_IntervalNow();
431
432 if (debug_mode)
433 printf
434 ("Alarms3 finished at %u, %u, %u\n",
435 ad[0].timein, ad[1].timein, ad[2].timein);
436
437 rv = PR_DestroyAlarm(alarm);
438 if (rv != PR_SUCCESS)
439 {
440 if (!debug_mode)
441 failed_already=1;
442 else
443 printf("***Destroying alarm status: FAIL\n");
444 }
445 PR_DestroyCondVar(cv);
446 PR_DestroyLock(ml);
447
448 overhead += (duration / 3);
449 overhead += (PR_IntervalNow() - timein);
450
451 return overhead;
452} /* Alarms3 */
453
454static PRUint32 TimeThis(
455 const char *msg, PRUint32 (*func)(PRUint32 loops), PRUint32 loops)
456{
457 PRUint32 overhead, usecs;
458 PRIntervalTime predicted, timein, timeout, ticks;
459
460 if (debug_mode)
461 printf("Testing %s ...", msg);
462
463 timein = PR_IntervalNow();
464 predicted = func(loops);
465 timeout = PR_IntervalNow();
466
467 if (debug_mode)
468 printf(" done\n");
469
470 ticks = timeout - timein;
471 usecs = PR_IntervalToMicroseconds(ticks);
472 overhead = PR_IntervalToMicroseconds(predicted);
473
474 if(ticks < predicted)
475 {
476 if (debug_mode) {
477 printf("\tFinished in negative time\n");
478 printf("\tpredicted overhead was %d usecs\n", overhead);
479 printf("\ttest completed in %d usecs\n\n", usecs);
480 }
481 }
482 else
483 {
484 if (debug_mode)
485 printf(
486 "\ttotal: %d usecs\n\toverhead: %d usecs\n\tcost: %6.3f usecs\n\n",
487 usecs, overhead, ((double)(usecs - overhead) / (double)loops));
488 }
489
490 return overhead;
491} /* TimeThis */
492
493int prmain(int argc, char** argv)
494{
495 PRUint32 cpu, cpus = 0, loops = 0;
496
497 /* The command line argument: -d is used to determine if the test is being run
498 in debug mode. The regress tool requires only one line output:PASS or FAIL.
499 All of the printfs associated with this test has been handled with a if (debug_mode)
500 test.
501 Usage: test_name [-d]
502 */
503 PLOptStatus os;
504 PLOptState *opt = PL_CreateOptState(argc, argv, "Gdl:c:");
505 while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
506 {
507 if (PL_OPT_BAD == os) continue;
508 switch (opt->option)
509 {
510 case 'G': /* GLOBAL threads */
511 thread_scope = PR_GLOBAL_THREAD;
512 break;
513 case 'd': /* debug mode */
514 debug_mode = 1;
515 break;
516 case 'l': /* loop count */
517 loops = atoi(opt->value);
518 break;
519 case 'c': /* concurrency limit */
520 cpus = atoi(opt->value);
521 break;
522 default:
523 break;
524 }
525 }
526 PL_DestroyOptState(opt);
527
528
529 if (cpus == 0) cpus = 1;
530 if (loops == 0) loops = 4;
531
532 if (debug_mode)
533 printf("Alarm: Using %d loops\n", loops);
534
535 if (debug_mode)
536 printf("Alarm: Using %d cpu(s)\n", cpus);
537#ifdef XP_MAC
538 SetupMacPrintfLog("alarm.log");
539 debug_mode = 1;
540#endif
541
542 for (cpu = 1; cpu <= cpus; ++cpu)
543 {
544 if (debug_mode)
545 printf("\nAlarm: Using %d CPU(s)\n", cpu);
546
547 PR_SetConcurrency(cpu);
548
549 /* some basic time test */
550 (void)TimeThis("ConditionNotify", ConditionNotify, loops);
551 (void)TimeThis("ConditionTimeout", ConditionTimeout, loops);
552 (void)TimeThis("Alarms1", Alarms1, loops);
553 (void)TimeThis("Alarms2", Alarms2, loops);
554 (void)TimeThis("Alarms3", Alarms3, loops);
555 }
556 return 0;
557}
558
559int main(int argc, char** argv)
560{
561 PR_Initialize(prmain, argc, argv, 0);
562 PR_STDIO_INIT();
563 if (failed_already) return 1;
564 else return 0;
565
566} /* main */
567
568
569/* alarmtst.c */
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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