task_api.c revision 290001
1/* 2 * Copyright (C) 2009-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 102void 103isc_taskmgr_setmode(isc_taskmgr_t *manager, isc_taskmgrmode_t mode) { 104 REQUIRE(ISCAPI_TASKMGR_VALID(manager)); 105 106 manager->methods->setmode(manager, mode); 107} 108 109isc_taskmgrmode_t 110isc_taskmgr_mode(isc_taskmgr_t *manager) { 111 REQUIRE(ISCAPI_TASKMGR_VALID(manager)); 112 113 return (manager->methods->mode(manager)); 114} 115 116isc_result_t 117isc_task_create(isc_taskmgr_t *manager, unsigned int quantum, 118 isc_task_t **taskp) 119{ 120 REQUIRE(ISCAPI_TASKMGR_VALID(manager)); 121 REQUIRE(taskp != NULL && *taskp == NULL); 122 123 return (manager->methods->taskcreate(manager, quantum, taskp)); 124} 125 126void 127isc_task_attach(isc_task_t *source, isc_task_t **targetp) { 128 REQUIRE(ISCAPI_TASK_VALID(source)); 129 REQUIRE(targetp != NULL && *targetp == NULL); 130 131 source->methods->attach(source, targetp); 132 133 ENSURE(*targetp == source); 134} 135 136void 137isc_task_detach(isc_task_t **taskp) { 138 REQUIRE(taskp != NULL && ISCAPI_TASK_VALID(*taskp)); 139 140 (*taskp)->methods->detach(taskp); 141 142 ENSURE(*taskp == NULL); 143} 144 145void 146isc_task_send(isc_task_t *task, isc_event_t **eventp) { 147 REQUIRE(ISCAPI_TASK_VALID(task)); 148 REQUIRE(eventp != NULL && *eventp != NULL); 149 150 task->methods->send(task, eventp); 151 152 ENSURE(*eventp == NULL); 153} 154 155void 156isc_task_sendanddetach(isc_task_t **taskp, isc_event_t **eventp) { 157 REQUIRE(taskp != NULL && ISCAPI_TASK_VALID(*taskp)); 158 REQUIRE(eventp != NULL && *eventp != NULL); 159 160 (*taskp)->methods->sendanddetach(taskp, eventp); 161 162 ENSURE(*taskp == NULL && *eventp == NULL); 163} 164 165unsigned int 166isc_task_unsend(isc_task_t *task, void *sender, isc_eventtype_t type, 167 void *tag, isc_eventlist_t *events) 168{ 169 REQUIRE(ISCAPI_TASK_VALID(task)); 170 171 return (task->methods->unsend(task, sender, type, tag, events)); 172} 173 174isc_result_t 175isc_task_onshutdown(isc_task_t *task, isc_taskaction_t action, const void *arg) 176{ 177 REQUIRE(ISCAPI_TASK_VALID(task)); 178 179 return (task->methods->onshutdown(task, action, arg)); 180} 181 182void 183isc_task_shutdown(isc_task_t *task) { 184 REQUIRE(ISCAPI_TASK_VALID(task)); 185 186 task->methods->shutdown(task); 187} 188 189void 190isc_task_setname(isc_task_t *task, const char *name, void *tag) { 191 REQUIRE(ISCAPI_TASK_VALID(task)); 192 193 task->methods->setname(task, name, tag); 194} 195 196unsigned int 197isc_task_purge(isc_task_t *task, void *sender, isc_eventtype_t type, void *tag) 198{ 199 REQUIRE(ISCAPI_TASK_VALID(task)); 200 201 return (task->methods->purgeevents(task, sender, type, tag)); 202} 203 204isc_result_t 205isc_task_beginexclusive(isc_task_t *task) { 206 REQUIRE(ISCAPI_TASK_VALID(task)); 207 208 return (task->methods->beginexclusive(task)); 209} 210 211void 212isc_task_endexclusive(isc_task_t *task) { 213 REQUIRE(ISCAPI_TASK_VALID(task)); 214 215 task->methods->endexclusive(task); 216} 217 218void 219isc_task_setprivilege(isc_task_t *task, isc_boolean_t priv) { 220 REQUIRE(ISCAPI_TASK_VALID(task)); 221 222 task->methods->setprivilege(task, priv); 223} 224 225isc_boolean_t 226isc_task_privilege(isc_task_t *task) { 227 REQUIRE(ISCAPI_TASK_VALID(task)); 228 229 return (task->methods->privilege(task)); 230} 231 232 233/*% 234 * This is necessary for libisc's internal timer implementation. Other 235 * implementation might skip implementing this. 236 */ 237unsigned int 238isc_task_purgerange(isc_task_t *task, void *sender, isc_eventtype_t first, 239 isc_eventtype_t last, void *tag) 240{ 241 REQUIRE(ISCAPI_TASK_VALID(task)); 242 243 return (task->methods->purgerange(task, sender, first, last, tag)); 244} 245