/*! * システムコール処理(tloc_mtx():mutexタイムアウト付きロック処理(プロトコルなし)) * *mcb : 対象mutexコントロールブロックへのポインタ * msec : タイムアウト値 * (返却値)E_PAR : パラメータエラー * (返却値)E_OK : 正常終了(mutexセマフォを取得,mutexセマフォ待ちタスクにつなげる) * (返却値)E_OK,E_ILUSE : dynamic_multipl_lock()の返却値(再帰ロック完了,多重再帰ロック) * (返却値)E_TMOUT : タイムアウト */ ER tloc_voidmtx_isr(MTXCB *mcb, int msec) { int tskid; tskid = current->init.tskid; /* ロックしてきたタスクのIDを取得 */ /* パラメータエラーチェック */ if (msec < TMO_FEVR) { putcurrent(); /* システムコール発行タスクをレディーへ */ return E_PAR; } /* ここからロック操作 */ else if (mcb->ownerid != -1) { /* ロックしているタスクがあるか */ /* オーナータスクでない場合 */ if (mcb->ownerid != tskid) { /* 取得できない場合で,ポーリングが設定された */ if (msec == TMO_POL) { putcurrent(); /* システムコール発行スレッドを戻す */ return E_TMOUT; } wait_mtx_tsk(mcb, msec); /* mutexセマフォ待ちタスクの追加 */ return E_OK; } /* オーナータスクの場合,再帰ロック */ else { return loc_multipl_mtx(mcb); /* mutex再帰ロックをする関数 */ } } /* 初期ロック */ else { loc_first_mtx(tskid, mcb); /* mutex初期ロックをする関数 */ return E_OK; } }
static kz_thread_id_t thread_run(kz_func_t func, char *name, int priority, int stacksize, int argc, char *argv[]) { int i; kz_thread *thp; uint32 *sp; extern char userstack; static char *thread_stack = &userstack; for(i = 0; i < THREAD_NUM; i++) { thp = &threads[i]; if (!thp->init.func) break; } if (i == THREAD_NUM) return -1; memset(thp, 0, sizeof(*thp)); /* setting for task controll block */ strcpy(thp->name, name); thp->next = NULL; thp->priority = priority; thp->flags = 0; thp->init.func = func; thp->init.argc = argc; thp->init.argv = argv; memset(thread_stack, 0, stacksize); thread_stack += stacksize; thp->stack = thread_stack; /* initialize stack */ sp = (uint32 *)thp->stack; *(--sp) = (uint32)thread_end; /* setting CCR */ *(--sp) = (uint32)thread_init | ((uint32)(priority ? 0 : 0xC0) << 24); *(--sp) = 0; /* ER6 */ *(--sp) = 0; /* ER5 */ *(--sp) = 0; /* ER4 */ *(--sp) = 0; /* ER3 */ *(--sp) = 0; /* ER2 */ *(--sp) = 0; /* ER1 */ *(--sp) = (uint32)thp; /* ER0 */ thp->context.sp = (uint32)sp; putcurrent(); current = thp; putcurrent(); return (kz_thread_id_t)current; }
static kz_thread_id_t thread_run(kz_func_t func, char* name, int stacksize, int argc, char* argv[]) { int i; kz_thread* thp; uint32* sp; extern char userstack; static char* thread_stack = &userstack; for(i=0; i<THREAD_NUM; ++i){ thp = &threads[i]; if(!thp->init.func) break; } if(i == THREAD_NUM){ return -1; } memset(thp, 0, sizeof(*thp)); strcpy(thp->name, name); thp->next = NULL; thp->init.func = func; thp->init.argc = argc; thp->init.argv = argv; /** initialize stack */ memset(thread_stack, 0, stacksize); thread_stack += stacksize; thp->stack = thread_stack; sp = (uint32*)thp->stack; *(--sp) = (uint32)thread_end; /** initialize program counter */ *(--sp) = (uint32)thread_init; *(--sp) = 0; /* ER6 */ *(--sp) = 0; /* ER5 */ *(--sp) = 0; /* ER4 */ *(--sp) = 0; /* ER3 */ *(--sp) = 0; /* ER2 */ *(--sp) = 0; /* ER1 */ *(--sp) = (uint32)thp; /* ER0 : argv[0] */ thp->context.sp = (uint32)sp; /** put thread called syscall to ready queue */ putcurrent(); /** put thread generated new to ready queue */ current = thp; putcurrent(); return (kz_thread_id_t)current; }
static int thread_wakeup(kz_thread_id_t id) { // wakeupを呼び出してスレッドを末尾へ putcurrent(); // 引数で指定されたスレッドをready que に戻す current = (kz_thread *)id; putcurrent(); return 0; }
/* システム・コールの処理(kz_wakeup():スレッドのウェイク・アップ) */ static int thread_wakeup(kz_thread_id_t id) { /* ウェイク・アップを呼び出したスレッドをレディー・キューに戻す */ putcurrent(); /* 指定されたスレッドをレディー・キューに接続してウェイク・アップする */ current = (kz_thread *)id; putcurrent(); return 0; }
static int thread_send(kz_msgbox_id_t id, int size, char *p) { kz_msgbox *mboxp = &msgboxes[id]; putcurrent(); sendmsg(mboxp, current, size, p); if (mboxp->receiver) { current = mboxp->receiver; recvmsg(mboxp); putcurrent(); } return size; }
/*! * 非タスクコンテキスト用の優先度変更関数 * -システムコール発行タスク(実行状態タスク)はレディーから抜き取られてくる場合と抜き取られない場合がある * 抜き取られる場合 : システムコール割込みの非タスクコンテキストで呼ばれる * 抜き取られない場合 : シリアル割込みハンドラの非タスクコンテキストで呼ばれる(シリアル割込みはタスクを切り替えず, * かつユーザが自作できるものとしてしている) * *tcb : 優先度変更対象タスク * tskpri : 変更する優先度 */ static void chg_pri_isyscall_isr(TCB *tcb, int tskpri) { /* * /優先度変更タスクが実行状態の場合,実行状態タスクはレディーから抜き取られる場合と * 抜き取られない場合がある * /抜き取られる場合は優先度を変更するのみ * /抜き取られない場合は一度レディーから実行状態タスクを抜き取り,優先度を変更して,再度レディーへ戻す */ if (tcb == g_current) { /* 抜き取られない場合 */ if (tcb->intr_info.type == SERIAL_INTERRUPT) { getcurrent(); /* 非タスクコンテキスト用システムコール発行タスクをレディーへ */ } g_current->priority = tskpri; /* 実行状態タスクの優先度変更 */ /* 抜き取られない場合 */ if (tcb->intr_info.type == SERIAL_INTERRUPT) { putcurrent(); /* 非タスクコンテキスト用システムコール発行タスクをレディーへ */ } DEBUG_LEVEL1_OUTVLE(g_current->init.tskid, 0); DEBUG_LEVEL1_OUTMSG(" out tskid : chg_pri_isyscall_isr().\n"); DEBUG_LEVEL1_OUTVLE(g_current->priority, 0); DEBUG_LEVEL1_OUTMSG(" change priority activ : chg_pri_isyscall_isr().\n"); } /* * 優先度変更タスクが実行可能状態(レディーに存在する)の場合,実行状態タスクはレディーから抜き取られないので, * 実行可能状態タスクをレディーから抜き取り,優先度を変更して,レディーへ戻す */ else if (tcb->state & TASK_READY) { get_tsk_readyque(tcb); /* レディーキューから抜き取る関数(scheduler.cにある) */ g_current->priority = tskpri; putcurrent(); DEBUG_LEVEL1_OUTVLE(g_current->init.tskid, 0); DEBUG_LEVEL1_OUTMSG(" out tskid : chg_pri_isyscall_isr().\n"); DEBUG_LEVEL1_OUTVLE(g_current->priority, 0); DEBUG_LEVEL1_OUTMSG(" change priority ready : chg_pri_isyscall_isr().\n"); } /* * 優先度変更タスクが待ち状態(レディーに存在しない)の場合,実行状態タスクはレディーから抜き取られないので, * 待ち状態タスクの優先度を変更のみ */ else { tcb->priority = tskpri; DEBUG_LEVEL1_OUTVLE(tcb->init.tskid, 0); DEBUG_LEVEL1_OUTMSG(" out tskid : chg_pri_isyscall_isr().\n"); DEBUG_LEVEL1_OUTVLE(tcb->priority, 0); DEBUG_LEVEL1_OUTMSG(" change priority sleep : chg_pri_isyscall_isr().\n"); } }
static int thread_wait(void) { // スレッドをいったん外して末尾に再接続することで // 他のスレッドを動作させる putcurrent(); return 0; }
/*! * mutexロック解除時,mutex待ちタスクを優先度が高いものからレディーへ入れる * (Priority Inheritanceでデッドロックが発生するシナリオはこちらでやらなくてはならない) * *mcb : mutex待ちタスクが存在するMTXCB */ static void put_mtx_pri_ready(MTXCB *mcb) { TCB *worktcb, *maxtcb; worktcb = maxtcb = mcb->waithead; /* 待ちタスクの中で最高優先度のものを探す */ while (worktcb->wait_info.wait_next != NULL) { if (worktcb->priority < maxtcb->priority) { maxtcb = worktcb; } worktcb = worktcb->wait_info.wait_next; } /* 最後の一回分(スリープTCBは双方リストか循環リストの方が効率がいい) */ if (worktcb->priority < maxtcb->priority) { maxtcb = worktcb; } get_tsk_mtx_waitque(mcb, maxtcb); /* mutex待ちキューからスリープTCBを抜き取る関数 */ /* セマフォ待ちタスクの中で優先度が最高のタスクをレディーへ入れる */ current = maxtcb; current->wait_info.wait_next = current->wait_info.wait_prev = NULL; mcb->ownerid = current->init.tskid; /* オーナーシップの設定 */ current->get_info.flags |= TASK_GET_MUTEX; /* 取得情報をセット(TCBに) */ current->get_info.gobjp = (GET_OBJP)mcb; /* 取得情報をセット(TCBに) */ current->state &= ~TASK_WAIT_MUTEX; /* 待ち情報のクリア(TCBに) */ current->wait_info.wobjp = 0; /* 待ち情報のクリア(TCBに) */ putcurrent(); DEBUG_OUTMSG("wait task ready que for interrupt handler.\n"); }
/*! * mutexロック解除時,mutex待ちタスクを先頭からレディーへ入れる * ラウンドロビンスケジューリングをしている時は先頭からレディーへ戻す * *mcb : mutex待ちタスクが存在するMTXCB */ static void put_mtx_fifo_ready(MTXCB *mcb) { /* 先頭のセマフォ待ちタスクをレディーへ */ current = mcb->waithead; mcb->waithead = current->wait_info.wait_next; mcb->waithead->wait_info.wait_prev = NULL; mcb->ownerid = current->init.tskid; /* オーナーシップの設定 */ /* currentが最尾の時tailをNULLにしておく */ if (current->wait_info.wait_next == NULL) { mcb->waittail = NULL; } current->wait_info.wait_next = current->wait_info.wait_next = NULL; mcb->ownerid = current->init.tskid; /* オーナーシップの設定 */ current->get_info.flags |= TASK_GET_MUTEX; /* 取得情報をセット(TCBに) */ current->get_info.gobjp = (GET_OBJP)mcb; /* 取得情報をセット(TCBに) */ current->state &= ~TASK_WAIT_MUTEX; /* 待ち情報のクリア(TCBに) */ current->wait_info.wobjp = 0; /* 待ち情報のクリア(TCBに) */ putcurrent(); DEBUG_OUTMSG("wait task ready que for interrupt handler.\n"); }
/* システム・コールの処理(kz_send():メッセージ送信) */ static int thread_send(kz_msgbox_id_t id, int size, char *p) { kz_msgbox *mboxp = &msgboxes[id]; putcurrent(); sendmsg(mboxp, current, size, p); /* メッセージの送信処理 */ /* 受信待ちスレッドが存在している場合には受信処理を行う */ if (mboxp->receiver) { current = mboxp->receiver; /* 受信待ちスレッド */ recvmsg(mboxp); /* メッセージの受信処理 */ putcurrent(); /* 受信により動作可能になったので,ブロック解除する */ } return size; }
/*! * 優先度逆転問題解消プロトコルによってアンロック処理を切り替える * *mcb : 対象mutexコントロールブロック * (返却値)E_NOSPT : スケジューラが認めていない * (返却値)E_OK : mutexセマフォ待ちタスクへ割り当て,mutexセマフォの解放, * 再帰ロック解除(not_lock_first_mtx()の返却値) * (返却値)E_ILUSE : オーナータスクでない場合,mutexセマフォ解放エラー * (すでに解放済み,not_lock_first_mtx()の返却値) */ ER check_unl_mtx_protocol(MTXCB *mcb) { READY_TYPE type = mg_ready_info.type; TCB *worktcb; for (worktcb = mg_mtx_info.virtual_mtx->waithead; worktcb != NULL; worktcb = worktcb->wait_info.wait_next) { DEBUG_OUTMSG("tskid "); DEBUG_OUTVLE(worktcb->init.tskid, 0); DEBUG_OUTMSG(" \n"); } /* スケジューラによって認めているか */ if (type == SINGLE_READY_QUEUE) { putcurrent(); /* システムコール発行タスクをレディーへ */ return E_NOSPT; } /* プロトコルなし */ else if (mcb->piver_type == TA_VOIDPCL) { return unl_voidmtx_isr(mcb); } /* Delay Highest Lockerプロトコル */ else if (mcb->piver_type == TA_DYHIGHLOC) { return unl_dyhighmtx_isr(mcb); } /* 優先度継承プロトコル */ else if (mcb->piver_type == TA_INHERIT) { return unl_inhermtx_isr(mcb); } /* 優先度上限プロトコル */ else if (mcb->piver_type == TA_CEILING) { return unl_ceilmtx_isr(mcb); } /*Immediate Highest Lockerプロトコル */ else if (mcb->piver_type == TA_IMHIGHLOC) { return unl_imhighmtx_isr(mcb); } /* virtual priority inheritanceプロトコル */ else if (mcb->piver_type == TA_VINHERIT) { return unl_vinhermtx_isr(mcb); } /* 以外 */ else { putcurrent(); /* システムコール発行スレッドをレディーへ */ return E_NOSPT; } }
/*! * schedule_rps()のコールバックルーチン * *argv : つねにNULL(タイマ割込みが発生したならば,現在実行中のタスクがcurrentに設定してあるため) */ void schedule_rps_callrte(void *argv) { /* タスクを回転させる(入れ替える) */ getcurrent(); /* 実行中のタスクは優先度レベルのレディーキュー先頭なので,先頭を抜き取る */ putcurrent(); /* 抜き取ったタスクを優先度レベルのレディーキューの最尾へつなぐ */ mg_schdul_info.entry->un.rps_schdul.tobjp = 0; /* タイマブロックとの接続をクリアにしておく */ }
static int thread_chpri(int priority) { int old = current->priority; if (priority >= 0) current->priority = priority; putcurrent(); return old; }
/*! * dly_tsk()のコールバックルーチン * *argv : 引数を格納したポインタ(ここではタスクIDの汎用ポインタ) */ void dly_callrte(void *argv) { current = (TCB *)argv; current->state &= ~TASK_WAIT_TIME_DELAY; /*時間経過したので,フラグを落としておく*/ current->wait_info.tobjp = 0; /*タスクとタイマコントロールブロックを未接続にする*/ /*待ちに入ったシステムコールの返却値は書き換えない*/ putcurrent(); /*レディーへ戻す*/ }
/* システム・コールの処理(kz_chpri():スレッドの優先度変更) */ static int thread_chpri(int priority) { int old = current->priority; if (priority >= 0) current->priority = priority; /* 優先度変更 */ putcurrent(); /* 新しい優先度のレディー・キューに繋ぎ直す */ return old; }
/*! * 優先度逆転問題解消プロトコルによってタイムアウト付きロック処理を切り替える * *mcb : 対象mutexコントロールブロックへのポインタ * msec : タイムアウト値 * (返却値)E_NOSPT : スケジューラが認めていない * (返却値)E_PAR : パラメータエラー * (返却値)E_OK : 正常終了(mutexセマフォを取得,mutexセマフォ待ちタスクにつなげる) * (返却値)E_OK,E_ILUSE : dynamic_multipl_lock()の返却値(再帰ロック完了,多重再帰ロック) * (返却値)E_TMOUT : タイムアウト * (返却値)E_NOSPT : プロトコルありでのtloc_sem()は認めない */ ER check_tloc_mtx_protocol(MTXCB *mcb, int msec) { READY_TYPE type = mg_ready_info.type; /* スケジューラによって認めているか */ if (type == SINGLE_READY_QUEUE) { putcurrent(); /* システムコール発行スレッドをレディーへ */ return E_NOSPT; } /* プロトコルなし */ else if (mcb->piver_type == TA_VOIDPCL) { return ploc_voidmtx_isr(mcb); } /* 以外 */ else { putcurrent(); /* システムコール発行スレッドをレディーへ */ return E_NOSPT; } }
/*! * タスクコンテキスト用の優先度変更関数 * システムコール発行タスク(実行状態タスク)はレディーから抜き取られてくる * *tcb : 優先度変更対象タスク * tskpri : 変更する優先度 */ static void chg_pri_syscall_isr(TCB *tcb, int tskpri) { /* * 優先度変更タスクが実行状態の場合,実行状態タスクはレディーから抜き取られてくるので, * 優先度を変更してから,実行状態タスクをレディーへ戻す */ if (tcb == g_current) { g_current->priority = tskpri; /* 実行状態タスクの優先度変更 */ putcurrent(); /* システムコール発行タスクをレディーへ */ DEBUG_LEVEL1_OUTVLE(g_current->init.tskid, 0); DEBUG_LEVEL1_OUTMSG(" out tskid : chg_pri_syscall_isr().\n"); DEBUG_LEVEL1_OUTVLE(g_current->priority, 0); DEBUG_LEVEL1_OUTMSG(" change priority activ : chg_pri_syscall_isr().\n"); } /* * 優先度変更タスクが実行可能状態(レディーに存在する)の場合,実行状態タスクはレディーから抜き取られてくるので, * 実行状態タスクをレディーへ戻してから(get_tsk_readyque()実行後,抜き取りタスクはg_currentに設定される), * 実行可能状態タスクをレディーから抜き取り,優先度を変更して,レディーへ戻す */ else if (tcb->state & TASK_READY) { putcurrent(); /* システムコール発行タスクをレディーへ */ get_tsk_readyque(tcb); /* レディーキューから抜き取る関数(scheduler.cにある) */ g_current->priority = tskpri; /* 実行可能状態タスクの優先度を変更 */ putcurrent(); /* 変更したタスクをレディーへ */ DEBUG_LEVEL1_OUTVLE(g_current->init.tskid, 0); DEBUG_LEVEL1_OUTMSG(" out tskid : chg_pri_syscall_isr().\n"); DEBUG_LEVEL1_OUTVLE(g_current->priority, 0); DEBUG_LEVEL1_OUTMSG(" change priority ready : chg_pri_syscall_isr().\n"); } /* * 優先度変更タスクが待ち状態(レディーに存在しない)の場合,実行状態タスクはレディーから抜き取られてくるので, * 待ち状態タスクの優先度を変更して,実行状態タスクをレディーへ戻す */ else { putcurrent(); /* システムコール発行タスクをレディーへ */ tcb->priority = tskpri; /* 待ち状態タスクの優先度変更 */ DEBUG_LEVEL1_OUTVLE(tcb->init.tskid, 0); DEBUG_LEVEL1_OUTMSG(" out tskid : chg_pri_syscall_isr().\n"); DEBUG_LEVEL1_OUTVLE(tcb->priority, 0); DEBUG_LEVEL1_OUTMSG(" change priority sleep : chg_pri_syscall_isr().\n"); } }
/*! * tslp_tsk()のコールバックルーチン * *argv : 引数を格納したポインタ(ここではタスクコントロールブロックへの汎用ポインタ) */ void tslp_callrte(void *argv) { ER *er; current = (TCB *)argv; current->state &= ~TASK_WAIT_TIME_SLEEP; /*タイムアウトしたので,フラグを落としておく*/ current->wait_info.tobjp = 0; /*タスクとタイマコントロールブロックを未接続にする*/ /*待ちに入ったシステムコールの返却値をポインタを経由して書き換える*/ er = (ER *)current->syscall_info.ret; *er = E_TMOUT; putcurrent(); /*レディーへ戻す*/ }
/*! * schedule_fr()のコールバックルーチン * *argv : つねにNULL(タイマ割込みが発生したならば,現在実行中のタスクがcurrentに設定してあるため) */ void schedule_fr_callrte(void *argv) { getcurrent(); /* 実行中タスクをレディーから抜く */ /* 実行時間の加算(CPUバウンドかI/Oバウンドの公平性実現) */ current->schdul_info->un.fr_schdul.rel_exetim += mg_schdul_info.entry->un.fr_schdul.tmout; putcurrent(); /* 再度レディーへ */ mg_schdul_info.entry->un.fr_schdul.tobjp = 0; /* タイマブロックとの接続をクリアにしておく */ }
/*! * システムコール処理(unl_mtx():mutexアンロック処理(プロトコルなし)) * *mcb : 対象mutexコントロールブロック * (返却値)E_OK : mutexセマフォ待ちタスクへ割り当て,mutexセマフォの解放, * 再帰ロック解除(not_lock_first_mtx()の返却値) * (返却値)E_ILUSE : オーナータスクでない場合,mutexセマフォ解放エラー * (すでに解放済み,not_lock_first_mtx()の返却値) */ ER unl_voidmtx_isr(MTXCB *mcb) { int tskid; tskid = current->init.tskid; /* ロックしてきたタスクのIDを取得 */ /* スリープTCBは一度にすべて戻してはいけない */ /* ここからアンロック操作 */ if (mcb->ownerid == tskid) { /* オーナータスクか */ /* 再帰ロック解除状態の場合 */ if (mcb->locks == 1) { /* 待ちタスクが存在する場合 */ if (mcb->waithead != NULL) { /* オーナータスクをレディーへ */ current = mg_tsk_info.id_table[tskid]; /* 取得情報クリア */ current->get_info.flags &= ~TASK_GET_MUTEX; current->get_info.gobjp = 0; putcurrent(); put_mtx_waittsk(mcb); /* 待ちタスクをレディーへ戻す */ return E_OK; } /* 待ちタスクが存在しなければ,オーナーシップのクリア */ else { current = mg_tsk_info.id_table[tskid]; putcurrent(); /* システムコール発行スレッドをレディーへ */ clear_mtx_ownership(mcb); /* オーナーシップのクリアをする関数 */ return E_OK; } } return not_lock_first_mtx(mcb); /* 初期ロック状態(mtxvalueが1)以外の場合の場合の処理 */ } /* オーナータスクでない場合 */ else { putcurrent(); /* システムコール発行スレッドをレディーへ */ DEBUG_OUTMSG("not release mutexID for interrput handler\n"); return E_ILUSE; } }
/*! * mutex再帰ロックをする関数 * *sb : 再帰ロックをするMTXCB * (返却値)E_ILUSE : 多重にロックされた * (返却値)E_OK : 正常終了 */ ER loc_multipl_mtx(MTXCB *mcb) { putcurrent(); /* オーナータスクをレディーへ */ /* 再帰ロック上限をオーバーした場合 */ if (mcb->maxlocks <= mcb->locks) { DEBUG_OUTMSG("not get multipl mutex semaphoreID for interrput handler\n"); return E_ILUSE; /* 上限値オーバーエラー終了 */ } mcb->locks += 1; DEBUG_OUTMSG("get multipl mutex semaphoreID for interrput handler\n"); return E_OK; }
/*! * schedule_mfq()のコールバックルーチン * *argv : つねにNULL(タイマ割込みが発生したならば,現在実行中のタスクがcurrentに設定してあるため) */ void schedule_mfq_callrte(void *argv) { getcurrent(); /* 実行中タスクをレディーから抜く */ /* 最低優先度になるまで優先度を下げる */ if (current->priority != PRIORITY_NUM - 1) { current->priority++; /* タイムアウトしたので優先度を一つ下げる */ } putcurrent(); /* レディーへ戻す */ mg_schdul_info.entry->un.mfq_schdul.tobjp = 0; /* タイマブロックとの接続をクリアにしておく */ }
/* システム・コールの処理(kz_setintr():割込みハンドラ登録) */ static int thread_setintr(softvec_type_t type, kz_handler_t handler) { static void thread_intr(softvec_type_t type, unsigned long sp); /* * 割込みを受け付けるために,ソフトウエア・割込みベクタに * OSの割込み処理の入口となる関数を登録する. */ softvec_setintr(type, thread_intr); handlers[type] = handler; /* OS側から呼び出す割込みハンドラを登録 */ putcurrent(); return 0; }
/*! * twai_sem()のコールバックルーチン * *argv : 引数を格納したポインタ(ここではタスクIDの汎用ポインタ) */ void twai_sem_callrte(void *argv) { SEMCB *scb; ER *er; current = (TCB *)argv; scb = (SEMCB *)current->wait_info.wobjp; get_tsk_sem_waitque(scb, current); /* 動的セマフォ待ちタスクキューからTCBを抜き取る(関数はsemaphore.cにある) */ current->state &= ~TASK_WAIT_SEMAPHORE; /* 待ち要因分だけリバースマスク */ current->wait_info.wobjp = current->wait_info.tobjp = 0; /* 待ちブロックとタイマブロックを未接続にする */ /* 待ちに入ったシステムコールの返却値をポインタを経由して書き換える */ er = (ER *)current->syscall_info.ret; *er = E_TMOUT; putcurrent(); /* タイムアウトしたタスクをレディーへ */ }
/*! * trcv_mbx()のコールバックルーチン * *argv : 引数を格納したポインタ(ここではタスクIDの汎用ポインタ) */ void twai_mbx_callrte(void *argv) { MBXCB *mbcb; ER *er; current = (TCB *)argv; mbcb = (MBXCB *)current->wait_info.wobjp; get_tsk_mbx_waitque(mbcb, current); /* mutex待ちタスクキューからTCBを抜き取る(関数はmutex.cにある) */ current->state &= ~TASK_WAIT_MAILBOX; /* 待ち要因分だけリバースマスク */ current->wait_info.wobjp = current->wait_info.tobjp = 0; /* 待ちブロックとタイマブロックを未接続にする */ /* 待ちに入ったシステムコールの返却値をポインタを経由して書き換える */ er = (ER *)current->syscall_info.ret; *er = E_TMOUT; putcurrent(); /*レディーへ戻す*/ }
/*! * システムコール処理(sta_tsk():タスクの起動) * タスクの状態としては休止状態から実行可能状態へ移行 * *tcb : 起動するtcb * (返却値)E_OK : 正常終了 * (返却値)E_OBJ : エラー終了(タスクが休止状態ではない) */ ER sta_tsk_isr(TCB *tcb) { g_current = tcb; g_current->syscall_info.flag = MZ_VOID; /* sta_tsk()のシステムコールは休止状態の時の使用可能 */ if (g_current->state == TASK_DORMANT) { g_current->state &= ~TASK_DORMANT; /* 休止状態解除 */ putcurrent(); /* 起動要求タスクをレディーへ */ return E_OK; } /* 休止状態ではない場合 */ else { return E_OBJ; } }
/*! * mutex初期ロック状態(mxvalueが1)以外の場合の場合の処理 * mcb->locksは1以外となっている * *mcb : 初期ロック状態(mxvalueが1)以外の操作をするMTXCB * (返却値) E_OK : 再帰ロック解除 * (返却値) E_ILUSE : すでに解放されている */ ER not_lock_first_mtx(MTXCB *mcb) { putcurrent(); /* システムコール発行スレッドをレディーへ戻す */ /* 再帰ロック解除処理 */ if (mcb->locks > 1) { mcb->locks -= 1; DEBUG_OUTMSG("release multipl mutex semaphoreID for interrput handler\n"); return E_OK; } /* すでにアンロック状態 */ else { DEBUG_OUTMSG("semaphoreID release yet.\n"); return E_ILUSE; /* すでに解放されてる.エラー終了 */ } }
/* システムコールの処理(kz_setintr(): 割り込みハンドラ登録) */ static int thread_setintr(softvec_type_t type, kz_handler_t handler) { static void thread_intr(softvec_type_t type, unsigned long sp); /* * 割り込みを受け付けるために、ソフトウェア割り込みベクタに * OSの割り込み処理の入口となる関数を登録する。 */ softvec_setintr(type, thread_intr); handlers[type] = handler; /* 処理後にレディキューに接続し直す */ putcurrent(); return 0; }
static kz_thread_id_t thread_recv(kz_msgbox_id_t id, int *sizep, char **pp) { kz_msgbox *mboxp = &msgboxes[id]; if (mboxp->receiver) kz_sysdown(); mboxp->receiver = current; if (mboxp->head == NULL) { return -1; } recvmsg(mboxp); putcurrent(); return current->syscall.param->un.recv.ret; }