bool_t mutex_check_ceilpri(TCB *p_tcb, uint_t bpriority) { MTXCB *p_mtxcb; /* * タスクがロックしている優先度上限ミューテックスの中で,上限優先 * 度がbpriorityよりも低いものがあれば,falseを返す. */ p_mtxcb = p_tcb->p_lastmtx; while (p_mtxcb != NULL) { if (MTX_CEILING(p_mtxcb) && bpriority < p_mtxcb->p_mtxinib->ceilpri) { return(false); } p_mtxcb = p_mtxcb->p_prevmtx; } /* * タスクが優先度上限ミューテックスのロックを待っている場合に,そ * の上限優先度がbpriorityよりも低くければ,falseを返す. */ if (TSTAT_WAIT_MTX(p_tcb->tstat)) { p_mtxcb = ((WINFO_MTX *)(p_tcb->p_winfo))->p_mtxcb; if (MTX_CEILING(p_mtxcb) && bpriority < p_mtxcb->p_mtxinib->ceilpri) { return(false); } } /* * いずれの条件にも当てはまらなければtrueを返す. */ return(true); }
bool_t mutex_check_ceilpri(TCB *p_tcb, uint_t bpriority) { QUEUE *p_queue; MTXCB *p_mtxcb; /* * タスクがロックしている優先度上限ミューテックスの中で,上限優先 * 度がbpriorityよりも低いものがあれば,falseを返す. */ p_queue = p_tcb->mutex_queue.p_next; while (p_queue != &(p_tcb->mutex_queue)) { p_mtxcb = MTXCB_QUEUE(p_queue); if (MTX_CEILING(p_mtxcb) && bpriority < p_mtxcb->p_mtxinib->ceilpri) { return(false); } p_queue = p_queue->p_next; } /* * タスクが優先度上限ミューテックスのロックを待っている場合に,そ * の上限優先度がbpriorityよりも低くければ,falseを返す. */ if (TSTAT_WAIT_MTX(p_tcb->tstat)) { p_mtxcb = ((WINFO_MTX *)(p_tcb->p_winfo))->p_mtxcb; if (MTX_CEILING(p_mtxcb) && bpriority < p_mtxcb->p_mtxinib->ceilpri) { return(false); } } /* * いずれの条件にも当てはまらなければtrueを返す. */ return(true); }
ER chg_pri(ID tskid, PRI tskpri) { TCB *p_tcb; uint_t newbpri; ER ercd; LOG_CHG_PRI_ENTER(tskid, tskpri); CHECK_TSKCTX_UNL(); CHECK_TSKID_SELF(tskid); CHECK_TPRI_INI(tskpri); p_tcb = get_tcb_self(tskid); t_lock_cpu(); if (p_tcb->p_tinib->tskatr == TA_NOEXS) { ercd = E_NOEXS; } else if (VIOLATE_ACPTN(p_tcb->p_tinib->acvct.acptn2)) { ercd = E_OACV; } else if (TSTAT_DORMANT(p_tcb->tstat)) { ercd = E_OBJ; } else { newbpri = (tskpri == TPRI_INI) ? p_tcb->p_tinib->ipriority : INT_PRIORITY(tskpri); if (!(newbpri >= p_runtsk->p_tinib->p_dominib->minpriority)) { ercd = E_ILUSE; } else if ((!queue_empty(&(p_tcb->mutex_queue)) || TSTAT_WAIT_MTX(p_tcb->tstat)) && !((*mtxhook_check_ceilpri)(p_tcb, newbpri))) { ercd = E_ILUSE; } else { p_tcb->bpriority = newbpri; if (queue_empty(&(p_tcb->mutex_queue)) || !((*mtxhook_scan_ceilmtx)(p_tcb))) { if (change_priority(p_tcb, newbpri, false)) { dispatch(); } } ercd = E_OK; } } t_unlock_cpu(); error_exit: LOG_CHG_PRI_LEAVE(ercd); return(ercd); }
ER chg_pri(ID tskid, PRI tskpri) { TCB *p_tcb; uint_t newbpri; ER ercd; LOG_CHG_PRI_ENTER(tskid, tskpri); CHECK_TSKCTX_UNL(); /*[NGKI1184][NGKI1185]*/ if (tskid == TSK_SELF) { p_tcb = p_runtsk; /*[NGKI1198]*/ } else { CHECK_ID(VALID_TSKID(tskid)); /*[NGKI1187]*/ p_tcb = get_tcb(tskid); } if (tskpri == TPRI_INI) { newbpri = p_tcb->p_tinib->ipriority; /*[NGKI1199]*/ } else { CHECK_PAR(VALID_TPRI(tskpri)); /*[NGKI1188]*/ newbpri = INT_PRIORITY(tskpri); } lock_cpu(); if (p_tcb->p_tinib->tskatr == TA_NOEXS) { ercd = E_NOEXS; /*[NGKI1189]*/ } else if (TSTAT_DORMANT(p_tcb->tstat)) { ercd = E_OBJ; /*[NGKI1191]*/ } else if ((p_tcb->p_lastmtx != NULL || TSTAT_WAIT_MTX(p_tcb->tstat)) && !((*mtxhook_check_ceilpri)(p_tcb, newbpri))) { ercd = E_ILUSE; /*[NGKI1201]*/ } else { p_tcb->bpriority = newbpri; /*[NGKI1192]*/ if (p_tcb->p_lastmtx == NULL || !((*mtxhook_scan_ceilmtx)(p_tcb))) { change_priority(p_tcb, newbpri, false); /*[NGKI1193]*/ if (p_runtsk != p_schedtsk) { dispatch(); } /*[NGKI1197]*/ } ercd = E_OK; } unlock_cpu(); error_exit: LOG_CHG_PRI_LEAVE(ercd); return(ercd); }
/* * ミューテックス毎の検査 */ static ER bit_mutex_mutex(ID mtxid) { MTXCB *p_mtxcb, *p_acquired_mtx; const MTXINIB *p_mtxinib; TCB *p_tcb; QUEUE *p_queue, *p_next; uint_t pri; if (!VALID_MTXID(mtxid)) { return(E_ID); } p_mtxcb = get_mtxcb(mtxid); p_mtxinib = p_mtxcb->p_mtxinib; /* * 初期化ブロックへのポインタの検査 */ if (p_mtxinib != &(mtxinib_table[INDEX_MTX(mtxid)])) { return(E_SYS_LINENO); } /* * ミューテックス待ちキューの検査 */ p_queue = p_mtxcb->wait_queue.p_next; if (p_queue->p_prev != &(p_mtxcb->wait_queue)) { return(E_SYS_LINENO); } pri = TMIN_TPRI; while (p_queue != &(p_mtxcb->wait_queue)) { p_tcb = (TCB *) p_queue; if (!VALID_TCB(p_tcb)) { return(E_SYS_LINENO); } /* * キューがタスク優先度順になっているかの検査 */ if (MTXPROTO(p_mtxinib) != TA_NULL) { if (p_tcb->priority < pri) { return(E_SYS_LINENO); } } pri = p_tcb->priority; /* * タスク状態の検査 * * ミューテックス待ち状態のタスクの検査は,タスク毎の検査で行っ * ているため,ここでは行わない. */ if (!TSTAT_WAIT_MTX(p_tcb->tstat)) { return(E_SYS_LINENO); } /* * 優先度上限の検査 */ if (MTX_CEILING(p_mtxinib)) { if (p_tcb->bpriority < p_mtxinib->ceilpri) { return(E_SYS_LINENO); } } /* * キューの次の要素に進む */ p_next = p_queue->p_next; if (p_next->p_prev != p_queue) { return(E_SYS_LINENO); } p_queue = p_next; } /* * ミューテックスをロックしているタスクの検査 */ p_tcb = p_mtxcb->p_loctsk; if (p_tcb == NULL) { /* * ミューテックスがロックされていない時 */ if (!queue_empty(&(p_mtxcb->wait_queue))) { return(E_SYS_LINENO); } } else { /* * ミューテックスがロックされている時 * * ミューテックスをロックしているタスクの検査は,タスク毎の検 * 査で行っているため,ここでは行わない. */ if (!VALID_TCB(p_tcb)) { return(E_SYS_LINENO); } p_acquired_mtx = p_tcb->p_lastmtx; while (p_mtxcb != NULL) { if (p_mtxcb == p_acquired_mtx) { break; } p_acquired_mtx = p_acquired_mtx->p_prevmtx; } if (p_mtxcb == NULL) { return(E_SYS_LINENO); } /* * 優先度上限の検査 */ if (MTX_CEILING(p_mtxinib)) { if (p_tcb->bpriority < p_mtxinib->ceilpri) { return(E_SYS_LINENO); } } } return(E_OK); }
/* * タスク毎の検査 */ static ER bit_mutex_task(ID tskid) { TCB *p_tcb; uint_t pri; MTXCB *p_mtxcb; const MTXINIB *p_mtxinib; if (!VALID_TSKID(tskid)) { return(E_ID); } p_tcb = get_tcb(tskid); pri = p_tcb->bpriority; /* * タスクがロックしているミューテックスのキューの検査 */ p_mtxcb = p_tcb->p_lastmtx; while (p_mtxcb != NULL) { if (!VALID_MTXCB(p_mtxcb)) { return(E_SYS_LINENO); } p_mtxinib = p_mtxcb->p_mtxinib; /* * ミューテックスをロックしているタスクのチェック */ if (p_mtxcb->p_loctsk != p_tcb) { return(E_SYS_LINENO); } /* * 現在優先度の計算 */ if (MTXPROTO(p_mtxinib)) { if (p_mtxinib->ceilpri < pri) { pri = p_mtxinib->ceilpri; } } /* * キューの次の要素に進む */ p_mtxcb = p_mtxcb->p_prevmtx; } /* * 現在優先度の検査 */ if (p_tcb->priority != pri) { return(E_SYS_LINENO); } /* * タスクが待っているミューテックスに関する検査 */ if (TSTAT_WAIT_MTX(p_tcb->tstat)) { p_mtxcb = ((WINFO_MTX *)(p_tcb->p_winfo))->p_mtxcb; if (!VALID_MTXCB(p_mtxcb)) { return(E_SYS_LINENO); } if (!in_queue(&(p_mtxcb->wait_queue), &(p_tcb->task_queue))) { return(E_SYS_LINENO); } } return(E_OK); }
/* * タスク毎の検査 */ static ER bit_mutex_task(ID tskid) { TCB *p_tcb; MTXCB *p_mtxcb; QUEUE *p_queue, *p_next; uint_t pri; if (!(TMIN_TSKID <= (tskid) && (tskid) <= tmax_tskid)) { return(E_ID); } p_tcb = get_tcb(tskid); pri = p_tcb->bpriority; /* * タスクがロックしているミューテックスのキューの検査 */ p_queue = p_tcb->mutex_queue.p_next; if (p_queue->p_prev != &(p_tcb->mutex_queue)) { return(E_SYS_LINENO); } while (p_queue != &(p_tcb->mutex_queue)) { p_mtxcb = MTXCB_QUEUE(p_queue); if (!VALID_MTXCB(p_mtxcb)) { return(E_SYS_LINENO); } /* * ミューテックスをロックしているタスクのチェック */ if (p_mtxcb->p_loctsk != p_tcb) { return(E_SYS_LINENO); } /* * 現在優先度の計算 */ if (MTXPROTO(p_mtxcb)) { if (p_mtxcb->p_mtxinib->ceilpri < pri) { pri = p_mtxcb->p_mtxinib->ceilpri; } } /* * キューの次の要素に進む */ p_next = p_queue->p_next; if (p_next->p_prev != p_queue) { return(E_SYS_LINENO); } p_queue = p_next; } /* * 現在優先度の検査 */ if (p_tcb->priority != pri) { return(E_SYS_LINENO); } /* * タスクが待っているミューテックスに関する検査 */ if (TSTAT_WAIT_MTX(p_tcb->tstat)) { p_mtxcb = ((WINFO_MTX *)(p_tcb->p_winfo))->p_mtxcb; if (!VALID_MTXCB(p_mtxcb)) { return(E_SYS_LINENO); } if (!in_queue(&(p_mtxcb->wait_queue), &(p_tcb->task_queue))) { return(E_SYS_LINENO); } } return(E_OK); }