📄 t_timers.c
字号:
/* * 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.22.206.2 2004/06/21 06:57:59 marka Exp $ */#include <config.h>#include <stdlib.h>#include <isc/condition.h>#include <isc/mem.h>#include <isc/platform.h>#include <isc/task.h>#include <isc/time.h>#include <isc/timer.h>#include <isc/util.h>#include <tests/t_api.h>#ifdef ISC_PLATFORM_USETHREADSisc_boolean_t threaded = ISC_TRUE;#elseisc_boolean_t threaded = ISC_FALSE;#endif#define Tx_FUDGE_SECONDS 0 /* in absence of clock_getres() */#define Tx_FUDGE_NANOSECONDS 500000000 /* 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 voidrequire_threads(void) { t_info("This test requires threads\n"); t_result(T_THREADONLY); return;}static voidtx_sde(isc_task_t *task, isc_event_t *event) { isc_result_t isc_result; task = task; event = event; /* * Signal shutdown processing complete. */ isc_result = isc_mutex_lock(&Tx_mx); if (isc_result != ISC_R_SUCCESS) { t_info("isc_mutex_lock failed %s\n", isc_result_totext(isc_result)); ++Tx_nprobs; } isc_result = isc_condition_signal(&Tx_cv); if (isc_result != ISC_R_SUCCESS) { t_info("isc_condition_signal failed %s\n", isc_result_totext(isc_result)); ++Tx_nprobs; } isc_result = isc_mutex_unlock(&Tx_mx); if (isc_result != ISC_R_SUCCESS) { t_info("isc_mutex_unlock failed %s\n", isc_result_totext(isc_result)); ++Tx_nprobs; } isc_event_free(&event);}static voidtx_te(isc_task_t *task, isc_event_t *event) { isc_result_t isc_result; isc_time_t now; isc_time_t base; isc_time_t ulim; isc_time_t llim; isc_interval_t interval; isc_eventtype_t expected_event_type; ++Tx_eventcnt; t_info("tick %d\n", Tx_eventcnt); expected_event_type = ISC_TIMEREVENT_LIFE; if ((isc_timertype_t) event->ev_arg == isc_timertype_ticker) expected_event_type = ISC_TIMEREVENT_TICK; if (event->ev_type != expected_event_type) { t_info("expected event type %d, got %d\n", expected_event_type, (int) event->ev_type); ++Tx_nfails; } isc_result = isc_time_now(&now); if (isc_result == ISC_R_SUCCESS) { interval.seconds = Tx_seconds; interval.nanoseconds = Tx_nanoseconds; isc_result = isc_time_add(&Tx_lasttime, &interval, &base); if (isc_result != ISC_R_SUCCESS) { t_info("isc_time_add failed %s\n", isc_result_totext(isc_result)); ++Tx_nprobs; } } else { t_info("isc_time_now failed %s\n", isc_result_totext(isc_result)); ++Tx_nprobs; } if (isc_result == ISC_R_SUCCESS) { interval.seconds = Tx_FUDGE_SECONDS; interval.nanoseconds = Tx_FUDGE_NANOSECONDS; isc_result = isc_time_add(&base, &interval, &ulim); if (isc_result != ISC_R_SUCCESS) { t_info("isc_time_add failed %s\n", isc_result_totext(isc_result)); ++Tx_nprobs; } } if (isc_result == ISC_R_SUCCESS) { isc_result = isc_time_subtract(&base, &interval, &llim); if (isc_result != ISC_R_SUCCESS) { t_info("isc_time_subtract failed %s\n", isc_result_totext(isc_result)); ++Tx_nprobs; } } if (isc_result == ISC_R_SUCCESS) { if (isc_time_compare(&llim, &now) > 0) { t_info("timer range error: early by " "%lu microseconds\n", (unsigned long)isc_time_microdiff(&base, &now)); ++Tx_nfails; } else if (isc_time_compare(&ulim, &now) < 0) { t_info("timer range error: late by " "%lu microseconds\n", (unsigned long)isc_time_microdiff(&now, &base)); ++Tx_nfails; } Tx_lasttime = now; } if (Tx_eventcnt == Tx_nevents) { isc_result = isc_time_now(&Tx_endtime); if (isc_result != ISC_R_SUCCESS) { t_info("isc_time_now failed %s\n", isc_result_totext(isc_result)); ++Tx_nprobs; } isc_timer_detach(&Tx_timer); isc_task_shutdown(task); } isc_event_free(&event);}static voidt_timers_x(isc_timertype_t timertype, isc_time_t *expires, isc_interval_t *interval, void (*action)(isc_task_t *, isc_event_t *)){ char *p; isc_mem_t *mctx; isc_taskmgr_t *tmgr; isc_task_t *task; unsigned int workers; isc_result_t isc_result; isc_timermgr_t *timermgr; Tx_eventcnt = 0; isc_time_settoepoch(&Tx_endtime); workers = 2; p = t_getenv("ISC_TASK_WORKERS"); if (p != NULL) workers = atoi(p); mctx = NULL; isc_result = isc_mem_create(0, 0, &mctx); if (isc_result != ISC_R_SUCCESS) { t_info("isc_mem_create failed %s\n", isc_result_totext(isc_result)); ++Tx_nprobs; return; } isc_result = isc_mutex_init(&Tx_mx); if (isc_result != ISC_R_SUCCESS) { t_info("isc_mutex_init failed %s\n", isc_result_totext(isc_result)); isc_mem_destroy(&mctx); ++Tx_nprobs; return; } isc_result = isc_condition_init(&Tx_cv); if (isc_result != ISC_R_SUCCESS) { t_info("isc_condition_init failed %s\n", isc_result_totext(isc_result)); DESTROYLOCK(&Tx_mx); isc_mem_destroy(&mctx); ++Tx_nprobs; return; } tmgr = NULL; isc_result = isc_taskmgr_create(mctx, workers, 0, &tmgr); if (isc_result != ISC_R_SUCCESS) { t_info("isc_taskmgr_create failed %s\n", isc_result_totext(isc_result)); DESTROYLOCK(&Tx_mx); isc_condition_destroy(&Tx_cv); isc_mem_destroy(&mctx); ++Tx_nprobs; return; } timermgr = NULL; isc_result = isc_timermgr_create(mctx, &timermgr); if (isc_result != ISC_R_SUCCESS) { t_info("isc_timermgr_create failed %s\n", isc_result_totext(isc_result)); isc_taskmgr_destroy(&tmgr); DESTROYLOCK(&Tx_mx); isc_condition_destroy(&Tx_cv); isc_mem_destroy(&mctx); ++Tx_nprobs; return; } isc_mutex_lock(&Tx_mx); if (isc_result != ISC_R_SUCCESS) { t_info("isc_mutex_lock failed %s\n", isc_result_totext(isc_result)); isc_timermgr_destroy(&timermgr); isc_taskmgr_destroy(&tmgr); DESTROYLOCK(&Tx_mx); isc_condition_destroy(&Tx_cv); isc_mem_destroy(&mctx); ++Tx_nprobs; return; } task = NULL; isc_result = isc_task_create(tmgr, 0, &task); if (isc_result != ISC_R_SUCCESS) { t_info("isc_task_create failed %s\n", isc_result_totext(isc_result)); isc_timermgr_destroy(&timermgr); isc_taskmgr_destroy(&tmgr); DESTROYLOCK(&Tx_mx); isc_condition_destroy(&Tx_cv); isc_mem_destroy(&mctx); ++Tx_nprobs; return; } isc_result = isc_task_onshutdown(task, tx_sde, NULL); if (isc_result != ISC_R_SUCCESS) { t_info("isc_task_onshutdown failed %s\n", isc_result_totext(isc_result)); isc_timermgr_destroy(&timermgr); isc_task_destroy(&task); isc_taskmgr_destroy(&tmgr); DESTROYLOCK(&Tx_mx); isc_condition_destroy(&Tx_cv); isc_mem_destroy(&mctx); ++Tx_nprobs; return; } isc_result = isc_time_now(&Tx_lasttime); if (isc_result != ISC_R_SUCCESS) { isc_timermgr_destroy(&timermgr); isc_task_destroy(&task); isc_taskmgr_destroy(&tmgr); DESTROYLOCK(&Tx_mx); isc_condition_destroy(&Tx_cv); isc_mem_destroy(&mctx); ++Tx_nprobs; return; } Tx_timer = NULL; isc_result = isc_timer_create(timermgr, timertype, expires, interval, task, action, (void *)timertype, &Tx_timer); if (isc_result != ISC_R_SUCCESS) { isc_timermgr_destroy(&timermgr); isc_task_destroy(&task); isc_taskmgr_destroy(&tmgr); DESTROYLOCK(&Tx_mx); isc_condition_destroy(&Tx_cv); isc_mem_destroy(&mctx); ++Tx_nprobs; return; } /* * Wait for shutdown processing to complete. */ while (Tx_eventcnt != Tx_nevents) { isc_result = isc_condition_wait(&Tx_cv, &Tx_mx); if (isc_result != ISC_R_SUCCESS) { t_info("isc_condition_waituntil failed %s\n", isc_result_totext(isc_result)); ++Tx_nprobs; } } isc_result = isc_mutex_unlock(&Tx_mx); if (isc_result != ISC_R_SUCCESS) { t_info("isc_mutex_unlock failed %s\n", isc_result_totext(isc_result)); ++Tx_nprobs; } isc_task_detach(&task); isc_taskmgr_destroy(&tmgr); isc_timermgr_destroy(&timermgr); DESTROYLOCK(&Tx_mx); isc_condition_destroy(&Tx_cv); isc_mem_destroy(&mctx);}#define T1_SECONDS 2#define T1_NANOSECONDS 500000000static 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 voidt1(void) { int result; isc_time_t expires; isc_interval_t interval; t_assert("isc_timer_create", 1, T_REQUIRED, a1); if (threaded) { Tx_nfails = 0; Tx_nprobs = 0; Tx_nevents = 12; Tx_seconds = T1_SECONDS; Tx_nanoseconds = T1_NANOSECONDS; isc_interval_set(&interval, Tx_seconds, Tx_nanoseconds); isc_time_settoepoch(&expires); t_timers_x(isc_timertype_ticker, &expires, &interval, tx_te); result = T_UNRESOLVED; if ((Tx_nfails == 0) && (Tx_nprobs == 0)) result = T_PASS; else if (Tx_nfails) result = T_FAIL; t_result(result); } else require_threads();}#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 voidt2(void) { int result; int isc_result; isc_time_t expires; isc_interval_t interval; t_assert("isc_timer_create", 2, T_REQUIRED, a2); if (threaded) { Tx_nfails = 0; Tx_nprobs = 0; Tx_nevents = 1; Tx_seconds = T2_SECONDS; Tx_nanoseconds = T2_NANOSECONDS; isc_interval_set(&interval, Tx_seconds, Tx_nanoseconds); isc_result = isc_time_nowplusinterval(&expires, &interval); if (isc_result == ISC_R_SUCCESS) { isc_interval_set(&interval, 0, 0); t_timers_x(isc_timertype_once, &expires, &interval, tx_te); } else { t_info("isc_time_nowplusinterval failed %s\n", isc_result_totext(isc_result)); } result = T_UNRESOLVED; if ((Tx_nfails == 0) && (Tx_nprobs == 0)) result = T_PASS; else if (Tx_nfails) result = T_FAIL; t_result(result); } else require_threads();}static voidt3_te(isc_task_t *task, isc_event_t *event) { isc_result_t isc_result; isc_time_t now; isc_time_t base; isc_time_t ulim; isc_time_t llim; isc_interval_t interval; ++Tx_eventcnt; t_info("tick %d\n", Tx_eventcnt); isc_result = isc_time_now(&now); if (isc_result != ISC_R_SUCCESS) { t_info("isc_time_now failed %s\n", isc_result_totext(isc_result)); ++Tx_nprobs; } if (isc_result == ISC_R_SUCCESS) { interval.seconds = Tx_seconds; interval.nanoseconds = Tx_nanoseconds; isc_result = isc_time_add(&Tx_lasttime, &interval, &base); if (isc_result != ISC_R_SUCCESS) { t_info("isc_time_add failed %s\n", isc_result_totext(isc_result)); ++Tx_nprobs; } } if (isc_result == ISC_R_SUCCESS) { interval.seconds = Tx_FUDGE_SECONDS; interval.nanoseconds = Tx_FUDGE_NANOSECONDS; isc_result = isc_time_add(&base, &interval, &ulim); if (isc_result != ISC_R_SUCCESS) { t_info("isc_time_add failed %s\n", isc_result_totext(isc_result)); ++Tx_nprobs; } } if (isc_result == ISC_R_SUCCESS) { isc_result = isc_time_subtract(&base, &interval, &llim); if (isc_result != ISC_R_SUCCESS) { t_info("isc_time_subtract failed %s\n", isc_result_totext(isc_result)); ++Tx_nprobs; } } if (isc_result == ISC_R_SUCCESS) { if (isc_time_compare(&llim, &now) > 0) { t_info("timer range error: early by " "%lu microseconds\n", (unsigned long)isc_time_microdiff(&base, &now)); ++Tx_nfails; } else if (isc_time_compare(&ulim, &now) < 0) { t_info("timer range error: late by " "%lu microseconds\n", (unsigned long)isc_time_microdiff(&now, &base)); ++Tx_nfails; } Tx_lasttime = now; } if (event->ev_type != ISC_TIMEREVENT_IDLE) { t_info("received event type %d, expected type %d\n", event->ev_type, ISC_TIMEREVENT_IDLE); ++Tx_nfails; } isc_timer_detach(&Tx_timer); isc_task_shutdown(task); isc_event_free(&event);}#define T3_SECONDS 4#define T3_NANOSECONDS 400000000static 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 voidt3(void) { int result; int isc_result; isc_time_t expires; isc_interval_t interval; t_assert("isc_timer_create", 3, T_REQUIRED, a3); if (threaded) { Tx_nfails = 0; Tx_nprobs = 0; Tx_nevents = 1; Tx_seconds = T3_SECONDS; Tx_nanoseconds = T3_NANOSECONDS; isc_interval_set(&interval, Tx_seconds + 1, Tx_nanoseconds); isc_result = isc_time_nowplusinterval(&expires, &interval); if (isc_result == ISC_R_SUCCESS) { isc_interval_set(&interval, Tx_seconds, Tx_nanoseconds); t_timers_x(isc_timertype_once, &expires, &interval, t3_te); } else { t_info("isc_time_nowplusinterval failed %s\n", isc_result_totext(isc_result)); ++Tx_nprobs; } result = T_UNRESOLVED; if ((Tx_nfails == 0) && (Tx_nprobs == 0)) result = T_PASS; else if (Tx_nfails) result = T_FAIL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -