task.c revision 744304361cf3e76aba2409e011b772d7c4c47d11
ca41b452ede6feaa9d8739ec3cae19389a7b0d03Bob Halley * Copyright (C) 1998-2001 Internet Software Consortium.
a3ab70dae26d009bf78b0594b2ab5eb9208f4b91Michael Graff * Permission to use, copy, modify, and distribute this software for any
a3ab70dae26d009bf78b0594b2ab5eb9208f4b91Michael Graff * purpose with or without fee is hereby granted, provided that the above
a3ab70dae26d009bf78b0594b2ab5eb9208f4b91Michael Graff * copyright notice and this permission notice appear in all copies.
a3ab70dae26d009bf78b0594b2ab5eb9208f4b91Michael Graff * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
a3ab70dae26d009bf78b0594b2ab5eb9208f4b91Michael Graff * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
a3ab70dae26d009bf78b0594b2ab5eb9208f4b91Michael Graff * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
a3ab70dae26d009bf78b0594b2ab5eb9208f4b91Michael Graff * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
a3ab70dae26d009bf78b0594b2ab5eb9208f4b91Michael Graff * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
a3ab70dae26d009bf78b0594b2ab5eb9208f4b91Michael Graff * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
a3ab70dae26d009bf78b0594b2ab5eb9208f4b91Michael Graff * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
a3ab70dae26d009bf78b0594b2ab5eb9208f4b91Michael Graff * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
a3ab70dae26d009bf78b0594b2ab5eb9208f4b91Michael Graff/* $Id: task.c,v 1.82 2001/02/07 21:16:12 bwelling Exp $ */
a3ab70dae26d009bf78b0594b2ab5eb9208f4b91Michael Graff * Principal Author: Bob Halley
a3ab70dae26d009bf78b0594b2ab5eb9208f4b91Michael Graff * XXXRTH Need to document the states a task can be in, and the rules
ae7d0a4375abaecfd5c5b0816616d9882831e69bMichael Graff * for changing states.
e4f074a2c2340ea80099beebecc3b89aa234fa8fMichael Graff#endif /* ISC_PLATFORM_USETHREADS */
e4f074a2c2340ea80099beebecc3b89aa234fa8fMichael Graff#define XTRACE(m) fprintf(stderr, "task %p thread %lu: %s\n", \
e4f074a2c2340ea80099beebecc3b89aa234fa8fMichael Graff#define XTTRACE(t, m) fprintf(stderr, "task %p thread %lu: %s\n", \
e4f074a2c2340ea80099beebecc3b89aa234fa8fMichael Graff#define XTHREADTRACE(m) fprintf(stderr, "thread %lu: %s\n", \
e4f074a2c2340ea80099beebecc3b89aa234fa8fMichael Grafftypedef enum {
e4f074a2c2340ea80099beebecc3b89aa234fa8fMichael Graff task_state_idle, task_state_ready, task_state_running,
e4f074a2c2340ea80099beebecc3b89aa234fa8fMichael Graff /* Not locked. */
e4f074a2c2340ea80099beebecc3b89aa234fa8fMichael Graff unsigned int magic;
7dbf5a0b64237aa3052f04f4c8f7d56be8ec5d79Michael Graff /* Locked by task lock. */
e4f074a2c2340ea80099beebecc3b89aa234fa8fMichael Graff unsigned int quantum;
e4f074a2c2340ea80099beebecc3b89aa234fa8fMichael Graff unsigned int flags;
e4f074a2c2340ea80099beebecc3b89aa234fa8fMichael Graff /* Locked by task manager lock. */
e4f074a2c2340ea80099beebecc3b89aa234fa8fMichael Graff#define TASK_SHUTTINGDOWN(t) (((t)->flags & TASK_F_SHUTTINGDOWN) \
e4f074a2c2340ea80099beebecc3b89aa234fa8fMichael Graff#define TASK_MANAGER_MAGIC 0x54534B4DU /* TSKM. */
e4f074a2c2340ea80099beebecc3b89aa234fa8fMichael Graff /* Not locked. */
e4f074a2c2340ea80099beebecc3b89aa234fa8fMichael Graff unsigned int magic;
e4f074a2c2340ea80099beebecc3b89aa234fa8fMichael Graff unsigned int workers;
e4f074a2c2340ea80099beebecc3b89aa234fa8fMichael Graff#endif /* ISC_PLATFORM_USETHREADS */
e4f074a2c2340ea80099beebecc3b89aa234fa8fMichael Graff /* Locked by task manager lock. */
e4f074a2c2340ea80099beebecc3b89aa234fa8fMichael Graff#endif /* ISC_PLATFORM_USETHREADS */
e4f074a2c2340ea80099beebecc3b89aa234fa8fMichael Graff unsigned int refs;
c05e003dce672b2f8555a3e56857f29ce89c1677Michael Graff#endif /* ISC_PLATFORM_USETHREADS */
c05e003dce672b2f8555a3e56857f29ce89c1677Michael Graff#define FINISHED(m) ((m)->exiting && EMPTY((m)->tasks))
c05e003dce672b2f8555a3e56857f29ce89c1677Michael Graff#endif /* ISC_PLATFORM_USETHREADS */
c05e003dce672b2f8555a3e56857f29ce89c1677Michael Graff * All tasks have completed and the
c05e003dce672b2f8555a3e56857f29ce89c1677Michael Graff * task manager is exiting. Wake up
c05e003dce672b2f8555a3e56857f29ce89c1677Michael Graff * any idle worker threads so they
7dbf5a0b64237aa3052f04f4c8f7d56be8ec5d79Michael Graff#endif /* ISC_PLATFORM_USETHREADS */
e24f605ad64182532640dc6721070456b13112d5Michael Graff isc_mem_put(manager->mctx, task, sizeof *task);
291b0d910d115e41a4b69d0603c3376aebf0c630Michael Graffisc_task_create(isc_taskmgr_t *manager, unsigned int quantum,
291b0d910d115e41a4b69d0603c3376aebf0c630Michael Graff task = isc_mem_get(manager->mctx, sizeof *task);
291b0d910d115e41a4b69d0603c3376aebf0c630Michael Graff if (isc_mutex_init(&task->lock) != ISC_R_SUCCESS) {
291b0d910d115e41a4b69d0603c3376aebf0c630Michael Graff isc_mem_put(manager->mctx, task, sizeof *task);
291b0d910d115e41a4b69d0603c3376aebf0c630Michael Graff "isc_mutex_init() %s",
d736db6dc53e615e3f2d66d1ddbe28473694d107Michael Graff isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
e24f605ad64182532640dc6721070456b13112d5Michael Graff isc_mem_put(manager->mctx, task, sizeof *task);
ae7d0a4375abaecfd5c5b0816616d9882831e69bMichael Graffisc_task_attach(isc_task_t *source, isc_task_t **targetp) {
ae7d0a4375abaecfd5c5b0816616d9882831e69bMichael Graff * Attach *targetp to source.
ae7d0a4375abaecfd5c5b0816616d9882831e69bMichael Graff * Caller must be holding the task's lock.
7dbf5a0b64237aa3052f04f4c8f7d56be8ec5d79Michael Graff XTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
ae7d0a4375abaecfd5c5b0816616d9882831e69bMichael Graff * Note that we post shutdown events LIFO.
2311073ce0ef26c0250e91e4a083d7cc94fa7d33Michael Graffstatic inline void
2311073ce0ef26c0250e91e4a083d7cc94fa7d33Michael Graff ENQUEUE(manager->ready_tasks, task, ready_link);
4e675038a097065ff13944232cd7c89ac5961984Michael Graff#endif /* ISC_PLATFORM_USETHREADS */
c05e003dce672b2f8555a3e56857f29ce89c1677Michael Graff * Caller must be holding the task lock.
ae7d0a4375abaecfd5c5b0816616d9882831e69bMichael Graff if (task->references == 0 && task->state == task_state_idle) {
return (ISC_TRUE);
return (ISC_FALSE);
if (was_idle)
static inline isc_boolean_t
return (was_idle);
if (was_idle) {
unsigned int count = 0;
count++;
return (count);
unsigned int count;
ISC_TRUE);
return (count);
void *tag)
return (ISC_FALSE);
return (ISC_TRUE);
ISC_FALSE));
ISC_FALSE));
NULL,
arg,
sizeof *event);
return (ISC_R_NOMEMORY);
if (disallowed)
return (result);
if (was_idle)
#ifdef ISC_TASK_NAMES
(void)name;
(void)tag;
#ifndef ISC_PLATFORM_USETHREADS
unsigned int total_dispatch_count = 0;
#ifdef ISC_PLATFORM_USETHREADS
unsigned int dispatch_count = 0;
#ifndef ISC_PLATFORM_USETHREADS
} while (!done);
if (finished)
if (requeue) {
#ifdef ISC_PLATFORM_USETHREADS
static isc_threadresult_t
#ifdef _WIN32
return ((isc_threadresult_t)0);
#ifdef ISC_PLATFORM_USETHREADS
unsigned int i, started = 0;
#ifndef ISC_PLATFORM_USETHREADS
UNUSED(i);
return (ISC_R_SUCCESS);
return (ISC_R_NOMEMORY);
return (ISC_R_UNEXPECTED);
#ifdef ISC_PLATFORM_USETHREADS
return (ISC_R_NOMEMORY);
return (ISC_R_UNEXPECTED);
if (default_quantum == 0)
#ifdef ISC_PLATFORM_USETHREADS
for (i = 0; i < workers; i++) {
started++;
if (started == 0) {
return (ISC_R_NOTHREADS);
return (ISC_R_SUCCESS);
#ifndef ISC_PLATFORM_USETHREADS
UNUSED(i);
#ifdef ISC_PLATFORM_USETHREADS
while (isc__taskmgr_ready())
(void)isc__taskmgr_dispatch();
#ifndef ISC_PLATFORM_USETHREADS
isc__taskmgr_ready(void) {
return (ISC_FALSE);
isc__taskmgr_dispatch(void) {
return (ISC_R_NOTFOUND);
return (ISC_R_SUCCESS);