1 /* 2 * Copyright (C) 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: timer.h,v 1.13 2020/09/14 08:40:44 florian Exp $ */ 18 19 #ifndef ISC_TIMER_H 20 #define ISC_TIMER_H 1 21 22 /***** 23 ***** Module Info 24 *****/ 25 26 /*! \file isc/timer.h 27 * \brief Provides timers which are event sources in the task system. 28 * 29 * Three types of timers are supported: 30 * 31 *\li 'ticker' timers generate a periodic tick event. 32 * 33 *\li 'once' timers generate an idle timeout event if they are idle for too 34 * long, and generate a life timeout event if their lifetime expires. 35 * They are used to implement both (possibly expiring) idle timers and 36 * 'one-shot' timers. 37 * 38 *\li 'limited' timers generate a periodic tick event until they reach 39 * their lifetime when they generate a life timeout event. 40 * 41 *\li 'inactive' timers generate no events. 42 * 43 * Timers can change type. It is typical to create a timer as 44 * an 'inactive' timer and then change it into a 'ticker' or 45 * 'once' timer. 46 * 47 *\li MP: 48 * The module ensures appropriate synchronization of data structures it 49 * creates and manipulates. 50 * Clients of this module must not be holding a timer's task's lock when 51 * making a call that affects that timer. Failure to follow this rule 52 * can result in deadlock. 53 * The caller must ensure that isc_timermgr_destroy() is called only 54 * once for a given manager. 55 * 56 * \li Reliability: 57 * No anticipated impact. 58 * 59 * \li Resources: 60 * TBS 61 * 62 * \li Security: 63 * No anticipated impact. 64 * 65 * \li Standards: 66 * None. 67 */ 68 69 /*** 70 *** Imports 71 ***/ 72 73 #include <time.h> 74 75 #include <isc/types.h> 76 #include <isc/event.h> 77 #include <isc/eventclass.h> 78 79 /*** 80 *** Types 81 ***/ 82 83 /*% Timer Type */ 84 85 typedef struct isc_timerevent { 86 struct isc_event common; 87 struct timespec due; 88 } isc_timerevent_t; 89 90 #define ISC_TIMEREVENT_FIRSTEVENT (ISC_EVENTCLASS_TIMER + 0) 91 #define ISC_TIMEREVENT_TICK (ISC_EVENTCLASS_TIMER + 1) 92 #define ISC_TIMEREVENT_IDLE (ISC_EVENTCLASS_TIMER + 2) 93 #define ISC_TIMEREVENT_LIFE (ISC_EVENTCLASS_TIMER + 3) 94 #define ISC_TIMEREVENT_LASTEVENT (ISC_EVENTCLASS_TIMER + 65535) 95 96 /*** 97 *** Timer and Timer Manager Functions 98 *** 99 *** Note: all Ensures conditions apply only if the result is success for 100 *** those functions which return an isc_result_t. 101 ***/ 102 103 isc_result_t 104 isc_timer_create(isc_timermgr_t *manager, 105 const struct timespec *interval, 106 isc_task_t *task, 107 isc_taskaction_t action, 108 void *arg, 109 isc_timer_t **timerp); 110 /*%< 111 * Create a new 'type' timer managed by 'manager'. The timers parameters 112 * are specified by 'expires' and 'interval'. Events will be posted to 113 * 'task' and when dispatched 'action' will be called with 'arg' as the 114 * arg value. The new timer is returned in 'timerp'. 115 * 116 * Notes: 117 * 118 *\li For ticker timers, the timer will generate a 'tick' event every 119 * 'interval' seconds. The value of 'expires' is ignored. 120 * 121 *\li For once timers, 'expires' specifies the time when a life timeout 122 * event should be generated. If 'expires' is 0 (the epoch), then no life 123 * timeout will be generated. 'interval' specifies how long the timer 124 * can be idle before it generates an idle timeout. If 0, then no 125 * idle timeout will be generated. 126 * 127 *\li If 'expires' is NULL, the epoch will be used. 128 * 129 * If 'interval' is NULL, the zero interval will be used. 130 * 131 * Requires: 132 * 133 *\li 'manager' is a valid manager 134 * 135 *\li 'task' is a valid task 136 * 137 *\li 'action' is a valid action 138 * 139 *\li 'expires' points to a valid time, or is NULL. 140 * 141 *\li 'interval' points to a valid interval, or is NULL. 142 * 143 *\li type == isc_timertype_inactive || 144 * ('expires' and 'interval' are not both 0) 145 * 146 *\li 'timerp' is a valid pointer, and *timerp == NULL 147 * 148 * Ensures: 149 * 150 *\li '*timerp' is attached to the newly created timer 151 * 152 *\li The timer is attached to the task 153 * 154 *\li An idle timeout will not be generated until at least Now + the 155 * timer's interval if 'timer' is a once timer with a non-zero 156 * interval. 157 * 158 * Returns: 159 * 160 *\li Success 161 *\li No memory 162 *\li Unexpected error 163 */ 164 165 isc_result_t 166 isc_timer_reset(isc_timer_t *timer, 167 const struct timespec *interval, 168 int purge); 169 /*%< 170 * Change the timer's type, expires, and interval values to the given 171 * values. If 'purge' is TRUE, any pending events from this timer 172 * are purged from its task's event queue. 173 * 174 * Notes: 175 * 176 *\li If 'expires' is NULL, the epoch will be used. 177 * 178 *\li If 'interval' is NULL, the zero interval will be used. 179 * 180 * Requires: 181 * 182 *\li 'timer' is a valid timer 183 * 184 *\li The same requirements that isc_timer_create() imposes on 'type', 185 * 'expires' and 'interval' apply. 186 * 187 * Ensures: 188 * 189 *\li An idle timeout will not be generated until at least Now + the 190 * timer's interval if 'timer' is a once timer with a non-zero 191 * interval. 192 * 193 * Returns: 194 * 195 *\li Success 196 *\li No memory 197 *\li Unexpected error 198 */ 199 200 void 201 isc_timer_touch(isc_timer_t *timer); 202 /*%< 203 * Set the last-touched time of 'timer' to the current time. 204 * 205 * Requires: 206 * 207 *\li 'timer' is a valid once timer. 208 * 209 * Ensures: 210 * 211 *\li An idle timeout will not be generated until at least Now + the 212 * timer's interval if 'timer' is a once timer with a non-zero 213 * interval. 214 * 215 */ 216 217 void 218 isc_timer_detach(isc_timer_t **timerp); 219 /*%< 220 * Detach *timerp from its timer. 221 * 222 * Requires: 223 * 224 *\li 'timerp' points to a valid timer. 225 * 226 * Ensures: 227 * 228 *\li *timerp is NULL. 229 * 230 *\li If '*timerp' is the last reference to the timer, 231 * then: 232 * 233 *\code 234 * The timer will be shutdown 235 * 236 * The timer will detach from its task 237 * 238 * All resources used by the timer have been freed 239 * 240 * Any events already posted by the timer will be purged. 241 * Therefore, if isc_timer_detach() is called in the context 242 * of the timer's task, it is guaranteed that no more 243 * timer event callbacks will run after the call. 244 *\endcode 245 */ 246 247 isc_result_t 248 isc_timermgr_create(isc_timermgr_t **managerp); 249 /*%< 250 * Create a timer manager. isc_timermgr_createinctx() also associates 251 * the new manager with the specified application context. 252 * 253 * Notes: 254 * 255 *\li All memory will be allocated in memory context 'mctx'. 256 * 257 * Requires: 258 * 259 *\li 'mctx' is a valid memory context. 260 * 261 *\li 'managerp' points to a NULL isc_timermgr_t. 262 * 263 *\li 'actx' is a valid application context (for createinctx()). 264 * 265 * Ensures: 266 * 267 *\li '*managerp' is a valid isc_timermgr_t. 268 * 269 * Returns: 270 * 271 *\li Success 272 *\li No memory 273 *\li Unexpected error 274 */ 275 276 void 277 isc_timermgr_destroy(isc_timermgr_t **managerp); 278 /*%< 279 * Destroy a timer manager. 280 * 281 * Notes: 282 * 283 *\li This routine blocks until there are no timers left in the manager, 284 * so if the caller holds any timer references using the manager, it 285 * must detach them before calling isc_timermgr_destroy() or it will 286 * block forever. 287 * 288 * Requires: 289 * 290 *\li '*managerp' is a valid isc_timermgr_t. 291 * 292 * Ensures: 293 * 294 *\li *managerp == NULL 295 * 296 *\li All resources used by the manager have been freed. 297 */ 298 299 #endif /* ISC_TIMER_H */ 300