nsprpub/pr/tests/alarm.c

Wed, 31 Dec 2014 07:53:36 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:53:36 +0100
branch
TOR_BUG_3246
changeset 5
4ab42b5ab56c
permissions
-rw-r--r--

Correct small whitespace inconsistency, lost while renaming variables.

     1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 /***********************************************************************
     7 **  1996 - Netscape Communications Corporation
     8 **
     9 ** Name: alarmtst.c
    10 **
    11 ** Description: Test alarms
    12 **
    13 ** Modification History:
    14 ** 13-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
    15 **	         The debug mode will print all of the printfs associated with this test.
    16 **			 The regress mode will be the default mode. Since the regress tool limits
    17 **           the output to a one line status:PASS or FAIL,all of the printf statements
    18 **			 have been handled with an if (debug_mode) statement.
    19 ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
    20 **			recognize the return code from tha main program.
    21 ***********************************************************************/
    23 /***********************************************************************
    24 ** Includes
    25 ***********************************************************************/
    27 #include "prlog.h"
    28 #include "prinit.h"
    29 #include "obsolete/pralarm.h"
    30 #include "prlock.h"
    31 #include "prlong.h"
    32 #include "prcvar.h"
    33 #include "prinrval.h"
    34 #include "prtime.h"
    36 /* Used to get the command line option */
    37 #include "plgetopt.h"
    38 #include <stdio.h>
    39 #include <stdlib.h>
    41 #if defined(XP_UNIX)
    42 #include <sys/time.h>
    43 #endif
    45 static PRIntn debug_mode;
    46 static PRIntn failed_already=0;
    47 static PRThreadScope thread_scope = PR_LOCAL_THREAD;
    49 typedef struct notifyData {
    50     PRLock *ml;
    51     PRCondVar *child;
    52     PRCondVar *parent;
    53     PRBool pending;
    54     PRUint32 counter;
    55 } NotifyData;
    57 static void Notifier(void *arg)
    58 {
    59     NotifyData *notifyData = (NotifyData*)arg;
    60     PR_Lock(notifyData->ml);
    61     while (notifyData->counter > 0)
    62     {
    63         while (!notifyData->pending)
    64             PR_WaitCondVar(notifyData->child, PR_INTERVAL_NO_TIMEOUT);
    65         notifyData->counter -= 1;
    66         notifyData->pending = PR_FALSE;
    67         PR_NotifyCondVar(notifyData->parent);
    68     }
    69     PR_Unlock(notifyData->ml);
    70 }  /* Notifier */
    71 /***********************************************************************
    72 ** PRIVATE FUNCTION:    ConditionNotify
    73 ** DESCRIPTION:
    74 ** 
    75 ** INPUTS:      loops
    76 ** OUTPUTS:     None
    77 ** RETURN:      overhead
    78 ** SIDE EFFECTS:
    79 **      
    80 ** RESTRICTIONS:
    81 **      None
    82 ** MEMORY:      NA
    83 ** ALGORITHM:
    84 **      
    85 ***********************************************************************/
    88 static PRIntervalTime ConditionNotify(PRUint32 loops)
    89 {
    90     PRThread *thread;
    91     NotifyData notifyData;
    92     PRIntervalTime timein, overhead;
    94     timein = PR_IntervalNow();
    96     notifyData.counter = loops;
    97     notifyData.ml = PR_NewLock();
    98     notifyData.child = PR_NewCondVar(notifyData.ml);
    99     notifyData.parent = PR_NewCondVar(notifyData.ml);
   100     thread = PR_CreateThread(
   101         PR_USER_THREAD, Notifier, &notifyData,
   102         PR_GetThreadPriority(PR_GetCurrentThread()),
   103         thread_scope, PR_JOINABLE_THREAD, 0);
   105     overhead = PR_IntervalNow() - timein;  /* elapsed so far */
   107     PR_Lock(notifyData.ml);
   108     while (notifyData.counter > 0)
   109     {
   110         notifyData.pending = PR_TRUE;
   111         PR_NotifyCondVar(notifyData.child);
   112         while (notifyData.pending)
   113             PR_WaitCondVar(notifyData.parent, PR_INTERVAL_NO_TIMEOUT);
   114     }
   115     PR_Unlock(notifyData.ml);
   117     timein = PR_IntervalNow();
   119     (void)PR_JoinThread(thread);
   120     PR_DestroyCondVar(notifyData.child);
   121     PR_DestroyCondVar(notifyData.parent);
   122     PR_DestroyLock(notifyData.ml);
   124     overhead += (PR_IntervalNow() - timein);  /* more overhead */
   126     return overhead;
   127 }  /* ConditionNotify */
   129 static PRIntervalTime ConditionTimeout(PRUint32 loops)
   130 {
   131     PRUintn count;
   132     PRIntervalTime overhead, timein = PR_IntervalNow();
   134     PRLock *ml = PR_NewLock();
   135     PRCondVar *cv = PR_NewCondVar(ml);
   136     PRIntervalTime interval = PR_MillisecondsToInterval(50);
   138     overhead = PR_IntervalNow() - timein;
   140     PR_Lock(ml);
   141     for (count = 0; count < loops; ++count)
   142     {
   143         overhead += interval;
   144         PR_ASSERT(PR_WaitCondVar(cv, interval) == PR_SUCCESS);
   145     }
   146     PR_Unlock(ml);
   148     timein = PR_IntervalNow();
   149     PR_DestroyCondVar(cv);
   150     PR_DestroyLock(ml);
   151     overhead += (PR_IntervalNow() - timein);
   153     return overhead;
   154 }  /* ConditionTimeout */
   156 typedef struct AlarmData {
   157     PRLock *ml;
   158     PRCondVar *cv;
   159     PRUint32 rate, late, times;
   160     PRIntervalTime duration, timein, period;
   161 } AlarmData;
   163 static PRBool AlarmFn1(PRAlarmID *id, void *clientData, PRUint32 late)
   164 {
   165     PRStatus rv = PR_SUCCESS;
   166     PRBool keepGoing, resetAlarm;
   167     PRIntervalTime interval, now = PR_IntervalNow();
   168     AlarmData *ad = (AlarmData*)clientData;
   170     PR_Lock(ad->ml);
   171     ad->late += late;
   172     ad->times += 1;
   173     keepGoing = ((PRIntervalTime)(now - ad->timein) < ad->duration) ?
   174         PR_TRUE : PR_FALSE;
   175     if (!keepGoing)
   176         rv = PR_NotifyCondVar(ad->cv);
   177     resetAlarm = ((ad->times % 31) == 0) ? PR_TRUE : PR_FALSE;
   179     interval = (ad->period + ad->rate - 1) / ad->rate;
   180     if (!late && (interval > 10))
   181     {
   182         interval &= (now & 0x03) + 1;
   183         PR_WaitCondVar(ad->cv, interval);
   184     }
   186     PR_Unlock(ad->ml);
   188     if (rv != PR_SUCCESS)
   189     {
   190 		if (!debug_mode) failed_already=1;
   191 		else
   192 		 printf("AlarmFn: notify status: FAIL\n");
   194 	}
   196     if (resetAlarm)
   197     {   
   198         ad->rate += 3;
   199         ad->late = ad->times = 0;
   200         if (PR_ResetAlarm(id, ad->period, ad->rate) != PR_SUCCESS)
   201         {
   202 			if (!debug_mode)
   203 				failed_already=1;
   204 			else		
   205 				printf("AlarmFn: Resetting alarm status: FAIL\n");
   207             keepGoing = PR_FALSE;
   208         }
   210     }
   212     return keepGoing;
   213 }  /* AlarmFn1 */
   215 static PRIntervalTime Alarms1(PRUint32 loops)
   216 {
   217     PRAlarm *alarm;
   218     AlarmData ad;
   219     PRIntervalTime overhead, timein = PR_IntervalNow();
   220     PRIntervalTime duration = PR_SecondsToInterval(3);
   222     PRLock *ml = PR_NewLock();
   223     PRCondVar *cv = PR_NewCondVar(ml);
   225     ad.ml = ml;
   226     ad.cv = cv;
   227     ad.rate = 1;
   228     ad.times = loops;
   229     ad.late = ad.times = 0;
   230     ad.duration = duration;
   231     ad.timein = PR_IntervalNow();
   232     ad.period = PR_SecondsToInterval(1);
   234     alarm = PR_CreateAlarm();
   236     (void)PR_SetAlarm(
   237         alarm, ad.period, ad.rate, AlarmFn1, &ad);
   239     overhead = PR_IntervalNow() - timein;
   241     PR_Lock(ml);
   242     while ((PRIntervalTime)(PR_IntervalNow() - ad.timein) < duration)
   243         PR_WaitCondVar(cv, PR_INTERVAL_NO_TIMEOUT);
   244     PR_Unlock(ml);
   246     timein = PR_IntervalNow();
   247     (void)PR_DestroyAlarm(alarm);
   248     PR_DestroyCondVar(cv);
   249     PR_DestroyLock(ml);
   250     overhead += (PR_IntervalNow() - timein);
   252     return duration + overhead;
   253 }  /* Alarms1 */
   255 static PRBool AlarmFn2(PRAlarmID *id, void *clientData, PRUint32 late)
   256 {
   257     PRBool keepGoing;
   258     PRStatus rv = PR_SUCCESS;
   259     AlarmData *ad = (AlarmData*)clientData;
   260     PRIntervalTime interval, now = PR_IntervalNow();
   262     PR_Lock(ad->ml);
   263     ad->times += 1;
   264     keepGoing = ((PRIntervalTime)(now - ad->timein) < ad->duration) ?
   265         PR_TRUE : PR_FALSE;
   266     interval = (ad->period + ad->rate - 1) / ad->rate;
   268     if (!late && (interval > 10))
   269     {
   270         interval &= (now & 0x03) + 1;
   271         PR_WaitCondVar(ad->cv, interval);
   272     }
   274     if (!keepGoing) rv = PR_NotifyCondVar(ad->cv);
   276     PR_Unlock(ad->ml);
   279     if (rv != PR_SUCCESS)
   280 		failed_already=1;;
   282     return keepGoing;
   283 }  /* AlarmFn2 */
   285 static PRIntervalTime Alarms2(PRUint32 loops)
   286 {
   287     PRStatus rv;
   288     PRAlarm *alarm;
   289     PRIntervalTime overhead, timein = PR_IntervalNow();
   290     AlarmData ad;
   291     PRIntervalTime duration = PR_SecondsToInterval(30);
   293     PRLock *ml = PR_NewLock();
   294     PRCondVar *cv = PR_NewCondVar(ml);
   296     ad.ml = ml;
   297     ad.cv = cv;
   298     ad.rate = 1;
   299     ad.times = loops;
   300     ad.late = ad.times = 0;
   301     ad.duration = duration;
   302     ad.timein = PR_IntervalNow();
   303     ad.period = PR_SecondsToInterval(1);
   305     alarm = PR_CreateAlarm();
   307     (void)PR_SetAlarm(
   308         alarm, ad.period, ad.rate, AlarmFn2, &ad);
   310     overhead = PR_IntervalNow() - timein;
   312     PR_Lock(ml);
   313     while ((PRIntervalTime)(PR_IntervalNow() - ad.timein) < duration)
   314         PR_WaitCondVar(cv, PR_INTERVAL_NO_TIMEOUT);
   315     PR_Unlock(ml);
   317     timein = PR_IntervalNow();
   319     rv = PR_DestroyAlarm(alarm);
   320     if (rv != PR_SUCCESS)
   321     {
   322 		if (!debug_mode)
   323 			failed_already=1;
   324 		else	
   325 			printf("***Destroying alarm status: FAIL\n");
   326     }
   329     PR_DestroyCondVar(cv);
   330     PR_DestroyLock(ml);
   332     overhead += (PR_IntervalNow() - timein);
   334     return duration + overhead;
   335 }  /* Alarms2 */
   337 static PRIntervalTime Alarms3(PRUint32 loops)
   338 {
   339     PRIntn i;
   340     PRStatus rv;
   341     PRAlarm *alarm;
   342     AlarmData ad[3];
   343     PRIntervalTime duration = PR_SecondsToInterval(30);
   344     PRIntervalTime overhead, timein = PR_IntervalNow();
   346     PRLock *ml = PR_NewLock();
   347     PRCondVar *cv = PR_NewCondVar(ml);
   349     for (i = 0; i < 3; ++i)
   350     {
   351         ad[i].ml = ml;
   352         ad[i].cv = cv;
   353         ad[i].rate = 1;
   354         ad[i].times = loops;
   355         ad[i].duration = duration;
   356         ad[i].late = ad[i].times = 0;
   357         ad[i].timein = PR_IntervalNow();
   358         ad[i].period = PR_SecondsToInterval(1);
   360         /* more loops, faster rate => same elapsed time */
   361         ad[i].times = (i + 1) * loops;
   362         ad[i].rate = (i + 1) * 10;
   363     }
   365     alarm = PR_CreateAlarm();
   367     for (i = 0; i < 3; ++i)
   368     {
   369         (void)PR_SetAlarm(
   370             alarm, ad[i].period, ad[i].rate,
   371             AlarmFn2, &ad[i]);
   372     }
   374     overhead = PR_IntervalNow() - timein;
   376     PR_Lock(ml);
   377     for (i = 0; i < 3; ++i)
   378     {
   379         while ((PRIntervalTime)(PR_IntervalNow() - ad[i].timein) < duration)
   380             PR_WaitCondVar(cv, PR_INTERVAL_NO_TIMEOUT);
   381     }
   382     PR_Unlock(ml);
   384     timein = PR_IntervalNow();
   386 	if (debug_mode)
   387 	printf
   388         ("Alarms3 finished at %u, %u, %u\n",
   389         ad[0].timein, ad[1].timein, ad[2].timein);
   391     rv = PR_DestroyAlarm(alarm);
   392     if (rv != PR_SUCCESS)
   393     {
   394 		if (!debug_mode)		
   395 			failed_already=1;
   396 		else	
   397 		   printf("***Destroying alarm status: FAIL\n");
   398 	}
   399     PR_DestroyCondVar(cv);
   400     PR_DestroyLock(ml);
   402     overhead += (duration / 3);
   403     overhead += (PR_IntervalNow() - timein);
   405     return overhead;
   406 }  /* Alarms3 */
   408 static PRUint32 TimeThis(
   409     const char *msg, PRUint32 (*func)(PRUint32 loops), PRUint32 loops)
   410 {
   411     PRUint32 overhead, usecs;
   412     PRIntervalTime predicted, timein, timeout, ticks;
   414  if (debug_mode)
   415     printf("Testing %s ...", msg);
   417     timein = PR_IntervalNow();
   418     predicted = func(loops);
   419     timeout = PR_IntervalNow();
   421   if (debug_mode)
   422     printf(" done\n");
   424     ticks = timeout - timein;
   425     usecs = PR_IntervalToMicroseconds(ticks);
   426     overhead = PR_IntervalToMicroseconds(predicted);
   428     if(ticks < predicted)
   429     {
   430 		if (debug_mode) {
   431         printf("\tFinished in negative time\n");
   432         printf("\tpredicted overhead was %d usecs\n", overhead);
   433         printf("\ttest completed in %d usecs\n\n", usecs);
   434 		}
   435     }
   436     else
   437     {
   438 	if (debug_mode)		
   439         printf(
   440             "\ttotal: %d usecs\n\toverhead: %d usecs\n\tcost: %6.3f usecs\n\n",
   441             usecs, overhead, ((double)(usecs - overhead) / (double)loops));
   442     }
   444     return overhead;
   445 }  /* TimeThis */
   447 int prmain(int argc, char** argv)
   448 {
   449     PRUint32 cpu, cpus = 0, loops = 0;
   451 	/* The command line argument: -d is used to determine if the test is being run
   452 	in debug mode. The regress tool requires only one line output:PASS or FAIL.
   453 	All of the printfs associated with this test has been handled with a if (debug_mode)
   454 	test.
   455 	Usage: test_name [-d]
   456 	*/
   457 	PLOptStatus os;
   458 	PLOptState *opt = PL_CreateOptState(argc, argv, "Gdl:c:");
   459 	while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
   460     {
   461 		if (PL_OPT_BAD == os) continue;
   462         switch (opt->option)
   463         {
   464         case 'G':  /* GLOBAL threads */
   465 			thread_scope = PR_GLOBAL_THREAD;
   466             break;
   467         case 'd':  /* debug mode */
   468 			debug_mode = 1;
   469             break;
   470         case 'l':  /* loop count */
   471 			loops = atoi(opt->value);
   472             break;
   473         case 'c':  /* concurrency limit */
   474 			cpus = atoi(opt->value);
   475             break;
   476          default:
   477             break;
   478         }
   479     }
   480 	PL_DestroyOptState(opt);
   483     if (cpus == 0) cpus = 1;
   484     if (loops == 0) loops = 4;
   486 	if (debug_mode)
   487 		printf("Alarm: Using %d loops\n", loops);
   489 	if (debug_mode)		
   490         printf("Alarm: Using %d cpu(s)\n", cpus);
   492     for (cpu = 1; cpu <= cpus; ++cpu)
   493     {
   494     if (debug_mode)
   495         printf("\nAlarm: Using %d CPU(s)\n", cpu);
   497 	PR_SetConcurrency(cpu);
   499         /* some basic time test */
   500         (void)TimeThis("ConditionNotify", ConditionNotify, loops);
   501         (void)TimeThis("ConditionTimeout", ConditionTimeout, loops);
   502         (void)TimeThis("Alarms1", Alarms1, loops);
   503         (void)TimeThis("Alarms2", Alarms2, loops);
   504         (void)TimeThis("Alarms3", Alarms3, loops);
   505     }
   506     return 0;
   507 }
   509 int main(int argc, char** argv)
   510 {
   511      PR_Initialize(prmain, argc, argv, 0);
   512      PR_STDIO_INIT();
   513 	 if (failed_already) return 1;
   514 	 else return 0;
   516 }  /* main */
   519 /* alarmtst.c */

mercurial