t_timers.c revision dafcb997e390efa4423883dafd100c975c4095d6
/*
* Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: t_timers.c,v 1.23 2004/03/05 05:04:12 marka Exp $ */
#include <config.h>
#include <stdlib.h>
#include <isc/condition.h>
#include <isc/platform.h>
#ifdef ISC_PLATFORM_USETHREADS
#else
#endif
#define Tx_FUDGE_SECONDS 0 /* in absence of clock_getres() */
static isc_time_t Tx_endtime;
static isc_time_t Tx_lasttime;
static int Tx_eventcnt;
static int Tx_nevents;
static isc_mutex_t Tx_mx;
static isc_condition_t Tx_cv;
static int Tx_nfails;
static int Tx_nprobs;
static isc_timer_t *Tx_timer;
static int Tx_seconds;
static int Tx_nanoseconds;
static void
require_threads(void) {
t_info("This test requires threads\n");
return;
}
static void
/*
* Signal shutdown processing complete.
*/
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_mutex_lock failed %s\n",
++Tx_nprobs;
}
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_condition_signal failed %s\n",
++Tx_nprobs;
}
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_mutex_unlock failed %s\n",
++Tx_nprobs;
}
}
static void
++Tx_eventcnt;
t_info("expected event type %d, got %d\n",
++Tx_nfails;
}
if (isc_result == ISC_R_SUCCESS) {
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_time_add failed %s\n",
++Tx_nprobs;
}
} else {
t_info("isc_time_now failed %s\n",
++Tx_nprobs;
}
if (isc_result == ISC_R_SUCCESS) {
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_time_add failed %s\n",
++Tx_nprobs;
}
}
if (isc_result == ISC_R_SUCCESS) {
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_time_subtract failed %s\n",
++Tx_nprobs;
}
}
if (isc_result == ISC_R_SUCCESS) {
t_info("timer range error: early by "
"%lu microseconds\n",
++Tx_nfails;
t_info("timer range error: late by "
"%lu microseconds\n",
++Tx_nfails;
}
Tx_lasttime = now;
}
if (Tx_eventcnt == Tx_nevents) {
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_time_now failed %s\n",
++Tx_nprobs;
}
}
}
static void
{
char *p;
unsigned int workers;
Tx_eventcnt = 0;
workers = 2;
p = t_getenv("ISC_TASK_WORKERS");
if (p != NULL)
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_mem_create failed %s\n",
++Tx_nprobs;
return;
}
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_mutex_init failed %s\n",
++Tx_nprobs;
return;
}
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_condition_init failed %s\n",
DESTROYLOCK(&Tx_mx);
++Tx_nprobs;
return;
}
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_taskmgr_create failed %s\n",
DESTROYLOCK(&Tx_mx);
++Tx_nprobs;
return;
}
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_timermgr_create failed %s\n",
DESTROYLOCK(&Tx_mx);
++Tx_nprobs;
return;
}
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_mutex_lock failed %s\n",
DESTROYLOCK(&Tx_mx);
++Tx_nprobs;
return;
}
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_task_create failed %s\n",
DESTROYLOCK(&Tx_mx);
++Tx_nprobs;
return;
}
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_task_onshutdown failed %s\n",
DESTROYLOCK(&Tx_mx);
++Tx_nprobs;
return;
}
if (isc_result != ISC_R_SUCCESS) {
DESTROYLOCK(&Tx_mx);
++Tx_nprobs;
return;
}
&Tx_timer);
if (isc_result != ISC_R_SUCCESS) {
DESTROYLOCK(&Tx_mx);
++Tx_nprobs;
return;
}
/*
* Wait for shutdown processing to complete.
*/
while (Tx_eventcnt != Tx_nevents) {
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_condition_waituntil failed %s\n",
++Tx_nprobs;
}
}
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_mutex_unlock failed %s\n",
++Tx_nprobs;
}
DESTROYLOCK(&Tx_mx);
}
#define T1_SECONDS 2
#define T1_NANOSECONDS 500000000
static const char *a1 =
"When type is isc_timertype_ticker, a call to isc_timer_create() "
"creates a timer that posts an ISC_TIMEREVENT_TICK event to the "
"specified task every 'interval' seconds and returns ISC_R_SUCCESS.";
static void
t1(void) {
int result;
if (threaded) {
Tx_nfails = 0;
Tx_nprobs = 0;
Tx_nevents = 12;
else if (Tx_nfails)
} else
}
#define T2_SECONDS 5
#define T2_NANOSECONDS 300000000;
static const char *a2 =
"When type is isc_timertype_once, a call to isc_timer_create() "
"creates a timer that posts an ISC_TIMEEVENT_LIFE event to the "
"specified task when the current time reaches or exceeds the time "
"specified by 'expires'.";
static void
t2(void) {
int result;
int isc_result;
if (threaded) {
Tx_nfails = 0;
Tx_nprobs = 0;
Tx_nevents = 1;
if (isc_result == ISC_R_SUCCESS) {
isc_interval_set(&interval, 0, 0);
tx_te);
} else {
t_info("isc_time_nowplusinterval failed %s\n",
}
else if (Tx_nfails)
} else
}
static void
++Tx_eventcnt;
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_time_now failed %s\n",
++Tx_nprobs;
}
if (isc_result == ISC_R_SUCCESS) {
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_time_add failed %s\n",
++Tx_nprobs;
}
}
if (isc_result == ISC_R_SUCCESS) {
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_time_add failed %s\n",
++Tx_nprobs;
}
}
if (isc_result == ISC_R_SUCCESS) {
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_time_subtract failed %s\n",
++Tx_nprobs;
}
}
if (isc_result == ISC_R_SUCCESS) {
t_info("timer range error: early by "
"%lu microseconds\n",
++Tx_nfails;
t_info("timer range error: late by "
"%lu microseconds\n",
++Tx_nfails;
}
Tx_lasttime = now;
}
t_info("received event type %d, expected type %d\n",
++Tx_nfails;
}
}
#define T3_SECONDS 4
#define T3_NANOSECONDS 400000000
static const char *a3 =
"When type is isc_timertype_once, a call to isc_timer_create() "
"creates a timer that posts an ISC_TIMEEVENT_IDLE event to the "
"specified task when the timer has been idle for 'interval' seconds.";
static void
t3(void) {
int result;
int isc_result;
if (threaded) {
Tx_nfails = 0;
Tx_nprobs = 0;
Tx_nevents = 1;
if (isc_result == ISC_R_SUCCESS) {
t3_te);
} else {
t_info("isc_time_nowplusinterval failed %s\n",
++Tx_nprobs;
}
else if (Tx_nfails)
} else
}
#define T4_SECONDS 2
#define T4_NANOSECONDS 500000000
static void
++Tx_eventcnt;
/*
* Check expired time.
*/
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_time_now failed %s\n",
++Tx_nprobs;
}
if (isc_result == ISC_R_SUCCESS) {
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_time_add failed %s\n",
++Tx_nprobs;
}
}
if (isc_result == ISC_R_SUCCESS) {
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_time_add failed %s\n",
++Tx_nprobs;
}
}
if (isc_result == ISC_R_SUCCESS) {
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_time_subtract failed %s\n",
++Tx_nprobs;
}
}
if (isc_result == ISC_R_SUCCESS) {
t_info("timer range error: early by "
"%lu microseconds\n",
++Tx_nfails;
t_info("timer range error: late by "
"%lu microseconds\n",
++Tx_nfails;
}
Tx_lasttime = now;
}
if (Tx_eventcnt < 3) {
t_info("received event type %d, expected type %d\n",
++Tx_nfails;
}
if (Tx_eventcnt == 2) {
&interval);
if (isc_result == ISC_R_SUCCESS) {
isc_interval_set(&interval, 0, 0);
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_timer_reset failed %s\n",
++Tx_nfails;
}
} else {
t_info("isc_time_nowplusinterval failed %s\n",
++Tx_nprobs;
}
}
} else {
t_info("received event type %d, expected type %d\n",
++Tx_nfails;
}
}
}
static const char *a4 =
"A call to isc_timer_reset() changes the timer's type, expires and "
"interval values to the given values.";
static void
t4(void) {
int result;
if (threaded) {
Tx_nfails = 0;
Tx_nprobs = 0;
Tx_nevents = 3;
else if (Tx_nfails)
} else
}
#define T5_NTICKS 4
#define T5_SECONDS 3
static int T5_startflag;
static int T5_shutdownflag;
static int T5_eventcnt;
static isc_mutex_t T5_mx;
static isc_condition_t T5_cv;
static int T5_nfails;
static int T5_nprobs;
static isc_timer_t *T5_tickertimer;
static isc_timer_t *T5_oncetimer;
static isc_task_t *T5_task1;
static isc_task_t *T5_task2;
/*
* T5_task1 blocks on T5_mx while events accumulate
* in it's queue, until signaled by T5_task2.
*/
static void
t_info("t5_start_event\n");
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_mutex_lock failed %s\n",
++T5_nprobs;
}
while (! T5_startflag) {
}
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_mutex_unlock failed %s\n",
++T5_nprobs;
}
}
static void
++T5_eventcnt;
/*
* On the first tick, purge all remaining tick events
* and then shut down the task.
*/
if (T5_eventcnt == 1) {
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_timer_reset failed %s\n",
++T5_nfails;
}
}
}
static void
t_info("t5_once_event\n");
/*
* Allow task1 to start processing events.
*/
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_mutex_lock failed %s\n",
++T5_nprobs;
}
T5_startflag = 1;
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_condition_broadcast failed %s\n",
++T5_nprobs;
}
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_mutex_unlock failed %s\n",
++T5_nprobs;
}
}
static void
t_info("t5_shutdown_event\n");
/*
* Signal shutdown processing complete.
*/
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_mutex_lock failed %s\n",
++T5_nprobs;
}
T5_shutdownflag = 1;
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_condition_signal failed %s\n",
++T5_nprobs;
}
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_mutex_unlock failed %s\n",
++T5_nprobs;
}
}
static int
t_timers5(void) {
char *p;
int result;
unsigned int workers;
T5_startflag = 0;
T5_shutdownflag = 0;
T5_eventcnt = 0;
workers = 2;
p = t_getenv("ISC_TASK_WORKERS");
if (p != NULL)
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_mem_create failed %s\n",
return(T_UNRESOLVED);
}
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_mutex_init failed %s\n",
return(T_UNRESOLVED);
}
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_condition_init failed %s\n",
DESTROYLOCK(&T5_mx);
return(T_UNRESOLVED);
}
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_taskmgr_create failed %s\n",
DESTROYLOCK(&T5_mx);
return(T_UNRESOLVED);
}
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_timermgr_create failed %s\n",
DESTROYLOCK(&T5_mx);
return(T_UNRESOLVED);
}
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_task_create failed %s\n",
DESTROYLOCK(&T5_mx);
return(T_UNRESOLVED);
}
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_task_onshutdown failed %s\n",
DESTROYLOCK(&T5_mx);
return(T_UNRESOLVED);
}
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_task_create failed %s\n",
DESTROYLOCK(&T5_mx);
return(T_UNRESOLVED);
}
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_mutex_lock failed %s\n",
DESTROYLOCK(&T5_mx);
return(T_UNRESOLVED);
}
if (isc_result != ISC_R_SUCCESS) {
(void) isc_condition_signal(&T5_cv);
(void) isc_mutex_unlock(&T5_mx);
DESTROYLOCK(&T5_mx);
return(T_UNRESOLVED);
}
T5_oncetimer = NULL;
if (isc_result != ISC_R_SUCCESS) {
(void)isc_condition_signal(&T5_cv);
(void)isc_mutex_unlock(&T5_mx);
DESTROYLOCK(&T5_mx);
return(T_UNRESOLVED);
}
isc_interval_set(&interval, 0, 0);
if (isc_result != ISC_R_SUCCESS) {
(void) isc_condition_signal(&T5_cv);
(void) isc_mutex_unlock(&T5_mx);
DESTROYLOCK(&T5_mx);
++T5_nprobs;
return(T_UNRESOLVED);
}
/*
* Wait for shutdown processing to complete.
*/
while (! T5_shutdownflag) {
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_condition_waituntil failed %s\n",
++T5_nprobs;
}
}
if (isc_result != ISC_R_SUCCESS) {
t_info("isc_mutex_unlock failed %s\n",
++T5_nprobs;
}
if (T5_eventcnt != 1) {
++T5_nfails;
}
DESTROYLOCK(&T5_mx);
else if (T5_nfails)
return (result);
}
static const char *a5 =
"When 'purge' is TRUE, a call to isc_timer_reset() purges any pending "
"events from 'timer' from the task's event queue.";
static void
t5(void) {
if (threaded)
else
}
testspec_t T_testlist[] = {
{ t1, "timer_create" },
{ t2, "timer_create" },
{ t3, "timer_create" },
{ t4, "timer_reset" },
{ t5, "timer_reset" },
};