picox  0.1
Xfiber

非リアルタイム協調型マルチタスクモジュール [詳解]

Xfiber 連携図

型定義

typedef void(* XFiberFunc) (void *)
 タスクのメイン関数ポインタ型です [詳解]
 
typedef int(* XFiberIdleHook) (void)
 アイドル時に呼び出されるフック関数のポインタ型です [詳解]
 
typedef XIntrusiveNode XFiberMessage
 

fiber_event_mode

XFiberEventのmode引数に指定可能な値です

#define X_FIBER_EVENT_WAIT_OR   (0)
 イベントのどれかを待ちます(OR待ち)
 
#define X_FIBER_EVENT_WAIT_AND   (1)
 イベントの全てが成立するまで待ちます(AND待ち)
 
#define X_FIBER_EVENT_CLEAR_ON_EXIT   (1 << 1)
 イベント成立時に、イベントのクリアを行います
 

fiber_kernel_control

XError xfiber_kernel_init (void *heap, size_t heapsize, XFiberIdleHook idlehook)
 カーネルを初期化します [詳解]
 
XError xfiber_kernel_start_scheduler (void)
 スケジューリングを開始します
 
void xfiber_kernel_end_scheduler (void)
 スケジューリングを終了します [詳解]
 

fiber_task_control

XError xfiber_create (XFiber **o_fiber, int priority, const char *name, size_t stack_size, XFiberFunc func, void *arg)
 タスクを生成します [詳解]
 
void xfiber_delay (XTicks time)
 タスクの実行を指定時間遅延します
 
XError xfiber_suspend (XFiber *fiber)
 タスクをサスペンド状態に遷移させます [詳解]
 
XError xfiber_resume (XFiber *fiber)
 タスクのサスペンド状態を解除します
 
void xfiber_yield ()
 タスクの実行を同一優先度の別のタスクにゆずります
 
XFiber * xfiber_self ()
 実行状態のタスクを返します
 
const char * xfiber_name (const XFiber *fiber)
 タスクの名前を返します
 

fiber_event

ビットフラグによるイベント待ちを行いたい場合に使用します

XError xfiber_event_create (XFiberEvent **o_event)
 イベントオブジェクトを生成します
 
void xfiber_event_destroy (XFiberEvent *event)
 イベントオブジェクトを破棄します [詳解]
 
XError xfiber_event_timed_wait (XFiberEvent *event, XMode mode, XBits wait_pattern, XBits *result, XTicks timeout)
 指定のイベントが成立するのをタイムアウト付きで待ちます [詳解]
 
XError xfiber_event_wait (XFiberEvent *event, XMode mode, XBits wait_pattern, XBits *result)
 指定のイベントが成立するのを待ちます [詳解]
 
XError xfiber_event_try_wait (XFiberEvent *event, XMode mode, XBits wait_pattern, XBits *result)
 指定のイベントが成立しているかをポーリングで確認します [詳解]
 
XError xfiber_event_set (XFiberEvent *event, XBits pattern)
 イベントをセットします
 
XError xfiber_event_set_isr (XFiberEvent *event, XBits pattern)
 割込みハンドラから呼び出し可能なxfiber_event_set()です
 
XBits xfiber_event_clear (XFiberEvent *event, XBits pattern)
 指定ビットをクリアします
 
XBits xfiber_event_clear_isr (XFiberEvent *event, XBits pattern)
 割込みハンドラから呼び出し可能なxfiber_event_clear()です
 
XBits xfiber_event_get (XFiberEvent *event)
 現在のビットパターンを返します
 
XBits xfiber_event_get_isr (XFiberEvent *event)
 割込みハンドラから呼び出し可能なxfiber_event_get()です
 

fiber_signal

ビットフラグによるイベント待ちを行いたい場合に使用します

イベントと似ていますが、オブジェクトを生成することなく、タスクに直接イベント を発行できる点が異なります。 簡易的なイベントフラグとして使用できます。

XError xfiber_signal_timed_wait (XBits sigs, XBits *result, XTicks timeout)
 シグナルが成立するのをタイムアウト付きで待ちます [詳解]
 
XError xfiber_signal_wait (XBits sigs, XBits *result)
 シグナルが成立するのを待ちます
 
XError xfiber_signal_try_wait (XBits sigs, XBits *result)
 シグナルが成立するのをポーリングで待ちます
 
XError xfiber_signal_raise (XFiber *fiber, XBits sigs)
 タスクにシグナルを発行します
 
XError xfiber_signal_raise_isr (XFiber *fiber, XBits sigs)
 割込みハンドラから呼び出し可能なxfiber_signal_raise()です
 
XBits xfiber_signal_get (XFiber *fiber)
 現在のビットパターンを返します
 
XBits xfiber_signal_get_isr (XFiber *fiber)
 割込みハンドラから呼び出し可能なxfiber_signal_get()です
 

fiber_queue

固定長のメッセージの受け渡しに使用します。リングバッファで実装されており、デ ータはバッファにコピーされます。

XError xfiber_queue_create (XFiberQueue **o_queue, size_t queue_len, size_t item_size)
 キューを生成します [詳解]
 
void xfiber_queue_destroy (XFiberQueue *queue)
 キューを破棄します [詳解]
 
XError xfiber_queue_timed_send_back (XFiberQueue *queue, const void *src, XTicks timeout)
 キューの末尾への要素の転送をタイムアウト付きで試みます
 
XError xfiber_queue_send_back (XFiberQueue *queue, const void *src)
 キューの末尾への要素の転送を試みます
 
XError xfiber_queue_try_send_back (XFiberQueue *queue, const void *src)
 キューの末尾への要素の転送をポーリングで試みます
 
XError xfiber_queue_send_back_isr (XFiberQueue *queue, const void *src)
 割込みハンドラから呼び出し可能なxfiber_queue_try_send_back()です
 
XError xfiber_queue_timed_send_front (XFiberQueue *queue, const void *src, XTicks timeout)
 キューの先頭への要素の転送をタイムアウト付きで試みます
 
XError xfiber_queue_send_front (XFiberQueue *queue, const void *src)
 キューの先頭への要素の転送を試みます
 
XError xfiber_queue_try_send_front (XFiberQueue *queue, const void *src)
 キューの先頭への要素の転送をポーリングで試みます
 
XError xfiber_queue_send_front_isr (XFiberQueue *queue, const void *src)
 割込みハンドラから呼び出し可能なxfiber_queue_try_send_front()です
 
XError xfiber_queue_timed_receive (XFiberQueue *queue, void *dst, XTicks timeout)
 キューの先頭から要素の受信をタイムアウト付きで試みます
 
XError xfiber_queue_receive (XFiberQueue *queue, void *dst)
 キューの先頭から要素の受信を試みます
 
XError xfiber_queue_try_receive (XFiberQueue *queue, void *dst)
 キューの先頭から要素の受信をポーリングで試みます
 
XError xfiber_queue_receive_isr (XFiberQueue *queue, void *dst)
 割込みハンドラから呼び出し可能なxfiber_queue_try_receive()です
 

fiber_channel

可変長のメッセージの受け渡しに使用します。リングバッファで実装されており、デ ータはバッファにコピーされます。

queueとの違いは以下の通りです

  • 可変長のため、要素ごとにsizeof(size_t)バイトの管理領域が必要
  • 先頭への送信は不可
XError xfiber_channel_create (XFiberChannel **o_channel, size_t capacity, size_t max_item_size)
 
void xfiber_channel_destroy (XFiberChannel *channel)
 
XError xfiber_channel_timed_send (XFiberChannel *channel, const void *src, size_t size, XTicks timeout)
 
XError xfiber_channel_send (XFiberChannel *channel, const void *src, size_t size)
 
XError xfiber_channel_try_send (XFiberChannel *channel, const void *src, size_t size)
 
XError xfiber_channel_send_isr (XFiberChannel *channel, const void *src, size_t size)
 
XError xfiber_channel_timed_receive (XFiberChannel *channel, void *dst, size_t *o_size, XTicks timeout)
 
XError xfiber_channel_receive (XFiberChannel *channel, void *dst, size_t *o_size)
 
XError xfiber_channel_try_receive (XFiberChannel *channel, void *dst, size_t *o_size)
 
XError xfiber_channel_receive_isr (XFiberChannel *channel, void *dst, size_t *o_size)
 

fiber_semaphore

競合資源の排他制御に使用します

ミューテックスとの違いは、資源が複数ある場合に使用するカウントを持っているこ とです。

XError xfiber_semaphore_create (XFiberSemaphore **o_semaphore, int initial_count)
 セマフォを生成します [詳解]
 
void xfiber_semaphore_destroy (XFiberSemaphore *semaphore)
 セマフォを破棄します [詳解]
 
XError xfiber_semaphore_timed_take (XFiberSemaphore *semaphore, XTicks timeout)
 セマフォの獲得をタイムアウト付きで試みます
 
XError xfiber_semaphore_take (XFiberSemaphore *semaphore)
 セマフォの獲得を試みます
 
XError xfiber_semaphore_try_take (XFiberSemaphore *semaphore)
 セマフォの獲得をポーリングで試みます
 
XError xfiber_semaphore_give (XFiberSemaphore *semaphore)
 セマフォを返却します
 
XError xfiber_semaphore_give_isr (XFiberSemaphore *semaphore)
 割込みハンドラで呼び出し可能なxfiber_semaphore_give()です
 

fiber_mutex

競合資源の排他制御に使用します

セマフォとの違いはロックされたままタスクが終了すると、自動的にロック解除を行 う点と、優先度逆転防止機構を持つことです。

注意
自動ロック解除と、優先度逆転防止機構はまだ未実装です
XError xfiber_mutex_create (XFiberMutex **o_mutex)
 ミューテックスを生成します
 
void xfiber_mutex_destroy (XFiberMutex *mutex)
 ミューテックスを破棄します
 
XError xfiber_mutex_timed_lock (XFiberMutex *mutex, XTicks timeout)
 ミューテックスを獲得をタイムアウト付きで試みます
 
XError xfiber_mutex_lock (XFiberMutex *mutex)
 ミューテックスを獲得を試みます
 
XError xfiber_mutex_try_lock (XFiberMutex *mutex)
 ミューテックスを獲得をタイムアウト付きで試みます
 
XError xfiber_mutex_unlock (XFiberMutex *mutex)
 ミューテックスのロック解除を行います
 
XError xfiber_mutex_unlock_isr (XFiberMutex *mutex)
 割込みハンドラから呼び出し可能なxfiber_mutex_unlock()です
 

fiber_mailbox

大きなデータの受け渡しに使用する通信機能です。リンクリストで実装しているので 、データのコピーが行われません。また、送信待ちが絶対に発生しないのも大きな特 徴です。

ただし、スタック上のデータを送信することができないという制限があり、データの 寿命管理にも気をつける必要があります。

XError xfiber_mailbox_create (XFiberMailbox **o_mailbox)
 メールボックスを生成します
 
void xfiber_mailbox_destroy (XFiberMailbox *mailbox)
 メールボックスを生成します [詳解]
 
XError xfiber_mailbox_send (XFiberMailbox *mailbox, XFiberMessage *message)
 メールボックス末尾にメッセージを追加します
 
XError xfiber_mailbox_send_isr (XFiberMailbox *mailbox, XFiberMessage *message)
 割込みハンドラから呼び出し可能なxfiber_mailbox_send()です
 
XError xfiber_mailbox_timed_receive (XFiberMailbox *mailbox, XFiberMessage **o_message, XTicks timeout)
 メールボックス先頭からメッセージの受信をタイムアウト付きで試みます
 
XError xfiber_mailbox_receive (XFiberMailbox *mailbox, XFiberMessage **o_message)
 メールボックス先頭からメッセージの受信を試みます
 
XError xfiber_mailbox_try_receive (XFiberMailbox *mailbox, XFiberMessage **o_message)
 メールボックス先頭からメッセージの受信をポーリングで試みます
 
XError xfiber_mailbox_receive_isr (XFiberMailbox *mailbox, XFiberMessage **o_message)
 割込みハンドラから呼び出し可能なxfiber_mailbox_try_receive()です
 

fiber_pool

固定長のメモリブロックを確保と解放を行えます

メールボックスのメッセージのメモリ確保と相性がいいです。固定長なので、確保と 解放は超高速です。

XError xfiber_pool_create (XFiberPool **o_pool, size_t block_size, size_t num_blocks)
 プールを生成します [詳解]
 
void xfiber_pool_destroy (XFiberPool *pool)
 プールを解放します [詳解]
 
XError xfiber_pool_timed_get (XFiberPool *pool, void **o_mem, XTicks timeout)
 プールからメモリの確保をタイムアウト付きで試みます
 
XError xfiber_pool_get (XFiberPool *pool, void **o_mem)
 プールからメモリの確保を試みます
 
XError xfiber_pool_try_get (XFiberPool *pool, void **o_mem)
 プールからメモリの確保をポーリングで試みます
 
XError xfiber_pool_get_isr (XFiberPool *pool, void **o_mem)
 割込みハンドラから呼び出し可能なxfiber_pool_try_get()です
 
XError xfiber_pool_release (XFiberPool *pool, void *mem)
 プールにメモリを返却します
 
XError xfiber_pool_release_isr (XFiberPool *pool, void *mem)
 割込みハンドラから呼び出し可能なxfiber_pool_release()です
 

詳解

非リアルタイム協調型マルチタスクモジュール

協調型のマルチタスクをスレッドと区別して、コルーチンやファイバーと呼ぶことが 多いです。

スクリプト言語を中心に、多くの言語でスレッドとは別にコルーチンやファイバーを サポートしています。

[コルーチン]

[ファイバー]

コルーチンやファイバーという用語に明確な定義はありませんが、最低限処理を中断 して、後から再開できる機能を持ちます。

picoxのファイバーでは、RTOS風にタスクの優先順位や待ち合わせ機能を多数用意し ていることが大きな特徴で、RTOSの代替として使用できることを目的としています。

RTOSの実装はC言語の機能だけでは実現不可能なため、CPUごとコンパイラごとにアセ ンブリ言語を記述する必要があり大変です。 移植部分が最小限になるように考慮して実装されたフリーのRTOSもありますが、それ でも敷居は高いものです。

このモジュールはC言語の機能のみでマルチタスクを実現しているため、移植作業な しで即座に使用することができます。

ただし、以下の制限があります。

RTOSを移植するまでの一時しのぎや、リソースに余裕のあるプロトタイプ段階でご利 用ください。

覚え書き
C言語で実装可能なコンテキストスイッチということで、C言語の限界に迫るトリッキ ーで面白い実装になっています。以下の技術資料にあるアイデアを元に実装を行いま した。

http://www.atdot.net/~ko1/activities/shiba-prosym2010-paper.pdf

興味のある方は是非ソースコードを覗いてみてください。

型定義詳解

typedef void(* XFiberFunc) (void *)

タスクのメイン関数ポインタ型です

引数のポインタが指すアドレスはスタック以外である必要があります。

typedef int(* XFiberIdleHook) (void)

アイドル時に呼び出されるフック関数のポインタ型です

0以外を返すと、スケジューリングは終了し、xfiber_kernel_start_scheduler()の呼 び出し直後の地点までジャンプします。

関数詳解

XError xfiber_channel_create ( XFiberChannel **  o_channel,
size_t  capacity,
size_t  max_item_size 
)

チャンネルを生成します

引数
o_channel生成したチャンネルのアドレスの格納先
capacityチャンネルバッファのバイト数
max_item_size1要素の最大バイト数

1要素ごとに管理領域が必要なため、capacity == 格納可能な総バイト数ではありま せん。 要素の受信時は、格納先は暗黙的にmax_item_sizeバイト以上の領域を持つことを前 提とします。

void xfiber_channel_destroy ( XFiberChannel *  channel)

チャンネル破棄します

全ての待ちタスクの待ちは解除され、待ちタスクにはX_ERR_CANCELEDが返ります

XError xfiber_channel_receive ( XFiberChannel *  channel,
void *  dst,
size_t *  o_size 
)

チャンネル先頭から要素の受信を試みます

XError xfiber_channel_receive_isr ( XFiberChannel *  channel,
void *  dst,
size_t *  o_size 
)

割込みハンドラから呼び出し可能なxfiber_channel_try_receive()です

XError xfiber_channel_send ( XFiberChannel *  channel,
const void *  src,
size_t  size 
)

チャンネルの末尾へsizeバイトの要素の転送を試みます

XError xfiber_channel_send_isr ( XFiberChannel *  channel,
const void *  src,
size_t  size 
)

割込みハンドラから呼び出し可能なxfiber_channel_try_send()です

XError xfiber_channel_timed_receive ( XFiberChannel *  channel,
void *  dst,
size_t *  o_size,
XTicks  timeout 
)

チャンネル先頭から要素の受信をタイムアウト付きで試みます

XError xfiber_channel_timed_send ( XFiberChannel *  channel,
const void *  src,
size_t  size,
XTicks  timeout 
)

チャンネルの末尾へsizeバイトの要素の転送をタイムアウト付きで試みます

XError xfiber_channel_try_receive ( XFiberChannel *  channel,
void *  dst,
size_t *  o_size 
)

チャンネル先頭から要素の受信をポーリングで試みます

XError xfiber_channel_try_send ( XFiberChannel *  channel,
const void *  src,
size_t  size 
)

チャンネルの末尾へsizeバイトの要素の転送をポーリングで試みます

XError xfiber_create ( XFiber **  o_fiber,
int  priority,
const char *  name,
size_t  stack_size,
XFiberFunc  func,
void *  arg 
)

タスクを生成します

引数
o_fiber生成したタスクのアドレスの格納先
priorityタスク優先度
nameタスク名
stack_sizeスタックのバイト数
funcメイン関数
argメイン関数の引数
void xfiber_event_destroy ( XFiberEvent *  event)

イベントオブジェクトを破棄します

全ての待ちタスクの待ちは解除され、待ちタスクにはX_ERR_CANCELEDが返ります

XError xfiber_event_timed_wait ( XFiberEvent *  event,
XMode  mode,
XBits  wait_pattern,
XBits result,
XTicks  timeout 
)

指定のイベントが成立するのをタイムアウト付きで待ちます

引数
mode
参照
fiber_event_mode
引数
wait_pattern待ちビットパターン
result待ち解除時のビットパターンの格納先
timeoutタイムアウト時間
XError xfiber_event_try_wait ( XFiberEvent *  event,
XMode  mode,
XBits  wait_pattern,
XBits result 
)

指定のイベントが成立しているかをポーリングで確認します

xfiber_event_timed_wait()でtimeoutに0を指定した場合と同じです

XError xfiber_event_wait ( XFiberEvent *  event,
XMode  mode,
XBits  wait_pattern,
XBits result 
)

指定のイベントが成立するのを待ちます

xfiber_event_timed_wait()でtimeoutにX_TICKS_FOREVERを指定した場合と同じです

void xfiber_kernel_end_scheduler ( void  )

スケジューリングを終了します

呼び出し後はxfiber_kernel_start_scheduler()の呼び出し直後の位置までジャンプ します。

XError xfiber_kernel_init ( void *  heap,
size_t  heapsize,
XFiberIdleHook  idlehook 
)

カーネルを初期化します

引数
heapワークバッファのアドレス
heapsizeワークバッファのサイズ
idlehook
参照
XFiberIdleHook

heapにNULLが指定された場合、x_malloc()でメモリを確保します。スタックやファイ バーオブジェクトは全てワークバッファから生成されます。

void xfiber_mailbox_destroy ( XFiberMailbox *  mailbox)

メールボックスを生成します

全ての待ちタスクの待ちは解除され、待ちタスクにはX_ERR_CANCELEDが返ります

XError xfiber_pool_create ( XFiberPool **  o_pool,
size_t  block_size,
size_t  num_blocks 
)

プールを生成します

引数
o_pool生成したプールのアドレスの格納先
block_size1ブロックのサイズ
num_blocksブロック数
void xfiber_pool_destroy ( XFiberPool *  pool)

プールを解放します

全ての待ちタスクの待ちは解除され、待ちタスクにはX_ERR_CANCELEDが返ります

XError xfiber_queue_create ( XFiberQueue **  o_queue,
size_t  queue_len,
size_t  item_size 
)

キューを生成します

引数
o_queue生成したキューのアドレスの格納先
queue_len格納可能な要素数
item_size1要素のバイト数

queue_len * item_sizeバイトのバッファが生成されます。

void xfiber_queue_destroy ( XFiberQueue *  queue)

キューを破棄します

全ての待ちタスクの待ちは解除され、待ちタスクにはX_ERR_CANCELEDが返ります

XError xfiber_semaphore_create ( XFiberSemaphore **  o_semaphore,
int  initial_count 
)

セマフォを生成します

引数
o_semaphore生成したセマフォのアドレスの格納先
initial_countカウンタの初期値
void xfiber_semaphore_destroy ( XFiberSemaphore *  semaphore)

セマフォを破棄します

全ての待ちタスクの待ちは解除され、待ちタスクにはX_ERR_CANCELEDが返ります

XError xfiber_signal_timed_wait ( XBits  sigs,
XBits result,
XTicks  timeout 
)

シグナルが成立するのをタイムアウト付きで待ちます

引数
sigs待ちビットパターン
result待ち解除時のビットパターンの格納先
timeoutタイムアウト時間
XError xfiber_suspend ( XFiber *  fiber)

タスクをサスペンド状態に遷移させます

サスペンド中のタスクはリジュームされるまで実行状態にはなりません。

既に待ち状態にあるタスクは、サスペンド・ウエイトという2重待ち状態になります 。この場合、サスペンドだけが解除されてもウエイト状態は継続し、ウエイトだけが 解除されてもサスペンド状態は継続します。