2
0
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:
Tatuya JINMEI 神明達哉
2009-09-01 00:22:28 +00:00
parent ad671240d6
commit 307d208450
193 changed files with 18162 additions and 1332 deletions

View File

@@ -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 */