task.h 21.3 KB
Newer Older
Bob Halley's avatar
Bob Halley committed
1
/*
Tinderbox User's avatar
Tinderbox User committed
2
 * Copyright (C) 2004-2007, 2009-2013  Internet Systems Consortium, Inc. ("ISC")
Mark Andrews's avatar
Mark Andrews committed
3
 * Copyright (C) 1998-2001, 2003  Internet Software Consortium.
4
 *
Automatic Updater's avatar
Automatic Updater committed
5
 * Permission to use, copy, modify, and/or distribute this software for any
Bob Halley's avatar
Bob Halley committed
6
7
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
8
 *
Mark Andrews's avatar
Mark Andrews committed
9
10
11
12
13
14
15
 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 * PERFORMANCE OF THIS SOFTWARE.
Bob Halley's avatar
Bob Halley committed
16
 */
Bob Halley's avatar
update  
Bob Halley committed
17

Mark Andrews's avatar
Mark Andrews committed
18
/* $Id$ */
David Lawrence's avatar
David Lawrence committed
19

Bob Halley's avatar
Bob Halley committed
20
21
#ifndef ISC_TASK_H
#define ISC_TASK_H 1
Bob Halley's avatar
update  
Bob Halley committed
22

Bob Halley's avatar
Bob Halley committed
23
24
25
26
/*****
 ***** Module Info
 *****/

27
/*! \file isc/task.h
28
 * \brief The task system provides a lightweight execution context, which is
Automatic Updater's avatar
Automatic Updater committed
29
 * basically an event queue.
30
31

 * When a task's event queue is non-empty, the
32
33
34
 * task is runnable.  A small work crew of threads, typically one per CPU,
 * execute runnable tasks by dispatching the events on the tasks' event
 * queues.  Context switching between tasks is fast.
Bob Halley's avatar
Bob Halley committed
35
 *
36
 * \li MP:
Bob Halley's avatar
Bob Halley committed
37
38
39
40
41
 *	The module ensures appropriate synchronization of data structures it
 *	creates and manipulates.
 *	The caller must ensure that isc_taskmgr_destroy() is called only
 *	once for a given manager.
 *
42
 * \li Reliability:
Bob Halley's avatar
Bob Halley committed
43
44
 *	No anticipated impact.
 *
45
46
 * \li Resources:
 *	TBS
Bob Halley's avatar
Bob Halley committed
47
 *
48
 * \li Security:
Bob Halley's avatar
Bob Halley committed
49
50
 *	No anticipated impact.
 *
51
 * \li Standards:
Bob Halley's avatar
Bob Halley committed
52
 *	None.
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
 *
 * \section purge Purging and Unsending
 *
 * Events which have been queued for a task but not delivered may be removed
 * from the task's event queue by purging or unsending.
 *
 * With both types, the caller specifies a matching pattern that selects
 * events based upon their sender, type, and tag.
 *
 * Purging calls isc_event_free() on the matching events.
 *
 * Unsending returns a list of events that matched the pattern.
 * The caller is then responsible for them.
 *
 * Consumers of events should purge, not unsend.
 *
 * Producers of events often want to remove events when the caller indicates
Francis Dupont's avatar
Francis Dupont committed
70
 * it is no longer interested in the object, e.g. by canceling a timer.
71
72
73
74
75
 * Sometimes this can be done by purging, but for some event types, the
 * calls to isc_event_free() cause deadlock because the event free routine
 * wants to acquire a lock the caller is already holding.  Unsending instead
 * of purging solves this problem.  As a general rule, producers should only
 * unsend events which they have sent.
Bob Halley's avatar
Bob Halley committed
76
77
78
79
80
81
82
 */


/***
 *** Imports.
 ***/

83
#include <isc/eventclass.h>
84
#include <isc/json.h>
Bob Halley's avatar
Bob Halley committed
85
#include <isc/lang.h>
86
#include <isc/stdtime.h>
87
#include <isc/types.h>
88
#include <isc/xml.h>
Bob Halley's avatar
update  
Bob Halley committed
89

90
91
#define ISC_TASKEVENT_FIRSTEVENT	(ISC_EVENTCLASS_TASK + 0)
#define ISC_TASKEVENT_SHUTDOWN		(ISC_EVENTCLASS_TASK + 1)
92
#define ISC_TASKEVENT_TEST		(ISC_EVENTCLASS_TASK + 1)
93
#define ISC_TASKEVENT_LASTEVENT		(ISC_EVENTCLASS_TASK + 65535)
Bob Halley's avatar
update    
Bob Halley committed
94

Bob Halley's avatar
Bob Halley committed
95
96
97
/*****
 ***** Tasks.
 *****/
Bob Halley's avatar
update  
Bob Halley committed
98

99
100
ISC_LANG_BEGINDECLS

101
102
103
104
/***
 *** Types
 ***/

105
106
107
108
109
typedef enum {
		isc_taskmgrmode_normal = 0,
		isc_taskmgrmode_privileged
} isc_taskmgrmode_t;

110
111
112
/*% Task and task manager methods */
typedef struct isc_taskmgrmethods {
	void		(*destroy)(isc_taskmgr_t **managerp);
113
114
115
	void		(*setmode)(isc_taskmgr_t *manager,
				   isc_taskmgrmode_t mode);
	isc_taskmgrmode_t (*mode)(isc_taskmgr_t *manager);
116
117
118
	isc_result_t	(*taskcreate)(isc_taskmgr_t *manager,
				      unsigned int quantum,
				      isc_task_t **taskp);
119
120
	void (*setexcltask)(isc_taskmgr_t *mgr, isc_task_t *task);
	isc_result_t (*excltask)(isc_taskmgr_t *mgr, isc_task_t **taskp);
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
} isc_taskmgrmethods_t;

typedef struct isc_taskmethods {
	void (*attach)(isc_task_t *source, isc_task_t **targetp);
	void (*detach)(isc_task_t **taskp);
	void (*destroy)(isc_task_t **taskp);
	void (*send)(isc_task_t *task, isc_event_t **eventp);
	void (*sendanddetach)(isc_task_t **taskp, isc_event_t **eventp);
	unsigned int (*unsend)(isc_task_t *task, void *sender, isc_eventtype_t type,
			       void *tag, isc_eventlist_t *events);
	isc_result_t (*onshutdown)(isc_task_t *task, isc_taskaction_t action,
				   const void *arg);
	void (*shutdown)(isc_task_t *task);
	void (*setname)(isc_task_t *task, const char *name, void *tag);
	unsigned int (*purgeevents)(isc_task_t *task, void *sender,
				    isc_eventtype_t type, void *tag);
	unsigned int (*purgerange)(isc_task_t *task, void *sender,
				   isc_eventtype_t first, isc_eventtype_t last,
				   void *tag);
140
141
	isc_result_t (*beginexclusive)(isc_task_t *task);
	void (*endexclusive)(isc_task_t *task);
142
143
    void (*setprivilege)(isc_task_t *task, isc_boolean_t priv);
    isc_boolean_t (*privilege)(isc_task_t *task);
144
145
146
147
148
149
} isc_taskmethods_t;

/*%
 * This structure is actually just the common prefix of a task manager
 * object implementation's version of an isc_taskmgr_t.
 * \brief
150
 * Direct use of this structure by clients is forbidden.  task implementations
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
 * may change the structure.  'magic' must be ISCAPI_TASKMGR_MAGIC for any
 * of the isc_task_ routines to work.  task implementations must maintain
 * all task invariants.
 */
struct isc_taskmgr {
	unsigned int		impmagic;
	unsigned int		magic;
	isc_taskmgrmethods_t	*methods;
};

#define ISCAPI_TASKMGR_MAGIC	ISC_MAGIC('A','t','m','g')
#define ISCAPI_TASKMGR_VALID(m)	((m) != NULL && \
				 (m)->magic == ISCAPI_TASKMGR_MAGIC)

/*%
 * This is the common prefix of a task object.  The same note as
 * that for the taskmgr structure applies.
 */
struct isc_task {
	unsigned int		impmagic;
	unsigned int		magic;
	isc_taskmethods_t	*methods;
};

#define ISCAPI_TASK_MAGIC	ISC_MAGIC('A','t','s','t')
#define ISCAPI_TASK_VALID(s)	((s) != NULL && \
				 (s)->magic == ISCAPI_TASK_MAGIC)

179
isc_result_t
180
181
isc_task_create(isc_taskmgr_t *manager, unsigned int quantum,
		isc_task_t **taskp);
182
/*%<
183
 * Create a task.
184
185
186
 *
 * Notes:
 *
187
 *\li	If 'quantum' is non-zero, then only that many events can be dispatched
188
189
190
191
 *	before the task must yield to other tasks waiting to execute.  If
 *	quantum is zero, then the default quantum of the task manager will
 *	be used.
 *
192
 *\li	The 'quantum' option may be removed from isc_task_create() in the
193
194
195
196
197
 *	future.  If this happens, isc_task_getquantum() and
 *	isc_task_setquantum() will be provided.
 *
 * Requires:
 *
198
 *\li	'manager' is a valid task manager.
199
 *
200
 *\li	taskp != NULL && *taskp == NULL
201
202
203
 *
 * Ensures:
 *
204
 *\li	On success, '*taskp' is bound to the new task.
205
206
207
 *
 * Returns:
 *
208
209
210
211
 *\li   #ISC_R_SUCCESS
 *\li	#ISC_R_NOMEMORY
 *\li	#ISC_R_UNEXPECTED
 *\li	#ISC_R_SHUTTINGDOWN
212
213
214
215
 */

void
isc_task_attach(isc_task_t *source, isc_task_t **targetp);
216
/*%<
217
218
219
220
 * Attach *targetp to source.
 *
 * Requires:
 *
221
 *\li	'source' is a valid task.
222
 *
223
 *\li	'targetp' points to a NULL isc_task_t *.
224
225
226
 *
 * Ensures:
 *
227
 *\li	*targetp is attached to source.
228
229
230
231
 */

void
isc_task_detach(isc_task_t **taskp);
232
/*%<
233
234
235
236
 * Detach *taskp from its task.
 *
 * Requires:
 *
237
 *\li	'*taskp' is a valid task.
238
239
240
 *
 * Ensures:
 *
241
 *\li	*taskp is NULL.
242
 *
243
 *\li	If '*taskp' is the last reference to the task, the task is idle (has
Bob Halley's avatar
Bob Halley committed
244
245
246
 *	an empty event queue), and has not been shutdown, the task will be
 *	shutdown.
 *
247
 *\li	If '*taskp' is the last reference to the task and
248
 *	the task has been shutdown,
249
 *		all resources used by the task will be freed.
250
251
 */

Bob Halley's avatar
Bob Halley committed
252
void
253
isc_task_send(isc_task_t *task, isc_event_t **eventp);
254
/*%<
255
256
257
258
 * Send '*event' to 'task'.
 *
 * Requires:
 *
259
260
 *\li	'task' is a valid task.
 *\li	eventp != NULL && *eventp != NULL.
261
 *
262
 * Ensures:
263
 *
264
 *\li	*eventp == NULL.
265
266
 */

Bob Halley's avatar
Bob Halley committed
267
void
Bob Halley's avatar
Bob Halley committed
268
isc_task_sendanddetach(isc_task_t **taskp, isc_event_t **eventp);
269
/*%<
Bob Halley's avatar
Bob Halley committed
270
271
272
273
274
 * Send '*event' to '*taskp' and then detach '*taskp' from its
 * task.
 *
 * Requires:
 *
275
276
 *\li	'*taskp' is a valid task.
 *\li	eventp != NULL && *eventp != NULL.
Bob Halley's avatar
Bob Halley committed
277
 *
278
 * Ensures:
Bob Halley's avatar
Bob Halley committed
279
 *
280
 *\li	*eventp == NULL.
Bob Halley's avatar
Bob Halley committed
281
 *
282
 *\li	*taskp == NULL.
Bob Halley's avatar
Bob Halley committed
283
 *
284
 *\li	If '*taskp' is the last reference to the task, the task is
Bob Halley's avatar
Bob Halley committed
285
286
 *	idle (has an empty event queue), and has not been shutdown,
 *	the task will be shutdown.
Bob Halley's avatar
Bob Halley committed
287
 *
288
 *\li	If '*taskp' is the last reference to the task and
Bob Halley's avatar
Bob Halley committed
289
 *	the task has been shutdown,
290
 *		all resources used by the task will be freed.
Bob Halley's avatar
Bob Halley committed
291
292
293
 */


294
295
unsigned int
isc_task_purgerange(isc_task_t *task, void *sender, isc_eventtype_t first,
Bob Halley's avatar
Bob Halley committed
296
		    isc_eventtype_t last, void *tag);
297
/*%<
298
299
300
301
 * Purge events from a task's event queue.
 *
 * Requires:
 *
302
 *\li	'task' is a valid task.
303
 *
304
 *\li	last >= first
305
 *
Bob Halley's avatar
Bob Halley committed
306
307
 * Ensures:
 *
308
 *\li	Events in the event queue of 'task' whose sender is 'sender', whose
Bob Halley's avatar
Bob Halley committed
309
310
 *	type is >= first and <= last, and whose tag is 'tag' will be purged,
 *	unless they are marked as unpurgable.
311
 *
312
 *\li	A sender of NULL will match any sender.  A NULL tag matches any
Bob Halley's avatar
Bob Halley committed
313
 *	tag.
Bob Halley's avatar
Bob Halley committed
314
 *
315
316
 * Returns:
 *
317
 *\li	The number of events purged.
318
319
320
 */

unsigned int
Bob Halley's avatar
Bob Halley committed
321
isc_task_purge(isc_task_t *task, void *sender, isc_eventtype_t type,
Bob Halley's avatar
Bob Halley committed
322
	       void *tag);
323
/*%<
324
325
326
327
 * Purge events from a task's event queue.
 *
 * Notes:
 *
328
 *\li	This function is equivalent to
329
 *
330
 *\code
Bob Halley's avatar
Bob Halley committed
331
 *		isc_task_purgerange(task, sender, type, type, tag);
332
 *\endcode
333
334
335
 *
 * Requires:
 *
336
 *\li	'task' is a valid task.
337
 *
Bob Halley's avatar
Bob Halley committed
338
339
 * Ensures:
 *
340
 *\li	Events in the event queue of 'task' whose sender is 'sender', whose
Bob Halley's avatar
Bob Halley committed
341
342
343
 *	type is 'type', and whose tag is 'tag' will be purged, unless they
 *	are marked as unpurgable.
 *
344
 *\li	A sender of NULL will match any sender.  A NULL tag matches any
Bob Halley's avatar
Bob Halley committed
345
 *	tag.
Bob Halley's avatar
Bob Halley committed
346
 *
347
348
 * Returns:
 *
349
 *\li	The number of events purged.
350
351
 */

Bob Halley's avatar
Bob Halley committed
352
353
isc_boolean_t
isc_task_purgeevent(isc_task_t *task, isc_event_t *event);
354
/*%<
Bob Halley's avatar
Bob Halley committed
355
356
 * Purge 'event' from a task's event queue.
 *
Bob Halley's avatar
Bob Halley committed
357
358
 * XXXRTH:  WARNING:  This method may be removed before beta.
 *
Bob Halley's avatar
Bob Halley committed
359
360
 * Notes:
 *
361
 *\li	If 'event' is on the task's event queue, it will be purged,
Bob Halley's avatar
Bob Halley committed
362
363
364
365
366
 * 	unless it is marked as unpurgeable.  'event' does not have to be
 *	on the task's event queue; in fact, it can even be an invalid
 *	pointer.  Purging only occurs if the event is actually on the task's
 *	event queue.
 *
367
 * \li	Purging never changes the state of the task.
Bob Halley's avatar
Bob Halley committed
368
369
370
 *
 * Requires:
 *
371
 *\li	'task' is a valid task.
Bob Halley's avatar
Bob Halley committed
372
373
374
 *
 * Ensures:
 *
375
 *\li	'event' is not in the event queue for 'task'.
Bob Halley's avatar
Bob Halley committed
376
377
378
 *
 * Returns:
 *
379
380
 *\li	#ISC_TRUE			The event was purged.
 *\li	#ISC_FALSE			The event was not in the event queue,
Bob Halley's avatar
Bob Halley committed
381
382
 *					or was marked unpurgeable.
 */
383

Bob Halley's avatar
Bob Halley committed
384
385
386
unsigned int
isc_task_unsendrange(isc_task_t *task, void *sender, isc_eventtype_t first,
		     isc_eventtype_t last, void *tag, isc_eventlist_t *events);
387
/*%<
Bob Halley's avatar
Bob Halley committed
388
389
390
391
 * Remove events from a task's event queue.
 *
 * Requires:
 *
392
 *\li	'task' is a valid task.
Bob Halley's avatar
Bob Halley committed
393
 *
394
 *\li	last >= first.
Bob Halley's avatar
Bob Halley committed
395
 *
396
 *\li	*events is a valid list.
Bob Halley's avatar
Bob Halley committed
397
398
399
 *
 * Ensures:
 *
400
 *\li	Events in the event queue of 'task' whose sender is 'sender', whose
Bob Halley's avatar
Bob Halley committed
401
402
 *	type is >= first and <= last, and whose tag is 'tag' will be dequeued
 *	and appended to *events.
403
 *
404
 *\li	A sender of NULL will match any sender.  A NULL tag matches any
Bob Halley's avatar
Bob Halley committed
405
406
407
408
 *	tag.
 *
 * Returns:
 *
409
 *\li	The number of events unsent.
Bob Halley's avatar
Bob Halley committed
410
411
412
413
414
 */

unsigned int
isc_task_unsend(isc_task_t *task, void *sender, isc_eventtype_t type,
		void *tag, isc_eventlist_t *events);
415
/*%<
Bob Halley's avatar
Bob Halley committed
416
417
418
419
 * Remove events from a task's event queue.
 *
 * Notes:
 *
420
 *\li	This function is equivalent to
Bob Halley's avatar
Bob Halley committed
421
 *
422
 *\code
Bob Halley's avatar
Bob Halley committed
423
 *		isc_task_unsendrange(task, sender, type, type, tag, events);
424
 *\endcode
Bob Halley's avatar
Bob Halley committed
425
426
427
 *
 * Requires:
 *
428
 *\li	'task' is a valid task.
Bob Halley's avatar
Bob Halley committed
429
 *
430
 *\li	*events is a valid list.
Bob Halley's avatar
Bob Halley committed
431
432
433
 *
 * Ensures:
 *
434
 *\li	Events in the event queue of 'task' whose sender is 'sender', whose
Bob Halley's avatar
Bob Halley committed
435
436
437
438
439
 *	type is 'type', and whose tag is 'tag' will be dequeued and appended
 *	to *events.
 *
 * Returns:
 *
440
 *\li	The number of events unsent.
Bob Halley's avatar
Bob Halley committed
441
442
 */

443
isc_result_t
David Lawrence's avatar
David Lawrence committed
444
445
isc_task_onshutdown(isc_task_t *task, isc_taskaction_t action,
		    const void *arg);
446
/*%<
447
448
449
450
451
 * Send a shutdown event with action 'action' and argument 'arg' when
 * 'task' is shutdown.
 *
 * Notes:
 *
452
 *\li	Shutdown events are posted in LIFO order.
453
454
455
 *
 * Requires:
 *
456
 *\li	'task' is a valid task.
457
 *
458
 *\li	'action' is a valid task action.
459
460
461
 *
 * Ensures:
 *
462
 *\li	When the task is shutdown, shutdown events requested with
463
464
 *	isc_task_onshutdown() will be appended to the task's event queue.
 *
David Lawrence's avatar
David Lawrence committed
465

466
467
 * Returns:
 *
468
469
470
 *\li	#ISC_R_SUCCESS
 *\li	#ISC_R_NOMEMORY
 *\li	#ISC_R_TASKSHUTTINGDOWN			Task is shutting down.
471
472
473
474
 */

void
isc_task_shutdown(isc_task_t *task);
475
/*%<
476
477
478
479
 * Shutdown 'task'.
 *
 * Notes:
 *
480
 *\li	Shutting down a task causes any shutdown events requested with
481
482
 *	isc_task_onshutdown() to be posted (in LIFO order).  The task
 *	moves into a "shutting down" mode which prevents further calls
Bob Halley's avatar
Bob Halley committed
483
 *	to isc_task_onshutdown().
484
 *
485
 *\li	Trying to shutdown a task that has already been shutdown has no
486
487
488
489
 *	effect.
 *
 * Requires:
 *
490
 *\li	'task' is a valid task.
491
492
493
 *
 * Ensures:
 *
494
 *\li	Any shutdown events requested with isc_task_onshutdown() have been
495
496
497
498
499
 *	posted (in LIFO order).
 */

void
isc_task_destroy(isc_task_t **taskp);
500
/*%<
501
502
503
504
 * Destroy '*taskp'.
 *
 * Notes:
 *
505
 *\li	This call is equivalent to:
506
 *
507
 *\code
Andreas Gustafsson's avatar
typo    
Andreas Gustafsson committed
508
 *		isc_task_shutdown(*taskp);
509
 *		isc_task_detach(taskp);
510
 *\endcode
511
512
513
514
515
516
517
 *
 * Requires:
 *
 *	'*taskp' is a valid task.
 *
 * Ensures:
 *
518
 *\li	Any shutdown events requested with isc_task_onshutdown() have been
519
520
 *	posted (in LIFO order).
 *
521
 *\li	*taskp == NULL
522
 *
523
524
 *\li	If '*taskp' is the last reference to the task,
 *		all resources used by the task will be freed.
525
 */
Bob Halley's avatar
update  
Bob Halley committed
526

527
void
David Lawrence's avatar
David Lawrence committed
528
isc_task_setname(isc_task_t *task, const char *name, void *tag);
529
/*%<
530
531
532
533
 * Name 'task'.
 *
 * Notes:
 *
534
 *\li	Only the first 15 characters of 'name' will be copied.
535
 *
536
 *\li	Naming a task is currently only useful for debugging purposes.
537
538
539
 *
 * Requires:
 *
540
 *\li	'task' is a valid task.
541
 */
Bob Halley's avatar
update  
Bob Halley committed
542

543
544
const char *
isc_task_getname(isc_task_t *task);
545
/*%<
546
547
548
 * Get the name of 'task', as previously set using isc_task_setname().
 *
 * Notes:
549
 *\li	This function is for debugging purposes only.
550
551
 *
 * Requires:
552
 *\li	'task' is a valid task.
553
554
 *
 * Returns:
555
 *\li	A non-NULL pointer to a null-terminated string.
556
557
558
559
560
561
562
 * 	If the task has not been named, the string is
 * 	empty.
 *
 */

void *
isc_task_gettag(isc_task_t *task);
563
/*%<
564
565
566
 * Get the tag value for  'task', as previously set using isc_task_settag().
 *
 * Notes:
567
 *\li	This function is for debugging purposes only.
568
569
 *
 * Requires:
570
 *\li	'task' is a valid task.
571
572
 */

573
574
isc_result_t
isc_task_beginexclusive(isc_task_t *task);
575
/*%<
576
577
578
579
580
 * Request exclusive access for 'task', which must be the calling
 * task.  Waits for any other concurrently executing tasks to finish their
 * current event, and prevents any new events from executing in any of the
 * tasks sharing a task manager with 'task'.
 *
Automatic Updater's avatar
Automatic Updater committed
581
 * The exclusive access must be relinquished by calling
582
583
584
 * isc_task_endexclusive() before returning from the current event handler.
 *
 * Requires:
585
 *\li	'task' is the calling task.
586
587
 *
 * Returns:
588
589
 *\li	#ISC_R_SUCCESS		The current task now has exclusive access.
 *\li	#ISC_R_LOCKBUSY		Another task has already requested exclusive
590
591
592
593
594
 *				access.
 */

void
isc_task_endexclusive(isc_task_t *task);
595
/*%<
Automatic Updater's avatar
Automatic Updater committed
596
 * Relinquish the exclusive access obtained by isc_task_beginexclusive(),
597
598
599
 * allowing other tasks to execute.
 *
 * Requires:
600
 *\li	'task' is the calling task, and has obtained
601
602
603
 *		exclusive access by calling isc_task_spl().
 */

604
605
void
isc_task_getcurrenttime(isc_task_t *task, isc_stdtime_t *t);
606
/*%<
607
608
609
610
 * Provide the most recent timestamp on the task.  The timestamp is considered
 * as the "current time" in the second-order granularity.
 *
 * Requires:
611
612
 *\li	'task' is a valid task.
 *\li	't' is a valid non NULL pointer.
613
614
 *
 * Ensures:
615
 *\li	'*t' has the "current time".
616
 */
617

618
isc_boolean_t
Mark Andrews's avatar
Mark Andrews committed
619
isc_task_exiting(isc_task_t *t);
620
621
622
623
624
625
626
627
/*%<
 * Returns ISC_TRUE if the task is in the process of shutting down,
 * ISC_FALSE otherwise.
 *
 * Requires:
 *\li	'task' is a valid task.
 */

628
629
630
631
void
isc_task_setprivilege(isc_task_t *task, isc_boolean_t priv);
/*%<
 * Set or unset the task's "privileged" flag depending on the value of
Automatic Updater's avatar
Automatic Updater committed
632
 * 'priv'.
633
634
 *
 * Under normal circumstances this flag has no effect on the task behavior,
Francis Dupont's avatar
Francis Dupont committed
635
 * but when the task manager has been set to privileged execution mode via
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
 * isc_taskmgr_setmode(), only tasks with the flag set will be executed,
 * and all other tasks will wait until they're done.  Once all privileged
 * tasks have finished executing, the task manager will automatically
 * return to normal execution mode and nonprivileged task can resume.
 *
 * Requires:
 *\li	'task' is a valid task.
 */

isc_boolean_t
isc_task_privilege(isc_task_t *task);
/*%<
 * Returns the current value of the task's privilege flag.
 *
 * Requires:
 *\li	'task' is a valid task.
 */

Bob Halley's avatar
Bob Halley committed
654
655
656
657
658
/*****
 ***** Task Manager.
 *****/

isc_result_t
659
660
661
662
isc_taskmgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx,
			unsigned int workers, unsigned int default_quantum,
			isc_taskmgr_t **managerp);
isc_result_t
Bob Halley's avatar
Bob Halley committed
663
664
isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers,
		   unsigned int default_quantum, isc_taskmgr_t **managerp);
665
/*%<
666
667
 * Create a new task manager.  isc_taskmgr_createinctx() also associates
 * the new manager with the specified application context.
Bob Halley's avatar
Bob Halley committed
668
669
670
 *
 * Notes:
 *
671
 *\li	'workers' in the number of worker threads to create.  In general,
Bob Halley's avatar
Bob Halley committed
672
673
674
675
676
 *	the value should be close to the number of processors in the system.
 *	The 'workers' value is advisory only.  An attempt will be made to
 *	create 'workers' threads, but if at least one thread creation
 *	succeeds, isc_taskmgr_create() may return ISC_R_SUCCESS.
 *
677
 *\li	If 'default_quantum' is non-zero, then it will be used as the default
678
679
680
 *	quantum value when tasks are created.  If zero, then an implementation
 *	defined default quantum will be used.
 *
Bob Halley's avatar
Bob Halley committed
681
682
 * Requires:
 *
683
 *\li      'mctx' is a valid memory context.
Bob Halley's avatar
Bob Halley committed
684
 *
685
 *\li	workers > 0
Bob Halley's avatar
Bob Halley committed
686
 *
687
 *\li	managerp != NULL && *managerp == NULL
Bob Halley's avatar
Bob Halley committed
688
 *
689
690
 *\li	'actx' is a valid application context (for createinctx()).
 *
Bob Halley's avatar
Bob Halley committed
691
692
 * Ensures:
 *
693
 *\li	On success, '*managerp' will be attached to the newly created task
Bob Halley's avatar
Bob Halley committed
694
695
696
697
 *	manager.
 *
 * Returns:
 *
698
699
 *\li	#ISC_R_SUCCESS
 *\li	#ISC_R_NOMEMORY
700
 *\li	#ISC_R_NOTHREADS		No threads could be created.
701
 *\li	#ISC_R_UNEXPECTED		An unexpected error occurred.
702
703
 *\li	#ISC_R_SHUTTINGDOWN      	The non-threaded, shared, task
 *					manager shutting down.
Bob Halley's avatar
Bob Halley committed
704
705
 */

706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
void
isc_taskmgr_setmode(isc_taskmgr_t *manager, isc_taskmgrmode_t mode);

isc_taskmgrmode_t
isc_taskmgr_mode(isc_taskmgr_t *manager);
/*%<
 * Set/get the current operating mode of the task manager.  Valid modes are:
 *
 *\li  isc_taskmgrmode_normal
 *\li  isc_taskmgrmode_privileged
 *
 * In privileged execution mode, only tasks that have had the "privilege"
 * flag set via isc_task_setprivilege() can be executed.  When all such
 * tasks are complete, the manager automatically returns to normal mode
 * and proceeds with running non-privileged ready tasks.  This means it is
 * necessary to have at least one privileged task waiting on the ready
 * queue *before* setting the manager into privileged execution mode,
 * which in turn means the task which calls this function should be in
 * task-exclusive mode when it does so.
 *
 * Requires:
 *
 *\li      'manager' is a valid task manager.
 */

731
732
void
isc_taskmgr_destroy(isc_taskmgr_t **managerp);
733
/*%<
734
735
736
737
 * Destroy '*managerp'.
 *
 * Notes:
 *
738
 *\li	Calling isc_taskmgr_destroy() will shutdown all tasks managed by
739
740
741
 *	*managerp that haven't already been shutdown.  The call will block
 *	until all tasks have entered the done state.
 *
742
 *\li	isc_taskmgr_destroy() must not be called by a task event action,
743
744
745
 *	because it would block forever waiting for the event action to
 *	complete.  An event action that wants to cause task manager shutdown
 *	should request some non-event action thread of execution to do the
Francis Dupont's avatar
Francis Dupont committed
746
 *	shutdown, e.g. by signaling a condition variable or using
747
748
 *	isc_app_shutdown().
 *
749
 *\li	Task manager references are not reference counted, so the caller
750
751
752
753
754
 *	must ensure that no attempt will be made to use the manager after
 *	isc_taskmgr_destroy() returns.
 *
 * Requires:
 *
755
 *\li	'*managerp' is a valid task manager.
756
 *
757
 *\li	isc_taskmgr_destroy() has not be called previously on '*managerp'.
758
759
760
 *
 * Ensures:
 *
761
 *\li	All resources used by the task manager, and any tasks it managed,
762
763
 *	have been freed.
 */
Bob Halley's avatar
update  
Bob Halley committed
764

Tinderbox User's avatar
Tinderbox User committed
765
void
766
767
768
769
770
771
772
773
isc_taskmgr_setexcltask(isc_taskmgr_t *mgr, isc_task_t *task);
/*%<
 * Set a task which will be used for all task-exclusive operations.
 *
 * Requires:
 *\li	'manager' is a valid task manager.
 *
 *\li	'task' is a valid task.
Tinderbox User's avatar
Tinderbox User committed
774
 */
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789

isc_result_t
isc_taskmgr_excltask(isc_taskmgr_t *mgr, isc_task_t **taskp);
/*%<
 * Attach '*taskp' to the task set by isc_taskmgr_getexcltask().
 * This task should be used whenever running in task-exclusive mode,
 * so as to prevent deadlock between two exclusive tasks.
 *
 * Requires:
 *\li	'manager' is a valid task manager.

 *\li	taskp != NULL && *taskp == NULL
 */


790
#ifdef HAVE_LIBXML2
Mark Andrews's avatar
Mark Andrews committed
791
int
792
isc_taskmgr_renderxml(isc_taskmgr_t *mgr, xmlTextWriterPtr writer);
793
#endif
794

795
796
797
#ifdef HAVE_JSON
isc_result_t
isc_taskmgr_renderjson(isc_taskmgr_t *mgr, json_object *tasksobj);
798
799
#endif

800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
/*%<
 * See isc_taskmgr_create() above.
 */
typedef isc_result_t
(*isc_taskmgrcreatefunc_t)(isc_mem_t *mctx, unsigned int workers,
			   unsigned int default_quantum,
			   isc_taskmgr_t **managerp);

isc_result_t
isc_task_register(isc_taskmgrcreatefunc_t createfunc);
/*%<
 * Register a new task management implementation and add it to the list of
 * supported implementations.  This function must be called when a different
 * event library is used than the one contained in the ISC library.
 */

isc_result_t
isc__task_register(void);
/*%<
 * A short cut function that specifies the task management module in the ISC
 * library for isc_task_register().  An application that uses the ISC library
 * usually do not have to care about this function: it would call
 * isc_lib_register(), which internally calls this function.
 */

Bob Halley's avatar
Bob Halley committed
825
826
ISC_LANG_ENDDECLS

Bob Halley's avatar
Bob Halley committed
827
#endif /* ISC_TASK_H */