xref: /netbsd/external/bsd/ntp/dist/lib/isc/include/isc/timer.h (revision 9034ec65)
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 
83 ISC_LANG_BEGINDECLS
84 
85 /***
86  *** Types
87  ***/
88 
89 /*% Timer Type */
90 typedef 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 
97 typedef 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 */
109 typedef 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 
121 typedef 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  */
139 struct 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  */
153 struct 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 
170 isc_result_t
171 isc_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 
234 isc_result_t
235 isc_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 
271 isc_result_t
272 isc_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 
292 void
293 isc_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 
308 void
309 isc_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 
338 isc_timertype_t
339 isc_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 
348 isc_result_t
349 isc_timermgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx,
350 			 isc_timermgr_t **managerp);
351 
352 isc_result_t
353 isc_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 
381 void
382 isc_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 
404 void isc_timermgr_poke(isc_timermgr_t *m);
405 
406 #ifdef USE_TIMERIMPREGISTER
407 /*%<
408  * See isc_timermgr_create() above.
409  */
410 typedef isc_result_t
411 (*isc_timermgrcreatefunc_t)(isc_mem_t *mctx, isc_timermgr_t **managerp);
412 
413 isc_result_t
414 isc__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 
421 isc_result_t
422 isc_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 
431 ISC_LANG_ENDDECLS
432 
433 #endif /* ISC_TIMER_H */
434