mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-30 14:07:59 +00:00
update
This commit is contained in:
@@ -10,17 +10,14 @@
|
|||||||
#include <isc/thread.h>
|
#include <isc/thread.h>
|
||||||
|
|
||||||
mem_context_t mctx = NULL;
|
mem_context_t mctx = NULL;
|
||||||
os_mutex_t timer_lock;
|
|
||||||
os_condition_t timer_wakeup;
|
|
||||||
|
|
||||||
/*ARGSUSED*/
|
/*ARGSUSED*/
|
||||||
static boolean_t
|
static boolean_t
|
||||||
my_callback(task_t __attribute__((unused)) task,
|
my_callback(task_t __attribute__((unused)) task,
|
||||||
void *arg,
|
|
||||||
task_event_t __attribute__((unused)) event)
|
task_event_t __attribute__((unused)) event)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
char *name = arg;
|
char *name = event->arg;
|
||||||
|
|
||||||
j = 0;
|
j = 0;
|
||||||
for (i = 0; i < 100000000; i++)
|
for (i = 0; i < 100000000; i++)
|
||||||
@@ -33,10 +30,9 @@ my_callback(task_t __attribute__((unused)) task,
|
|||||||
/*ARGSUSED*/
|
/*ARGSUSED*/
|
||||||
static boolean_t
|
static boolean_t
|
||||||
my_shutdown(task_t __attribute__((unused)) task,
|
my_shutdown(task_t __attribute__((unused)) task,
|
||||||
void *arg,
|
|
||||||
task_event_t __attribute__((unused)) event)
|
task_event_t __attribute__((unused)) event)
|
||||||
{
|
{
|
||||||
char *name = arg;
|
char *name = event->arg;
|
||||||
|
|
||||||
printf("shutdown %s\n", name);
|
printf("shutdown %s\n", name);
|
||||||
return (TRUE);
|
return (TRUE);
|
||||||
@@ -45,50 +41,25 @@ my_shutdown(task_t __attribute__((unused)) task,
|
|||||||
/*ARGSUSED*/
|
/*ARGSUSED*/
|
||||||
static boolean_t
|
static boolean_t
|
||||||
my_tick(task_t __attribute__((unused)) task,
|
my_tick(task_t __attribute__((unused)) task,
|
||||||
void *arg,
|
|
||||||
task_event_t __attribute__((unused)) event)
|
task_event_t __attribute__((unused)) event)
|
||||||
{
|
{
|
||||||
char *name = arg;
|
char *name = event->arg;
|
||||||
|
|
||||||
printf("tick %s\n", name);
|
printf("tick %s\n", name);
|
||||||
return (FALSE);
|
return (FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*ARGSUSED*/
|
|
||||||
static boolean_t
|
|
||||||
wakeup_timer(task_t __attribute__((unused)) task,
|
|
||||||
void *arg,
|
|
||||||
task_event_t __attribute__((unused)) event)
|
|
||||||
{
|
|
||||||
printf("wakeup timer\n");
|
|
||||||
(void)os_condition_broadcast(&timer_wakeup);
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *
|
void *
|
||||||
simple_timer_run(void *arg) {
|
simple_timer_run(void *arg) {
|
||||||
task_t task = arg;
|
task_t task = arg;
|
||||||
task_event_t event;
|
task_event_t event;
|
||||||
int i;
|
int i;
|
||||||
struct timespec ts;
|
|
||||||
struct timeval tv;
|
|
||||||
struct timeval tv1;
|
|
||||||
boolean_t timeout;
|
|
||||||
|
|
||||||
for (i = 0; i < 5; i++) {
|
for (i = 0; i < 10; i++) {
|
||||||
(void)gettimeofday(&tv, NULL);
|
sleep(1);
|
||||||
ts.tv_sec = tv.tv_sec + 5;
|
|
||||||
ts.tv_nsec = 0;
|
|
||||||
(void)os_mutex_lock(&timer_lock);
|
|
||||||
(void)os_condition_waituntil(&timer_wakeup, &timer_lock, &ts,
|
|
||||||
&timeout);
|
|
||||||
(void)os_mutex_unlock(&timer_lock);
|
|
||||||
(void)gettimeofday(&tv1, NULL);
|
|
||||||
printf("slept %d secs\n", tv1.tv_sec - tv.tv_sec);
|
|
||||||
if (timeout)
|
|
||||||
printf("timer timeout\n");
|
|
||||||
printf("sending timer to %p\n", task);
|
printf("sending timer to %p\n", task);
|
||||||
event = task_event_allocate(mctx, 2, my_tick, NULL, sizeof *event);
|
event = task_event_allocate(mctx, 2, my_tick, "foo",
|
||||||
|
sizeof *event);
|
||||||
INSIST(event != NULL);
|
INSIST(event != NULL);
|
||||||
(void)task_send_event(task, &event);
|
(void)task_send_event(task, &event);
|
||||||
}
|
}
|
||||||
@@ -104,8 +75,6 @@ simple_timer_init(task_t task) {
|
|||||||
|
|
||||||
task_clone = NULL;
|
task_clone = NULL;
|
||||||
task_attach(task, &task_clone);
|
task_attach(task, &task_clone);
|
||||||
(void)os_mutex_init(&timer_lock);
|
|
||||||
(void)os_condition_init(&timer_wakeup);
|
|
||||||
INSIST(os_thread_create(simple_timer_run, task_clone, &t));
|
INSIST(os_thread_create(simple_timer_run, task_clone, &t));
|
||||||
(void)os_thread_detach(t);
|
(void)os_thread_detach(t);
|
||||||
}
|
}
|
||||||
@@ -128,10 +97,10 @@ main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
INSIST(task_manager_create(mctx, workers, 0, &manager) == workers);
|
INSIST(task_manager_create(mctx, workers, 0, &manager) == workers);
|
||||||
|
|
||||||
INSIST(task_create(manager, "1", my_shutdown, 0, &t1));
|
INSIST(task_create(manager, my_shutdown, "1", 0, &t1));
|
||||||
INSIST(task_create(manager, "2", my_shutdown, 0, &t2));
|
INSIST(task_create(manager, my_shutdown, "2", 0, &t2));
|
||||||
INSIST(task_create(manager, "3", my_shutdown, 0, &t3));
|
INSIST(task_create(manager, my_shutdown, "3", 0, &t3));
|
||||||
INSIST(task_create(manager, "4", my_shutdown, 0, &t4));
|
INSIST(task_create(manager, my_shutdown, "4", 0, &t4));
|
||||||
|
|
||||||
simple_timer_init(t1);
|
simple_timer_init(t1);
|
||||||
simple_timer_init(t2);
|
simple_timer_init(t2);
|
||||||
@@ -139,35 +108,33 @@ main(int argc, char *argv[]) {
|
|||||||
printf("task 2 = %p\n", t2);
|
printf("task 2 = %p\n", t2);
|
||||||
sleep(2);
|
sleep(2);
|
||||||
|
|
||||||
event = task_event_allocate(mctx, 1, my_callback, NULL, sizeof *event);
|
event = task_event_allocate(mctx, 1, my_callback, "1", sizeof *event);
|
||||||
task_send_event(t1, &event);
|
task_send_event(t1, &event);
|
||||||
event = task_event_allocate(mctx, 1, wakeup_timer, NULL, sizeof *event);
|
event = task_event_allocate(mctx, 1, my_callback, "1", sizeof *event);
|
||||||
task_send_event(t1, &event);
|
task_send_event(t1, &event);
|
||||||
event = task_event_allocate(mctx, 1, my_callback, NULL, sizeof *event);
|
event = task_event_allocate(mctx, 1, my_callback, "1", sizeof *event);
|
||||||
task_send_event(t1, &event);
|
task_send_event(t1, &event);
|
||||||
event = task_event_allocate(mctx, 1, my_callback, NULL, sizeof *event);
|
event = task_event_allocate(mctx, 1, my_callback, "1", sizeof *event);
|
||||||
task_send_event(t1, &event);
|
task_send_event(t1, &event);
|
||||||
event = task_event_allocate(mctx, 1, my_callback, NULL, sizeof *event);
|
event = task_event_allocate(mctx, 1, my_callback, "1", sizeof *event);
|
||||||
task_send_event(t1, &event);
|
task_send_event(t1, &event);
|
||||||
event = task_event_allocate(mctx, 1, my_callback, NULL, sizeof *event);
|
event = task_event_allocate(mctx, 1, my_callback, "1", sizeof *event);
|
||||||
task_send_event(t1, &event);
|
task_send_event(t1, &event);
|
||||||
event = task_event_allocate(mctx, 1, my_callback, NULL, sizeof *event);
|
event = task_event_allocate(mctx, 1, my_callback, "1", sizeof *event);
|
||||||
task_send_event(t1, &event);
|
task_send_event(t1, &event);
|
||||||
event = task_event_allocate(mctx, 1, my_callback, NULL, sizeof *event);
|
event = task_event_allocate(mctx, 1, my_callback, "1", sizeof *event);
|
||||||
task_send_event(t1, &event);
|
task_send_event(t1, &event);
|
||||||
event = task_event_allocate(mctx, 1, my_callback, NULL, sizeof *event);
|
event = task_event_allocate(mctx, 1, my_callback, "2", sizeof *event);
|
||||||
task_send_event(t1, &event);
|
|
||||||
event = task_event_allocate(mctx, 1, my_callback, NULL, sizeof *event);
|
|
||||||
task_send_event(t2, &event);
|
task_send_event(t2, &event);
|
||||||
event = task_event_allocate(mctx, 1, my_callback, NULL, sizeof *event);
|
event = task_event_allocate(mctx, 1, my_callback, "3", sizeof *event);
|
||||||
task_send_event(t3, &event);
|
task_send_event(t3, &event);
|
||||||
event = task_event_allocate(mctx, 1, my_callback, NULL, sizeof *event);
|
event = task_event_allocate(mctx, 1, my_callback, "4", sizeof *event);
|
||||||
task_send_event(t4, &event);
|
task_send_event(t4, &event);
|
||||||
event = task_event_allocate(mctx, 1, my_callback, NULL, sizeof *event);
|
event = task_event_allocate(mctx, 1, my_callback, "2", sizeof *event);
|
||||||
task_send_event(t2, &event);
|
task_send_event(t2, &event);
|
||||||
event = task_event_allocate(mctx, 1, my_callback, NULL, sizeof *event);
|
event = task_event_allocate(mctx, 1, my_callback, "3", sizeof *event);
|
||||||
task_send_event(t3, &event);
|
task_send_event(t3, &event);
|
||||||
event = task_event_allocate(mctx, 1, my_callback, NULL, sizeof *event);
|
event = task_event_allocate(mctx, 1, my_callback, "4", sizeof *event);
|
||||||
task_send_event(t4, &event);
|
task_send_event(t4, &event);
|
||||||
|
|
||||||
task_detach(&t1);
|
task_detach(&t1);
|
||||||
|
@@ -30,8 +30,7 @@ typedef struct task_manager * task_manager_t;
|
|||||||
*/
|
*/
|
||||||
typedef int task_eventtype_t;
|
typedef int task_eventtype_t;
|
||||||
|
|
||||||
typedef boolean_t (*task_action_t)(task_t, void *,
|
typedef boolean_t (*task_action_t)(task_t, task_event_t);
|
||||||
task_event_t);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This structure is public because "subclassing" it may be useful when
|
* This structure is public because "subclassing" it may be useful when
|
||||||
@@ -46,6 +45,9 @@ struct task_event {
|
|||||||
LINK(struct task_event) link;
|
LINK(struct task_event) link;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define TASK_EVENT_NOP 0
|
||||||
|
#define TASK_EVENT_SHUTDOWN (-1)
|
||||||
|
|
||||||
typedef LIST(struct task_event) task_eventlist_t;
|
typedef LIST(struct task_event) task_eventlist_t;
|
||||||
|
|
||||||
task_event_t task_event_allocate(mem_context_t,
|
task_event_t task_event_allocate(mem_context_t,
|
||||||
@@ -61,8 +63,8 @@ void task_event_free(task_event_t *);
|
|||||||
***/
|
***/
|
||||||
|
|
||||||
boolean_t task_create(task_manager_t,
|
boolean_t task_create(task_manager_t,
|
||||||
void *,
|
|
||||||
task_action_t,
|
task_action_t,
|
||||||
|
void *,
|
||||||
unsigned int,
|
unsigned int,
|
||||||
task_t *);
|
task_t *);
|
||||||
void task_attach(task_t, task_t *);
|
void task_attach(task_t, task_t *);
|
||||||
|
195
lib/isc/task.c
195
lib/isc/task.c
@@ -53,9 +53,8 @@ struct task {
|
|||||||
unsigned int references;
|
unsigned int references;
|
||||||
task_eventlist_t events;
|
task_eventlist_t events;
|
||||||
unsigned int quantum;
|
unsigned int quantum;
|
||||||
boolean_t shutdown_pending;
|
boolean_t enqueue_allowed;
|
||||||
task_action_t shutdown_action;
|
task_event_t shutdown_event;
|
||||||
void * arg;
|
|
||||||
/* Locked by task manager lock. */
|
/* Locked by task manager lock. */
|
||||||
LINK(struct task) link;
|
LINK(struct task) link;
|
||||||
LINK(struct task) ready_link;
|
LINK(struct task) ready_link;
|
||||||
@@ -83,6 +82,56 @@ struct task_manager {
|
|||||||
#define DEFAULT_DEFAULT_QUANTUM 5
|
#define DEFAULT_DEFAULT_QUANTUM 5
|
||||||
#define FINISHED(m) ((m)->exiting && EMPTY((m)->tasks))
|
#define FINISHED(m) ((m)->exiting && EMPTY((m)->tasks))
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
*** Events.
|
||||||
|
***/
|
||||||
|
|
||||||
|
static inline task_event_t
|
||||||
|
event_allocate(mem_context_t mctx, task_eventtype_t type,
|
||||||
|
task_action_t action, void *arg, size_t size)
|
||||||
|
{
|
||||||
|
task_event_t event;
|
||||||
|
|
||||||
|
event = mem_get(mctx, size);
|
||||||
|
if (event == NULL)
|
||||||
|
return (NULL);
|
||||||
|
event->mctx = mctx;
|
||||||
|
event->size = size;
|
||||||
|
event->type = type;
|
||||||
|
event->action = action;
|
||||||
|
event->arg = arg;
|
||||||
|
|
||||||
|
return (event);
|
||||||
|
}
|
||||||
|
|
||||||
|
task_event_t
|
||||||
|
task_event_allocate(mem_context_t mctx, task_eventtype_t type,
|
||||||
|
task_action_t action, void *arg, size_t size)
|
||||||
|
{
|
||||||
|
if (size < sizeof (struct task_event))
|
||||||
|
return (NULL);
|
||||||
|
if (type < 0)
|
||||||
|
return (NULL);
|
||||||
|
if (action == NULL)
|
||||||
|
return (NULL);
|
||||||
|
|
||||||
|
return (event_allocate(mctx, type, action, arg, size));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
task_event_free(task_event_t *eventp) {
|
||||||
|
task_event_t event;
|
||||||
|
|
||||||
|
REQUIRE(eventp != NULL);
|
||||||
|
event = *eventp;
|
||||||
|
REQUIRE(event != NULL);
|
||||||
|
|
||||||
|
mem_put(event->mctx, event, event->size);
|
||||||
|
|
||||||
|
*eventp = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/***
|
/***
|
||||||
*** Tasks.
|
*** Tasks.
|
||||||
***/
|
***/
|
||||||
@@ -107,14 +156,15 @@ task_free(task_t task) {
|
|||||||
}
|
}
|
||||||
UNLOCK(&manager->lock);
|
UNLOCK(&manager->lock);
|
||||||
(void)os_mutex_destroy(&task->lock);
|
(void)os_mutex_destroy(&task->lock);
|
||||||
|
if (task->shutdown_event != NULL)
|
||||||
|
task_event_free(&task->shutdown_event);
|
||||||
task->magic = 0;
|
task->magic = 0;
|
||||||
mem_put(manager->mctx, task, sizeof *task);
|
mem_put(manager->mctx, task, sizeof *task);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean_t
|
boolean_t
|
||||||
task_create(task_manager_t manager, void *arg,
|
task_create(task_manager_t manager, task_action_t shutdown_action,
|
||||||
task_action_t shutdown_action, unsigned int quantum,
|
void *shutdown_arg, unsigned int quantum, task_t *taskp)
|
||||||
task_t *taskp)
|
|
||||||
{
|
{
|
||||||
task_t task;
|
task_t task;
|
||||||
|
|
||||||
@@ -135,9 +185,17 @@ task_create(task_manager_t manager, void *arg,
|
|||||||
task->references = 1;
|
task->references = 1;
|
||||||
INIT_LIST(task->events);
|
INIT_LIST(task->events);
|
||||||
task->quantum = quantum;
|
task->quantum = quantum;
|
||||||
task->shutdown_pending = FALSE;
|
task->enqueue_allowed = TRUE;
|
||||||
task->arg = arg;
|
task->shutdown_event = event_allocate(manager->mctx,
|
||||||
task->shutdown_action = shutdown_action;
|
TASK_EVENT_SHUTDOWN,
|
||||||
|
shutdown_action,
|
||||||
|
shutdown_arg,
|
||||||
|
sizeof *task->shutdown_event);
|
||||||
|
if (task->shutdown_event == NULL) {
|
||||||
|
(void)os_mutex_destroy(&task->lock);
|
||||||
|
mem_put(manager->mctx, task, sizeof *task);
|
||||||
|
return (FALSE);
|
||||||
|
}
|
||||||
INIT_LINK(task, link);
|
INIT_LINK(task, link);
|
||||||
INIT_LINK(task, ready_link);
|
INIT_LINK(task, ready_link);
|
||||||
|
|
||||||
@@ -204,6 +262,7 @@ task_send_event(task_t task, task_event_t *eventp) {
|
|||||||
REQUIRE(eventp != NULL);
|
REQUIRE(eventp != NULL);
|
||||||
event = *eventp;
|
event = *eventp;
|
||||||
REQUIRE(event != NULL);
|
REQUIRE(event != NULL);
|
||||||
|
REQUIRE(event->type >= 0);
|
||||||
|
|
||||||
XTRACE("sending");
|
XTRACE("sending");
|
||||||
/*
|
/*
|
||||||
@@ -212,7 +271,7 @@ task_send_event(task_t task, task_event_t *eventp) {
|
|||||||
* some processing is deferred until after a lock is released.
|
* some processing is deferred until after a lock is released.
|
||||||
*/
|
*/
|
||||||
LOCK(&task->lock);
|
LOCK(&task->lock);
|
||||||
if (task->state != task_state_shutdown && !task->shutdown_pending) {
|
if (task->enqueue_allowed) {
|
||||||
if (task->state == task_state_idle) {
|
if (task->state == task_state_idle) {
|
||||||
was_idle = TRUE;
|
was_idle = TRUE;
|
||||||
INSIST(EMPTY(task->events));
|
INSIST(EMPTY(task->events));
|
||||||
@@ -289,7 +348,7 @@ task_shutdown(task_t task) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
LOCK(&task->lock);
|
LOCK(&task->lock);
|
||||||
if (task->state != task_state_shutdown && !task->shutdown_pending) {
|
if (task->enqueue_allowed) {
|
||||||
if (task->state == task_state_idle) {
|
if (task->state == task_state_idle) {
|
||||||
was_idle = TRUE;
|
was_idle = TRUE;
|
||||||
INSIST(EMPTY(task->events));
|
INSIST(EMPTY(task->events));
|
||||||
@@ -297,7 +356,10 @@ task_shutdown(task_t task) {
|
|||||||
}
|
}
|
||||||
INSIST(task->state == task_state_ready ||
|
INSIST(task->state == task_state_ready ||
|
||||||
task->state == task_state_running);
|
task->state == task_state_running);
|
||||||
task->shutdown_pending = TRUE;
|
INSIST(task->shutdown_event != NULL);
|
||||||
|
ENQUEUE(task->events, task->shutdown_event, link);
|
||||||
|
task->shutdown_event = NULL;
|
||||||
|
task->enqueue_allowed = FALSE;
|
||||||
} else
|
} else
|
||||||
discard = TRUE;
|
discard = TRUE;
|
||||||
UNLOCK(&task->lock);
|
UNLOCK(&task->lock);
|
||||||
@@ -419,9 +481,8 @@ void *task_manager_run(void *uap) {
|
|||||||
boolean_t done = FALSE;
|
boolean_t done = FALSE;
|
||||||
boolean_t requeue = FALSE;
|
boolean_t requeue = FALSE;
|
||||||
boolean_t wants_shutdown;
|
boolean_t wants_shutdown;
|
||||||
|
boolean_t is_shutdown;
|
||||||
boolean_t free_task = FALSE;
|
boolean_t free_task = FALSE;
|
||||||
void *arg;
|
|
||||||
task_action_t action;
|
|
||||||
task_event_t event;
|
task_event_t event;
|
||||||
task_eventlist_t remaining_events;
|
task_eventlist_t remaining_events;
|
||||||
boolean_t discard_remaining = FALSE;
|
boolean_t discard_remaining = FALSE;
|
||||||
@@ -439,52 +500,36 @@ void *task_manager_run(void *uap) {
|
|||||||
LOCK(&task->lock);
|
LOCK(&task->lock);
|
||||||
task->state = task_state_running;
|
task->state = task_state_running;
|
||||||
while (!done) {
|
while (!done) {
|
||||||
INSIST(task->shutdown_pending ||
|
INSIST(!EMPTY(task->events));
|
||||||
!EMPTY(task->events));
|
|
||||||
if (task->shutdown_pending &&
|
|
||||||
EMPTY(task->events)) {
|
|
||||||
event = NULL;
|
|
||||||
action = task->shutdown_action;
|
|
||||||
} else {
|
|
||||||
event = HEAD(task->events);
|
event = HEAD(task->events);
|
||||||
action = event->action;
|
|
||||||
DEQUEUE(task->events, event, link);
|
DEQUEUE(task->events, event, link);
|
||||||
}
|
|
||||||
arg = task->arg;
|
|
||||||
UNLOCK(&task->lock);
|
UNLOCK(&task->lock);
|
||||||
|
|
||||||
|
if (event->type == TASK_EVENT_SHUTDOWN)
|
||||||
|
is_shutdown = TRUE;
|
||||||
|
else
|
||||||
|
is_shutdown = FALSE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Execute the event action.
|
* Execute the event action.
|
||||||
*/
|
*/
|
||||||
XTRACE("execute action");
|
XTRACE("execute action");
|
||||||
if (action != NULL)
|
if (event->action != NULL)
|
||||||
wants_shutdown = (*action)(task,
|
wants_shutdown =
|
||||||
arg,
|
(event->action)(task, event);
|
||||||
event);
|
|
||||||
else
|
else
|
||||||
wants_shutdown = FALSE;
|
wants_shutdown = FALSE;
|
||||||
dispatch_count++;
|
dispatch_count++;
|
||||||
|
|
||||||
/*
|
|
||||||
* If this wasn't a shutdown event, we
|
|
||||||
* need to free it.
|
|
||||||
*
|
|
||||||
* Also, if we've delivered the shutdown
|
|
||||||
* event to the task, then we are going
|
|
||||||
* to shut it down no matter what the task
|
|
||||||
* callback returned.
|
|
||||||
*/
|
|
||||||
if (event != NULL)
|
|
||||||
task_event_free(&event);
|
task_event_free(&event);
|
||||||
else
|
|
||||||
wants_shutdown = TRUE;
|
|
||||||
|
|
||||||
LOCK(&task->lock);
|
LOCK(&task->lock);
|
||||||
if (wants_shutdown) {
|
if (wants_shutdown || is_shutdown) {
|
||||||
/*
|
/*
|
||||||
* The task has either had the
|
* The event action has either
|
||||||
* shutdown event sent to it, or
|
* requested shutdown, or the event
|
||||||
* an event action requested shutdown.
|
* we just executed was the shutdown
|
||||||
|
* event.
|
||||||
*
|
*
|
||||||
* Since no more events can be
|
* Since no more events can be
|
||||||
* delivered to the task, we purge
|
* delivered to the task, we purge
|
||||||
@@ -502,10 +547,9 @@ void *task_manager_run(void *uap) {
|
|||||||
if (task->references == 0)
|
if (task->references == 0)
|
||||||
free_task = TRUE;
|
free_task = TRUE;
|
||||||
task->state = task_state_shutdown;
|
task->state = task_state_shutdown;
|
||||||
task->shutdown_pending = FALSE;
|
task->enqueue_allowed = FALSE;
|
||||||
done = TRUE;
|
done = TRUE;
|
||||||
} else if (EMPTY(task->events) &&
|
} else if (EMPTY(task->events)) {
|
||||||
!task->shutdown_pending) {
|
|
||||||
/*
|
/*
|
||||||
* Nothing else to do for this task.
|
* Nothing else to do for this task.
|
||||||
* Put it to sleep.
|
* Put it to sleep.
|
||||||
@@ -690,16 +734,25 @@ task_manager_destroy(task_manager_t *managerp) {
|
|||||||
manager->exiting = TRUE;
|
manager->exiting = TRUE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Post a shutdown event to every task.
|
* Post the shutdown event to every task (if it hasn't already been
|
||||||
|
* posted).
|
||||||
*/
|
*/
|
||||||
for (task = HEAD(manager->tasks);
|
for (task = HEAD(manager->tasks);
|
||||||
task != NULL;
|
task != NULL;
|
||||||
task = NEXT(task, link)) {
|
task = NEXT(task, link)) {
|
||||||
LOCK(&task->lock);
|
LOCK(&task->lock);
|
||||||
task->shutdown_pending = TRUE;
|
if (task->enqueue_allowed) {
|
||||||
|
INSIST(task->shutdown_event != NULL);
|
||||||
|
ENQUEUE(task->events, task->shutdown_event, link);
|
||||||
|
task->shutdown_event = NULL;
|
||||||
if (task->state == task_state_idle) {
|
if (task->state == task_state_idle) {
|
||||||
task->state = task_state_ready;
|
task->state = task_state_ready;
|
||||||
ENQUEUE(manager->ready_tasks, task, ready_link);
|
ENQUEUE(manager->ready_tasks, task,
|
||||||
|
ready_link);
|
||||||
|
}
|
||||||
|
INSIST(task->state == task_state_ready ||
|
||||||
|
task->state == task_state_running);
|
||||||
|
task->enqueue_allowed = FALSE;
|
||||||
}
|
}
|
||||||
UNLOCK(&task->lock);
|
UNLOCK(&task->lock);
|
||||||
}
|
}
|
||||||
@@ -723,45 +776,3 @@ task_manager_destroy(task_manager_t *managerp) {
|
|||||||
|
|
||||||
*managerp = NULL;
|
*managerp = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/***
|
|
||||||
*** Events.
|
|
||||||
***/
|
|
||||||
|
|
||||||
task_event_t
|
|
||||||
task_event_allocate(mem_context_t mctx, task_eventtype_t type,
|
|
||||||
task_action_t action, void *arg, size_t size)
|
|
||||||
{
|
|
||||||
task_event_t event;
|
|
||||||
|
|
||||||
if (size < sizeof *event)
|
|
||||||
return (NULL);
|
|
||||||
if (type < 0)
|
|
||||||
return (NULL);
|
|
||||||
if (action == NULL)
|
|
||||||
return (NULL);
|
|
||||||
event = mem_get(mctx, size);
|
|
||||||
if (event == NULL)
|
|
||||||
return (NULL);
|
|
||||||
event->mctx = mctx;
|
|
||||||
event->size = size;
|
|
||||||
event->type = type;
|
|
||||||
event->action = action;
|
|
||||||
event->arg = arg;
|
|
||||||
|
|
||||||
return (event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
task_event_free(task_event_t *eventp) {
|
|
||||||
task_event_t event;
|
|
||||||
|
|
||||||
REQUIRE(eventp != NULL);
|
|
||||||
event = *eventp;
|
|
||||||
REQUIRE(event != NULL);
|
|
||||||
|
|
||||||
mem_put(event->mctx, event, event->size);
|
|
||||||
|
|
||||||
*eventp = NULL;
|
|
||||||
}
|
|
||||||
|
Reference in New Issue
Block a user