Date: Sat, 13 May 2000 15:48:08 +0100 (BST) From: Doug Rabson <dfr@nlsystems.com> To: Chuck Paterson <cp@bsdi.com> Cc: arch@freebsd.org Subject: Re: A new api for asynchronous task execution Message-ID: <Pine.BSF.4.21.0005131540090.47945-200000@salmon.nlsystems.com> In-Reply-To: <200005131422.IAA00701@berserker.bsdi.com>
index | next in thread | previous in thread | raw e-mail
[-- Attachment #1 --]
On Sat, 13 May 2000, Chuck Paterson wrote:
>
> Doug,
> You might want to consider having a separate function/macro
> to enqueue on the taskqueue_swi. Instead of passing in the actual
> name of the task queue you would pass in some sort of flag which
> for now could be something like TASKQUEUE(foobar, TASKQUEUE_SWI).
> This would allow the lower level taskqueue_enqueue to just do the
> enqueueing without having to check if a software interrupt needs
> to be generated. For now the flag could be totally ignored, adding
> zero weight to what you have now. Later on, supposing that the
> system can support multiple interrupt threads on multiple processors,
> the flag could be used in a switch statement that determines which
> level/queue the task gets enqueued on. In a macro this code would
> be determined at compile time. Also it may be useful to have a flag
> that prevents immediate execution, ie no scheduling event, if the
> task is enqueued from the top half. This also is not needed at all
> now.
I don't want to make the api too specific to one particular method of
running the queue (i.e. software interrupts). The intention is that the
taskqueue_xxx() apis simply deal with moving tasks onto and off the queue.
The system defines specific implementations of queues which are drained at
particular times (initially I have defined one using SWI). I want to make
it as easy as possible to define different lightweight queues for various
types of work. The 'enqueue' function pointer in the taskqueue structure
defines the run policy for the queue.
I can imagine various queues being written which drain at different times
(e.g. on clock tick, once after autoconfiguration, driver-specific work
queues etc.)
Take a look at my initial implementation to see how taskqueue_swi is
implemented. Note that the implementation of taskqueue_swi is logically
separate from the taskqueue api itself.
--
Doug Rabson Mail: dfr@nlsystems.com
Nonlinear Systems Ltd. Phone: +44 20 8442 9037
[-- Attachment #2 --]
/*-
* Copyright (c) 2000 Doug Rabson
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/queue.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/taskqueue.h>
#include <sys/interrupt.h>
#include <machine/ipl.h>
void
taskqueue_init(struct taskqueue *queue,
void (*enqueue)(struct taskqueue *queue))
{
STAILQ_INIT(&queue->queue);
queue->enqueue = enqueue;
}
void
taskqueue_enqueue(struct taskqueue *queue, struct task *task)
{
int s = splhigh();
/*
* Count multiple enqueues.
*/
if (task->pending) {
task->pending++;
return;
}
STAILQ_INSERT_TAIL(&queue->queue, task, link);
task->pending = 1;
if (queue->enqueue)
queue->enqueue(queue);
splx(s);
}
void
taskqueue_run(struct taskqueue *queue)
{
int s;
struct task *task;
int pending;
while (STAILQ_FIRST(&queue->queue)) {
/*
* Carefully remove the first task from the queue and
* zero its pending count.
*/
s = splhigh();
task = STAILQ_FIRST(&queue->queue);
STAILQ_REMOVE_HEAD(&queue->queue, link);
pending = task->pending;
task->pending = 0;
splx(s);
task->func(task->arg, pending);
}
}
struct taskqueue taskqueue_swi;
static void
taskqueue_swi_enqueue(struct taskqueue *queue)
{
setsofttq();
}
static void
taskqueue_swi_run(void)
{
taskqueue_run(&taskqueue_swi);
}
static void
taskqueue_swi_init(void *arg)
{
taskqueue_init(&taskqueue_swi, taskqueue_swi_enqueue);
register_swi(SWI_TQ, taskqueue_swi_run);
}
SYSINIT(taskqueue, SI_SUB_CONFIGURE, SI_ORDER_SECOND,
taskqueue_swi_init, NULL);
home |
help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.4.21.0005131540090.47945-200000>
