Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/nsprpub/pr/tests/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 12 kB image not shown  

Quelle  alarm.c   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


/***********************************************************************
**  1996 - Netscape Communications Corporation
**
** Name: alarmtst.c
**
** Description: Test alarms
**
** Modification History:
** 13-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
**           The debug mode will print all of the printfs associated with this
*test.
**           The regress mode will be the default mode. Since the regress tool
*limits
**           the output to a one line status:PASS or FAIL,all of the printf
*statements
**           have been handled with an if (debug_mode) statement.
** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been
*updated to
**          recognize the return code from tha main program.
***********************************************************************/


/***********************************************************************
** Includes
***********************************************************************/


#include "prlog.h"
#include "prinit.h"
#include "obsolete/pralarm.h"
#include "prlock.h"
#include "prlong.h"
#include "prcvar.h"
#include "prinrval.h"
#include "prtime.h"

/* Used to get the command line option */
#include "plgetopt.h"
#include <stdio.h>
#include <stdlib.h>

#if defined(XP_UNIX)
#  include <sys/time.h>
#endif

static PRIntn debug_mode;
static PRIntn failed_already = 0;
static PRThreadScope thread_scope = PR_LOCAL_THREAD;

typedef struct notifyData {
  PRLock* ml;
  PRCondVar* child;
  PRCondVar* parent;
  PRBool pending;
  PRUint32 counter;
} NotifyData;

static void Notifier(void* arg) {
  NotifyData* notifyData = (NotifyData*)arg;
  PR_Lock(notifyData->ml);
  while (notifyData->counter > 0) {
    while (!notifyData->pending) {
      PR_WaitCondVar(notifyData->child, PR_INTERVAL_NO_TIMEOUT);
    }
    notifyData->counter -= 1;
    notifyData->pending = PR_FALSE;
    PR_NotifyCondVar(notifyData->parent);
  }
  PR_Unlock(notifyData->ml);
/* Notifier */
/***********************************************************************
** PRIVATE FUNCTION:    ConditionNotify
** DESCRIPTION:
**
** INPUTS:      loops
** OUTPUTS:     None
** RETURN:      overhead
** SIDE EFFECTS:
**
** RESTRICTIONS:
**      None
** MEMORY:      NA
** ALGORITHM:
**
***********************************************************************/


static PRIntervalTime ConditionNotify(PRUint32 loops) {
  PRThread* thread;
  NotifyData notifyData;
  PRIntervalTime timein, overhead;

  timein = PR_IntervalNow();

  notifyData.counter = loops;
  notifyData.ml = PR_NewLock();
  notifyData.child = PR_NewCondVar(notifyData.ml);
  notifyData.parent = PR_NewCondVar(notifyData.ml);
  thread = PR_CreateThread(PR_USER_THREAD, Notifier, ¬ifyData,
                           PR_GetThreadPriority(PR_GetCurrentThread()),
                           thread_scope, PR_JOINABLE_THREAD, 0);

  overhead = PR_IntervalNow() - timein; /* elapsed so far */

  PR_Lock(notifyData.ml);
  while (notifyData.counter > 0) {
    notifyData.pending = PR_TRUE;
    PR_NotifyCondVar(notifyData.child);
    while (notifyData.pending) {
      PR_WaitCondVar(notifyData.parent, PR_INTERVAL_NO_TIMEOUT);
    }
  }
  PR_Unlock(notifyData.ml);

  timein = PR_IntervalNow();

  (void)PR_JoinThread(thread);
  PR_DestroyCondVar(notifyData.child);
  PR_DestroyCondVar(notifyData.parent);
  PR_DestroyLock(notifyData.ml);

  overhead += (PR_IntervalNow() - timein); /* more overhead */

  return overhead;
/* ConditionNotify */

static PRIntervalTime ConditionTimeout(PRUint32 loops) {
  PRUintn count;
  PRIntervalTime overhead, timein = PR_IntervalNow();

  PRLock* ml = PR_NewLock();
  PRCondVar* cv = PR_NewCondVar(ml);
  PRIntervalTime interval = PR_MillisecondsToInterval(50);

  overhead = PR_IntervalNow() - timein;

  PR_Lock(ml);
  for (count = 0; count < loops; ++count) {
    overhead += interval;
    PR_ASSERT(PR_WaitCondVar(cv, interval) == PR_SUCCESS);
  }
  PR_Unlock(ml);

  timein = PR_IntervalNow();
  PR_DestroyCondVar(cv);
  PR_DestroyLock(ml);
  overhead += (PR_IntervalNow() - timein);

  return overhead;
/* ConditionTimeout */

typedef struct AlarmData {
  PRLock* ml;
  PRCondVar* cv;
  PRUint32 rate, late, times;
  PRIntervalTime duration, timein, period;
} AlarmData;

static PRBool AlarmFn1(PRAlarmID* id, void* clientData, PRUint32 late) {
  PRStatus rv = PR_SUCCESS;
  PRBool keepGoing, resetAlarm;
  PRIntervalTime interval, now = PR_IntervalNow();
  AlarmData* ad = (AlarmData*)clientData;

  PR_Lock(ad->ml);
  ad->late += late;
  ad->times += 1;
  keepGoing =
      ((PRIntervalTime)(now - ad->timein) < ad->duration) ? PR_TRUE : PR_FALSE;
  if (!keepGoing) {
    rv = PR_NotifyCondVar(ad->cv);
  }
  resetAlarm = ((ad->times % 31) == 0) ? PR_TRUE : PR_FALSE;

  interval = (ad->period + ad->rate - 1) / ad->rate;
  if (!late && (interval > 10)) {
    interval &= (now & 0x03) + 1;
    PR_WaitCondVar(ad->cv, interval);
  }

  PR_Unlock(ad->ml);

  if (rv != PR_SUCCESS) {
    if (!debug_mode) {
      failed_already = 1;
    } else {
      printf("AlarmFn: notify status: FAIL\n");
    }
  }

  if (resetAlarm) {
    ad->rate += 3;
    ad->late = ad->times = 0;
    if (PR_ResetAlarm(id, ad->period, ad->rate) != PR_SUCCESS) {
      if (!debug_mode) {
        failed_already = 1;
      } else {
        printf("AlarmFn: Resetting alarm status: FAIL\n");
      }

      keepGoing = PR_FALSE;
    }
  }

  return keepGoing;
/* AlarmFn1 */

static PRIntervalTime Alarms1(PRUint32 loops) {
  PRAlarm* alarm;
  AlarmData ad;
  PRIntervalTime overhead, timein = PR_IntervalNow();
  PRIntervalTime duration = PR_SecondsToInterval(3);

  PRLock* ml = PR_NewLock();
  PRCondVar* cv = PR_NewCondVar(ml);

  ad.ml = ml;
  ad.cv = cv;
  ad.rate = 1;
  ad.times = loops;
  ad.late = ad.times = 0;
  ad.duration = duration;
  ad.timein = PR_IntervalNow();
  ad.period = PR_SecondsToInterval(1);

  alarm = PR_CreateAlarm();

  (void)PR_SetAlarm(alarm, ad.period, ad.rate, AlarmFn1, &ad);

  overhead = PR_IntervalNow() - timein;

  PR_Lock(ml);
  while ((PRIntervalTime)(PR_IntervalNow() - ad.timein) < duration) {
    PR_WaitCondVar(cv, PR_INTERVAL_NO_TIMEOUT);
  }
  PR_Unlock(ml);

  timein = PR_IntervalNow();
  (void)PR_DestroyAlarm(alarm);
  PR_DestroyCondVar(cv);
  PR_DestroyLock(ml);
  overhead += (PR_IntervalNow() - timein);

  return duration + overhead;
/* Alarms1 */

static PRBool AlarmFn2(PRAlarmID* id, void* clientData, PRUint32 late) {
  PRBool keepGoing;
  PRStatus rv = PR_SUCCESS;
  AlarmData* ad = (AlarmData*)clientData;
  PRIntervalTime interval, now = PR_IntervalNow();

  PR_Lock(ad->ml);
  ad->times += 1;
  keepGoing =
      ((PRIntervalTime)(now - ad->timein) < ad->duration) ? PR_TRUE : PR_FALSE;
  interval = (ad->period + ad->rate - 1) / ad->rate;

  if (!late && (interval > 10)) {
    interval &= (now & 0x03) + 1;
    PR_WaitCondVar(ad->cv, interval);
  }

  if (!keepGoing) {
    rv = PR_NotifyCondVar(ad->cv);
  }

  PR_Unlock(ad->ml);

  if (rv != PR_SUCCESS) {
    failed_already = 1;
  };

  return keepGoing;
/* AlarmFn2 */

static PRIntervalTime Alarms2(PRUint32 loops) {
  PRStatus rv;
  PRAlarm* alarm;
  PRIntervalTime overhead, timein = PR_IntervalNow();
  AlarmData ad;
  PRIntervalTime duration = PR_SecondsToInterval(30);

  PRLock* ml = PR_NewLock();
  PRCondVar* cv = PR_NewCondVar(ml);

  ad.ml = ml;
  ad.cv = cv;
  ad.rate = 1;
  ad.times = loops;
  ad.late = ad.times = 0;
  ad.duration = duration;
  ad.timein = PR_IntervalNow();
  ad.period = PR_SecondsToInterval(1);

  alarm = PR_CreateAlarm();

  (void)PR_SetAlarm(alarm, ad.period, ad.rate, AlarmFn2, &ad);

  overhead = PR_IntervalNow() - timein;

  PR_Lock(ml);
  while ((PRIntervalTime)(PR_IntervalNow() - ad.timein) < duration) {
    PR_WaitCondVar(cv, PR_INTERVAL_NO_TIMEOUT);
  }
  PR_Unlock(ml);

  timein = PR_IntervalNow();

  rv = PR_DestroyAlarm(alarm);
  if (rv != PR_SUCCESS) {
    if (!debug_mode) {
      failed_already = 1;
    } else {
      printf("***Destroying alarm status: FAIL\n");
    }
  }

  PR_DestroyCondVar(cv);
  PR_DestroyLock(ml);

  overhead += (PR_IntervalNow() - timein);

  return duration + overhead;
/* Alarms2 */

static PRIntervalTime Alarms3(PRUint32 loops) {
  PRIntn i;
  PRStatus rv;
  PRAlarm* alarm;
  AlarmData ad[3];
  PRIntervalTime duration = PR_SecondsToInterval(30);
  PRIntervalTime overhead, timein = PR_IntervalNow();

  PRLock* ml = PR_NewLock();
  PRCondVar* cv = PR_NewCondVar(ml);

  for (i = 0; i < 3; ++i) {
    ad[i].ml = ml;
    ad[i].cv = cv;
    ad[i].rate = 1;
    ad[i].times = loops;
    ad[i].duration = duration;
    ad[i].late = ad[i].times = 0;
    ad[i].timein = PR_IntervalNow();
    ad[i].period = PR_SecondsToInterval(1);

    /* more loops, faster rate => same elapsed time */
    ad[i].times = (i + 1) * loops;
    ad[i].rate = (i + 1) * 10;
  }

  alarm = PR_CreateAlarm();

  for (i = 0; i < 3; ++i) {
    (void)PR_SetAlarm(alarm, ad[i].period, ad[i].rate, AlarmFn2, &ad[i]);
  }

  overhead = PR_IntervalNow() - timein;

  PR_Lock(ml);
  for (i = 0; i < 3; ++i) {
    while ((PRIntervalTime)(PR_IntervalNow() - ad[i].timein) < duration) {
      PR_WaitCondVar(cv, PR_INTERVAL_NO_TIMEOUT);
    }
  }
  PR_Unlock(ml);

  timein = PR_IntervalNow();

  if (debug_mode)
    printf("Alarms3 finished at %u, %u, %u\n", ad[0].timein, ad[1].timein,
           ad[2].timein);

  rv = PR_DestroyAlarm(alarm);
  if (rv != PR_SUCCESS) {
    if (!debug_mode) {
      failed_already = 1;
    } else {
      printf("***Destroying alarm status: FAIL\n");
    }
  }
  PR_DestroyCondVar(cv);
  PR_DestroyLock(ml);

  overhead += (duration / 3);
  overhead += (PR_IntervalNow() - timein);

  return overhead;
/* Alarms3 */

static PRUint32 TimeThis(const char* msg, PRUint32 (*func)(PRUint32 loops),
                         PRUint32 loops) {
  PRUint32 overhead, usecs;
  PRIntervalTime predicted, timein, timeout, ticks;

  if (debug_mode) {
    printf("Testing %s ...", msg);
  }

  timein = PR_IntervalNow();
  predicted = func(loops);
  timeout = PR_IntervalNow();

  if (debug_mode) {
    printf(" done\n");
  }

  ticks = timeout - timein;
  usecs = PR_IntervalToMicroseconds(ticks);
  overhead = PR_IntervalToMicroseconds(predicted);

  if (ticks < predicted) {
    if (debug_mode) {
      printf("\tFinished in negative time\n");
      printf("\tpredicted overhead was %d usecs\n", overhead);
      printf("\ttest completed in %d usecs\n\n", usecs);
    }
  } else {
    if (debug_mode)
      printf("\ttotal: %d usecs\n\toverhead: %d usecs\n\tcost: %6.3f usecs\n\n",
             usecs, overhead, ((double)(usecs - overhead) / (double)loops));
  }

  return overhead;
/* TimeThis */

int prmain(int argc, char** argv) {
  PRUint32 cpu, cpus = 0, loops = 0;

  /* The command line argument: -d is used to determine if the test is being run
  in debug mode. The regress tool requires only one line output:PASS or FAIL.
  All of the printfs associated with this test has been handled with a if
  (debug_mode) test. Usage: test_name [-d]
  */

  PLOptStatus os;
  PLOptState* opt = PL_CreateOptState(argc, argv, "Gdl:c:");
  while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) {
    if (PL_OPT_BAD == os) {
      continue;
    }
    switch (opt->option) {
      case 'G'/* GLOBAL threads */
        thread_scope = PR_GLOBAL_THREAD;
        break;
      case 'd'/* debug mode */
        debug_mode = 1;
        break;
      case 'l'/* loop count */
        loops = atoi(opt->value);
        break;
      case 'c'/* concurrency limit */
        cpus = atoi(opt->value);
        break;
      default:
        break;
    }
  }
  PL_DestroyOptState(opt);

  if (cpus == 0) {
    cpus = 1;
  }
  if (loops == 0) {
    loops = 4;
  }

  if (debug_mode) {
    printf("Alarm: Using %d loops\n", loops);
  }

  if (debug_mode) {
    printf("Alarm: Using %d cpu(s)\n", cpus);
  }

  for (cpu = 1; cpu <= cpus; ++cpu) {
    if (debug_mode) {
      printf("\nAlarm: Using %d CPU(s)\n", cpu);
    }

    PR_SetConcurrency(cpu);

    /* some basic time test */
    (void)TimeThis("ConditionNotify", ConditionNotify, loops);
    (void)TimeThis("ConditionTimeout", ConditionTimeout, loops);
    (void)TimeThis("Alarms1", Alarms1, loops);
    (void)TimeThis("Alarms2", Alarms2, loops);
    (void)TimeThis("Alarms3", Alarms3, loops);
  }
  return 0;
}

int main(int argc, char** argv) {
  PR_Initialize(prmain, argc, argv, 0);
  PR_STDIO_INIT();
  if (failed_already) {
    return 1;
  } else {
    return 0;
  }

/* main */

/* alarmtst.c */

Messung V0.5
C=95 H=77 G=86

¤ Dauer der Verarbeitung: 0.1 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.