Section 20.4. Device Driver Interface for Task Queues


20.4. Device Driver Interface for Task Queues

Device driver or file system developers should use the documented DDI for all taskq operations. These interfaces are defined in the usr/src/uts/common/sys/ sunddi.h header file. The exported interface consists of the following functions.

ddi_taskq_t *ddi_taskq_create(dev_info_t *dip, const char *name, int nthreads,                               pri_t pri, uint_t flags); Creates a new taskq object with specified number of threads servicing it. All threads will run with a single specified priority. The priority may have a special value  TASKQ_ DEFAULTPRI meaning that the priority will be chosen by the system. dip is a pointer to the dev_info_t structure (Some subsystems do not have a dip pointer and may pass NULL instead). name is a descriptive string. The priority of threads servicing the task queue can be specified by pri (drivers and modules should specify TASKQ_DEFAULTPRI). flags should be always zero in this release. int ddi_taskq_dispatch(ddi_taskq_t *taskq, void (* func)(void *), void *arg,                        uint_t dflags); Schedules a task for a specified taskq, as returned by ddi_taskq_create(). A task is just a pair {f, a} where f is a function, accepting a single pointer argument and a is its argument value. Additional flags specify whether dispatch may or may not sleep waiting for resources. Once the task is dispatched it will be scheduled asynchronously at some later time and there is no way to cancel a task that is dispatched but has not been executed yet. All the tasks are executed with a fixed priority specified at the time of taskq creation. Flags controlling the dispatch behavior are specified by flags: DDI_SLEEP, allow sleeping/blocking) until memory is available; or DDI_NOSLEEP, return DDI_FAILURE immediately if memory is not available. void ddi_taskq_wait(ddi_taskq_t *taskq); Blocks the taskq from any new dispatches and waits for all previously scheduled tasks to complete, then unblocks the taskq. This function does not stop any new task dispatches. Its single argument is the taskq to wait for. void ddi_taskq_suspend(ddi_taskq_t *taskq); Suspends all task execution until ddi_taskq_resume() is called. Although ddi_taskq_suspend() attempts to suspend pending tasks, there are no guarantees that they will be suspended. The only guarantee is that all tasks dispatched after ddi_taskq_suspend() will not be executed. Because it will trigger a deadlock, the function should never be called by a task executing on a taskq. Its single argument is the taskq to suspend. boolean_t ddi_taskq_suspended(ddi_taskq_t *taskq); Returns B_TRUE if taskq is suspended, and B_FALSE otherwise. It is intended to ASSERT that the task queue is suspended. Its single argument is the taskq to check. void ddi_taskq_resume(ddi_taskq_t *taskq); Resumes taskq execution. Its single argument is the taskq to resume.                                                      See usr/src/uts/common/sys/sunddi.h 


Each taskq is implemented as a list of tasks protected by a per-taskq lock. One or more worker threads execute tasks one by one by calling f(a) and then sleep, waiting for new entries. A taskq created with a single servicing thread has an important property: It guarantees that all its tasks are executed in the order they are scheduled. We call such a task queue a sequential taskq. When a task queue is created with several servicing threads, task execution order is not predictable; we call such task queue a dynamic taskq.

Task queues keep a cache of structures needed to schedule a task, and programmers can prepopulate this cache to guarantee that dispatch operation will succeed without waiting for memory.




SolarisT Internals. Solaris 10 and OpenSolaris Kernel Architecture
Solaris Internals: Solaris 10 and OpenSolaris Kernel Architecture (2nd Edition)
ISBN: 0131482092
EAN: 2147483647
Year: 2004
Pages: 244

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net