1 /* $NetBSD: timer.h,v 1.8 2014/12/10 04:38:00 christos Exp $ */ 2 3 /* 4 * Copyright (C) 2004-2009, 2012-2014 Internet Systems Consortium, Inc. ("ISC") 5 * Copyright (C) 1998-2002 Internet Software Consortium. 6 * 7 * Permission to use, copy, modify, and/or distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 /* Id: timer.h,v 1.43 2009/09/02 23:48:03 tbox Exp */ 21 22 #ifndef ISC_TIMER_H 23 #define ISC_TIMER_H 1 24 25 /***** 26 ***** Module Info 27 *****/ 28 29 /*! \file isc/timer.h 30 * \brief Provides timers which are event sources in the task system. 31 * 32 * Three types of timers are supported: 33 * 34 *\li 'ticker' timers generate a periodic tick event. 35 * 36 *\li 'once' timers generate an idle timeout event if they are idle for too 37 * long, and generate a life timeout event if their lifetime expires. 38 * They are used to implement both (possibly expiring) idle timers and 39 * 'one-shot' timers. 40 * 41 *\li 'limited' timers generate a periodic tick event until they reach 42 * their lifetime when they generate a life timeout event. 43 * 44 *\li 'inactive' timers generate no events. 45 * 46 * Timers can change type. It is typical to create a timer as 47 * an 'inactive' timer and then change it into a 'ticker' or 48 * 'once' timer. 49 * 50 *\li MP: 51 * The module ensures appropriate synchronization of data structures it 52 * creates and manipulates. 53 * Clients of this module must not be holding a timer's task's lock when 54 * making a call that affects that timer. Failure to follow this rule 55 * can result in deadlock. 56 * The caller must ensure that isc_timermgr_destroy() is called only 57 * once for a given manager. 58 * 59 * \li Reliability: 60 * No anticipated impact. 61 * 62 * \li Resources: 63 * TBS 64 * 65 * \li Security: 66 * No anticipated impact. 67 * 68 * \li Standards: 69 * None. 70 */ 71 72 73 /*** 74 *** Imports 75 ***/ 76 77 #include <isc/types.h> 78 #include <isc/event.h> 79 #include <isc/eventclass.h> 80 #include <isc/lang.h> 81 #include <isc/time.h> 82 83 ISC_LANG_BEGINDECLS 84 85 /*** 86 *** Types 87 ***/ 88 89 /*% Timer Type */ 90 typedef enum { 91 isc_timertype_undefined = -1, /*%< Undefined */ 92 isc_timertype_ticker = 0, /*%< Ticker */ 93 isc_timertype_once = 1, /*%< Once */ 94 isc_timertype_limited = 2, /*%< Limited */ 95 isc_timertype_inactive = 3 /*%< Inactive */ 96 } isc_timertype_t; 97 98 typedef struct isc_timerevent { 99 struct isc_event common; 100 isc_time_t due; 101 } isc_timerevent_t; 102 103 #define ISC_TIMEREVENT_FIRSTEVENT (ISC_EVENTCLASS_TIMER + 0) 104 #define ISC_TIMEREVENT_TICK (ISC_EVENTCLASS_TIMER + 1) 105 #define ISC_TIMEREVENT_IDLE (ISC_EVENTCLASS_TIMER + 2) 106 #define ISC_TIMEREVENT_LIFE (ISC_EVENTCLASS_TIMER + 3) 107 #define ISC_TIMEREVENT_LASTEVENT (ISC_EVENTCLASS_TIMER + 65535) 108 109 /*% Timer and timer manager methods */ 110 typedef struct { 111 void (*destroy)(isc_timermgr_t **managerp); 112 isc_result_t (*timercreate)(isc_timermgr_t *manager, 113 isc_timertype_t type, 114 const isc_time_t *expires, 115 const isc_interval_t *interval, 116 isc_task_t *task, 117 isc_taskaction_t action, 118 void *arg, 119 isc_timer_t **timerp); 120 } isc_timermgrmethods_t; 121 122 typedef struct { 123 void (*attach)(isc_timer_t *timer, isc_timer_t **timerp); 124 void (*detach)(isc_timer_t **timerp); 125 isc_result_t (*reset)(isc_timer_t *timer, isc_timertype_t type, 126 const isc_time_t *expires, 127 const isc_interval_t *interval, 128 isc_boolean_t purge); 129 isc_result_t (*touch)(isc_timer_t *timer); 130 } isc_timermethods_t; 131 132 /*% 133 * This structure is actually just the common prefix of a timer manager 134 * object implementation's version of an isc_timermgr_t. 135 * \brief 136 * Direct use of this structure by clients is forbidden. timer implementations 137 * may change the structure. 'magic' must be ISCAPI_TIMERMGR_MAGIC for any 138 * of the isc_timer_ routines to work. timer implementations must maintain 139 * all timer invariants. 140 */ 141 struct isc_timermgr { 142 unsigned int impmagic; 143 unsigned int magic; 144 isc_timermgrmethods_t *methods; 145 }; 146 147 #define ISCAPI_TIMERMGR_MAGIC ISC_MAGIC('A','t','m','g') 148 #define ISCAPI_TIMERMGR_VALID(m) ((m) != NULL && \ 149 (m)->magic == ISCAPI_TIMERMGR_MAGIC) 150 151 /*% 152 * This is the common prefix of a timer object. The same note as 153 * that for the timermgr structure applies. 154 */ 155 struct isc_timer { 156 unsigned int impmagic; 157 unsigned int magic; 158 isc_timermethods_t *methods; 159 }; 160 161 #define ISCAPI_TIMER_MAGIC ISC_MAGIC('A','t','m','r') 162 #define ISCAPI_TIMER_VALID(s) ((s) != NULL && \ 163 (s)->magic == ISCAPI_TIMER_MAGIC) 164 165 /*** 166 *** Timer and Timer Manager Functions 167 *** 168 *** Note: all Ensures conditions apply only if the result is success for 169 *** those functions which return an isc_result_t. 170 ***/ 171 172 isc_result_t 173 isc_timer_create(isc_timermgr_t *manager, 174 isc_timertype_t type, 175 const isc_time_t *expires, 176 const isc_interval_t *interval, 177 isc_task_t *task, 178 isc_taskaction_t action, 179 void *arg, 180 isc_timer_t **timerp); 181 /*%< 182 * Create a new 'type' timer managed by 'manager'. The timers parameters 183 * are specified by 'expires' and 'interval'. Events will be posted to 184 * 'task' and when dispatched 'action' will be called with 'arg' as the 185 * arg value. The new timer is returned in 'timerp'. 186 * 187 * Notes: 188 * 189 *\li For ticker timers, the timer will generate a 'tick' event every 190 * 'interval' seconds. The value of 'expires' is ignored. 191 * 192 *\li For once timers, 'expires' specifies the time when a life timeout 193 * event should be generated. If 'expires' is 0 (the epoch), then no life 194 * timeout will be generated. 'interval' specifies how long the timer 195 * can be idle before it generates an idle timeout. If 0, then no 196 * idle timeout will be generated. 197 * 198 *\li If 'expires' is NULL, the epoch will be used. 199 * 200 * If 'interval' is NULL, the zero interval will be used. 201 * 202 * Requires: 203 * 204 *\li 'manager' is a valid manager 205 * 206 *\li 'task' is a valid task 207 * 208 *\li 'action' is a valid action 209 * 210 *\li 'expires' points to a valid time, or is NULL. 211 * 212 *\li 'interval' points to a valid interval, or is NULL. 213 * 214 *\li type == isc_timertype_inactive || 215 * ('expires' and 'interval' are not both 0) 216 * 217 *\li 'timerp' is a valid pointer, and *timerp == NULL 218 * 219 * Ensures: 220 * 221 *\li '*timerp' is attached to the newly created timer 222 * 223 *\li The timer is attached to the task 224 * 225 *\li An idle timeout will not be generated until at least Now + the 226 * timer's interval if 'timer' is a once timer with a non-zero 227 * interval. 228 * 229 * Returns: 230 * 231 *\li Success 232 *\li No memory 233 *\li Unexpected error 234 */ 235 236 isc_result_t 237 isc_timer_reset(isc_timer_t *timer, 238 isc_timertype_t type, 239 const isc_time_t *expires, 240 const isc_interval_t *interval, 241 isc_boolean_t purge); 242 /*%< 243 * Change the timer's type, expires, and interval values to the given 244 * values. If 'purge' is TRUE, any pending events from this timer 245 * are purged from its task's event queue. 246 * 247 * Notes: 248 * 249 *\li If 'expires' is NULL, the epoch will be used. 250 * 251 *\li If 'interval' is NULL, the zero interval will be used. 252 * 253 * Requires: 254 * 255 *\li 'timer' is a valid timer 256 * 257 *\li The same requirements that isc_timer_create() imposes on 'type', 258 * 'expires' and 'interval' apply. 259 * 260 * Ensures: 261 * 262 *\li An idle timeout will not be generated until at least Now + the 263 * timer's interval if 'timer' is a once timer with a non-zero 264 * interval. 265 * 266 * Returns: 267 * 268 *\li Success 269 *\li No memory 270 *\li Unexpected error 271 */ 272 273 isc_result_t 274 isc_timer_touch(isc_timer_t *timer); 275 /*%< 276 * Set the last-touched time of 'timer' to the current time. 277 * 278 * Requires: 279 * 280 *\li 'timer' is a valid once timer. 281 * 282 * Ensures: 283 * 284 *\li An idle timeout will not be generated until at least Now + the 285 * timer's interval if 'timer' is a once timer with a non-zero 286 * interval. 287 * 288 * Returns: 289 * 290 *\li Success 291 *\li Unexpected error 292 */ 293 294 void 295 isc_timer_attach(isc_timer_t *timer, isc_timer_t **timerp); 296 /*%< 297 * Attach *timerp to timer. 298 * 299 * Requires: 300 * 301 *\li 'timer' is a valid timer. 302 * 303 *\li 'timerp' points to a NULL timer. 304 * 305 * Ensures: 306 * 307 *\li *timerp is attached to timer. 308 */ 309 310 void 311 isc_timer_detach(isc_timer_t **timerp); 312 /*%< 313 * Detach *timerp from its timer. 314 * 315 * Requires: 316 * 317 *\li 'timerp' points to a valid timer. 318 * 319 * Ensures: 320 * 321 *\li *timerp is NULL. 322 * 323 *\li If '*timerp' is the last reference to the timer, 324 * then: 325 * 326 *\code 327 * The timer will be shutdown 328 * 329 * The timer will detach from its task 330 * 331 * All resources used by the timer have been freed 332 * 333 * Any events already posted by the timer will be purged. 334 * Therefore, if isc_timer_detach() is called in the context 335 * of the timer's task, it is guaranteed that no more 336 * timer event callbacks will run after the call. 337 *\endcode 338 */ 339 340 isc_timertype_t 341 isc_timer_gettype(isc_timer_t *timer); 342 /*%< 343 * Return the timer type. 344 * 345 * Requires: 346 * 347 *\li 'timer' to be a valid timer. 348 */ 349 350 isc_result_t 351 isc_timermgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx, 352 isc_timermgr_t **managerp); 353 354 isc_result_t 355 isc_timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp); 356 /*%< 357 * Create a timer manager. isc_timermgr_createinctx() also associates 358 * the new manager with the specified application context. 359 * 360 * Notes: 361 * 362 *\li All memory will be allocated in memory context 'mctx'. 363 * 364 * Requires: 365 * 366 *\li 'mctx' is a valid memory context. 367 * 368 *\li 'managerp' points to a NULL isc_timermgr_t. 369 * 370 *\li 'actx' is a valid application context (for createinctx()). 371 * 372 * Ensures: 373 * 374 *\li '*managerp' is a valid isc_timermgr_t. 375 * 376 * Returns: 377 * 378 *\li Success 379 *\li No memory 380 *\li Unexpected error 381 */ 382 383 void 384 isc_timermgr_destroy(isc_timermgr_t **managerp); 385 /*%< 386 * Destroy a timer manager. 387 * 388 * Notes: 389 * 390 *\li This routine blocks until there are no timers left in the manager, 391 * so if the caller holds any timer references using the manager, it 392 * must detach them before calling isc_timermgr_destroy() or it will 393 * block forever. 394 * 395 * Requires: 396 * 397 *\li '*managerp' is a valid isc_timermgr_t. 398 * 399 * Ensures: 400 * 401 *\li *managerp == NULL 402 * 403 *\li All resources used by the manager have been freed. 404 */ 405 406 void isc_timermgr_poke(isc_timermgr_t *m); 407 408 /*%< 409 * See isc_timermgr_create() above. 410 */ 411 typedef isc_result_t 412 (*isc_timermgrcreatefunc_t)(isc_mem_t *mctx, isc_timermgr_t **managerp); 413 414 isc_result_t 415 isc__timer_register(void); 416 /*%< 417 * Register a new timer management implementation and add it to the list of 418 * supported implementations. This function must be called when a different 419 * event library is used than the one contained in the ISC library. 420 */ 421 422 isc_result_t 423 isc_timer_register(isc_timermgrcreatefunc_t createfunc); 424 /*%< 425 * A short cut function that specifies the timer management module in the ISC 426 * library for isc_timer_register(). An application that uses the ISC library 427 * usually do not have to care about this function: it would call 428 * isc_lib_register(), which internally calls this function. 429 */ 430 431 ISC_LANG_ENDDECLS 432 433 #endif /* ISC_TIMER_H */ 434