1/* 2 * Copyright (C) 2009, 2010, 2012 Internet Systems Consortium, Inc. ("ISC") 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 10 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 13 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 14 * PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17/* $Id$ */ 18 19#include <config.h> 20 21#include <unistd.h> 22 23#include <isc/app.h> 24#include <isc/magic.h> 25#include <isc/mutex.h> 26#include <isc/once.h> 27#include <isc/task.h> 28#include <isc/util.h> 29 30static isc_mutex_t createlock; 31static isc_once_t once = ISC_ONCE_INIT; 32static isc_taskmgrcreatefunc_t taskmgr_createfunc = NULL; 33 34static void 35initialize(void) { 36 RUNTIME_CHECK(isc_mutex_init(&createlock) == ISC_R_SUCCESS); 37} 38 39isc_result_t 40isc_task_register(isc_taskmgrcreatefunc_t createfunc) { 41 isc_result_t result = ISC_R_SUCCESS; 42 43 RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS); 44 45 LOCK(&createlock); 46 if (taskmgr_createfunc == NULL) 47 taskmgr_createfunc = createfunc; 48 else 49 result = ISC_R_EXISTS; 50 UNLOCK(&createlock); 51 52 return (result); 53} 54 55isc_result_t 56isc_taskmgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx, 57 unsigned int workers, unsigned int default_quantum, 58 isc_taskmgr_t **managerp) 59{ 60 isc_result_t result; 61 62 LOCK(&createlock); 63 64 REQUIRE(taskmgr_createfunc != NULL); 65 result = (*taskmgr_createfunc)(mctx, workers, default_quantum, 66 managerp); 67 68 UNLOCK(&createlock); 69 70 if (result == ISC_R_SUCCESS) 71 isc_appctx_settaskmgr(actx, *managerp); 72 73 return (result); 74} 75 76isc_result_t 77isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers, 78 unsigned int default_quantum, isc_taskmgr_t **managerp) 79{ 80 isc_result_t result; 81 82 LOCK(&createlock); 83 84 REQUIRE(taskmgr_createfunc != NULL); 85 result = (*taskmgr_createfunc)(mctx, workers, default_quantum, 86 managerp); 87 88 UNLOCK(&createlock); 89 90 return (result); 91} 92 93void 94isc_taskmgr_destroy(isc_taskmgr_t **managerp) { 95 REQUIRE(managerp != NULL && ISCAPI_TASKMGR_VALID(*managerp)); 96 97 (*managerp)->methods->destroy(managerp); 98 99 ENSURE(*managerp == NULL); 100} 101 102isc_result_t 103isc_task_create(isc_taskmgr_t *manager, unsigned int quantum, 104 isc_task_t **taskp) 105{ 106 REQUIRE(ISCAPI_TASKMGR_VALID(manager)); 107 REQUIRE(taskp != NULL && *taskp == NULL); 108 109 return (manager->methods->taskcreate(manager, quantum, taskp)); 110} 111 112void 113isc_task_attach(isc_task_t *source, isc_task_t **targetp) { 114 REQUIRE(ISCAPI_TASK_VALID(source)); 115 REQUIRE(targetp != NULL && *targetp == NULL); 116 117 source->methods->attach(source, targetp); 118 119 ENSURE(*targetp == source); 120} 121 122void 123isc_task_detach(isc_task_t **taskp) { 124 REQUIRE(taskp != NULL && ISCAPI_TASK_VALID(*taskp)); 125 126 (*taskp)->methods->detach(taskp); 127 128 ENSURE(*taskp == NULL); 129} 130 131void 132isc_task_send(isc_task_t *task, isc_event_t **eventp) { 133 REQUIRE(ISCAPI_TASK_VALID(task)); 134 REQUIRE(eventp != NULL && *eventp != NULL); 135 136 task->methods->send(task, eventp); 137 138 ENSURE(*eventp == NULL); 139} 140 141void 142isc_task_sendanddetach(isc_task_t **taskp, isc_event_t **eventp) { 143 REQUIRE(taskp != NULL && ISCAPI_TASK_VALID(*taskp)); 144 REQUIRE(eventp != NULL && *eventp != NULL); 145 146 (*taskp)->methods->sendanddetach(taskp, eventp); 147 148 ENSURE(*taskp == NULL && *eventp == NULL); 149} 150 151unsigned int 152isc_task_unsend(isc_task_t *task, void *sender, isc_eventtype_t type, 153 void *tag, isc_eventlist_t *events) 154{ 155 REQUIRE(ISCAPI_TASK_VALID(task)); 156 157 return (task->methods->unsend(task, sender, type, tag, events)); 158} 159 160isc_result_t 161isc_task_onshutdown(isc_task_t *task, isc_taskaction_t action, const void *arg) 162{ 163 REQUIRE(ISCAPI_TASK_VALID(task)); 164 165 return (task->methods->onshutdown(task, action, arg)); 166} 167 168void 169isc_task_shutdown(isc_task_t *task) { 170 REQUIRE(ISCAPI_TASK_VALID(task)); 171 172 task->methods->shutdown(task); 173} 174 175void 176isc_task_setname(isc_task_t *task, const char *name, void *tag) { 177 REQUIRE(ISCAPI_TASK_VALID(task)); 178 179 task->methods->setname(task, name, tag); 180} 181 182unsigned int 183isc_task_purge(isc_task_t *task, void *sender, isc_eventtype_t type, void *tag) 184{ 185 REQUIRE(ISCAPI_TASK_VALID(task)); 186 187 return (task->methods->purgeevents(task, sender, type, tag)); 188} 189 190isc_result_t 191isc_task_beginexclusive(isc_task_t *task) { 192 REQUIRE(ISCAPI_TASK_VALID(task)); 193 194 return (task->methods->beginexclusive(task)); 195} 196 197void 198isc_task_endexclusive(isc_task_t *task) { 199 REQUIRE(ISCAPI_TASK_VALID(task)); 200 201 task->methods->endexclusive(task); 202} 203 204 205/*% 206 * This is necessary for libisc's internal timer implementation. Other 207 * implementation might skip implementing this. 208 */ 209unsigned int 210isc_task_purgerange(isc_task_t *task, void *sender, isc_eventtype_t first, 211 isc_eventtype_t last, void *tag) 212{ 213 REQUIRE(ISCAPI_TASK_VALID(task)); 214 215 return (task->methods->purgerange(task, sender, first, last, tag)); 216} 217