mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-31 14:35:26 +00:00
2660. [func] Add a new set of DNS libraries for non-BIND9
applications. See README.libdns. [RT #19369]
This commit is contained in:
490
lib/isc/task.c
490
lib/isc/task.c
@@ -15,7 +15,7 @@
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: task.c,v 1.107 2008/03/27 23:46:57 tbox Exp $ */
|
||||
/* $Id: task.c,v 1.108 2009/09/01 00:22:28 jinmei Exp $ */
|
||||
|
||||
/*! \file
|
||||
* \author Principal Author: Bob Halley
|
||||
@@ -40,9 +40,29 @@
|
||||
#include <isc/util.h>
|
||||
#include <isc/xml.h>
|
||||
|
||||
#ifndef ISC_PLATFORM_USETHREADS
|
||||
/*%
|
||||
* For BIND9 internal applications:
|
||||
* when built with threads we use multiple worker threads shared by the whole
|
||||
* application.
|
||||
* when built without threads we share a single global task manager and use
|
||||
* an integrated event loop for socket, timer, and other generic task events.
|
||||
* For generic library:
|
||||
* we don't use either of them: an application can have multiple task managers
|
||||
* whether or not it's threaded, and if the application is threaded each thread
|
||||
* is expected to have a separate manager; no "worker threads" are shared by
|
||||
* the application threads.
|
||||
*/
|
||||
#ifdef BIND9
|
||||
#ifdef ISC_PLATFORM_USETHREADS
|
||||
#define USE_WORKER_THREADS
|
||||
#else
|
||||
#define USE_SHARED_MANAGER
|
||||
#endif /* ISC_PLATFORM_USETHREADS */
|
||||
#endif /* BIND9 */
|
||||
|
||||
#ifndef USE_WORKER_THREADS
|
||||
#include "task_p.h"
|
||||
#endif /* ISC_PLATFORM_USETHREADS */
|
||||
#endif /* USE_WORKER_THREADS */
|
||||
|
||||
#ifdef ISC_TASK_TRACE
|
||||
#define XTRACE(m) fprintf(stderr, "task %p thread %lu: %s\n", \
|
||||
@@ -66,7 +86,7 @@ typedef enum {
|
||||
task_state_done
|
||||
} task_state_t;
|
||||
|
||||
#ifdef HAVE_LIBXML2
|
||||
#if defined(HAVE_LIBXML2) && defined(BIND9)
|
||||
static const char *statenames[] = {
|
||||
"idle", "ready", "running", "done",
|
||||
};
|
||||
@@ -75,10 +95,13 @@ static const char *statenames[] = {
|
||||
#define TASK_MAGIC ISC_MAGIC('T', 'A', 'S', 'K')
|
||||
#define VALID_TASK(t) ISC_MAGIC_VALID(t, TASK_MAGIC)
|
||||
|
||||
struct isc_task {
|
||||
typedef struct isc__task isc__task_t;
|
||||
typedef struct isc__taskmgr isc__taskmgr_t;
|
||||
|
||||
struct isc__task {
|
||||
/* Not locked. */
|
||||
unsigned int magic;
|
||||
isc_taskmgr_t * manager;
|
||||
isc_task_t common;
|
||||
isc__taskmgr_t * manager;
|
||||
isc_mutex_t lock;
|
||||
/* Locked by task lock. */
|
||||
task_state_t state;
|
||||
@@ -91,8 +114,8 @@ struct isc_task {
|
||||
char name[16];
|
||||
void * tag;
|
||||
/* Locked by task manager lock. */
|
||||
LINK(isc_task_t) link;
|
||||
LINK(isc_task_t) ready_link;
|
||||
LINK(isc__task_t) link;
|
||||
LINK(isc__task_t) ready_link;
|
||||
};
|
||||
|
||||
#define TASK_F_SHUTTINGDOWN 0x01
|
||||
@@ -103,9 +126,11 @@ struct isc_task {
|
||||
#define TASK_MANAGER_MAGIC ISC_MAGIC('T', 'S', 'K', 'M')
|
||||
#define VALID_MANAGER(m) ISC_MAGIC_VALID(m, TASK_MANAGER_MAGIC)
|
||||
|
||||
struct isc_taskmgr {
|
||||
typedef ISC_LIST(isc__task_t) isc__tasklist_t;
|
||||
|
||||
struct isc__taskmgr {
|
||||
/* Not locked. */
|
||||
unsigned int magic;
|
||||
isc_taskmgr_t common;
|
||||
isc_mem_t * mctx;
|
||||
isc_mutex_t lock;
|
||||
#ifdef ISC_PLATFORM_USETHREADS
|
||||
@@ -114,8 +139,8 @@ struct isc_taskmgr {
|
||||
#endif /* ISC_PLATFORM_USETHREADS */
|
||||
/* Locked by task manager lock. */
|
||||
unsigned int default_quantum;
|
||||
LIST(isc_task_t) tasks;
|
||||
isc_tasklist_t ready_tasks;
|
||||
LIST(isc__task_t) tasks;
|
||||
isc__tasklist_t ready_tasks;
|
||||
#ifdef ISC_PLATFORM_USETHREADS
|
||||
isc_condition_t work_available;
|
||||
isc_condition_t exclusive_granted;
|
||||
@@ -123,7 +148,7 @@ struct isc_taskmgr {
|
||||
unsigned int tasks_running;
|
||||
isc_boolean_t exclusive_requested;
|
||||
isc_boolean_t exiting;
|
||||
#ifndef ISC_PLATFORM_USETHREADS
|
||||
#ifdef USE_SHARED_MANAGER
|
||||
unsigned int refs;
|
||||
#endif /* ISC_PLATFORM_USETHREADS */
|
||||
};
|
||||
@@ -132,17 +157,112 @@ struct isc_taskmgr {
|
||||
#define DEFAULT_DEFAULT_QUANTUM 5
|
||||
#define FINISHED(m) ((m)->exiting && EMPTY((m)->tasks))
|
||||
|
||||
#ifndef ISC_PLATFORM_USETHREADS
|
||||
static isc_taskmgr_t *taskmgr = NULL;
|
||||
#endif /* ISC_PLATFORM_USETHREADS */
|
||||
#ifdef USE_SHARED_MANAGER
|
||||
static isc__taskmgr_t *taskmgr = NULL;
|
||||
#endif /* USE_SHARED_MANAGER */
|
||||
|
||||
/*%
|
||||
* The following can be either static or public, depending on build environment.
|
||||
*/
|
||||
|
||||
#ifdef BIND9
|
||||
#define ISC_TASKFUNC_SCOPE
|
||||
#else
|
||||
#define ISC_TASKFUNC_SCOPE static
|
||||
#endif
|
||||
|
||||
ISC_TASKFUNC_SCOPE isc_result_t
|
||||
isc__task_create(isc_taskmgr_t *manager0, unsigned int quantum,
|
||||
isc_task_t **taskp);
|
||||
ISC_TASKFUNC_SCOPE void
|
||||
isc__task_attach(isc_task_t *source0, isc_task_t **targetp);
|
||||
ISC_TASKFUNC_SCOPE void
|
||||
isc__task_detach(isc_task_t **taskp);
|
||||
ISC_TASKFUNC_SCOPE void
|
||||
isc__task_send(isc_task_t *task0, isc_event_t **eventp);
|
||||
ISC_TASKFUNC_SCOPE void
|
||||
isc__task_sendanddetach(isc_task_t **taskp, isc_event_t **eventp);
|
||||
ISC_TASKFUNC_SCOPE unsigned int
|
||||
isc__task_purgerange(isc_task_t *task0, void *sender, isc_eventtype_t first,
|
||||
isc_eventtype_t last, void *tag);
|
||||
ISC_TASKFUNC_SCOPE unsigned int
|
||||
isc__task_purge(isc_task_t *task, void *sender, isc_eventtype_t type,
|
||||
void *tag);
|
||||
ISC_TASKFUNC_SCOPE isc_boolean_t
|
||||
isc__task_purgeevent(isc_task_t *task0, isc_event_t *event);
|
||||
ISC_TASKFUNC_SCOPE 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);
|
||||
ISC_TASKFUNC_SCOPE unsigned int
|
||||
isc__task_unsend(isc_task_t *task, void *sender, isc_eventtype_t type,
|
||||
void *tag, isc_eventlist_t *events);
|
||||
ISC_TASKFUNC_SCOPE isc_result_t
|
||||
isc__task_onshutdown(isc_task_t *task0, isc_taskaction_t action,
|
||||
const void *arg);
|
||||
ISC_TASKFUNC_SCOPE void
|
||||
isc__task_shutdown(isc_task_t *task0);
|
||||
ISC_TASKFUNC_SCOPE void
|
||||
isc__task_destroy(isc_task_t **taskp);
|
||||
ISC_TASKFUNC_SCOPE void
|
||||
isc__task_setname(isc_task_t *task0, const char *name, void *tag);
|
||||
ISC_TASKFUNC_SCOPE const char *
|
||||
isc__task_getname(isc_task_t *task0);
|
||||
ISC_TASKFUNC_SCOPE void *
|
||||
isc__task_gettag(isc_task_t *task0);
|
||||
ISC_TASKFUNC_SCOPE void
|
||||
isc__task_getcurrenttime(isc_task_t *task0, isc_stdtime_t *t);
|
||||
ISC_TASKFUNC_SCOPE isc_result_t
|
||||
isc__taskmgr_create(isc_mem_t *mctx, unsigned int workers,
|
||||
unsigned int default_quantum, isc_taskmgr_t **managerp);
|
||||
ISC_TASKFUNC_SCOPE void
|
||||
isc__taskmgr_destroy(isc_taskmgr_t **managerp);
|
||||
ISC_TASKFUNC_SCOPE isc_result_t
|
||||
isc__task_beginexclusive(isc_task_t *task);
|
||||
ISC_TASKFUNC_SCOPE void
|
||||
isc__task_endexclusive(isc_task_t *task0);
|
||||
|
||||
static struct isc__taskmethods {
|
||||
isc_taskmethods_t methods;
|
||||
|
||||
/*%
|
||||
* The following are defined just for avoiding unused static functions.
|
||||
*/
|
||||
void *purgeevent, *unsendrange,
|
||||
*getname, *gettag, *getcurrenttime, *beginexclusive,
|
||||
*endexclusive;
|
||||
} taskmethods = {
|
||||
{
|
||||
isc__task_attach,
|
||||
isc__task_detach,
|
||||
isc__task_destroy,
|
||||
isc__task_send,
|
||||
isc__task_sendanddetach,
|
||||
isc__task_unsend,
|
||||
isc__task_onshutdown,
|
||||
isc__task_shutdown,
|
||||
isc__task_setname,
|
||||
isc__task_purge,
|
||||
isc__task_purgerange
|
||||
},
|
||||
isc__task_purgeevent, isc__task_unsendrange,
|
||||
isc__task_getname, isc__task_gettag,
|
||||
isc__task_getcurrenttime, isc__task_beginexclusive,
|
||||
isc__task_endexclusive
|
||||
};
|
||||
|
||||
static isc_taskmgrmethods_t taskmgrmethods = {
|
||||
isc__taskmgr_destroy,
|
||||
isc__task_create
|
||||
};
|
||||
|
||||
/***
|
||||
*** Tasks.
|
||||
***/
|
||||
|
||||
static void
|
||||
task_finished(isc_task_t *task) {
|
||||
isc_taskmgr_t *manager = task->manager;
|
||||
task_finished(isc__task_t *task) {
|
||||
isc__taskmgr_t *manager = task->manager;
|
||||
|
||||
REQUIRE(EMPTY(task->events));
|
||||
REQUIRE(EMPTY(task->on_shutdown));
|
||||
@@ -153,7 +273,7 @@ task_finished(isc_task_t *task) {
|
||||
|
||||
LOCK(&manager->lock);
|
||||
UNLINK(manager->tasks, task, link);
|
||||
#ifdef ISC_PLATFORM_USETHREADS
|
||||
#ifdef USE_WORKER_THREADS
|
||||
if (FINISHED(manager)) {
|
||||
/*
|
||||
* All tasks have completed and the
|
||||
@@ -163,19 +283,21 @@ task_finished(isc_task_t *task) {
|
||||
*/
|
||||
BROADCAST(&manager->work_available);
|
||||
}
|
||||
#endif /* ISC_PLATFORM_USETHREADS */
|
||||
#endif /* USE_WORKER_THREADS */
|
||||
UNLOCK(&manager->lock);
|
||||
|
||||
DESTROYLOCK(&task->lock);
|
||||
task->magic = 0;
|
||||
task->common.impmagic = 0;
|
||||
task->common.magic = 0;
|
||||
isc_mem_put(manager->mctx, task, sizeof(*task));
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_task_create(isc_taskmgr_t *manager, unsigned int quantum,
|
||||
isc_task_t **taskp)
|
||||
ISC_TASKFUNC_SCOPE isc_result_t
|
||||
isc__task_create(isc_taskmgr_t *manager0, unsigned int quantum,
|
||||
isc_task_t **taskp)
|
||||
{
|
||||
isc_task_t *task;
|
||||
isc__taskmgr_t *manager = (isc__taskmgr_t *)manager0;
|
||||
isc__task_t *task;
|
||||
isc_boolean_t exiting;
|
||||
isc_result_t result;
|
||||
|
||||
@@ -220,14 +342,17 @@ isc_task_create(isc_taskmgr_t *manager, unsigned int quantum,
|
||||
return (ISC_R_SHUTTINGDOWN);
|
||||
}
|
||||
|
||||
task->magic = TASK_MAGIC;
|
||||
*taskp = task;
|
||||
task->common.methods = (isc_taskmethods_t *)&taskmethods;
|
||||
task->common.magic = ISCAPI_TASK_MAGIC;
|
||||
task->common.impmagic = TASK_MAGIC;
|
||||
*taskp = (isc_task_t *)task;
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
void
|
||||
isc_task_attach(isc_task_t *source, isc_task_t **targetp) {
|
||||
ISC_TASKFUNC_SCOPE void
|
||||
isc__task_attach(isc_task_t *source0, isc_task_t **targetp) {
|
||||
isc__task_t *source = (isc__task_t *)source0;
|
||||
|
||||
/*
|
||||
* Attach *targetp to source.
|
||||
@@ -242,11 +367,11 @@ isc_task_attach(isc_task_t *source, isc_task_t **targetp) {
|
||||
source->references++;
|
||||
UNLOCK(&source->lock);
|
||||
|
||||
*targetp = source;
|
||||
*targetp = (isc_task_t *)source;
|
||||
}
|
||||
|
||||
static inline isc_boolean_t
|
||||
task_shutdown(isc_task_t *task) {
|
||||
task_shutdown(isc__task_t *task) {
|
||||
isc_boolean_t was_idle = ISC_FALSE;
|
||||
isc_event_t *event, *prev;
|
||||
|
||||
@@ -283,8 +408,8 @@ task_shutdown(isc_task_t *task) {
|
||||
}
|
||||
|
||||
static inline void
|
||||
task_ready(isc_task_t *task) {
|
||||
isc_taskmgr_t *manager = task->manager;
|
||||
task_ready(isc__task_t *task) {
|
||||
isc__taskmgr_t *manager = task->manager;
|
||||
|
||||
REQUIRE(VALID_MANAGER(manager));
|
||||
REQUIRE(task->state == task_state_ready);
|
||||
@@ -294,15 +419,15 @@ task_ready(isc_task_t *task) {
|
||||
LOCK(&manager->lock);
|
||||
|
||||
ENQUEUE(manager->ready_tasks, task, ready_link);
|
||||
#ifdef ISC_PLATFORM_USETHREADS
|
||||
#ifdef USE_WORKER_THREADS
|
||||
SIGNAL(&manager->work_available);
|
||||
#endif /* ISC_PLATFORM_USETHREADS */
|
||||
#endif /* USE_WORKER_THREADS */
|
||||
|
||||
UNLOCK(&manager->lock);
|
||||
}
|
||||
|
||||
static inline isc_boolean_t
|
||||
task_detach(isc_task_t *task) {
|
||||
task_detach(isc__task_t *task) {
|
||||
|
||||
/*
|
||||
* Caller must be holding the task lock.
|
||||
@@ -330,9 +455,9 @@ task_detach(isc_task_t *task) {
|
||||
return (ISC_FALSE);
|
||||
}
|
||||
|
||||
void
|
||||
isc_task_detach(isc_task_t **taskp) {
|
||||
isc_task_t *task;
|
||||
ISC_TASKFUNC_SCOPE void
|
||||
isc__task_detach(isc_task_t **taskp) {
|
||||
isc__task_t *task;
|
||||
isc_boolean_t was_idle;
|
||||
|
||||
/*
|
||||
@@ -340,7 +465,7 @@ isc_task_detach(isc_task_t **taskp) {
|
||||
*/
|
||||
|
||||
REQUIRE(taskp != NULL);
|
||||
task = *taskp;
|
||||
task = (isc__task_t *)*taskp;
|
||||
REQUIRE(VALID_TASK(task));
|
||||
|
||||
XTRACE("isc_task_detach");
|
||||
@@ -356,7 +481,7 @@ isc_task_detach(isc_task_t **taskp) {
|
||||
}
|
||||
|
||||
static inline isc_boolean_t
|
||||
task_send(isc_task_t *task, isc_event_t **eventp) {
|
||||
task_send(isc__task_t *task, isc_event_t **eventp) {
|
||||
isc_boolean_t was_idle = ISC_FALSE;
|
||||
isc_event_t *event;
|
||||
|
||||
@@ -385,8 +510,9 @@ task_send(isc_task_t *task, isc_event_t **eventp) {
|
||||
return (was_idle);
|
||||
}
|
||||
|
||||
void
|
||||
isc_task_send(isc_task_t *task, isc_event_t **eventp) {
|
||||
ISC_TASKFUNC_SCOPE void
|
||||
isc__task_send(isc_task_t *task0, isc_event_t **eventp) {
|
||||
isc__task_t *task = (isc__task_t *)task0;
|
||||
isc_boolean_t was_idle;
|
||||
|
||||
/*
|
||||
@@ -426,10 +552,10 @@ isc_task_send(isc_task_t *task, isc_event_t **eventp) {
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
isc_task_sendanddetach(isc_task_t **taskp, isc_event_t **eventp) {
|
||||
ISC_TASKFUNC_SCOPE void
|
||||
isc__task_sendanddetach(isc_task_t **taskp, isc_event_t **eventp) {
|
||||
isc_boolean_t idle1, idle2;
|
||||
isc_task_t *task;
|
||||
isc__task_t *task;
|
||||
|
||||
/*
|
||||
* Send '*event' to '*taskp' and then detach '*taskp' from its
|
||||
@@ -437,7 +563,7 @@ isc_task_sendanddetach(isc_task_t **taskp, isc_event_t **eventp) {
|
||||
*/
|
||||
|
||||
REQUIRE(taskp != NULL);
|
||||
task = *taskp;
|
||||
task = (isc__task_t *)*taskp;
|
||||
REQUIRE(VALID_TASK(task));
|
||||
|
||||
XTRACE("isc_task_sendanddetach");
|
||||
@@ -463,7 +589,7 @@ isc_task_sendanddetach(isc_task_t **taskp, isc_event_t **eventp) {
|
||||
#define PURGE_OK(event) (((event)->ev_attributes & ISC_EVENTATTR_NOPURGE) == 0)
|
||||
|
||||
static unsigned int
|
||||
dequeue_events(isc_task_t *task, void *sender, isc_eventtype_t first,
|
||||
dequeue_events(isc__task_t *task, void *sender, isc_eventtype_t first,
|
||||
isc_eventtype_t last, void *tag,
|
||||
isc_eventlist_t *events, isc_boolean_t purging)
|
||||
{
|
||||
@@ -502,10 +628,11 @@ dequeue_events(isc_task_t *task, void *sender, isc_eventtype_t first,
|
||||
return (count);
|
||||
}
|
||||
|
||||
unsigned int
|
||||
isc_task_purgerange(isc_task_t *task, void *sender, isc_eventtype_t first,
|
||||
isc_eventtype_t last, void *tag)
|
||||
ISC_TASKFUNC_SCOPE unsigned int
|
||||
isc__task_purgerange(isc_task_t *task0, void *sender, isc_eventtype_t first,
|
||||
isc_eventtype_t last, void *tag)
|
||||
{
|
||||
isc__task_t *task = (isc__task_t *)task0;
|
||||
unsigned int count;
|
||||
isc_eventlist_t events;
|
||||
isc_event_t *event, *next_event;
|
||||
@@ -533,9 +660,9 @@ isc_task_purgerange(isc_task_t *task, void *sender, isc_eventtype_t first,
|
||||
return (count);
|
||||
}
|
||||
|
||||
unsigned int
|
||||
isc_task_purge(isc_task_t *task, void *sender, isc_eventtype_t type,
|
||||
void *tag)
|
||||
ISC_TASKFUNC_SCOPE unsigned int
|
||||
isc__task_purge(isc_task_t *task, void *sender, isc_eventtype_t type,
|
||||
void *tag)
|
||||
{
|
||||
/*
|
||||
* Purge events from a task's event queue.
|
||||
@@ -543,11 +670,12 @@ isc_task_purge(isc_task_t *task, void *sender, isc_eventtype_t type,
|
||||
|
||||
XTRACE("isc_task_purge");
|
||||
|
||||
return (isc_task_purgerange(task, sender, type, type, tag));
|
||||
return (isc__task_purgerange(task, sender, type, type, tag));
|
||||
}
|
||||
|
||||
isc_boolean_t
|
||||
isc_task_purgeevent(isc_task_t *task, isc_event_t *event) {
|
||||
ISC_TASKFUNC_SCOPE isc_boolean_t
|
||||
isc__task_purgeevent(isc_task_t *task0, isc_event_t *event) {
|
||||
isc__task_t *task = (isc__task_t *)task0;
|
||||
isc_event_t *curr_event, *next_event;
|
||||
|
||||
/*
|
||||
@@ -588,10 +716,10 @@ isc_task_purgeevent(isc_task_t *task, isc_event_t *event) {
|
||||
return (ISC_TRUE);
|
||||
}
|
||||
|
||||
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)
|
||||
ISC_TASKFUNC_SCOPE 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)
|
||||
{
|
||||
/*
|
||||
* Remove events from a task's event queue.
|
||||
@@ -599,13 +727,13 @@ isc_task_unsendrange(isc_task_t *task, void *sender, isc_eventtype_t first,
|
||||
|
||||
XTRACE("isc_task_unsendrange");
|
||||
|
||||
return (dequeue_events(task, sender, first, last, tag, events,
|
||||
ISC_FALSE));
|
||||
return (dequeue_events((isc__task_t *)task, sender, first,
|
||||
last, tag, events, ISC_FALSE));
|
||||
}
|
||||
|
||||
unsigned int
|
||||
isc_task_unsend(isc_task_t *task, void *sender, isc_eventtype_t type,
|
||||
void *tag, isc_eventlist_t *events)
|
||||
ISC_TASKFUNC_SCOPE unsigned int
|
||||
isc__task_unsend(isc_task_t *task, void *sender, isc_eventtype_t type,
|
||||
void *tag, isc_eventlist_t *events)
|
||||
{
|
||||
/*
|
||||
* Remove events from a task's event queue.
|
||||
@@ -613,13 +741,15 @@ isc_task_unsend(isc_task_t *task, void *sender, isc_eventtype_t type,
|
||||
|
||||
XTRACE("isc_task_unsend");
|
||||
|
||||
return (dequeue_events(task, sender, type, type, tag, events,
|
||||
ISC_FALSE));
|
||||
return (dequeue_events((isc__task_t *)task, sender, type,
|
||||
type, tag, events, ISC_FALSE));
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_task_onshutdown(isc_task_t *task, isc_taskaction_t action, const void *arg)
|
||||
ISC_TASKFUNC_SCOPE isc_result_t
|
||||
isc__task_onshutdown(isc_task_t *task0, isc_taskaction_t action,
|
||||
const void *arg)
|
||||
{
|
||||
isc__task_t *task = (isc__task_t *)task0;
|
||||
isc_boolean_t disallowed = ISC_FALSE;
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
isc_event_t *event;
|
||||
@@ -655,8 +785,9 @@ isc_task_onshutdown(isc_task_t *task, isc_taskaction_t action, const void *arg)
|
||||
return (result);
|
||||
}
|
||||
|
||||
void
|
||||
isc_task_shutdown(isc_task_t *task) {
|
||||
ISC_TASKFUNC_SCOPE void
|
||||
isc__task_shutdown(isc_task_t *task0) {
|
||||
isc__task_t *task = (isc__task_t *)task0;
|
||||
isc_boolean_t was_idle;
|
||||
|
||||
/*
|
||||
@@ -673,8 +804,8 @@ isc_task_shutdown(isc_task_t *task) {
|
||||
task_ready(task);
|
||||
}
|
||||
|
||||
void
|
||||
isc_task_destroy(isc_task_t **taskp) {
|
||||
ISC_TASKFUNC_SCOPE void
|
||||
isc__task_destroy(isc_task_t **taskp) {
|
||||
|
||||
/*
|
||||
* Destroy '*taskp'.
|
||||
@@ -686,8 +817,9 @@ isc_task_destroy(isc_task_t **taskp) {
|
||||
isc_task_detach(taskp);
|
||||
}
|
||||
|
||||
void
|
||||
isc_task_setname(isc_task_t *task, const char *name, void *tag) {
|
||||
ISC_TASKFUNC_SCOPE void
|
||||
isc__task_setname(isc_task_t *task0, const char *name, void *tag) {
|
||||
isc__task_t *task = (isc__task_t *)task0;
|
||||
|
||||
/*
|
||||
* Name 'task'.
|
||||
@@ -702,18 +834,28 @@ isc_task_setname(isc_task_t *task, const char *name, void *tag) {
|
||||
UNLOCK(&task->lock);
|
||||
}
|
||||
|
||||
const char *
|
||||
isc_task_getname(isc_task_t *task) {
|
||||
ISC_TASKFUNC_SCOPE const char *
|
||||
isc__task_getname(isc_task_t *task0) {
|
||||
isc__task_t *task = (isc__task_t *)task0;
|
||||
|
||||
REQUIRE(VALID_TASK(task));
|
||||
|
||||
return (task->name);
|
||||
}
|
||||
|
||||
void *
|
||||
isc_task_gettag(isc_task_t *task) {
|
||||
ISC_TASKFUNC_SCOPE void *
|
||||
isc__task_gettag(isc_task_t *task0) {
|
||||
isc__task_t *task = (isc__task_t *)task0;
|
||||
|
||||
REQUIRE(VALID_TASK(task));
|
||||
|
||||
return (task->tag);
|
||||
}
|
||||
|
||||
void
|
||||
isc_task_getcurrenttime(isc_task_t *task, isc_stdtime_t *t) {
|
||||
ISC_TASKFUNC_SCOPE void
|
||||
isc__task_getcurrenttime(isc_task_t *task0, isc_stdtime_t *t) {
|
||||
isc__task_t *task = (isc__task_t *)task0;
|
||||
|
||||
REQUIRE(VALID_TASK(task));
|
||||
REQUIRE(t != NULL);
|
||||
|
||||
@@ -728,12 +870,12 @@ isc_task_getcurrenttime(isc_task_t *task, isc_stdtime_t *t) {
|
||||
*** Task Manager.
|
||||
***/
|
||||
static void
|
||||
dispatch(isc_taskmgr_t *manager) {
|
||||
isc_task_t *task;
|
||||
#ifndef ISC_PLATFORM_USETHREADS
|
||||
dispatch(isc__taskmgr_t *manager) {
|
||||
isc__task_t *task;
|
||||
#ifndef USE_WORKER_THREADS
|
||||
unsigned int total_dispatch_count = 0;
|
||||
isc_tasklist_t ready_tasks;
|
||||
#endif /* ISC_PLATFORM_USETHREADS */
|
||||
isc__tasklist_t ready_tasks;
|
||||
#endif /* USE_WORKER_THREADS */
|
||||
|
||||
REQUIRE(VALID_MANAGER(manager));
|
||||
|
||||
@@ -787,12 +929,12 @@ dispatch(isc_taskmgr_t *manager) {
|
||||
* unlocks. The while expression is always protected by the lock.
|
||||
*/
|
||||
|
||||
#ifndef ISC_PLATFORM_USETHREADS
|
||||
#ifndef USE_WORKER_THREADS
|
||||
ISC_LIST_INIT(ready_tasks);
|
||||
#endif
|
||||
LOCK(&manager->lock);
|
||||
while (!FINISHED(manager)) {
|
||||
#ifdef ISC_PLATFORM_USETHREADS
|
||||
#ifdef USE_WORKER_THREADS
|
||||
/*
|
||||
* For reasons similar to those given in the comment in
|
||||
* isc_task_send() above, it is safe for us to dequeue
|
||||
@@ -812,11 +954,11 @@ dispatch(isc_taskmgr_t *manager) {
|
||||
ISC_MSGSET_TASK,
|
||||
ISC_MSG_AWAKE, "awake"));
|
||||
}
|
||||
#else /* ISC_PLATFORM_USETHREADS */
|
||||
#else /* USE_WORKER_THREADS */
|
||||
if (total_dispatch_count >= DEFAULT_TASKMGR_QUANTUM ||
|
||||
EMPTY(manager->ready_tasks))
|
||||
break;
|
||||
#endif /* ISC_PLATFORM_USETHREADS */
|
||||
#endif /* USE_WORKER_THREADS */
|
||||
XTHREADTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_TASK,
|
||||
ISC_MSG_WORKING, "working"));
|
||||
|
||||
@@ -859,13 +1001,15 @@ dispatch(isc_taskmgr_t *manager) {
|
||||
"execute action"));
|
||||
if (event->ev_action != NULL) {
|
||||
UNLOCK(&task->lock);
|
||||
(event->ev_action)(task,event);
|
||||
(event->ev_action)(
|
||||
(isc_task_t *)task,
|
||||
event);
|
||||
LOCK(&task->lock);
|
||||
}
|
||||
dispatch_count++;
|
||||
#ifndef ISC_PLATFORM_USETHREADS
|
||||
#ifndef USE_WORKER_THREADS
|
||||
total_dispatch_count++;
|
||||
#endif /* ISC_PLATFORM_USETHREADS */
|
||||
#endif /* USE_WORKER_THREADS */
|
||||
}
|
||||
|
||||
if (task->references == 0 &&
|
||||
@@ -950,12 +1094,12 @@ dispatch(isc_taskmgr_t *manager) {
|
||||
|
||||
LOCK(&manager->lock);
|
||||
manager->tasks_running--;
|
||||
#ifdef ISC_PLATFORM_USETHREADS
|
||||
#ifdef USE_WORKER_THREADS
|
||||
if (manager->exclusive_requested &&
|
||||
manager->tasks_running == 1) {
|
||||
SIGNAL(&manager->exclusive_granted);
|
||||
}
|
||||
#endif /* ISC_PLATFORM_USETHREADS */
|
||||
#endif /* USE_WORKER_THREADS */
|
||||
if (requeue) {
|
||||
/*
|
||||
* We know we're awake, so we don't have
|
||||
@@ -976,7 +1120,7 @@ dispatch(isc_taskmgr_t *manager) {
|
||||
* were usually nonempty, the 'optimization'
|
||||
* might even hurt rather than help.
|
||||
*/
|
||||
#ifdef ISC_PLATFORM_USETHREADS
|
||||
#ifdef USE_WORKER_THREADS
|
||||
ENQUEUE(manager->ready_tasks, task,
|
||||
ready_link);
|
||||
#else
|
||||
@@ -985,19 +1129,19 @@ dispatch(isc_taskmgr_t *manager) {
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifndef ISC_PLATFORM_USETHREADS
|
||||
#ifndef USE_WORKER_THREADS
|
||||
ISC_LIST_APPENDLIST(manager->ready_tasks, ready_tasks, ready_link);
|
||||
#endif
|
||||
UNLOCK(&manager->lock);
|
||||
}
|
||||
|
||||
#ifdef ISC_PLATFORM_USETHREADS
|
||||
#ifdef USE_WORKER_THREADS
|
||||
static isc_threadresult_t
|
||||
#ifdef _WIN32
|
||||
WINAPI
|
||||
#endif
|
||||
run(void *uap) {
|
||||
isc_taskmgr_t *manager = uap;
|
||||
isc__taskmgr_t *manager = uap;
|
||||
|
||||
XTHREADTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
|
||||
ISC_MSG_STARTING, "starting"));
|
||||
@@ -1009,31 +1153,36 @@ run(void *uap) {
|
||||
|
||||
return ((isc_threadresult_t)0);
|
||||
}
|
||||
#endif /* ISC_PLATFORM_USETHREADS */
|
||||
#endif /* USE_WORKER_THREADS */
|
||||
|
||||
static void
|
||||
manager_free(isc_taskmgr_t *manager) {
|
||||
manager_free(isc__taskmgr_t *manager) {
|
||||
isc_mem_t *mctx;
|
||||
|
||||
#ifdef ISC_PLATFORM_USETHREADS
|
||||
#ifdef USE_WORKER_THREADS
|
||||
(void)isc_condition_destroy(&manager->exclusive_granted);
|
||||
(void)isc_condition_destroy(&manager->work_available);
|
||||
isc_mem_free(manager->mctx, manager->threads);
|
||||
#endif /* ISC_PLATFORM_USETHREADS */
|
||||
#endif /* USE_WORKER_THREADS */
|
||||
DESTROYLOCK(&manager->lock);
|
||||
manager->magic = 0;
|
||||
manager->common.impmagic = 0;
|
||||
manager->common.magic = 0;
|
||||
mctx = manager->mctx;
|
||||
isc_mem_put(mctx, manager, sizeof(*manager));
|
||||
isc_mem_detach(&mctx);
|
||||
|
||||
#ifdef USE_SHARED_MANAGER
|
||||
taskmgr = NULL;
|
||||
#endif /* USE_SHARED_MANAGER */
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers,
|
||||
unsigned int default_quantum, isc_taskmgr_t **managerp)
|
||||
ISC_TASKFUNC_SCOPE isc_result_t
|
||||
isc__taskmgr_create(isc_mem_t *mctx, unsigned int workers,
|
||||
unsigned int default_quantum, isc_taskmgr_t **managerp)
|
||||
{
|
||||
isc_result_t result;
|
||||
unsigned int i, started = 0;
|
||||
isc_taskmgr_t *manager;
|
||||
isc__taskmgr_t *manager;
|
||||
|
||||
/*
|
||||
* Create a new task manager.
|
||||
@@ -1042,28 +1191,31 @@ isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers,
|
||||
REQUIRE(workers > 0);
|
||||
REQUIRE(managerp != NULL && *managerp == NULL);
|
||||
|
||||
#ifndef ISC_PLATFORM_USETHREADS
|
||||
#ifndef USE_WORKER_THREADS
|
||||
UNUSED(i);
|
||||
UNUSED(started);
|
||||
UNUSED(workers);
|
||||
#endif
|
||||
|
||||
#ifdef USE_SHARED_MANAGER
|
||||
if (taskmgr != NULL) {
|
||||
taskmgr->refs++;
|
||||
*managerp = taskmgr;
|
||||
*managerp = (isc_taskmgr_t *)taskmgr;
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
#endif /* ISC_PLATFORM_USETHREADS */
|
||||
#endif /* USE_SHARED_MANAGER */
|
||||
|
||||
manager = isc_mem_get(mctx, sizeof(*manager));
|
||||
if (manager == NULL)
|
||||
return (ISC_R_NOMEMORY);
|
||||
manager->magic = TASK_MANAGER_MAGIC;
|
||||
manager->common.methods = &taskmgrmethods;
|
||||
manager->common.impmagic = TASK_MANAGER_MAGIC;
|
||||
manager->common.magic = ISCAPI_TASKMGR_MAGIC;
|
||||
manager->mctx = NULL;
|
||||
result = isc_mutex_init(&manager->lock);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup_mgr;
|
||||
|
||||
#ifdef ISC_PLATFORM_USETHREADS
|
||||
#ifdef USE_WORKER_THREADS
|
||||
manager->workers = 0;
|
||||
manager->threads = isc_mem_allocate(mctx,
|
||||
workers * sizeof(isc_thread_t));
|
||||
@@ -1087,7 +1239,7 @@ isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers,
|
||||
result = ISC_R_UNEXPECTED;
|
||||
goto cleanup_workavailable;
|
||||
}
|
||||
#endif /* ISC_PLATFORM_USETHREADS */
|
||||
#endif /* USE_WORKER_THREADS */
|
||||
if (default_quantum == 0)
|
||||
default_quantum = DEFAULT_DEFAULT_QUANTUM;
|
||||
manager->default_quantum = default_quantum;
|
||||
@@ -1099,7 +1251,7 @@ isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers,
|
||||
|
||||
isc_mem_attach(mctx, &manager->mctx);
|
||||
|
||||
#ifdef ISC_PLATFORM_USETHREADS
|
||||
#ifdef USE_WORKER_THREADS
|
||||
LOCK(&manager->lock);
|
||||
/*
|
||||
* Start workers.
|
||||
@@ -1119,16 +1271,17 @@ isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers,
|
||||
return (ISC_R_NOTHREADS);
|
||||
}
|
||||
isc_thread_setconcurrency(workers);
|
||||
#else /* ISC_PLATFORM_USETHREADS */
|
||||
#endif /* USE_WORKER_THREADS */
|
||||
#ifdef USE_SHARED_MANAGER
|
||||
manager->refs = 1;
|
||||
taskmgr = manager;
|
||||
#endif /* ISC_PLATFORM_USETHREADS */
|
||||
#endif /* USE_SHARED_MANAGER */
|
||||
|
||||
*managerp = manager;
|
||||
*managerp = (isc_taskmgr_t *)manager;
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
#ifdef ISC_PLATFORM_USETHREADS
|
||||
#ifdef USE_WORKER_THREADS
|
||||
cleanup_workavailable:
|
||||
(void)isc_condition_destroy(&manager->work_available);
|
||||
cleanup_threads:
|
||||
@@ -1141,10 +1294,10 @@ isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers,
|
||||
return (result);
|
||||
}
|
||||
|
||||
void
|
||||
isc_taskmgr_destroy(isc_taskmgr_t **managerp) {
|
||||
isc_taskmgr_t *manager;
|
||||
isc_task_t *task;
|
||||
ISC_TASKFUNC_SCOPE void
|
||||
isc__taskmgr_destroy(isc_taskmgr_t **managerp) {
|
||||
isc__taskmgr_t *manager;
|
||||
isc__task_t *task;
|
||||
unsigned int i;
|
||||
|
||||
/*
|
||||
@@ -1152,18 +1305,20 @@ isc_taskmgr_destroy(isc_taskmgr_t **managerp) {
|
||||
*/
|
||||
|
||||
REQUIRE(managerp != NULL);
|
||||
manager = *managerp;
|
||||
manager = (isc__taskmgr_t *)*managerp;
|
||||
REQUIRE(VALID_MANAGER(manager));
|
||||
|
||||
#ifndef ISC_PLATFORM_USETHREADS
|
||||
#ifndef USE_WORKER_THREADS
|
||||
UNUSED(i);
|
||||
#endif /* USE_WORKER_THREADS */
|
||||
|
||||
#ifdef USE_SHARED_MANAGER
|
||||
if (manager->refs > 1) {
|
||||
manager->refs--;
|
||||
*managerp = NULL;
|
||||
return;
|
||||
}
|
||||
#endif /* ISC_PLATFORM_USETHREADS */
|
||||
#endif
|
||||
|
||||
XTHREADTRACE("isc_taskmgr_destroy");
|
||||
/*
|
||||
@@ -1203,7 +1358,7 @@ isc_taskmgr_destroy(isc_taskmgr_t **managerp) {
|
||||
ENQUEUE(manager->ready_tasks, task, ready_link);
|
||||
UNLOCK(&task->lock);
|
||||
}
|
||||
#ifdef ISC_PLATFORM_USETHREADS
|
||||
#ifdef USE_WORKER_THREADS
|
||||
/*
|
||||
* Wake up any sleeping workers. This ensures we get work done if
|
||||
* there's work left to do, and if there are already no tasks left
|
||||
@@ -1217,36 +1372,48 @@ isc_taskmgr_destroy(isc_taskmgr_t **managerp) {
|
||||
*/
|
||||
for (i = 0; i < manager->workers; i++)
|
||||
(void)isc_thread_join(manager->threads[i], NULL);
|
||||
#else /* ISC_PLATFORM_USETHREADS */
|
||||
#else /* USE_WORKER_THREADS */
|
||||
/*
|
||||
* Dispatch the shutdown events.
|
||||
*/
|
||||
UNLOCK(&manager->lock);
|
||||
while (isc__taskmgr_ready())
|
||||
(void)isc__taskmgr_dispatch();
|
||||
while (isc__taskmgr_ready((isc_taskmgr_t *)manager))
|
||||
(void)isc__taskmgr_dispatch((isc_taskmgr_t *)manager);
|
||||
#ifdef BIND9
|
||||
if (!ISC_LIST_EMPTY(manager->tasks))
|
||||
isc_mem_printallactive(stderr);
|
||||
#endif
|
||||
INSIST(ISC_LIST_EMPTY(manager->tasks));
|
||||
#endif /* ISC_PLATFORM_USETHREADS */
|
||||
#endif /* USE_WORKER_THREADS */
|
||||
|
||||
manager_free(manager);
|
||||
|
||||
*managerp = NULL;
|
||||
}
|
||||
|
||||
#ifndef ISC_PLATFORM_USETHREADS
|
||||
#ifndef USE_WORKER_THREADS
|
||||
isc_boolean_t
|
||||
isc__taskmgr_ready(void) {
|
||||
if (taskmgr == NULL)
|
||||
isc__taskmgr_ready(isc_taskmgr_t *manager0) {
|
||||
isc__taskmgr_t *manager = (isc__taskmgr_t *)manager0;
|
||||
|
||||
#ifdef USE_SHARED_MANAGER
|
||||
if (manager == NULL)
|
||||
manager = taskmgr;
|
||||
#endif
|
||||
if (manager == NULL)
|
||||
return (ISC_FALSE);
|
||||
return (ISC_TF(!ISC_LIST_EMPTY(taskmgr->ready_tasks)));
|
||||
return (ISC_TF(!ISC_LIST_EMPTY(manager->ready_tasks)));
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc__taskmgr_dispatch(void) {
|
||||
isc_taskmgr_t *manager = taskmgr;
|
||||
isc__taskmgr_dispatch(isc_taskmgr_t *manager0) {
|
||||
isc__taskmgr_t *manager = (isc__taskmgr_t *)manager0;
|
||||
|
||||
if (taskmgr == NULL)
|
||||
#ifdef USE_SHARED_MANAGER
|
||||
if (manager == NULL)
|
||||
manager = taskmgr;
|
||||
#endif
|
||||
if (manager == NULL)
|
||||
return (ISC_R_NOTFOUND);
|
||||
|
||||
dispatch(manager);
|
||||
@@ -1254,12 +1421,13 @@ isc__taskmgr_dispatch(void) {
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
#endif /* ISC_PLATFORM_USETHREADS */
|
||||
#endif /* USE_WORKER_THREADS */
|
||||
|
||||
isc_result_t
|
||||
isc_task_beginexclusive(isc_task_t *task) {
|
||||
#ifdef ISC_PLATFORM_USETHREADS
|
||||
isc_taskmgr_t *manager = task->manager;
|
||||
ISC_TASKFUNC_SCOPE isc_result_t
|
||||
isc__task_beginexclusive(isc_task_t *task0) {
|
||||
#ifdef USE_WORKER_THREADS
|
||||
isc__task_t *task = (isc__task_t *)task0;
|
||||
isc__taskmgr_t *manager = task->manager;
|
||||
REQUIRE(task->state == task_state_running);
|
||||
LOCK(&manager->lock);
|
||||
if (manager->exclusive_requested) {
|
||||
@@ -1272,15 +1440,17 @@ isc_task_beginexclusive(isc_task_t *task) {
|
||||
}
|
||||
UNLOCK(&manager->lock);
|
||||
#else
|
||||
UNUSED(task);
|
||||
UNUSED(task0);
|
||||
#endif
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
void
|
||||
isc_task_endexclusive(isc_task_t *task) {
|
||||
#ifdef ISC_PLATFORM_USETHREADS
|
||||
isc_taskmgr_t *manager = task->manager;
|
||||
ISC_TASKFUNC_SCOPE void
|
||||
isc__task_endexclusive(isc_task_t *task0) {
|
||||
#ifdef USE_WORKER_THREADS
|
||||
isc__task_t *task = (isc__task_t *)task0;
|
||||
isc__taskmgr_t *manager = task->manager;
|
||||
|
||||
REQUIRE(task->state == task_state_running);
|
||||
LOCK(&manager->lock);
|
||||
REQUIRE(manager->exclusive_requested);
|
||||
@@ -1288,16 +1458,22 @@ isc_task_endexclusive(isc_task_t *task) {
|
||||
BROADCAST(&manager->work_available);
|
||||
UNLOCK(&manager->lock);
|
||||
#else
|
||||
UNUSED(task);
|
||||
UNUSED(task0);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBXML2
|
||||
#ifdef USE_SOCKETIMPREGISTER
|
||||
isc_result_t
|
||||
isc__task_register() {
|
||||
return (isc_task_register(isc__taskmgr_create));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_LIBXML2) && defined(BIND9)
|
||||
void
|
||||
isc_taskmgr_renderxml(isc_taskmgr_t *mgr, xmlTextWriterPtr writer)
|
||||
{
|
||||
isc_task_t *task;
|
||||
isc_taskmgr_renderxml(isc_taskmgr_t *mgr0, xmlTextWriterPtr writer) {
|
||||
isc__taskmgr_t *mgr = (isc__taskmgr_t *)mgr0;
|
||||
isc__task_t *task;
|
||||
|
||||
LOCK(&mgr->lock);
|
||||
|
||||
@@ -1373,4 +1549,4 @@ isc_taskmgr_renderxml(isc_taskmgr_t *mgr, xmlTextWriterPtr writer)
|
||||
|
||||
UNLOCK(&mgr->lock);
|
||||
}
|
||||
#endif /* HAVE_LIBXML2 */
|
||||
#endif /* HAVE_LIBXML2 && BIND9 */
|
||||
|
Reference in New Issue
Block a user