⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 timer.c

📁 bind 9.3结合mysql数据库
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (C) 2004  Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2002  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: timer.c,v 1.64.12.9 2004/03/08 09:04:50 marka Exp $ */#include <config.h>#include <isc/condition.h>#include <isc/heap.h>#include <isc/log.h>#include <isc/magic.h>#include <isc/mem.h>#include <isc/msgs.h>#include <isc/platform.h>#include <isc/task.h>#include <isc/thread.h>#include <isc/time.h>#include <isc/timer.h>#include <isc/util.h>#ifndef ISC_PLATFORM_USETHREADS#include "timer_p.h"#endif /* ISC_PLATFORM_USETHREADS */#ifdef ISC_TIMER_TRACE#define XTRACE(s)			fprintf(stderr, "%s\n", (s))#define XTRACEID(s, t)			fprintf(stderr, "%s %p\n", (s), (t))#define XTRACETIME(s, d)		fprintf(stderr, "%s %u.%09u\n", (s), \					       (d).seconds, (d).nanoseconds)#define XTRACETIME2(s, d, n)		fprintf(stderr, "%s %u.%09u %u.%09u\n", (s), \					       (d).seconds, (d).nanoseconds, (n).seconds, (n).nanoseconds)#define XTRACETIMER(s, t, d)		fprintf(stderr, "%s %p %u.%09u\n", (s), (t), \					       (d).seconds, (d).nanoseconds)#else#define XTRACE(s)#define XTRACEID(s, t)#define XTRACETIME(s, d)#define XTRACETIME2(s, d, n)#define XTRACETIMER(s, t, d)#endif /* ISC_TIMER_TRACE */#define TIMER_MAGIC			ISC_MAGIC('T', 'I', 'M', 'R')#define VALID_TIMER(t)			ISC_MAGIC_VALID(t, TIMER_MAGIC)struct isc_timer {	/* Not locked. */	unsigned int			magic;	isc_timermgr_t *		manager;	isc_mutex_t			lock;	/* Locked by timer lock. */	unsigned int			references;	isc_time_t			idle;	/* Locked by manager lock. */	isc_timertype_t			type;	isc_time_t			expires;	isc_interval_t			interval;	isc_task_t *			task;	isc_taskaction_t		action;	void *				arg;	unsigned int			index;	isc_time_t			due;	LINK(isc_timer_t)		link;};#define TIMER_MANAGER_MAGIC		ISC_MAGIC('T', 'I', 'M', 'M')#define VALID_MANAGER(m)		ISC_MAGIC_VALID(m, TIMER_MANAGER_MAGIC)struct isc_timermgr {	/* Not locked. */	unsigned int			magic;	isc_mem_t *			mctx;	isc_mutex_t			lock;	/* Locked by manager lock. */	isc_boolean_t			done;	LIST(isc_timer_t)		timers;	unsigned int			nscheduled;	isc_time_t			due;#ifdef ISC_PLATFORM_USETHREADS	isc_condition_t			wakeup;	isc_thread_t			thread;#else /* ISC_PLATFORM_USETHREADS */	unsigned int			refs;#endif /* ISC_PLATFORM_USETHREADS */	isc_heap_t *			heap;};#ifndef ISC_PLATFORM_USETHREADS/* * If threads are not in use, there can be only one. */static isc_timermgr_t *timermgr = NULL;#endif /* ISC_PLATFORM_USETHREADS */static inline isc_result_tschedule(isc_timer_t *timer, isc_time_t *now, isc_boolean_t signal_ok) {	isc_result_t result;	isc_timermgr_t *manager;	isc_time_t due;	int cmp;#ifdef ISC_PLATFORM_USETHREADS	isc_boolean_t timedwait;#endif	/*	 * Note: the caller must ensure locking.	 */	REQUIRE(timer->type != isc_timertype_inactive);#ifndef ISC_PLATFORM_USETHREADS	UNUSED(signal_ok);#endif /* ISC_PLATFORM_USETHREADS */	manager = timer->manager;#ifdef ISC_PLATFORM_USETHREADS	/*	 * If the manager was timed wait, we may need to signal the	 * manager to force a wakeup.	 */	timedwait = ISC_TF(manager->nscheduled > 0 &&			   isc_time_seconds(&manager->due) != 0);#endif	/*	 * Compute the new due time.	 */	if (timer->type != isc_timertype_once) {		result = isc_time_add(now, &timer->interval, &due);		if (result != ISC_R_SUCCESS)			return (result);		if (timer->type == isc_timertype_limited &&		    isc_time_compare(&timer->expires, &due) < 0)			due = timer->expires;	} else {		if (isc_time_isepoch(&timer->idle))			due = timer->expires;		else if (isc_time_isepoch(&timer->expires))			due = timer->idle;		else if (isc_time_compare(&timer->idle, &timer->expires) < 0)			due = timer->idle;		else			due = timer->expires;	}	/*	 * Schedule the timer.	 */	if (timer->index > 0) {		/*		 * Already scheduled.		 */		cmp = isc_time_compare(&due, &timer->due);		timer->due = due;		switch (cmp) {		case -1:			isc_heap_increased(manager->heap, timer->index);			break;		case 1:			isc_heap_decreased(manager->heap, timer->index);			break;		case 0:			/* Nothing to do. */			break;		}	} else {		timer->due = due;		result = isc_heap_insert(manager->heap, timer);		if (result != ISC_R_SUCCESS) {			INSIST(result == ISC_R_NOMEMORY);			return (ISC_R_NOMEMORY);		}		manager->nscheduled++;	}	XTRACETIMER(isc_msgcat_get(isc_msgcat, ISC_MSGSET_TIMER,				   ISC_MSG_SCHEDULE, "schedule"), timer, due);	/*	 * If this timer is at the head of the queue, we need to ensure	 * that we won't miss it if it has a more recent due time than	 * the current "next" timer.  We do this either by waking up the	 * run thread, or explicitly setting the value in the manager.	 */#ifdef ISC_PLATFORM_USETHREADS	/*	 * This is a temporary (probably) hack to fix a bug on tru64 5.1	 * and 5.1a.  Sometimes, pthread_cond_timedwait() doesn't actually	 * return when the time expires, so here, we check to see if	 * we're 15 seconds or more behind, and if we are, we signal	 * the dispatcher.  This isn't such a bad idea as a general purpose	 * watchdog, so perhaps we should just leave it in here.	 */	if (signal_ok && timedwait) {		isc_interval_t fifteen;		isc_time_t then;		isc_interval_set(&fifteen, 15, 0);		isc_time_add(&manager->due, &fifteen, &then);		if (isc_time_compare(&then, now) < 0) {			SIGNAL(&manager->wakeup);			signal_ok = ISC_FALSE;			isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,				      ISC_LOGMODULE_TIMER, ISC_LOG_WARNING,				      "*** POKED TIMER ***");		}	}			if (timer->index == 1 && signal_ok) {		XTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_TIMER,				      ISC_MSG_SIGNALSCHED,				      "signal (schedule)"));		SIGNAL(&manager->wakeup);	}#else /* ISC_PLATFORM_USETHREADS */	if (timer->index == 1 &&	    isc_time_compare(&timer->due, &manager->due) < 0)		manager->due = timer->due;#endif /* ISC_PLATFORM_USETHREADS */	return (ISC_R_SUCCESS);}static inline voiddeschedule(isc_timer_t *timer) {	isc_boolean_t need_wakeup = ISC_FALSE;	isc_timermgr_t *manager;	/*	 * The caller must ensure locking.	 */	manager = timer->manager;	if (timer->index > 0) {		if (timer->index == 1)			need_wakeup = ISC_TRUE;		isc_heap_delete(manager->heap, timer->index);		timer->index = 0;		INSIST(manager->nscheduled > 0);		manager->nscheduled--;#ifdef ISC_PLATFORM_USETHREADS		if (need_wakeup) {			XTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_TIMER,					      ISC_MSG_SIGNALDESCHED,					      "signal (deschedule)"));			SIGNAL(&manager->wakeup);		}#endif /* ISC_PLATFORM_USETHREADS */	}}static voiddestroy(isc_timer_t *timer) {	isc_timermgr_t *manager = timer->manager;	/*	 * The caller must ensure it is safe to destroy the timer.	 */	LOCK(&manager->lock);	(void)isc_task_purgerange(timer->task,				  timer,				  ISC_TIMEREVENT_FIRSTEVENT,				  ISC_TIMEREVENT_LASTEVENT,				  NULL);	deschedule(timer);	UNLINK(manager->timers, timer, link);	UNLOCK(&manager->lock);	isc_task_detach(&timer->task);	DESTROYLOCK(&timer->lock);	timer->magic = 0;	isc_mem_put(manager->mctx, timer, sizeof(*timer));}isc_result_tisc_timer_create(isc_timermgr_t *manager, isc_timertype_t type,		 isc_time_t *expires, isc_interval_t *interval,		 isc_task_t *task, isc_taskaction_t action, const void *arg,		 isc_timer_t **timerp){	isc_timer_t *timer;	isc_result_t result;	isc_time_t now;	/*	 * Create a new 'type' timer managed by 'manager'.  The timers	 * parameters are specified by 'expires' and 'interval'.  Events	 * will be posted to 'task' and when dispatched 'action' will be	 * called with 'arg' as the arg value.  The new timer is returned	 * in 'timerp'.	 */	REQUIRE(VALID_MANAGER(manager));	REQUIRE(task != NULL);	REQUIRE(action != NULL);	if (expires == NULL)		expires = isc_time_epoch;	if (interval == NULL)		interval = isc_interval_zero;	REQUIRE(type == isc_timertype_inactive ||		!(isc_time_isepoch(expires) && isc_interval_iszero(interval)));	REQUIRE(timerp != NULL && *timerp == NULL);	REQUIRE(type != isc_timertype_limited ||		!(isc_time_isepoch(expires) || isc_interval_iszero(interval)));	/*	 * Get current time.	 */	if (type != isc_timertype_inactive) {		TIME_NOW(&now);	} else {		/*		 * We don't have to do this, but it keeps the compiler from		 * complaining about "now" possibly being used without being		 * set, even though it will never actually happen.		 */		isc_time_settoepoch(&now);	}	timer = isc_mem_get(manager->mctx, sizeof(*timer));	if (timer == NULL)		return (ISC_R_NOMEMORY);	timer->manager = manager;	timer->references = 1;	if (type == isc_timertype_once && !isc_interval_iszero(interval)) {		result = isc_time_add(&now, interval, &timer->idle);		if (result != ISC_R_SUCCESS)			return (result);	} else		isc_time_settoepoch(&timer->idle);	timer->type = type;	timer->expires = *expires;	timer->interval = *interval;	timer->task = NULL;	isc_task_attach(task, &timer->task);	timer->action = action;	/*	 * Removing the const attribute from "arg" is the best of two	 * evils here.  If the timer->arg member is made const, then	 * it affects a great many recipients of the timer event	 * which did not pass in an "arg" that was truly const.	 * Changing isc_timer_create() to not have "arg" prototyped as const,	 * though, can cause compilers warnings for calls that *do*	 * have a truly const arg.  The caller will have to carefully	 * keep track of whether arg started as a true const.	 */	DE_CONST(arg, timer->arg);	timer->index = 0;	if (isc_mutex_init(&timer->lock) != ISC_R_SUCCESS) {		isc_task_detach(&timer->task);		isc_mem_put(manager->mctx, timer, sizeof(*timer));		UNEXPECTED_ERROR(__FILE__, __LINE__,				 "isc_mutex_init() %s",				 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,						ISC_MSG_FAILED, "failed"));		return (ISC_R_UNEXPECTED);	}	ISC_LINK_INIT(timer, link);	timer->magic = TIMER_MAGIC;	LOCK(&manager->lock);	/*	 * Note we don't have to lock the timer like we normally would because	 * there are no external references to it yet.	 */	if (type != isc_timertype_inactive)		result = schedule(timer, &now, ISC_TRUE);	else		result = ISC_R_SUCCESS;	if (result == ISC_R_SUCCESS)		APPEND(manager->timers, timer, link);	UNLOCK(&manager->lock);	if (result != ISC_R_SUCCESS) {		timer->magic = 0;		DESTROYLOCK(&timer->lock);		isc_task_detach(&timer->task);		isc_mem_put(manager->mctx, timer, sizeof(*timer));		return (result);	}	*timerp = timer;	return (ISC_R_SUCCESS);}isc_result_tisc_timer_reset(isc_timer_t *timer, isc_timertype_t type,		isc_time_t *expires, isc_interval_t *interval,		isc_boolean_t purge){	isc_time_t now;	isc_timermgr_t *manager;	isc_result_t result;	/*	 * Change the timer's type, expires, and interval values to the given	 * values.  If 'purge' is ISC_TRUE, any pending events from this timer	 * are purged from its task's event queue.	 */	REQUIRE(VALID_TIMER(timer));	manager = timer->manager;	REQUIRE(VALID_MANAGER(manager));	if (expires == NULL)		expires = isc_time_epoch;	if (interval == NULL)		interval = isc_interval_zero;	REQUIRE(type == isc_timertype_inactive ||		!(isc_time_isepoch(expires) && isc_interval_iszero(interval)));	REQUIRE(type != isc_timertype_limited ||		!(isc_time_isepoch(expires) || isc_interval_iszero(interval)));	/*	 * Get current time.	 */	if (type != isc_timertype_inactive) {		TIME_NOW(&now);	} else {		/*		 * We don't have to do this, but it keeps the compiler from		 * complaining about "now" possibly being used without being		 * set, even though it will never actually happen.		 */		isc_time_settoepoch(&now);	}	manager = timer->manager;	LOCK(&manager->lock);	LOCK(&timer->lock);	if (purge)		(void)isc_task_purgerange(timer->task,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -