ISC_TIMERFUNC_SCOPE void isc__timermgr_destroy(isc_timermgr_t **managerp) { isc__timermgr_t *manager; isc_mem_t *mctx; /* * Destroy a timer manager. */ REQUIRE(managerp != NULL); manager = (isc__timermgr_t *)*managerp; REQUIRE(VALID_MANAGER(manager)); LOCK(&manager->lock); #ifdef USE_SHARED_MANAGER manager->refs--; if (manager->refs > 0) { UNLOCK(&manager->lock); *managerp = NULL; return; } timermgr = NULL; #endif /* USE_SHARED_MANAGER */ #ifndef USE_TIMER_THREAD isc__timermgr_dispatch((isc_timermgr_t *)manager); #endif REQUIRE(EMPTY(manager->timers)); manager->done = ISC_TRUE; #ifdef USE_TIMER_THREAD XTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_TIMER, ISC_MSG_SIGNALDESTROY, "signal (destroy)")); SIGNAL(&manager->wakeup); #endif /* USE_TIMER_THREAD */ UNLOCK(&manager->lock); #ifdef USE_TIMER_THREAD /* * Wait for thread to exit. */ if (isc_thread_join(manager->thread, NULL) != ISC_R_SUCCESS) UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_thread_join() %s", isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, ISC_MSG_FAILED, "failed")); #endif /* USE_TIMER_THREAD */ /* * Clean up. */ #ifdef USE_TIMER_THREAD (void)isc_condition_destroy(&manager->wakeup); #endif /* USE_TIMER_THREAD */ DESTROYLOCK(&manager->lock); isc_heap_destroy(&manager->heap); manager->common.impmagic = 0; manager->common.magic = 0; mctx = manager->mctx; isc_mem_put(mctx, manager, sizeof(*manager)); isc_mem_detach(&mctx); *managerp = NULL; #ifdef USE_SHARED_MANAGER timermgr = NULL; #endif }
/*! * Event loop for nonthreaded programs. */ static isc_result_t evloop() { isc_result_t result; while (!want_shutdown) { int n; isc_time_t when, now; struct timeval tv, *tvp; fd_set *readfds, *writefds; int maxfd; isc_boolean_t readytasks; isc_boolean_t call_timer_dispatch = ISC_FALSE; readytasks = isc__taskmgr_ready(); if (readytasks) { tv.tv_sec = 0; tv.tv_usec = 0; tvp = &tv; call_timer_dispatch = ISC_TRUE; } else { result = isc__timermgr_nextevent(&when); if (result != ISC_R_SUCCESS) tvp = NULL; else { isc_uint64_t us; TIME_NOW(&now); us = isc_time_microdiff(&when, &now); if (us == 0) call_timer_dispatch = ISC_TRUE; tv.tv_sec = us / 1000000; tv.tv_usec = us % 1000000; tvp = &tv; } } isc__socketmgr_getfdsets(&readfds, &writefds, &maxfd); n = select(maxfd, readfds, writefds, NULL, tvp); if (n == 0 || call_timer_dispatch) { /* * We call isc__timermgr_dispatch() only when * necessary, in order to reduce overhead. If the * select() call indicates a timeout, we need the * dispatch. Even if not, if we set the 0-timeout * for the select() call, we need to check the timer * events. In the 'readytasks' case, there may be no * timeout event actually, but there is no other way * to reduce the overhead. * Note that we do not have to worry about the case * where a new timer is inserted during the select() * call, since this loop only runs in the non-thread * mode. */ isc__timermgr_dispatch(); } if (n > 0) (void)isc__socketmgr_dispatch(readfds, writefds, maxfd); (void)isc__taskmgr_dispatch(); if (want_reload) { want_reload = ISC_FALSE; return (ISC_R_RELOAD); } } return (ISC_R_SUCCESS); }
/*! * Event loop for nonthreaded programs. */ static isc_result_t evloop(isc__appctx_t *ctx) { isc_result_t result; while (!ctx->want_shutdown) { int n; isc_time_t when, now; struct timeval tv, *tvp; isc_socketwait_t *swait; isc_boolean_t readytasks; isc_boolean_t call_timer_dispatch = ISC_FALSE; /* * Check the reload (or suspend) case first for exiting the * loop as fast as possible in case: * - the direct call to isc__taskmgr_dispatch() in * isc__app_ctxrun() completes all the tasks so far, * - there is thus currently no active task, and * - there is a timer event */ if (ctx->want_reload) { ctx->want_reload = ISC_FALSE; return (ISC_R_RELOAD); } readytasks = isc__taskmgr_ready(ctx->taskmgr); if (readytasks) { tv.tv_sec = 0; tv.tv_usec = 0; tvp = &tv; call_timer_dispatch = ISC_TRUE; } else { result = isc__timermgr_nextevent(ctx->timermgr, &when); if (result != ISC_R_SUCCESS) tvp = NULL; else { isc_uint64_t us; TIME_NOW(&now); us = isc_time_microdiff(&when, &now); if (us == 0) call_timer_dispatch = ISC_TRUE; tv.tv_sec = us / 1000000; tv.tv_usec = us % 1000000; tvp = &tv; } } swait = NULL; n = isc__socketmgr_waitevents(ctx->socketmgr, tvp, &swait); if (n == 0 || call_timer_dispatch) { /* * We call isc__timermgr_dispatch() only when * necessary, in order to reduce overhead. If the * select() call indicates a timeout, we need the * dispatch. Even if not, if we set the 0-timeout * for the select() call, we need to check the timer * events. In the 'readytasks' case, there may be no * timeout event actually, but there is no other way * to reduce the overhead. * Note that we do not have to worry about the case * where a new timer is inserted during the select() * call, since this loop only runs in the non-thread * mode. */ isc__timermgr_dispatch(ctx->timermgr); } if (n > 0) (void)isc__socketmgr_dispatch(ctx->socketmgr, swait); (void)isc__taskmgr_dispatch(ctx->taskmgr); } return (ISC_R_SUCCESS); }
void isc_timermgr_destroy(isc_timermgr_t **managerp) { isc_timermgr_t *manager; isc_mem_t *mctx; /* * Destroy a timer manager. */ REQUIRE(managerp != NULL); manager = *managerp; REQUIRE(VALID_MANAGER(manager)); LOCK(&manager->lock); #ifndef ISC_PLATFORM_USETHREADS if (manager->refs > 1) { manager->refs--; UNLOCK(&manager->lock); *managerp = NULL; return; } isc__timermgr_dispatch(); #endif /* ISC_PLATFORM_USETHREADS */ REQUIRE(EMPTY(manager->timers)); manager->done = ISC_TRUE; #ifdef ISC_PLATFORM_USETHREADS XTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_TIMER, ISC_MSG_SIGNALDESTROY, "signal (destroy)")); SIGNAL(&manager->wakeup); #endif /* ISC_PLATFORM_USETHREADS */ UNLOCK(&manager->lock); #ifdef ISC_PLATFORM_USETHREADS /* * Wait for thread to exit. */ if (isc_thread_join(manager->thread, NULL) != ISC_R_SUCCESS) UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_thread_join() %s", isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, ISC_MSG_FAILED, "failed")); #endif /* ISC_PLATFORM_USETHREADS */ /* * Clean up. */ #ifdef ISC_PLATFORM_USETHREADS (void)isc_condition_destroy(&manager->wakeup); #endif /* ISC_PLATFORM_USETHREADS */ DESTROYLOCK(&manager->lock); isc_heap_destroy(&manager->heap); manager->magic = 0; mctx = manager->mctx; isc_mem_put(mctx, manager, sizeof(*manager)); isc_mem_detach(&mctx); *managerp = NULL; }