/*---------------------------------------------------------------------------* Project: Horizon File: nos_horizon.h Copyright (C)2009 Nintendo Co., Ltd. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Rev: 19672 $ *---------------------------------------------------------------------------*/ #include #include #include #include #include #include #include #include #include #ifndef NN_NET_OSL_OSL_COMPATIBLE_H_ #define NN_NET_OSL_OSL_COMPATIBLE_H_ #ifdef __cplusplus extern "C" { #endif /* * システム依存パラメータ * * システムのアロケータを呼び出す際、各モジュールは * アラインサイズとして以下のいずれかを指定します。 * 適切な値を定義してください。 */ #define NOS_MEM_ALIGN_STRUCT_SAFE 8 /**< 構造体として使用する領域のメモリ確保で指定するアライン */ #define NOS_MEM_ALIGN_4 4 /**< 4byte長以下のアラインで良い領域のメモリ確保で指定するアライン */ #define NOS_MEM_ALIGN_STACK 8 /**< スレッドのスタックとして使用する領域のメモリ確保で指定するアライン */ #define NN_INLINE extern __inline #define BOOL s32 #define TRUE 1 #define FALSE 0 typedef void (*nnosThreadFunc)(uptr param); /* thread */ /** * スレッド構造体。 */ typedef nnosThread NOSThread; /** * NOS_CreateThread()で返されるID。 * * 以後、スレッドに対する操作は、NOSThreadにではなく、 * NOSThreadIdに対して行ってください。 */ typedef nnosThread *NOSThreadId; /** * スレッドキュー構造体。 */ typedef nnosEvent NOSThreadQueue; /** * スレッドの作成と起動 * * スレッドを作成し、起動します。 * * thread は作成するスレッド構造体へのポインタです。スレッドは func から実行されます。 * arg に入れられた値は func の第一引数として扱われます。 * スタック領域は stack と stackSize で指定します。stack はスタックポインタの開始アドレスで、 * スタック領域の最上位アドレス(+1)となります。 * * (例) * id = NOS_CreateAndStartThread( &thread, proc, NULL, stack+STACK_SIZE/sizeof(u64), STACK_SIZE,THREAD_PRIO ); * * * @param thread 初期化するスレッド構造体へのポインタ * @param func 実行を開始する関数へのポインタ * @param arg 実行を開始する関数へ渡す引数 * @param stack スタックポインタの開始アドレス。スタックは下位方向に積まれていくので、 * スタックの最上位の位置を指定しなければならない点に注意してください。 * アドレスは4バイトアラインメントされたものである必要があります。 * @param stackSize スタックのサイズ。単位はバイトです。4の倍数である必要があります。 * @param prio スレッドの優先度です。 * * @return NULL 生成失敗。 * @return それ以外 スレッドID。以後このスレッドに対する操作を行う場合、このIDを渡してください。 * * @see NOS_DestroyThread * @see NOS_WakeupThread * @see NOS_WakeupThreadDirect * @see NOS_ExitThread * @see NOS_DestroyThread */ NN_INLINE NOSThreadId NOS_CreateAndStartThread( NOSThread* thread, void (*func)(void*), void* arg, void* stack, u32 stackSize, u32 prio ) { NN_UNUSED_VAR(stackSize); bool result = nnosThreadTryInitializeAndStart(thread, (nnosThreadFunc)func, (uptr)arg, (uptr)stack, prio, NN_OS_CORE_NO_USE_PROCESS_VALUE); if (!result) { return 0; } return (NOSThreadId)thread; } /** * スレッドの結合と終了 * * 指定のスレッドを結合し終了します。その後、他の実行可能なスレッドに切り替わります。 * * スレッド thread が mutex をロックしている場合は、それらロックしている全ての mutex をアンロックします。 * * @param threadId 終了させるスレッドのスレッドID * * @return なし * * @see NOS_CreateThread * @see NOS_ExitThread */ NN_INLINE void NOS_JoinAndDestroyThread(NOSThreadId threadId) { nnosThreadJoin(threadId); nnosThreadFinalize(threadId); } /** * スレッドの作成 * * スレッドを作成します。 * * thread は作成するスレッド構造体へのポインタです。スレッドは func から実行されます。 * arg に入れられた値は func の第一引数として扱われます。 * スタック領域は stack と stackSize で指定します。stack はスタックポインタの開始アドレスで、 * スタック領域の最上位アドレス(+1)となります。 * * (例) * id = NOS_CreateThread( &thread, proc, NULL, stack+STACK_SIZE/sizeof(u64), STACK_SIZE,THREAD_PRIO ); * * NOS_CreateThread() で作成された直後のスレッドは休止状態になっていますので、 * NOS_WakeupThreadDirect() で明示的に動作状態にしてやる必要があります。 * * @param thread 初期化するスレッド構造体へのポインタ * @param func 実行を開始する関数へのポインタ * @param arg 実行を開始する関数へ渡す引数 * @param stack スタックポインタの開始アドレス。スタックは下位方向に積まれていくので、 * スタックの最上位の位置を指定しなければならない点に注意してください。 * アドレスは4バイトアラインメントされたものである必要があります。 * @param stackSize スタックのサイズ。単位はバイトです。4の倍数である必要があります。 * @param prio スレッドの優先度です。 * * @return NULL 生成失敗。 * @return それ以外 スレッドID。以後このスレッドに対する操作を行う場合、このIDを渡してください。 * * @see NOS_DestroyThread * @see NOS_WakeupThread * @see NOS_WakeupThreadDirect * @see NOS_ExitThread * @see NOS_DestroyThread */ NN_INLINE NOSThreadId NOS_CreateThread( NOSThread* thread, void (*func)(void*), void* arg, void* stack, u32 stackSize, u32 prio ) { NN_UNUSED_VAR(stackSize); bool result = nnosThreadTryInitializeAndStart(thread, (nnosThreadFunc)func, (uptr)arg, (uptr)stack, prio, NN_OS_CORE_NO_USE_PROCESS_VALUE); if (!result) { return 0; } return (NOSThreadId)thread; } /** * スレッドの終了 * * 指定のスレッドを終了します。その後、他の実行可能なスレッドに切り替わります。 * * スレッド thread が mutex をロックしている場合は、それらロックしている全ての mutex をアンロックします。 * * @param threadId 終了させるスレッドのスレッドID * * @return なし * * @see NOS_CreateThread * @see NOS_ExitThread */ NN_INLINE void NOS_DestroyThread(NOSThreadId threadId) { // 終了していないスレッドを破棄してはいけない nnosThreadJoin(threadId); nnosThreadFinalize(threadId); } /** * カレントスレッドIDの取得 * * カレントスレッドのスレッドIDを取得します。 * * @param なし * * @return カレントスレッドのスレッドID * * @see NOS_CreateThread */ NN_INLINE NOSThreadId NOS_GetCurrentThread(void) { return (NOSThreadId)nnosThreadGetCurrentId(); } /** * スレッドの起床 * * カレントスレッドのスレッドIDを取得します。 * 指定されたスレッドを一時停止状態から復帰させます。 * この関数を呼ぶことでスレッドの再スケジューリングが発生します。 * 復帰したスレッドが実行可能なスレッドの中で最も優先度が高ければ実行権が移ります。 * * @param threadId 起床させるスレッドのスレッドID * * @return なし * * @see NOS_CreateThread * @see NOS_SleepThread * @see NOS_WakeupThread */ NN_INLINE void NOS_WakeupThreadDirect(NOSThreadId threadId) { NN_UNUSED_VAR(threadId); return; } /** * スレッドキューの初期化 * * NOS_SleepThread() と NOS_WakeupThread() を含む、他のスレッド関数で * 使われるスレッドキューを初期化します。 * * queue には複数のスレッドを登録することができ、これにより NOS_WakeupThread() で * 複数のスレッドを一度に起動状態にすることができます。 * * @param queue 初期化するスレッドキューへのポインタ * * @return なし * * @see NOS_CreateThread * @see NOS_WakeupThread */ NN_INLINE void NOS_InitThreadQueue(NOSThreadQueue* queue) { nnosEventInitialize(queue, TRUE); } /** * スレッドキューの起床 * * 指定されたスレッドキュー中のスレッドを全て復帰します。 * スレッドキュー queue が指定された NOS_SleepThread() で一時停止状態になっている * スレッドをまとめて実行可能状態にします。 * * @param queue 起床させるスレッドが登録されているのスレッドキューへのポインタ * * @return なし * * @see NOS_CreateThread * @see NOS_SleepThread * @see NOS_WakeupThreadDirect */ NN_INLINE void NOS_WakeupThread(NOSThreadQueue* queue) { nnosEventSignal(queue); } /** * カレントスレッドの停止とスレッドキューへの登録 * * カレントスレッドを一時停止し、queue で指定したスレッドキューへ登録します。 * この queue を引数にしてNOS_WakeupThread() が呼ばれるまで、一時停止状態のままと * なります。ただし、それまでにNOS_WakeupThreadDirect() でこのスレッドが指定されれば * 一時停止状態から実行可能状態に遷移します。 * * queue がNULLの場合はスレッドキューへの登録を行ないませんので、他スレッドからの * NOS_WakeupThreadDirect() でのみ復帰することが出来ます。 * * @param queue 現在のスレッドを登録するスレッドキューへのポインタ。 * NULL ならスレッドキューへの登録を行ないません。 * * @return なし * * @see NOS_CreateThread * @see NOS_WakeupThread * @see NOS_WakeupThreadDirect */ NN_INLINE void NOS_SleepThread(NOSThreadQueue* queue) { // 同期オブジェクトを使用せずに自らスレッドを休眠させる事は許さない NN_TASSERT_(queue != NULL); nnosEventClearSignal(queue); nnosEventWaitSignal(queue); } /** * スレッドの結合 * * スレッドを結合し、指定のスレッドが終了するまで待ちます。 * 既に指定のスレッドが終了しているときには何もしません。 * * 複数のスレッドが、一つのスレッドに対し OS_JoinThread() しても構いません。 * * @param threadId 結合するスレッドのスレッドID * * @return なし */ NN_INLINE void NOS_JoinThread(NOSThreadId threadId) { nnosThreadJoin(threadId); } /* sleep */ /** * スレッドの休止 * * スレッドを一定時間休止状態にします。 * * @param msec 休止状態にする時間 (ミリ秒) * * @return なし */ NN_INLINE void NOS_Sleep(u32 msec) { nnosThreadSleep((s64)msec*1000000 + 1); } NN_INLINE void NOS_YieldThread(void) { nnosThreadYield(); } /* mutex */ /** * Mutex構造体。 */ typedef nnosCriticalSection NOSMutex; /** * Mutex ID。 * * NOS_CreateMutex()で返されるID。 * 以後、Mutexに対する操作は、NOSMutexにではなく * NOSMutexIdに対して行ってください。 */ typedef nnosCriticalSection *NOSMutexId; /** * Mutexの作成 * * Mutexを作成します。 * * @param m 作成するMutex構造体へのポインタ。 * * @return NULL 作成失敗 * @return それ以外 Mutex ID。 * * @see NOS_DestroyMutex * @see NOS_LockMutex * @see NOS_UnlockMutex * @see NOS_TryLockMutex */ NN_INLINE NOSMutexId NOS_CreateMutex(NOSMutex *m) { NN_ASSERT(m != NULL); bool result = nnosCriticalSectionTryInitialize(m); if (!result) { return 0; } return (NOSMutexId)m; } /** * Mutexの削除 * * 指定のMutexを削除します。 * * @param mutexId Mutex ID。 * * @return なし * * @see NOS_CreateMutex */ NN_INLINE void NOS_DestroyMutex(NOSMutexId mutexId) { NN_ASSERT(mutexId != NULL); nnosCriticalSectionFinalize(mutexId); } /** * Mutexのロック * * 呼び出したスレッドは、mutexId で指定したミューテックスのロックを試みます。 * * mutexId が、別のスレッドによって保持されている場合、mutexId が解放されるまで呼び出したスレッドは一時停止されます。 * mutexId が、現在のスレッドに既に保持されている場合はすぐに戻ります。 * 但し、OS_LockMutex() を呼び出した回数は記録されていて、同じ回数だけアンロックされなければ mutex は解放されません。 * * mutex をロックしているスレッドが OS_ExitThread() によって終了したときは、そのmutex は自動的にアンロックされます。 * * @param mutexId Mutex ID。 * * @return なし * * @see NOS_UnlockMutex * @see NOS_TryLockMutex * @see NOS_ExitThread */ NN_INLINE void NOS_LockMutex(NOSMutexId mutexId) { NN_ASSERT(mutexId != NULL); nnosCriticalSectionEnter(mutexId); } /** * Mutexの解除 * * * 呼び出したスレッドは mutexId を解放します。 * 呼び出したスレッドは、mutexId の所有者でなければなりません。 * * ただし、呼び出したスレッドがこの mutexId を n 回ロックしていた場合、 * n 番目の OS_LockMutex() でのみ実際にmutex を解放します。 * * mutex をロックしているスレッドが OS_ExitThread() によって終了したときは、そのmutex は自動的にアンロックされます。 * * @param mutexId Mutex ID。 * * @return なし * * @see NOS_LockMutex * @see NOS_TryLockMutex * @see NOS_ExitThread */ NN_INLINE void NOS_UnlockMutex(NOSMutexId mutexId) { NN_ASSERT(mutexId != NULL); nnosCriticalSectionLeave(mutexId); } /** * Mutexのロックを試みる * * 呼び出したスレッドは、mutexId で指定したミューテックスのロックを試みます。 * * ロックできない場合は FALSE を返します。ロックできる場合は、OS_LockMutex() の処理に準じます。 * * @param mutexId Mutex ID。 * * @return なし * * @see NOS_UnlockMutex * @see NOS_LockMutex * @see NOS_ExitThread */ NN_INLINE BOOL NOS_TryLockMutex(NOSMutexId mutexId) { NN_ASSERT(mutexId != NULL); return nnosCriticalSectionTryEnter(mutexId); } /* tick */ /** * チック値 * * NOSTickは必ずu64長で、u64全域で一周すカウンタとして * 実装してください。 */ typedef u64 NOSTick; /** * チック値の取得 * * OS_GetTick()がu64より小さい値域を返す場合は、 * なんらかの方法でu64全域の値となるような実装を * 行ってください。 * * @return チック値 */ NN_INLINE NOSTick NOS_GetTick(void) { //TODO: 回り込み対策 return (NOSTick)nnosTickGetSystemCurrent(); } /** * NOSTickの大小比較 * * aとbはNOSTickの半域以上離れていないとします。 * * NOS_CmpTick(a, b) > 0 なら a > b。 * NOS_CmpTick(a, b) < 0 なら a < b。 * NOS_CmpTick(a, b) = 0 なら a = b。 * * @param a チック値A。 * @param b チック値B。 * * @return チックの差分。 */ NN_INLINE s64 NOS_CmpTick(NOSTick a, NOSTick b) { return (s64)(a - b); } NN_INLINE s64 NOS_TicksToSeconds(s64 tick) { return nnosTickConvertToSeconds(tick); } NN_INLINE s64 NOS_TicksToMilliSeconds(s64 tick) { return nnosTickConvertToMilliSeconds(tick); } NN_INLINE s64 NOS_TicksToMicroSeconds(s64 tick) { return nnosTickConvertToMicroSeconds(tick); } NN_INLINE s64 NOS_TicksToNanoSeconds(s64 tick) { return nnosTickConvertToNanoSeconds(tick); } NN_INLINE NOSTick NOS_SecondsToTicks(s64 s) { return nnosTickConvertFromSeconds(s); } NN_INLINE NOSTick NOS_MilliSecondsToTicks(s64 ms) { return nnosTickConvertFromMilliSeconds(ms); } NN_INLINE NOSTick NOS_MicroSecondsToTicks(s64 ms) { return nnosTickConvertFromMicroSeconds(ms); } NN_INLINE NOSTick NOS_NanoSecondsToTicks(s64 ns) { return nnosTickConvertFromNanoSeconds(ns); } /* messagequeue */ #define NOS_MESSAGE_NOBLOCK 0 #define NOS_MESSAGE_BLOCK 1 /** * メッセージキュー構造体 */ typedef nnosBlockingQueue NOSMessageQueue; /** * メッセージキューID */ typedef nnosBlockingQueue *NOSMessageQueueId; /** * メッセージ */ typedef uptr NOSMessage; /** * メッセージキューの作成 * * メッセージキューを作成して、そのIDを返します。 * * 引数 msgArray は、このキューついてメッセージを保持する配列へのポインタで、 * 引数 msgCount は、キューが保持できるメッセージ数 (すなわち、配列のサイズ) です。 * * @param mq メッセージキュー構造体へのポインタ * @param msgArray メッセージを保持する配列へのポインタ * @param msgCount 配列が保持できるメッセージ数 * * @return メッセージキューID。 * * @see NOS_DestroyMessageQueue * @see NOS_ReceiveMessage * @see NOS_SendMessage * @see NOS_ReadMessage * @see NOS_JamMessage */ NN_INLINE NOSMessageQueueId NOS_CreateMessageQueue(NOSMessageQueue *mq, NOSMessage *msgArray, s32 msgCount) { bool result = nnosBlockingQueueTryInitialize(mq, msgArray, msgCount); if (!result) { return 0; } return (NOSMessageQueueId)mq; } /** * メッセージキューの削除 * * メッセージキューを削除します。 * * @param mqId メッセージキューID。 * * @return なし * * @see NOS_CreateMessageQueue */ NN_INLINE void NOS_DestroyMessageQueue(NOSMessageQueueId mqId) { nnosBlockingQueueFinalize(mqId); } /** * メッセージキューからメッセージの取り出し * * メッセージキューからメッセージを取り出します。 * また、このキューにメッセージを送るために待ち状態のスレッドをどれも実行可能状態にします。 * 送信スレッドは、優先順位の順に実行されます。 * * * flag にOS_MESSAGE_BLOCKを設定した場合、キューが空 (empty) であれば、 * この関数を呼び出したスレッドは一時停止されます。メッセージがキューに送られるとすぐに再開されます。 * より高い優先順位の受信スレッドが他にあった場合、これらのスレッドが最初に実行し、 * メッセージを取り出す点に注意してください。 * このスレッドが実行する時にメッセージキューが空であった場合、 * 他のメッセージがキューに送られるまで、このスレッドは再び一時停止します。 * * flagにOS_MESSAGE_NOBLOCKを設定した場合、呼び出したスレッドにすぐに戻ります。 * キューが空でなければ、TRUEを返し、キューが空であればFALSEを返します。 * * @param mqId メッセージキューID * @param msg 受信するメッセージ * @param flag OS_MESSAGE_BLOCKを設定した場合、OS_ReceiveMessage関数は、空のキューをブロックします。
* OS_MESSAGE_NOBLOCKを設定した場合、OS_ReceiveMessage関数は、キューが空であろうとなかろうと、 すぐに返ります。 * * @return TRUE メッセージがうまく取り出せた場合 * @return FALSE OS_MESSAGE_NOBLOCK が指定され、キューが空であった場合 * * @see NOS_SendMessage * @see NOS_ReadMessage * @see NOS_JamMessage */ NN_INLINE BOOL NOS_ReceiveMessage(NOSMessageQueueId mqId, NOSMessage *msg, s32 flag) { if (flag == NOS_MESSAGE_BLOCK) { *msg = nnosBlockingQueueDequeue(mqId); return TRUE; } else { return nnosBlockingQueueTryDequeue(mqId, msg); } } /** * メッセージキューの末尾にメッセージを挿入 * * 指定したメッセージキューの末尾にメッセージを挿入します。 * また、このメッセージキューで待ち状態のスレッドを実行可能状態にします。受信スレッドは、優先順位の順に実行されます。 * * flag にOS_MESSAGE_BLOCKを設定した場合、キューが一杯 (full) であれば、 * この関数を呼び出したスレッドを一時停止します。受信スレッドが動作して、 * キューからメッセージを取り出すとすぐに再開されます。 * より高い優先順位の送信スレッドが他にあった場合、それらが最初に動作し、 * 再度メッセージキューが一杯になるかもしれない点に注意してください。 * これが起こった場合、受信スレッドがメッセージキューに空をつくるまで、このスレッドは、再び一時停止します。 * * flag にOS_MESSAGE_NOBLOCKを設定した場合、呼び出したスレッドにすぐに返ります。 * キューが一杯でない場合、TRUEが返されます。キューが一杯であった場合、 FALSEが返されます。 * * @param mqId メッセージキューID * @param msg 送信するメッセージ * @param flag OS_MESSAGE_BLOCKを設定した場合、OS_SendMessage関数は、キューが一杯の時ブロックします。
* OS_MESSAGE_NOBLOCKを設定した場合、OS_SendMessage関数は、キューが一杯であろうとなかろうと、 すぐに返ります。 * * @return TRUE メッセージがうまく送られた場合 * @return FALSE OS_MESSAGE_NOBLOCK が指定され、キューが一杯であった場合 * * @see NOS_ReceiveMessage * @see NOS_ReadMessage * @see NOS_JamMessage */ NN_INLINE BOOL NOS_SendMessage(NOSMessageQueueId mqId, NOSMessage msg, s32 flag) { if (flag == NOS_MESSAGE_BLOCK) { nnosBlockingQueueEnqueue(mqId, msg); return TRUE; } else { return nnosBlockingQueueTryEnqueue(mqId, msg); } } /** * メッセージキューの先頭のメッセージのコピー * * メッセージキューの先頭のメッセージをコピーします。 * メッセージキューの状態は変化しません。また OS_ReceiveMessatge() と違って、 * このキューにメッセージを送るために待ち状態のスレッドを実行可能状態にすることもありません。 * いわば、OS_ReadMessage() は、メッセージキューの先頭のメッセージを覗くための関数です。 * * flagsにOS_MESSAGE_BLOCKを設定した場合、キューが空 (empty) であれば、 * この関数を呼び出したスレッドは一時停止されます。メッセージがキューに送られるとすぐに再開されます。 * より高い優先順位の受信スレッドが他にあった場合、これらのスレッドが最初に実行し、 * メッセージを取り出す点に注意してください。 * このスレッドが実行する時にメッセージキューが空であった場合、他のメッセージがキューに送られるまで、 * このスレッドは再び一時停止します。 * * flagsにOS_MESSAGE_NOBLOCKを設定した場合、呼び出したスレッドにすぐに戻ります。 * キューが空でなければ、TRUE を返し、キューが空であればFALSE を返します。 * * @param mqId メッセージキューID * @param msg 覗いたメッセージ * @param flag OS_MESSAGE_BLOCKを設定した場合、OS_ReadMessage関数は、空のキューをブロックします。
* OS_MESSAGE_NOBLOCKを設定した場合、OS_ReadMessage関数は、キューが空であろうとなかろうと、 すぐに返ります。 * * @return TRUE メッセージがうまく取り出せた場合 * @return FALSE OS_MESSAGE_NOBLOCK が指定され、キューが空であった場合 * * @see NOS_ReceiveMessage * @see NOS_SendMessage * @see NOS_JamMessage */ NN_INLINE BOOL NOS_ReadMessage(NOSMessageQueueId mqId, NOSMessage *msg, s32 flag) { if (flag == NOS_MESSAGE_BLOCK) { *msg = nnosBlockingQueueGetFront(mqId); return TRUE; } else { return nnosBlockingQueueTryGetFront(mqId, msg); } } /** * メッセージキューの先頭にメッセージを挿入 * * 指定したメッセージキューの先頭にメッセージを挿入する事以外は、OS_SendMessage()関数と同じです。 * この呼び出しは、優先順位の高いメッセージを伝達するために使います。 * * flag にOS_MESSAGE_BLOCKを設定した場合、キューが一杯 (full) であれば、 * この関数を呼び出したスレッドを一時停止します。受信スレッドが動作して、 * キューからメッセージを取り出すとすぐに再開されます。 * より高い優先順位の送信スレッドが他にあった場合、それらが最初に動作し、 * 再度メッセージキューが一杯になるかもしれない点に注意してください。 * これが起こった場合、受信スレッドがメッセージキューに空をつくるまで、このスレッドは、再び一時停止します。 * * flag にOS_MESSAGE_NOBLOCKを設定した場合、呼び出したスレッドにすぐに返ります。 * キューが一杯でない場合、TRUEが返されます。キューが一杯であった場合、 FALSEが返されます。 * * @param mqId メッセージキューID * @param msg 送信するメッセージ * @param flag OS_MESSAGE_BLOCKを設定した場合、OS_SendMessage関数は、キューが一杯の時ブロックします。
* OS_MESSAGE_NOBLOCKを設定した場合、OS_SendMessage関数は、キューが一杯であろうとなかろうと、 すぐに返ります。 * * @return TRUE メッセージがうまく送られた場合 * @return FALSE OS_MESSAGE_NOBLOCK が指定され、キューが一杯であった場合 * * @see NOS_ReceiveMessage * @see NOS_ReadMessage * @see NOS_JamMessage */ NN_INLINE BOOL NOS_JamMessage(NOSMessageQueueId mqId, NOSMessage msg, s32 flag) { if (flag == NOS_MESSAGE_BLOCK) { nnosBlockingQueueJam(mqId, msg); return TRUE; } else { return nnosBlockingQueueTryJam(mqId, msg); } } typedef void (*NOSAlarmHandler) (void *); /**< タイムアウト時に呼び出すユーザのコールバック関数 */ /** * アラーム構造体 */ typedef struct NOSAlarm { nnosAlarm alarm; NOSAlarmHandler handler; void* arg; } NOSAlarm; /** * アラームID */ typedef NOSAlarm *NOSAlarmId; /* NOS_alarm.c */ NN_INLINE s32 NOS_InitAlarm(void){ return 0; } NOSAlarmId NOS_CreateAlarm(NOSAlarm *pAlarm); void NOSi_AlarmHandler(void* param, bool cancelled); s32 NOS_SetAlarm(NOSAlarmId alarmId, NOSTick tick, NOSAlarmHandler callback, void *arg); s32 NOS_CancelAlarm(NOSAlarmId alarmId); void NOS_DestroyAlarm(NOSAlarmId alarmId); s32 NOS_SetPeriodicAlarm(NOSAlarmId alarmId, NOSTick start, NOSTick period, NOSAlarmHandler callback, void *arg); typedef struct { nnnetOslEventFlag eventFlag; NLIBLink link; s32 priority; } NOSEvent; typedef NOSEvent *NOSEventId; #define NOS_TMO_FEVR 0xffffffffffffffff typedef enum { NOS_EVENT_MODE_AND = NN_NET_OSL_WAITMODE_AND, NOS_EVENT_MODE_OR = NN_NET_OSL_WAITMODE_OR } NOSEventMode; NN_INLINE NOSEventId NOS_CreateEvent(NOSEvent* pEvent) { bool result = nnnetOslEventFlagTryInitialize(&pEvent->eventFlag); if (!result) { return 0; } return (NOSEventId)pEvent; } NN_INLINE void NOS_DestroyEvent(NOSEventId eventId) { NOSEvent* pEvent = (NOSEvent*)eventId; nnnetOslEventFlagFinalize(&pEvent->eventFlag); } NN_INLINE u32 NOS_WaitEvent(NOSEventId eventId, u32 pattern, NOSEventMode mode) { NOSEvent* pEvent = (NOSEvent*)eventId; return nnnetOslEventFlagWaitSignal(&pEvent->eventFlag, pattern, (nnnetOslWaitMode)mode, NN_OS_WAIT_INFINITE); } NN_INLINE u32 NOS_WaitEvent_And(NOSEventId eventId, u32 pattern) { NOSEvent* pEvent = (NOSEvent*)eventId; return nnnetOslEventFlagWaitSignal(&pEvent->eventFlag, pattern, NN_NET_OSL_WAITMODE_AND, NN_OS_WAIT_INFINITE); } NN_INLINE u32 NOS_WaitEvent_Or(NOSEventId eventId, u32 pattern) { NOSEvent* pEvent = (NOSEvent*)eventId; return nnnetOslEventFlagWaitSignal(&pEvent->eventFlag, pattern, NN_NET_OSL_WAITMODE_OR, NN_OS_WAIT_INFINITE); } NN_INLINE u32 NOS_WaitEventEx(NOSEventId eventId, u32 pattern, NOSEventMode mode, u32 clearBit) { NOSEvent* pEvent = (NOSEvent*)eventId; return nnnetOslEventFlagWaitAndClear(&pEvent->eventFlag, pattern, (nnnetOslWaitMode)mode, clearBit, NN_OS_WAIT_INFINITE); } NN_INLINE u32 NOS_WaitEventEx_And(NOSEventId eventId, u32 pattern, u32 clearBit) { NOSEvent* pEvent = (NOSEvent*)eventId; return nnnetOslEventFlagWaitAndClear(&pEvent->eventFlag, pattern, NN_NET_OSL_WAITMODE_AND, clearBit, NN_OS_WAIT_INFINITE); } NN_INLINE u32 NOS_WaitEventEx_Or(NOSEventId eventId, u32 pattern, u32 clearBit) { NOSEvent* pEvent = (NOSEvent*)eventId; return nnnetOslEventFlagWaitAndClear(&pEvent->eventFlag, pattern, NN_NET_OSL_WAITMODE_OR, clearBit, NN_OS_WAIT_INFINITE); } NN_INLINE void NOS_SignalEvent(NOSEventId eventId, u32 setPattern) { NOSEvent* pEvent = (NOSEvent*)eventId; nnnetOslEventFlagSignal(&pEvent->eventFlag, setPattern); } NN_INLINE u32 NOS_PollEvent(NOSEventId eventId, u32 pattern, NOSEventMode mode) { NOSEvent* pEvent = (NOSEvent*)eventId; return nnnetOslEventFlagWaitSignal(&pEvent->eventFlag, pattern, (nnnetOslWaitMode)mode, 0); } NN_INLINE void NOS_ClearEvent(NOSEventId eventId, u32 clearBit) { NOSEvent* pEvent = (NOSEvent*)eventId; nnnetOslEventFlagClearSignal(&pEvent->eventFlag, clearBit); } NN_INLINE void NOS_ClearAllEvent(NOSEventId eventId) { NOSEvent* pEvent = (NOSEvent*)eventId; nnnetOslEventFlagClearSignal(&pEvent->eventFlag, 0xffffffff); } NN_INLINE u32 NOS_TimeWaitEventEx(NOSEventId eventId, u32 pattern, NOSEventMode mode, u32 clearBit, NOSTick timeout) { NOSEvent* pEvent = (NOSEvent*)eventId; return nnnetOslEventFlagWaitAndClear(&pEvent->eventFlag, pattern, (nnnetOslWaitMode)mode, clearBit, NOS_TicksToNanoSeconds(timeout)); } /* EventQueue */ typedef NLIBQueue NOSEventQueue; typedef NOSEventQueue *NOSEventQueueId; /** * イベントキューの作成 * * イベントキューを作成します。 * * @param eq 作成するEventQueue構造体へのポインタ。 * * @return NULL 作成失敗 * @return それ以外 EventQueueID。 * * @see NOS_DestroyEventQueue * @see NOS_EnqueueEventQueue * @see NOS_DequeueEventQueue * @see NOS_SignalEventQueue */ NN_INLINE NOSEventQueueId NOS_CreateEventQueue(NOSEventQueue *eq) { NLIB_Queue_Init((NLIBQueue *)eq); return (NOSEventQueueId)eq; } /** * イベントキューの削除 * * 指定のイベントキューを削除します。 * * @param eqId EventQueueID。 * * @return なし * * @see NOS_CreateEventQueue * @see NOS_EnqueueEventQueue * @see NOS_DequeueEventQueue * @see NOS_SignalEventQueue */ NN_INLINE void NOS_DestroyEventQueue(NOSEventQueueId eqId) { NN_UNUSED_VAR(eqId) ; } extern void NOS_EnqueueEventQueue(NOSEventQueueId queueId, NOSEventId eventId); extern void NOS_DequeueEventQueue(NOSEventQueueId queueId, NOSEventId eventId); extern void NOS_SignalEventQueue(NOSEventQueueId queueId, u32 pattern); /* mbuf */ //#define NOS_MBUF_SIZE NN_NET_OSL_MBUF_DATA_SIZE /**< 一つのmbufに入るデータサイズ */ //#define NOS_MBUF_NUM 512 /**< mbufの数 */ #define NOS_M_BCAST NN_NET_OSL_M_BCAST #define NOS_M_MCAST NN_NET_OSL_M_MCAST #define NOS_M_LOOPBACK NN_NET_OSL_M_LOOPBACK #define NOS_M_DONTWAIT 0 /**< 待ちなし */ #define NOS_M_WAIT 1 /**< 待ちあり */ #define NOS_M_FREELIST 0x8000 /**< mbufはフリーリストにある(デバッグ用) */ #define NOS_MT_DATA 1 /**< データタイプ */ #define NOS_MBUF_ADDR_SIZE 6 /**< MACアドレスのサイズ */ #define NOS_M_CAT_NWCM 0x01 /**< NWCM(暫定無線ドライバ)が受信パケットのために確保 */ #define NOS_M_CAT_NWMETH 0x01 /**< NWMETHが受信パケットのために確保 */ #define NOS_M_CAT_ARP 0x02 /**< NSOCがARP受信パケットのために確保 */ #define NOS_M_CAT_ICMPERR 0x03 /**< NSOCがICMPエラーパケット送信のために確保 */ #define NOS_M_CAT_ICMPECHO 0x04 /**< NSOCがpingパケット送信のために確保 */ #define NOS_M_CAT_IGMP 0x05 /**< NSOCがIGMPパケット送信のために確保 */ #define NOS_M_CAT_IPREASM 0x06 /**< NSOCがIPパケット再構築のために確保 */ #define NOS_M_CAT_IPFRAG 0x07 /**< NSOCがIPパケットのフラグメントのために確保 */ #define NOS_M_CAT_TCPRESP 0x08 /**< NSOCがTCP応答のために確保 */ #define NOS_M_CAT_TCPSEND 0x09 /**< NSOCがTCPパケット送信のために確保 */ #define NOS_M_CAT_UDP 0x0a /**< NSOCがUDPパケット送信のために確保 */ #define NOS_M_CAT_NDP 0x0b /**< NSOCがNDPパケット送信のために確保 */ #define NOS_M_CAT_MLD 0x0c /**< NSOCがMLDパケット送信のために確保 */ #define NOS_M_CAT_PPPOE 0x81 /**< NSOCがPPPoEパケット送信のために確保 */ #define NOS_M_CAT_PPP 0x82 /**< NSOCがPPPパケット送信のために確保 */ #ifdef NDEBUG_ENABLE #define NOS_M_OWN_NSOC 0x02 /* NSOCが使用中 */ #define NOS_M_OWN_NPOE 0x03 /* NPOEが使用中 */ #define NOS_M_OWN_NPPP 0x04 /* NPPPが使用中 */ #endif typedef nnnetOslMbuf NOSMessageBuf; #define NOS_mtod(m, t) ((t)(nnnetOslMbuf_tod(m))) NN_EXTERN_C s32 NOS_m_init(void); NN_EXTERN_C NOSMessageBuf* NOS_m_getm(u32 name, NOSMessageBuf *orig, s32 len, s32 how, u8 type); NN_INLINE void NOS_m_freem(NOSMessageBuf *mbuf) { nnnetOslMbuf_freem(mbuf); } NN_INLINE s32 NOS_m_adj(NOSMessageBuf *mbuf, s32 len) { return nnnetOslMbuf_adj(mbuf, len); } NN_INLINE s32 NOS_m_append(NOSMessageBuf *mbuf, s32 len, const u8 *cp) { return nnnetOslMbuf_append(mbuf, len, cp); } NN_INLINE NOSMessageBuf *NOS_m_prepend(NOSMessageBuf *mbuf, s32 len, int how) { return nnnetOslMbuf_prepend(mbuf, len, how); } NN_INLINE NOSMessageBuf *NOS_m_pullup(NOSMessageBuf *mbuf, s32 len) { return nnnetOslMbuf_pullup(mbuf, len); } NN_INLINE NOSMessageBuf *NOS_m_dup(NOSMessageBuf *mbuf, int how) { return nnnetOslMbuf_dup(mbuf, how); } NN_INLINE s32 NOS_m_copydata(const NOSMessageBuf *mbuf, s32 offset, s32 len, u8 *buf) { return nnnetOslMbuf_copydata(mbuf, offset, len, buf); } NN_INLINE s32 NOS_m_copyback(NOSMessageBuf *mbuf, s32 offset, s32 len, const u8 *buf) { return nnnetOslMbuf_copyback(mbuf, offset, len, buf); } NN_INLINE s32 NOS_m_cat(NOSMessageBuf *mbuf, NOSMessageBuf *n) { return nnnetOslMbuf_cat(mbuf, n); } NN_INLINE NOSMessageBuf *NOS_m_split(NOSMessageBuf *mbuf, s32 len, int how) { return nnnetOslMbuf_split(mbuf, len, how); } NN_INLINE s32 NOS_m_length(NOSMessageBuf *mbuf, NOSMessageBuf **last) { return nnnetOslMbuf_length(mbuf, last); } NN_INLINE s32 NOS_m_apply(NOSMessageBuf *mbuf, s32 offset, s32 len, s32 (*f)(void *arg, void *data, s32 len), void *arg) { return nnnetOslMbuf_apply(mbuf, offset, len, f, arg); } #ifdef NDEBUG_ENABLE NN_INLINE s32 NOS_m_getfree(void) { return 0; } NN_INLINE void NOS_m_setowner(NOSMessageBuf *mbuf, u16 owner) { NN_UNUSED_VAR(mbuf); NN_UNUSED_VAR(owner); } NN_INLINE s32 NOS_m_getnum(u16 owner) { NN_UNUSED_VAR(owner); return 0; } NN_INLINE NOSMessageBuf *NOS_m_getaddr(int index) { NN_UNUSED_VAR(index); return NULL; } #endif #ifdef NDEBUG_PRINT_ENABLE NN_INLINE void NOS_m_dump(NOSMessageBuf *mbuf) { nnnetOslMbuf_dump(mbuf); } #endif /* NOS_main.c */ extern s32 NOS_Init(void); #ifdef __cplusplus } #endif #endif