static void manager_free(isc_taskmgr_t *manager) { isc_mem_t *mctx; #ifdef ISC_PLATFORM_USETHREADS (void)isc_condition_destroy(&manager->exclusive_granted); (void)isc_condition_destroy(&manager->work_available); isc_mem_free(manager->mctx, manager->threads); #endif /* ISC_PLATFORM_USETHREADS */ DESTROYLOCK(&manager->lock); manager->magic = 0; mctx = manager->mctx; isc_mem_put(mctx, manager, sizeof(*manager)); isc_mem_detach(&mctx); }
/* * Destroy a semaphore. * * sem - semaphore to be destroyed. */ void semaphore_destroy(semaphore_t *sem) { if (sem == NULL) return; RUNTIME_CHECK(isc_mutex_destroy(&sem->mutex) == ISC_R_SUCCESS); RUNTIME_CHECK(isc_condition_destroy(&sem->cond) == ISC_R_SUCCESS); }
static void manager_free(isc__taskmgr_t *manager) { isc_mem_t *mctx; #ifdef USE_WORKER_THREADS (void)isc_condition_destroy(&manager->exclusive_granted); (void)isc_condition_destroy(&manager->work_available); isc_mem_free(manager->mctx, manager->threads); #endif /* USE_WORKER_THREADS */ DESTROYLOCK(&manager->lock); manager->common.impmagic = 0; manager->common.magic = 0; mctx = manager->mctx; isc_mem_put(mctx, manager, sizeof(*manager)); isc_mem_detach(&mctx); #ifdef USE_SHARED_MANAGER taskmgr = NULL; #endif /* USE_SHARED_MANAGER */ }
void isc_rwlock_destroy(isc_rwlock_t *rwl) { REQUIRE(VALID_RWLOCK(rwl)); #if defined(ISC_PLATFORM_HAVEXADD) && defined(ISC_PLATFORM_HAVECMPXCHG) REQUIRE(rwl->write_requests == rwl->write_completions && rwl->cnt_and_flag == 0 && rwl->readers_waiting == 0); #else LOCK(&rwl->lock); REQUIRE(rwl->active == 0 && rwl->readers_waiting == 0 && rwl->writers_waiting == 0); UNLOCK(&rwl->lock); #endif rwl->magic = 0; (void)isc_condition_destroy(&rwl->readable); (void)isc_condition_destroy(&rwl->writeable); DESTROYLOCK(&rwl->lock); }
isc_result_t isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers, unsigned int default_quantum, isc_taskmgr_t **managerp) { isc_result_t result; unsigned int i, started = 0; isc_taskmgr_t *manager; /* * Create a new task manager. */ REQUIRE(workers > 0); REQUIRE(managerp != NULL && *managerp == NULL); #ifndef ISC_PLATFORM_USETHREADS UNUSED(i); UNUSED(started); UNUSED(workers); if (taskmgr != NULL) { taskmgr->refs++; *managerp = taskmgr; return (ISC_R_SUCCESS); } #endif /* ISC_PLATFORM_USETHREADS */ manager = isc_mem_get(mctx, sizeof(*manager)); if (manager == NULL) return (ISC_R_NOMEMORY); manager->magic = TASK_MANAGER_MAGIC; manager->mctx = NULL; result = isc_mutex_init(&manager->lock); if (result != ISC_R_SUCCESS) goto cleanup_mgr; #ifdef ISC_PLATFORM_USETHREADS manager->workers = 0; manager->threads = isc_mem_allocate(mctx, workers * sizeof(isc_thread_t)); if (manager->threads == NULL) { result = ISC_R_NOMEMORY; goto cleanup_lock; } if (isc_condition_init(&manager->work_available) != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_condition_init() %s", isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, ISC_MSG_FAILED, "failed")); result = ISC_R_UNEXPECTED; goto cleanup_threads; } if (isc_condition_init(&manager->exclusive_granted) != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_condition_init() %s", isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, ISC_MSG_FAILED, "failed")); result = ISC_R_UNEXPECTED; goto cleanup_workavailable; } #endif /* ISC_PLATFORM_USETHREADS */ if (default_quantum == 0) default_quantum = DEFAULT_DEFAULT_QUANTUM; manager->default_quantum = default_quantum; INIT_LIST(manager->tasks); INIT_LIST(manager->ready_tasks); manager->tasks_running = 0; manager->exclusive_requested = ISC_FALSE; manager->exiting = ISC_FALSE; isc_mem_attach(mctx, &manager->mctx); #ifdef ISC_PLATFORM_USETHREADS LOCK(&manager->lock); /* * Start workers. */ for (i = 0; i < workers; i++) { if (isc_thread_create(run, manager, &manager->threads[manager->workers]) == ISC_R_SUCCESS) { manager->workers++; started++; } } UNLOCK(&manager->lock); if (started == 0) { manager_free(manager); return (ISC_R_NOTHREADS); } isc_thread_setconcurrency(workers); #else /* ISC_PLATFORM_USETHREADS */ manager->refs = 1; taskmgr = manager; #endif /* ISC_PLATFORM_USETHREADS */ *managerp = manager; return (ISC_R_SUCCESS); #ifdef ISC_PLATFORM_USETHREADS cleanup_workavailable: (void)isc_condition_destroy(&manager->work_available); cleanup_threads: isc_mem_free(mctx, manager->threads); cleanup_lock: DESTROYLOCK(&manager->lock); #endif cleanup_mgr: isc_mem_put(mctx, manager, sizeof(*manager)); return (result); }
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 }
ISC_TIMERFUNC_SCOPE isc_result_t isc__timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp) { isc__timermgr_t *manager; isc_result_t result; /* * Create a timer manager. */ REQUIRE(managerp != NULL && *managerp == NULL); #ifdef USE_SHARED_MANAGER if (timermgr != NULL) { timermgr->refs++; *managerp = (isc_timermgr_t *)timermgr; return (ISC_R_SUCCESS); } #endif /* USE_SHARED_MANAGER */ manager = isc_mem_get(mctx, sizeof(*manager)); if (manager == NULL) return (ISC_R_NOMEMORY); manager->common.impmagic = TIMER_MANAGER_MAGIC; manager->common.magic = ISCAPI_TIMERMGR_MAGIC; manager->common.methods = (isc_timermgrmethods_t *)&timermgrmethods; manager->mctx = NULL; manager->done = ISC_FALSE; INIT_LIST(manager->timers); manager->nscheduled = 0; isc_time_settoepoch(&manager->due); manager->heap = NULL; result = isc_heap_create(mctx, sooner, set_index, 0, &manager->heap); if (result != ISC_R_SUCCESS) { INSIST(result == ISC_R_NOMEMORY); isc_mem_put(mctx, manager, sizeof(*manager)); return (ISC_R_NOMEMORY); } result = isc_mutex_init(&manager->lock); if (result != ISC_R_SUCCESS) { isc_heap_destroy(&manager->heap); isc_mem_put(mctx, manager, sizeof(*manager)); return (result); } isc_mem_attach(mctx, &manager->mctx); #ifdef USE_TIMER_THREAD if (isc_condition_init(&manager->wakeup) != ISC_R_SUCCESS) { isc_mem_detach(&manager->mctx); DESTROYLOCK(&manager->lock); isc_heap_destroy(&manager->heap); isc_mem_put(mctx, manager, sizeof(*manager)); UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_condition_init() %s", isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, ISC_MSG_FAILED, "failed")); return (ISC_R_UNEXPECTED); } if (isc_thread_create(run, manager, &manager->thread) != ISC_R_SUCCESS) { isc_mem_detach(&manager->mctx); (void)isc_condition_destroy(&manager->wakeup); DESTROYLOCK(&manager->lock); isc_heap_destroy(&manager->heap); isc_mem_put(mctx, manager, sizeof(*manager)); UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_thread_create() %s", isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, ISC_MSG_FAILED, "failed")); return (ISC_R_UNEXPECTED); } #endif #ifdef USE_SHARED_MANAGER manager->refs = 1; timermgr = manager; #endif /* USE_SHARED_MANAGER */ *managerp = (isc_timermgr_t *)manager; return (ISC_R_SUCCESS); }
static int t_timers5(void) { char *p; int result; isc_mem_t *mctx; isc_taskmgr_t *tmgr; unsigned int workers; isc_result_t isc_result; isc_timermgr_t *timermgr; isc_event_t *event; isc_time_t expires; isc_interval_t interval; T5_startflag = 0; T5_shutdownflag = 0; T5_eventcnt = 0; 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)); return(T_UNRESOLVED); } isc_result = isc_mutex_init(&T5_mx); if (isc_result != ISC_R_SUCCESS) { t_info("isc_mutex_init failed %s\n", isc_result_totext(isc_result)); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } isc_result = isc_condition_init(&T5_cv); if (isc_result != ISC_R_SUCCESS) { t_info("isc_condition_init failed %s\n", isc_result_totext(isc_result)); DESTROYLOCK(&T5_mx); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } 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(&T5_mx); (void) isc_condition_destroy(&T5_cv); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } 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(&T5_mx); (void) isc_condition_destroy(&T5_cv); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } T5_task1 = NULL; isc_result = isc_task_create(tmgr, 0, &T5_task1); 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(&T5_mx); (void) isc_condition_destroy(&T5_cv); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } isc_result = isc_task_onshutdown(T5_task1, t5_shutdown_event, 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(&T5_task1); isc_taskmgr_destroy(&tmgr); DESTROYLOCK(&T5_mx); (void) isc_condition_destroy(&T5_cv); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } T5_task2 = NULL; isc_result = isc_task_create(tmgr, 0, &T5_task2); if (isc_result != ISC_R_SUCCESS) { t_info("isc_task_create failed %s\n", isc_result_totext(isc_result)); isc_timermgr_destroy(&timermgr); isc_task_destroy(&T5_task1); isc_taskmgr_destroy(&tmgr); DESTROYLOCK(&T5_mx); (void) isc_condition_destroy(&T5_cv); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } isc_result = isc_mutex_lock(&T5_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(&T5_mx); (void) isc_condition_destroy(&T5_cv); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } event = isc_event_allocate(mctx, (void *)1 , (isc_eventtype_t)1, t5_start_event, NULL, sizeof(*event)); isc_task_send(T5_task1, &event); isc_time_settoepoch(&expires); isc_interval_set(&interval, T5_SECONDS, 0); T5_tickertimer = NULL; isc_result = isc_timer_create(timermgr, isc_timertype_ticker, &expires, &interval, T5_task1, t5_tick_event, NULL, &T5_tickertimer); if (isc_result != ISC_R_SUCCESS) { isc_timermgr_destroy(&timermgr); (void) isc_condition_signal(&T5_cv); (void) isc_mutex_unlock(&T5_mx); isc_task_destroy(&T5_task1); isc_task_destroy(&T5_task2); isc_taskmgr_destroy(&tmgr); DESTROYLOCK(&T5_mx); (void) isc_condition_destroy(&T5_cv); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } T5_oncetimer = NULL; isc_interval_set(&interval, (T5_SECONDS * T5_NTICKS) + 2, 0); isc_result = isc_time_nowplusinterval(&expires, &interval); if (isc_result != ISC_R_SUCCESS) { isc_timer_detach(&T5_tickertimer); isc_timermgr_destroy(&timermgr); (void)isc_condition_signal(&T5_cv); (void)isc_mutex_unlock(&T5_mx); isc_task_destroy(&T5_task1); isc_task_destroy(&T5_task2); isc_taskmgr_destroy(&tmgr); DESTROYLOCK(&T5_mx); (void) isc_condition_destroy(&T5_cv); isc_mem_destroy(&mctx); return(T_UNRESOLVED); } isc_interval_set(&interval, 0, 0); isc_result = isc_timer_create(timermgr, isc_timertype_once, &expires, &interval, T5_task2, t5_once_event, NULL, &T5_oncetimer); if (isc_result != ISC_R_SUCCESS) { isc_timer_detach(&T5_tickertimer); isc_timermgr_destroy(&timermgr); (void) isc_condition_signal(&T5_cv); (void) isc_mutex_unlock(&T5_mx); isc_task_destroy(&T5_task1); isc_task_destroy(&T5_task2); isc_taskmgr_destroy(&tmgr); DESTROYLOCK(&T5_mx); (void) isc_condition_destroy(&T5_cv); isc_mem_destroy(&mctx); ++T5_nprobs; return(T_UNRESOLVED); } /* * Wait for shutdown processing to complete. */ while (! T5_shutdownflag) { isc_result = isc_condition_wait(&T5_cv, &T5_mx); if (isc_result != ISC_R_SUCCESS) { t_info("isc_condition_waituntil failed %s\n", isc_result_totext(isc_result)); ++T5_nprobs; } } isc_result = isc_mutex_unlock(&T5_mx); if (isc_result != ISC_R_SUCCESS) { t_info("isc_mutex_unlock failed %s\n", isc_result_totext(isc_result)); ++T5_nprobs; } if (T5_eventcnt != 1) { t_info("processed %d events\n", T5_eventcnt); ++T5_nfails; } isc_timer_detach(&T5_tickertimer); isc_timer_detach(&T5_oncetimer); isc_timermgr_destroy(&timermgr); isc_task_destroy(&T5_task1); isc_task_destroy(&T5_task2); isc_taskmgr_destroy(&tmgr); DESTROYLOCK(&T5_mx); (void) isc_condition_destroy(&T5_cv); isc_mem_destroy(&mctx); result = T_UNRESOLVED; if ((T5_nfails == 0) && (T5_nprobs == 0)) result = T_PASS; else if (T5_nfails) result = T_FAIL; return (result); }
static void t_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); (void) 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); (void) isc_condition_destroy(&Tx_cv); isc_mem_destroy(&mctx); ++Tx_nprobs; return; } 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)); isc_timermgr_destroy(&timermgr); isc_taskmgr_destroy(&tmgr); DESTROYLOCK(&Tx_mx); (void) 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); (void) 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); (void) 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); (void) 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); (void) 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); (void) isc_condition_destroy(&Tx_cv); isc_mem_destroy(&mctx); }
isc_result_t isc_rwlock_init(isc_rwlock_t *rwl, unsigned int read_quota, unsigned int write_quota) { isc_result_t result; REQUIRE(rwl != NULL); /* * In case there's trouble initializing, we zero magic now. If all * goes well, we'll set it to RWLOCK_MAGIC. */ rwl->magic = 0; rwl->spins = 0; #if defined(ISC_PLATFORM_HAVEXADD) && defined(ISC_PLATFORM_HAVECMPXCHG) rwl->write_requests = 0; rwl->write_completions = 0; rwl->cnt_and_flag = 0; rwl->readers_waiting = 0; rwl->write_granted = 0; if (read_quota != 0) { UNEXPECTED_ERROR(__FILE__, __LINE__, "read quota is not supported"); } if (write_quota == 0) write_quota = RWLOCK_DEFAULT_WRITE_QUOTA; rwl->write_quota = write_quota; #else rwl->type = isc_rwlocktype_read; rwl->original = isc_rwlocktype_none; rwl->active = 0; rwl->granted = 0; rwl->readers_waiting = 0; rwl->writers_waiting = 0; if (read_quota == 0) read_quota = RWLOCK_DEFAULT_READ_QUOTA; rwl->read_quota = read_quota; if (write_quota == 0) write_quota = RWLOCK_DEFAULT_WRITE_QUOTA; rwl->write_quota = write_quota; #endif result = isc_mutex_init(&rwl->lock); if (result != ISC_R_SUCCESS) return (result); result = isc_condition_init(&rwl->readable); if (result != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_condition_init(readable) %s: %s", isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, ISC_MSG_FAILED, "failed"), isc_result_totext(result)); result = ISC_R_UNEXPECTED; goto destroy_lock; } result = isc_condition_init(&rwl->writeable); if (result != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_condition_init(writeable) %s: %s", isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, ISC_MSG_FAILED, "failed"), isc_result_totext(result)); result = ISC_R_UNEXPECTED; goto destroy_rcond; } rwl->magic = RWLOCK_MAGIC; return (ISC_R_SUCCESS); destroy_rcond: (void)isc_condition_destroy(&rwl->readable); destroy_lock: DESTROYLOCK(&rwl->lock); return (result); }
isc_result_t isc__app_ctxstart(isc_appctx_t *ctx0) { isc__appctx_t *ctx = (isc__appctx_t *)ctx0; isc_result_t result; int presult; sigset_t sset; char strbuf[ISC_STRERRORSIZE]; REQUIRE(VALID_APPCTX(ctx)); /* * Start an ISC library application. */ #ifdef NEED_PTHREAD_INIT /* * BSDI 3.1 seg faults in pthread_sigmask() if we don't do this. */ presult = pthread_init(); if (presult != 0) { isc__strerror(presult, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_app_start() pthread_init: %s", strbuf); return (ISC_R_UNEXPECTED); } #endif #ifdef ISC_PLATFORM_USETHREADS #ifdef HAVE_LINUXTHREADS main_thread = pthread_self(); #endif /* HAVE_LINUXTHREADS */ result = isc_mutex_init(&ctx->readylock); if (result != ISC_R_SUCCESS) return (result); result = isc_condition_init(&ctx->ready); if (result != ISC_R_SUCCESS) goto cleanup_rlock; result = isc_mutex_init(&ctx->lock); if (result != ISC_R_SUCCESS) goto cleanup_rcond; #else /* ISC_PLATFORM_USETHREADS */ result = isc_mutex_init(&ctx->lock); if (result != ISC_R_SUCCESS) goto cleanup; #endif /* ISC_PLATFORM_USETHREADS */ ISC_LIST_INIT(ctx->on_run); ctx->shutdown_requested = ISC_FALSE; ctx->running = ISC_FALSE; ctx->want_shutdown = ISC_FALSE; ctx->want_reload = ISC_FALSE; ctx->blocked = ISC_FALSE; #ifndef HAVE_SIGWAIT /* * Install do-nothing handlers for SIGINT and SIGTERM. * * We install them now because BSDI 3.1 won't block * the default actions, regardless of what we do with * pthread_sigmask(). */ result = handle_signal(SIGINT, exit_action); if (result != ISC_R_SUCCESS) goto cleanup; result = handle_signal(SIGTERM, exit_action); if (result != ISC_R_SUCCESS) goto cleanup; #endif /* * Always ignore SIGPIPE. */ result = handle_signal(SIGPIPE, SIG_IGN); if (result != ISC_R_SUCCESS) goto cleanup; /* * On Solaris 2, delivery of a signal whose action is SIG_IGN * will not cause sigwait() to return. We may have inherited * unexpected actions for SIGHUP, SIGINT, and SIGTERM from our parent * process (e.g, Solaris cron). Set an action of SIG_DFL to make * sure sigwait() works as expected. Only do this for SIGTERM and * SIGINT if we don't have sigwait(), since a different handler is * installed above. */ result = handle_signal(SIGHUP, SIG_DFL); if (result != ISC_R_SUCCESS) goto cleanup; #ifdef HAVE_SIGWAIT result = handle_signal(SIGTERM, SIG_DFL); if (result != ISC_R_SUCCESS) goto cleanup; result = handle_signal(SIGINT, SIG_DFL); if (result != ISC_R_SUCCESS) goto cleanup; #endif #ifdef ISC_PLATFORM_USETHREADS if (isc_bind9) { /* * Block SIGHUP, SIGINT, SIGTERM. * * If isc_app_start() is called from the main thread before any other * threads have been created, then the pthread_sigmask() call below * will result in all threads having SIGHUP, SIGINT and SIGTERM * blocked by default, ensuring that only the thread that calls * sigwait() for them will get those signals. */ if (sigemptyset(&sset) != 0 || sigaddset(&sset, SIGHUP) != 0 || sigaddset(&sset, SIGINT) != 0 || sigaddset(&sset, SIGTERM) != 0) { isc__strerror(errno, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_app_start() sigsetops: %s", strbuf); result = ISC_R_UNEXPECTED; goto cleanup; } presult = pthread_sigmask(SIG_BLOCK, &sset, NULL); if (presult != 0) { isc__strerror(presult, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_app_start() pthread_sigmask: %s", strbuf); result = ISC_R_UNEXPECTED; goto cleanup; } } #else /* ISC_PLATFORM_USETHREADS */ /* * Unblock SIGHUP, SIGINT, SIGTERM. * * If we're not using threads, we need to make sure that SIGHUP, * SIGINT and SIGTERM are not inherited as blocked from the parent * process. */ if (sigemptyset(&sset) != 0 || sigaddset(&sset, SIGHUP) != 0 || sigaddset(&sset, SIGINT) != 0 || sigaddset(&sset, SIGTERM) != 0) { isc__strerror(errno, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_app_start() sigsetops: %s", strbuf); result = ISC_R_UNEXPECTED; goto cleanup; } presult = sigprocmask(SIG_UNBLOCK, &sset, NULL); if (presult != 0) { isc__strerror(errno, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_app_start() sigprocmask: %s", strbuf); result = ISC_R_UNEXPECTED; goto cleanup; } #endif /* ISC_PLATFORM_USETHREADS */ return (ISC_R_SUCCESS); cleanup: #ifdef ISC_PLATFORM_USETHREADS cleanup_rcond: (void)isc_condition_destroy(&ctx->ready); cleanup_rlock: (void)isc_mutex_destroy(&ctx->readylock); #endif /* ISC_PLATFORM_USETHREADS */ return (result); }
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; }