1/*	$NetBSD: timer.h,v 1.6 2020/05/25 20:47:21 christos Exp $	*/
2
3/*
4 * Copyright (C) 2004-2009  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
83ISC_LANG_BEGINDECLS
84
85/***
86 *** Types
87 ***/
88
89/*% Timer Type */
90typedef enum {
91	isc_timertype_ticker = 0, 	/*%< Ticker */
92	isc_timertype_once = 1, 	/*%< Once */
93	isc_timertype_limited = 2, 	/*%< Limited */
94	isc_timertype_inactive = 3 	/*%< Inactive */
95} isc_timertype_t;
96
97typedef struct isc_timerevent {
98	struct isc_event	common;
99	isc_time_t		due;
100} isc_timerevent_t;
101
102#define ISC_TIMEREVENT_FIRSTEVENT	(ISC_EVENTCLASS_TIMER + 0)
103#define ISC_TIMEREVENT_TICK		(ISC_EVENTCLASS_TIMER + 1)
104#define ISC_TIMEREVENT_IDLE		(ISC_EVENTCLASS_TIMER + 2)
105#define ISC_TIMEREVENT_LIFE		(ISC_EVENTCLASS_TIMER + 3)
106#define ISC_TIMEREVENT_LASTEVENT	(ISC_EVENTCLASS_TIMER + 65535)
107
108/*% Timer and timer manager methods */
109typedef struct {
110	void		(*destroy)(isc_timermgr_t **managerp);
111	isc_result_t	(*timercreate)(isc_timermgr_t *manager,
112				       isc_timertype_t type,
113				       isc_time_t *expires,
114				       isc_interval_t *interval,
115				       isc_task_t *task,
116				       isc_taskaction_t action,
117				       const void *arg,
118				       isc_timer_t **timerp);
119} isc_timermgrmethods_t;
120
121typedef struct {
122	void		(*attach)(isc_timer_t *timer, isc_timer_t **timerp);
123	void		(*detach)(isc_timer_t **timerp);
124	isc_result_t	(*reset)(isc_timer_t *timer, isc_timertype_t type,
125				 isc_time_t *expires, isc_interval_t *interval,
126				 isc_boolean_t purge);
127	isc_result_t	(*touch)(isc_timer_t *timer);
128} isc_timermethods_t;
129
130/*%
131 * This structure is actually just the common prefix of a timer manager
132 * object implementation's version of an isc_timermgr_t.
133 * \brief
134 * Direct use of this structure by clients is forbidden.  timer implementations
135 * may change the structure.  'magic' must be ISCAPI_TIMERMGR_MAGIC for any
136 * of the isc_timer_ routines to work.  timer implementations must maintain
137 * all timer invariants.
138 */
139struct isc_timermgr {
140	unsigned int		impmagic;
141	unsigned int		magic;
142	isc_timermgrmethods_t	*methods;
143};
144
145#define ISCAPI_TIMERMGR_MAGIC		ISC_MAGIC('A','t','m','g')
146#define ISCAPI_TIMERMGR_VALID(m)	((m) != NULL && \
147					 (m)->magic == ISCAPI_TIMERMGR_MAGIC)
148
149/*%
150 * This is the common prefix of a timer object.  The same note as
151 * that for the timermgr structure applies.
152 */
153struct isc_timer {
154	unsigned int		impmagic;
155	unsigned int		magic;
156	isc_timermethods_t	*methods;
157};
158
159#define ISCAPI_TIMER_MAGIC	ISC_MAGIC('A','t','m','r')
160#define ISCAPI_TIMER_VALID(s)	((s) != NULL && \
161				 (s)->magic == ISCAPI_TIMER_MAGIC)
162
163/***
164 *** Timer and Timer Manager Functions
165 ***
166 *** Note: all Ensures conditions apply only if the result is success for
167 *** those functions which return an isc_result_t.
168 ***/
169
170isc_result_t
171isc_timer_create(isc_timermgr_t *manager,
172		 isc_timertype_t type,
173		 isc_time_t *expires,
174		 isc_interval_t *interval,
175		 isc_task_t *task,
176		 isc_taskaction_t action,
177		 const void *arg,
178		 isc_timer_t **timerp);
179/*%<
180 * Create a new 'type' timer managed by 'manager'.  The timers parameters
181 * are specified by 'expires' and 'interval'.  Events will be posted to
182 * 'task' and when dispatched 'action' will be called with 'arg' as the
183 * arg value.  The new timer is returned in 'timerp'.
184 *
185 * Notes:
186 *
187 *\li	For ticker timers, the timer will generate a 'tick' event every
188 *	'interval' seconds.  The value of 'expires' is ignored.
189 *
190 *\li	For once timers, 'expires' specifies the time when a life timeout
191 *	event should be generated.  If 'expires' is 0 (the epoch), then no life
192 *	timeout will be generated.  'interval' specifies how long the timer
193 *	can be idle before it generates an idle timeout.  If 0, then no
194 *	idle timeout will be generated.
195 *
196 *\li	If 'expires' is NULL, the epoch will be used.
197 *
198 *	If 'interval' is NULL, the zero interval will be used.
199 *
200 * Requires:
201 *
202 *\li	'manager' is a valid manager
203 *
204 *\li	'task' is a valid task
205 *
206 *\li	'action' is a valid action
207 *
208 *\li	'expires' points to a valid time, or is NULL.
209 *
210 *\li	'interval' points to a valid interval, or is NULL.
211 *
212 *\li	type == isc_timertype_inactive ||
213 *	('expires' and 'interval' are not both 0)
214 *
215 *\li	'timerp' is a valid pointer, and *timerp == NULL
216 *
217 * Ensures:
218 *
219 *\li	'*timerp' is attached to the newly created timer
220 *
221 *\li	The timer is attached to the task
222 *
223 *\li	An idle timeout will not be generated until at least Now + the
224 *	timer's interval if 'timer' is a once timer with a non-zero
225 *	interval.
226 *
227 * Returns:
228 *
229 *\li	Success
230 *\li	No memory
231 *\li	Unexpected error
232 */
233
234isc_result_t
235isc_timer_reset(isc_timer_t *timer,
236		isc_timertype_t type,
237		isc_time_t *expires,
238		isc_interval_t *interval,
239		isc_boolean_t purge);
240/*%<
241 * Change the timer's type, expires, and interval values to the given
242 * values.  If 'purge' is TRUE, any pending events from this timer
243 * are purged from its task's event queue.
244 *
245 * Notes:
246 *
247 *\li	If 'expires' is NULL, the epoch will be used.
248 *
249 *\li	If 'interval' is NULL, the zero interval will be used.
250 *
251 * Requires:
252 *
253 *\li	'timer' is a valid timer
254 *
255 *\li	The same requirements that isc_timer_create() imposes on 'type',
256 *	'expires' and 'interval' apply.
257 *
258 * Ensures:
259 *
260 *\li	An idle timeout will not be generated until at least Now + the
261 *	timer's interval if 'timer' is a once timer with a non-zero
262 *	interval.
263 *
264 * Returns:
265 *
266 *\li	Success
267 *\li	No memory
268 *\li	Unexpected error
269 */
270
271isc_result_t
272isc_timer_touch(isc_timer_t *timer);
273/*%<
274 * Set the last-touched time of 'timer' to the current time.
275 *
276 * Requires:
277 *
278 *\li	'timer' is a valid once timer.
279 *
280 * Ensures:
281 *
282 *\li	An idle timeout will not be generated until at least Now + the
283 *	timer's interval if 'timer' is a once timer with a non-zero
284 *	interval.
285 *
286 * Returns:
287 *
288 *\li	Success
289 *\li	Unexpected error
290 */
291
292void
293isc_timer_attach(isc_timer_t *timer, isc_timer_t **timerp);
294/*%<
295 * Attach *timerp to timer.
296 *
297 * Requires:
298 *
299 *\li	'timer' is a valid timer.
300 *
301 *\li	'timerp' points to a NULL timer.
302 *
303 * Ensures:
304 *
305 *\li	*timerp is attached to timer.
306 */
307
308void
309isc_timer_detach(isc_timer_t **timerp);
310/*%<
311 * Detach *timerp from its timer.
312 *
313 * Requires:
314 *
315 *\li	'timerp' points to a valid timer.
316 *
317 * Ensures:
318 *
319 *\li	*timerp is NULL.
320 *
321 *\li	If '*timerp' is the last reference to the timer,
322 *	then:
323 *
324 *\code
325 *		The timer will be shutdown
326 *
327 *		The timer will detach from its task
328 *
329 *		All resources used by the timer have been freed
330 *
331 *		Any events already posted by the timer will be purged.
332 *		Therefore, if isc_timer_detach() is called in the context
333 *		of the timer's task, it is guaranteed that no more
334 *		timer event callbacks will run after the call.
335 *\endcode
336 */
337
338isc_timertype_t
339isc_timer_gettype(isc_timer_t *timer);
340/*%<
341 * Return the timer type.
342 *
343 * Requires:
344 *
345 *\li	'timer' to be a valid timer.
346 */
347
348isc_result_t
349isc_timermgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx,
350			 isc_timermgr_t **managerp);
351
352isc_result_t
353isc_timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp);
354/*%<
355 * Create a timer manager.  isc_timermgr_createinctx() also associates
356 * the new manager with the specified application context.
357 *
358 * Notes:
359 *
360 *\li	All memory will be allocated in memory context 'mctx'.
361 *
362 * Requires:
363 *
364 *\li	'mctx' is a valid memory context.
365 *
366 *\li	'managerp' points to a NULL isc_timermgr_t.
367 *
368 *\li	'actx' is a valid application context (for createinctx()).
369 *
370 * Ensures:
371 *
372 *\li	'*managerp' is a valid isc_timermgr_t.
373 *
374 * Returns:
375 *
376 *\li	Success
377 *\li	No memory
378 *\li	Unexpected error
379 */
380
381void
382isc_timermgr_destroy(isc_timermgr_t **managerp);
383/*%<
384 * Destroy a timer manager.
385 *
386 * Notes:
387 *
388 *\li	This routine blocks until there are no timers left in the manager,
389 *	so if the caller holds any timer references using the manager, it
390 *	must detach them before calling isc_timermgr_destroy() or it will
391 *	block forever.
392 *
393 * Requires:
394 *
395 *\li	'*managerp' is a valid isc_timermgr_t.
396 *
397 * Ensures:
398 *
399 *\li	*managerp == NULL
400 *
401 *\li	All resources used by the manager have been freed.
402 */
403
404void isc_timermgr_poke(isc_timermgr_t *m);
405
406#ifdef USE_TIMERIMPREGISTER
407/*%<
408 * See isc_timermgr_create() above.
409 */
410typedef isc_result_t
411(*isc_timermgrcreatefunc_t)(isc_mem_t *mctx, isc_timermgr_t **managerp);
412
413isc_result_t
414isc__timer_register(void);
415/*%<
416 * Register a new timer management implementation and add it to the list of
417 * supported implementations.  This function must be called when a different
418 * event library is used than the one contained in the ISC library.
419 */
420
421isc_result_t
422isc_timer_register(isc_timermgrcreatefunc_t createfunc);
423/*%<
424 * A short cut function that specifies the timer management module in the ISC
425 * library for isc_timer_register().  An application that uses the ISC library
426 * usually do not have to care about this function: it would call
427 * isc_lib_register(), which internally calls this function.
428 */
429#endif /* USE_TIMERIMPREGISTER */
430
431ISC_LANG_ENDDECLS
432
433#endif /* ISC_TIMER_H */
434