スポンサーリンク

TASKQUEUE(9) FreeBSD カーネル開発者マニュアル TASKQUEUE(9)

名称

taskqueue − 非同期タスクの実行

書式

#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/taskqueue.h>

typedef void (*task_fn)(void *context, int pending);

typedef void (*taskqueue_enqueue_fn)(void *context);

struct task {

STAILQ_ENTRY(task)

ta_link;

/* キューのためのリンク */

int

ta_pending;

/* キューに入った回数 */

int

ta_priority;

/* キュー内タスク優先度 */

task_fn

ta_func;

/* タスクハンドラ */

void

*ta_context;

/* ハンドラの引数 */

};

struct taskqueue *

taskqueue_create(const char *name, int mflags, taskqueue_enqueue_fn enqueue, void *context);

void

taskqueue_free(struct taskqueue *queue);

struct taskqueue *

taskqueue_find(const char *name);

int

taskqueue_enqueue(struct taskqueue *queue, struct task *task);

int

taskqueue_enqueue_fast(struct taskqueue *queue, struct task *task);

void

taskqueue_run(struct taskqueue *queue);

TASK_INIT(struct task *task, int priority, task_fn_t *func, void *context);

TASKQUEUE_DECLARE(name);

TASKQUEUE_DEFINE(name, taskqueue_enqueue_fn enqueue, void *context, init);

TASKQUEUE_DEFINE_THREAD(name);

解説

これらの関数はコードの非同期の実行のための単純なインタフェースを提供しま す。

関数 taskqueue_create() は新しいキューを作成するために使用されます。 taskqueue_create() への引数は、唯一であるべき名前、 malloc() の呼び出しが スリープを認めるかどうかを指定する malloc(9) フラグの組、タスクがキューに 追加されたときに taskqueue_enqueue() から呼び出される関数を含みます。これ は、(たとえば、ソフトウェア割り込みによるスケジューリングまたはカーネルス レッドが起こされることによって) キューが後で実行されるために準備されるこ とができるようにするためです。

関数 taskqueue_free() はキューのグローバルなリストからそのキューを取り除 くためと、キューによって使用されたメモリを開放するために使用されるべきで す。キュー上の全てのタスクはこのとき実行されます。

システムは、 taskqueue_find() を使用して検索されることが可能な、全ての キューのリストを管理します。名前が一致する最初のキューが返され、そうでな ければ NULL が返されます。

タスクキュー上のキューに入れられたタスクのリストに、タスクを追加するため には、キューへのポインタとタスクへのポインタを指定して taskqueue_enqueue() を呼び出します。タスクの ta_pending フィールドが 0 で ない場合には、タスクがキューに入れられた回数に反映するために単純にインク リメントされます。そうでない場合には、そのタスクはより低い ta_priority 値 を持つ最初のタスクの前に、またはより低い優先度持つタスクがない場合はリス トの最後に、追加されます。タスクをキューに入れることは、割り込みハンドラ の中から呼び出されることに適応するために、メモリの割り当てを実行しませ ん。この関数は、そのキューが開放されようとしている場合には、 EPIPE を返し ます。

関数 taskqueue_enqueue_fast() は、高速割り込みハンドラからキューに入れる ことが発生するときには、 taskqueue_enqueue() の代わりに使用されるべきで す。このメソッドは高速割り込みコンテキスト内でスリープの可能性を避けるた めにスピンロックを使用します。

キュー上の全てのタスクを実行するには、 taskqueue_run() を呼び出します。タ スクが実行されるときには、先ずそのタスクがキューから取り除かれ、 ta_pending の値が記録されそれからそのフィールドが 0 でクリアされます。 task 構造体の ta_func 関数は ta_context フィールドの値を最初の引数とし て、 ta_pending の値を 2 番目の引数として、呼び出されます。

便利なマクロ TASK_INIT(task, priority, func, context) は task 構造体を初 期化するために提供されています。 priority, func および context の値は単純 に task 構造体のフィールドにコピーされ、 ta_pending フィールドはクリアさ れます。

3 つのマクロ TASKQUEUE_DECLARE(name), TASKQUEUE_DEFINE(name, enqueue, context, init) および +.Fn TASKQUEUE_DEFINE_THREAD "name" は、グローバル なキューへの参照の宣言、そのキューの実装の定義、および所有するスレッドを 使用するキューを宣言するために使用されます。 TASKQUEUE_DEFINE() マクロは name, enqueue および context 引数の値で、システムの初期化の間に taskqueue_create() を呼び出すための手配を行います。 taskqueue_create() の 呼び出しの後で、(割り込みハンドラの登録などの) その他の初期化が実行される ことを可能にするために、このマクロへの init 引数が C のステートメントとし て実行されます。

TASKQUEUE_DEFINE_THREAD() マクロはタスクを取り扱う自身が所有するカーネル スレッドで新しいタスクキューを定義します。変数 struct proc *taskqueue_name_proc はタスクを取り扱うカーネルスレッドを含んで定義されま す。変数 struct taskqueue *taskqueue_name はそのキューにタスクを追加する ために使用されます。

システムは 3 つのグローバルなタスクキュー taskqueue_swi, taskqueue_swi_giant, および taskqueue_thread を提供します。 swi タスク キューはソフトウェア割り込みの仕組みを介して実行されます。 taskqueue_swi キューは Giant カーネルロックの保護無しで実行し、 taskqueue_swi_giant キューは Giant カーネルロックの保護有りで実行します。スレッドタスクキュー はカーネルスレッドコンテキストで実行され、このスレッドから実行されるタス クは、Giant カーネルロック下で実行されません。呼び出し側が Giant ロック下 で実行したい場合には、呼び出し側のタスクキューハンドラルーチンの中で、呼 び出し側が明確に Giant ロックの獲得および解放を行なうべきです。

このキューを使用するためには、使用したいキュー ( taskqueue_swi, taskqueue_swi_giant または taskqueue_thread ) のためのグローバルタスク キュー変数の値で taskqueue_enqueue() を呼び出します。

ソフトウェア割り込みキューは、例えば、ハンドラの中で著しい量の処理を実行 しなければならない割り込みハンドラを実装するために、使用されることが可能 です。ハードウェア割り込みハンドラは、その割り込みの最小の処理を実行し、 それから作業を完了させるためにタスクをキューに入れます。これは、割り込み が無効化されて費やされる時間を最小量にまで縮小します。

スレッドキューは、例えば、スレッドコンテキストからのみ実行することが可能 な何かを行なうカーネル関数を呼び出すことが必要な、割り込みレベルのルーチ ンによって使用されることが可能です。 (例えば、M_WAITOK フラグを伴った malloc の呼び出しです。)

歴史

このインタフェースは FreeBSD 5.0 ではじめて登場しました。 Linux カーネル で tqueue と呼ばれる同様のファシリティがあります。

作者

このマニュアルページは Doug Rabson が書きました。

FreeBSD 10.0 May 12, 2000 FreeBSD 10.0

スポンサーリンク