diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 16:49:04 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 16:49:04 +0000 |
commit | 16f504a9dca3fe3b70568f67b7d41241ae485288 (patch) | |
tree | c60f36ada0496ba928b7161059ba5ab1ab224f9d /src/libs/xpcom18a4/nsprpub/pr/tests/alarm.c | |
parent | Initial commit. (diff) | |
download | virtualbox-16f504a9dca3fe3b70568f67b7d41241ae485288.tar.xz virtualbox-16f504a9dca3fe3b70568f67b7d41241ae485288.zip |
Adding upstream version 7.0.6-dfsg.upstream/7.0.6-dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/libs/xpcom18a4/nsprpub/pr/tests/alarm.c')
-rw-r--r-- | src/libs/xpcom18a4/nsprpub/pr/tests/alarm.c | 569 |
1 files changed, 569 insertions, 0 deletions
diff --git a/src/libs/xpcom18a4/nsprpub/pr/tests/alarm.c b/src/libs/xpcom18a4/nsprpub/pr/tests/alarm.c new file mode 100644 index 00000000..7af2ed4c --- /dev/null +++ b/src/libs/xpcom18a4/nsprpub/pr/tests/alarm.c @@ -0,0 +1,569 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Netscape Portable Runtime (NSPR). + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998-2000 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/*********************************************************************** +** 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" +#ifdef XP_MAC +#include "pralarm.h" +#else +#include "obsolete/pralarm.h" +#endif +#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 + +#ifdef XP_MAC +#include "prlog.h" +#define printf PR_LogPrint +extern void SetupMacPrintfLog(char *logFile); +#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) +{ +#if defined(XP_MAC) +#pragma unused (id) +#endif + + 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); +#ifdef XP_MAC + SetupMacPrintfLog("alarm.log"); + debug_mode = 1; +#endif + + 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 */ |