home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / nsprpub / pr / tests / alarm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  14.3 KB  |  547 lines

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