@node thread, utils, stream, Top
@comment  node-name,  next,  previous,  up
@chapter thread

@menu
* history_thread::              
* task.c::                      
@end menu

@node history_thread, task.c, thread, thread
@comment  node-name,  next,  previous,  up
@section  thread 履歴

@table @samp
@item 02/08/12
@heading UNIX 版task.c の変更
スレッドが頻繁に生成されたり、削除されたりすると、Solaris の場合、使用メモリが大量に増えたり、マシンに過大なロードがかかる問題があります。
そこで、一度生成したスレッドは終了しても、しばらくはアイドルさせておき再利用する仕組みを作りました。
@end table

@node task.c,  , history_thread, thread
@comment  node-name,  next,  previous,  up
@section ./task.c

@defun close_lock
@cartouche
@example
#include "task.h"
int
close_lock(SEM @var{s});
@end example
@end cartouche

@heading 説明

@example
@var{s} : ロック用セマフォ
@end example

与えられたセマフォ@var{s} を破壊し、使用していたメモリなどの資源を解放する。

@heading リターンデータ
ごみ

@heading 詳細
もし、与えられたセマフォを待っているスレッドがあった場合、その動作は保証されなくて良い。

@end defun


@defun create_task
@cartouche
@example
#include "task.h"
int
create_task(int (*func)(),int @var{data})
@end example
@end cartouche

@heading 説明

@example
func : タスク(thread) として起動する関数
@var{data} : func に渡す最初の引数
@end example

func で示される関数が、スレッドとして起動される。

@heading リターンデータ
成功したら0, 失敗したらエラーコード

@heading 詳細
func は

@example
func(TKEY k)
@end example

という形で呼び出される。そこで、func の頭で、

@example
func(TKEY k)
@{
    int @var{data};
    @var{data} = GET_TKEY(k);
    ....
@}
@end example

とすることによって、create_task の第二引数@var{data} が取り出せる。

@end defun



@defun get_tid
@cartouche
@example
#include "task.h"
int
get_tid( );
@end example
@end cartouche

@heading 説明
自タスク（スレッド）のID を返す。

@heading リターンデータ
自タスクID

@end defun


@defun GET_TKEY
@cartouche
@example
#include "task.h"
int
GET_TKEY(TKEY @var{d})
@end example
@end cartouche

@heading 説明
@example
@var{d} : スレッドとして呼び出される関数の引数
@end example

@heading リターンデータ
create_task の第二引数

@end defun


@defun init_fifo
@defunx insert_fifo
@defunx delete_fifo
@cartouche
@example
#include "task.h"
int
init_fifo(FIFO * @var{fifo});
int
insert_fifo(FIFO * @var{fifo},FIFO_EL * @var{e});
FIFO_EL *
delete_fifo(FIFO * @var{fifo});
@end example
@end cartouche

@heading 説明
FIFO の操作。現在このコードは使っていないので省略

@end defun


@defun init_task
@cartouche
@example
#include "task.h"
int
init_task( );
@end example
@end cartouche

@heading 説明
スレッドライブラリの初期化。

@heading リターンデータ
ごみ

@heading 詳細
UNIX バージョンでは、スレッド動作時に発生しては困るイベントをマスクしたりなどの操作をしている。

@end defun


@defun lock_task
@cartouche
@example
#include "task.h"
int
lock_task(SEM @var{s});
@end example
@end cartouche

@heading 説明
@example
@var{s}: ロック用セマフォ
@end example

与えられたセマフォで、ロックする。もし他のタスクによってすでにロックされていた場合は、ロックが解放されるまで待つ。

@heading リターンデータ
ごみ

@end defun


@defun new_lock
@cartouche
@example
#include "task.h"
SEM
new_lock( );
@end example
@end cartouche

@heading 説明
新しい、ロック用セマフォを生成し、セマフォ構造体へのポインタ、あるいはセマフォ識別子を返す。

@heading リターンデータ
セマフォ識別子

@heading 詳細
UNIX バージョンでは、

@example
#include ”semaphore.h”
typedef sem t * SEM;
@end example

である。
基本的にロック用としてセマフォを使っているので、二値セマフォで良い。または、ロックやミューテックスを使っても良いだろう。
このセマフォの最初の状態は、ロックを解放した状態である。つまり、セマフォの値=1 である。

@end defun


@defun read_lock
@cartouche
@example
#include "task.h"
int
read_lock(RW_LOCK * @var{rwl});
@end example
@end cartouche

@heading 説明
@example
@var{rwl} : リードライトロック構造体
@end example

@var{rwl} をリードロックする。

@heading リターンデータ
ごみ

@end defun


@defun rw_lock_init
@cartouche
@example
#include "task.h"
int
rw_lock_init(RW_LOCK * @var{rwl});
@end example
@end cartouche

@heading 説明
@example
@var{rwl} : リードライトロック構造体
@end example

リードライトロック構造体を初期化する。

@heading リターンデータ
ごみ

@heading 詳細
リードライト構造体は以下の３つの状態を持っている。

@example
アンロック状態
リードロック状態
ライトロック状態
@end example

これに対して、各タスクは、リードロック、ライトロック、アンロックといった三つの操作を施す。リードロック、ライトロックはロックをかける操作。アンロックはロックを外す操作である。ロックをかける操作と、外す操作は数が一致していなければならない。
リードライトロック構造体がアンロック状態のときは、あらゆるロックを受け付け、その操作に対応した状態へ遷移する。
リードライトロック構造体がリードロック状態の時は、ライトロックはかけられない。ライトロックをかけたタスクは待ち状態に入る。リードロックはいくつもかかる。
ライトロック状態の時は、いずれのロックもかからない。
これで書き込みの一貫性が保証できる。

@end defun


@defun rwl_unlock
@cartouche
@example
#include "task.h"
int
rwl_unlock(RW_LOCK * @var{rwl});
@end example
@end cartouche

@heading 説明
@example
@var{rwl} : リードライトロック構造体
@end example

@var{rwl} をアンロックする。

@heading リターンデータ
ごみ

@end defun


@defun unlock_task
@cartouche
@example
#include "task.h"
int
unlock_task(SEM @var{s},char * @var{str});
@end example
@end cartouche

@heading 説明
@example
@var{s}   : ロック用セマフォ
@var{str} : デバグ用文字列
@end example

@var{s} で与えられたセマフォを解放する。

@heading リターンデータ
ごみ

@heading 詳細
ロックしたセマフォを解放する。このセマフォを待っていたタスクを一つrun 状態にする。どのタスクがrun 状態になるかは、実装依存でよい。

@end defun


@defun write_lock
@cartouche
@example
#include "task.h"
int
write_lock(RW_LOCK * @var{rwl});
@end example
@end cartouche

@heading 説明
@example
@var{rwl} : リードライトロック構造体
@end example

@var{rwl} をライトロックする。


@heading リターンデータ
ごみ

@end defun


@defun sleep_task
@cartouche
@example
#include "task.h"
int
sleep_task(unsigned int @var{key},SEM @var{s});
@end example
@end cartouche

@heading 説明
@example
@var{key} : wakeup のためのkey
@var{s}   : ロックを外すべきセマフォ
@end example

これを呼んだタスクは@var{s} で示されるロックを外して、wakeup によって起こされるまでスリープする。

@heading リターンデータ
ごみ

@heading 履歴
@table @samp
@item 02/04/12
この関数の中のクリティカルセクションにバグがあったので訂正します。基本的に最初のロックlock task(sw lock)
の範囲が分かれていたのを一つにしました。
@end table

@end defun


@defun wakeup_task
@cartouche
@example
#include "task.h"
int
wakeup_task(unsigned int @var{key});
@end example
@end cartouche

@heading 説明
@example
@var{key} : wakeup のためのkey
@end example

key を引数として寝ているタスクをすべて起こす。

@heading リターンデータ
ごみ

@end defun
