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 tloc_mtx(ID mtxid, TMO tmout) { MTXCB *p_mtxcb; WINFO_MTX winfo_mtx; TMEVTB tmevtb; ER ercd; LOG_TLOC_MTX_ENTER(mtxid, tmout); CHECK_DISPATCH(); CHECK_ID(VALID_MTXID(mtxid)); CHECK_PAR(VALID_TMOUT(tmout)); p_mtxcb = get_mtxcb(mtxid); lock_cpu_dsp(); if (p_mtxcb->p_mtxinib->mtxatr == TA_NOEXS) { ercd = E_NOEXS; } else if (VIOLATE_ACPTN(p_mtxcb->p_mtxinib->acvct.acptn1)) { ercd = E_OACV; } else if (MTX_CEILING(p_mtxcb) && p_mtxcb->p_mtxinib->ceilpri < p_runtsk->p_dominib->minpriority && VIOLATE_ACPTN(p_runtsk->p_dominib->acvct.acptn2)) { ercd = E_OACV; /*[NGKI5124]*/ } else if (p_runtsk->raster) { ercd = E_RASTER; } else if (MTX_CEILING(p_mtxcb) && p_runtsk->bpriority < p_mtxcb->p_mtxinib->ceilpri) { ercd = E_ILUSE; } else if (p_mtxcb->p_loctsk == NULL) { mutex_acquire(p_runtsk, p_mtxcb); /* * 優先度上限ミューテックスをロックした場合,p_runtskの優先度 * が上がる可能性があるが,ディスパッチが必要になることはない. */ assert(p_runtsk == p_schedtsk); ercd = E_OK; } else if (p_mtxcb->p_loctsk == p_runtsk) { ercd = E_OBJ; } else if (tmout == TMO_POL) { ercd = E_TMOUT; } else { wobj_make_wait_tmout((WOBJCB *) p_mtxcb, TS_WAITING_MTX, (WINFO_WOBJ *) &winfo_mtx, &tmevtb, tmout); dispatch(); ercd = winfo_mtx.winfo.wercd; } unlock_cpu_dsp(); error_exit: LOG_TLOC_MTX_LEAVE(ercd); return(ercd); }
ER ploc_mtx(ID mtxid) { MTXCB *p_mtxcb; ER ercd; LOG_PLOC_MTX_ENTER(mtxid); CHECK_TSKCTX_UNL(); CHECK_ID(VALID_MTXID(mtxid)); p_mtxcb = get_mtxcb(mtxid); lock_cpu(); if (p_mtxcb->p_mtxinib->mtxatr == TA_NOEXS) { ercd = E_NOEXS; } else if (VIOLATE_ACPTN(p_mtxcb->p_mtxinib->acvct.acptn1)) { ercd = E_OACV; } else if (MTX_CEILING(p_mtxcb) && p_mtxcb->p_mtxinib->ceilpri < p_runtsk->p_dominib->minpriority && VIOLATE_ACPTN(p_runtsk->p_dominib->acvct.acptn2)) { ercd = E_OACV; /*[NGKI5124]*/ } else if (MTX_CEILING(p_mtxcb) && p_runtsk->bpriority < p_mtxcb->p_mtxinib->ceilpri) { ercd = E_ILUSE; } else if (p_mtxcb->p_loctsk == NULL) { mutex_acquire(p_runtsk, p_mtxcb); /* * 優先度上限ミューテックスをロックした場合,p_runtskの優先度 * が上がる可能性があるが,ディスパッチが必要になることはない. */ assert(p_runtsk == p_schedtsk); ercd = E_OK; } else if (p_mtxcb->p_loctsk == p_runtsk) { ercd = E_OBJ; } else { ercd = E_TMOUT; } unlock_cpu(); error_exit: LOG_PLOC_MTX_LEAVE(ercd); return(ercd); }
void mutex_release(MTXCB *p_mtxcb) { TCB *p_tcb; if (queue_empty(&(p_mtxcb->wait_queue))) { p_mtxcb->p_loctsk = NULL; } else { /* * ミューテックス待ちキューの先頭タスク(p_tcb)に,ミューテッ * クスをロックさせる. */ p_tcb = (TCB *) queue_delete_next(&(p_mtxcb->wait_queue)); wait_dequeue_tmevtb(p_tcb); p_tcb->p_winfo->wercd = E_OK; p_mtxcb->p_loctsk = p_tcb; p_mtxcb->p_prevmtx = p_tcb->p_lastmtx; p_tcb->p_lastmtx = p_mtxcb; if (MTX_CEILING(p_mtxcb)) { if (p_mtxcb->p_mtxinib->ceilpri < p_tcb->priority) { p_tcb->priority = p_mtxcb->p_mtxinib->ceilpri; } } make_non_wait(p_tcb); } }
ER ini_mtx(ID mtxid) { MTXCB *p_mtxcb; TCB *p_loctsk; bool_t dspreq; ER ercd; LOG_INI_MTX_ENTER(mtxid); CHECK_TSKCTX_UNL(); CHECK_MTXID(mtxid); p_mtxcb = get_mtxcb(mtxid); t_lock_cpu(); dspreq = init_wait_queue(&(p_mtxcb->wait_queue)); p_loctsk = p_mtxcb->p_loctsk; if (p_loctsk != NULL) { queue_delete(&(p_mtxcb->mutex_queue)); p_mtxcb->p_loctsk = NULL; if (MTX_CEILING(p_mtxcb)) { if (mutex_drop_priority(p_loctsk, p_mtxcb->p_mtxinib->ceilpri)) { dspreq = true; } } } if (dspreq) { dispatch(); } ercd = E_OK; t_unlock_cpu(); error_exit: LOG_INI_MTX_LEAVE(ercd); return(ercd); }
/* * ミューテックスをロックした場合の処理 */ Inline bool_t mutex_acquire(TCB *p_loctsk, MTXCB *p_mtxcb) { p_mtxcb->p_loctsk = p_loctsk; queue_insert_next(&(p_loctsk->mutex_queue), &(p_mtxcb->mutex_queue)); if (MTX_CEILING(p_mtxcb)) { return(mutex_raise_priority(p_loctsk, p_mtxcb->p_mtxinib->ceilpri)); } return(false); }
void mutex_acquire(TCB *p_tcb, MTXCB *p_mtxcb) { p_mtxcb->p_loctsk = p_tcb; p_mtxcb->p_prevmtx = p_tcb->p_lastmtx; p_tcb->p_lastmtx = p_mtxcb; if (MTX_CEILING(p_mtxcb) && p_mtxcb->p_mtxinib->ceilpri < p_tcb->priority) { change_priority(p_tcb, p_mtxcb->p_mtxinib->ceilpri, true); } }
void mutex_drop_priority(TCB *p_tcb, MTXCB *p_mtxcb) { uint_t newpri; if (MTX_CEILING(p_mtxcb) && p_mtxcb->p_mtxinib->ceilpri == p_tcb->priority) { newpri = mutex_calc_priority(p_tcb); if (newpri != p_tcb->priority) { change_priority(p_tcb, newpri, true); } } }
bool_t mutex_scan_ceilmtx(TCB *p_tcb) { MTXCB *p_mtxcb; p_mtxcb = p_tcb->p_lastmtx; while (p_mtxcb != NULL) { if (MTX_CEILING(p_mtxcb)) { return(true); } p_mtxcb = p_mtxcb->p_prevmtx; } return(false); }
/* * タスクの現在優先度の計算 * * p_tcbで指定されるタスクの現在優先度(に設定すべき値)を計算する. */ Inline uint_t mutex_calc_priority(TCB *p_tcb) { uint_t priority; MTXCB *p_mtxcb; priority = p_tcb->bpriority; p_mtxcb = p_tcb->p_lastmtx; while (p_mtxcb != NULL) { if (MTX_CEILING(p_mtxcb) && p_mtxcb->p_mtxinib->ceilpri < priority) { priority = p_mtxcb->p_mtxinib->ceilpri; } p_mtxcb = p_mtxcb->p_prevmtx; } return(priority); }
bool_t mutex_scan_ceilmtx(TCB *p_tcb) { QUEUE *p_queue; MTXCB *p_mtxcb; 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)) { return(true); } p_queue = p_queue->p_next; } return(false); }
ER tloc_mtx(ID mtxid, TMO tmout) { MTXCB *p_mtxcb; WINFO_MTX winfo_mtx; TMEVTB tmevtb; ER ercd; LOG_TLOC_MTX_ENTER(mtxid, tmout); CHECK_DISPATCH(); CHECK_MTXID(mtxid); CHECK_TMOUT(tmout); p_mtxcb = get_mtxcb(mtxid); t_lock_cpu(); if (MTX_CEILING(p_mtxcb) && p_runtsk->bpriority < p_mtxcb->p_mtxinib->ceilpri) { ercd = E_ILUSE; } else if (p_mtxcb->p_loctsk == NULL) { (void) mutex_acquire(p_runtsk, p_mtxcb); /* * 優先度上限ミューテックスをロックした場合,p_runtskの優先度 * が上がる可能性があるが,ディスパッチが必要になることはない. */ assert(!(p_runtsk != p_schedtsk && dspflg)); ercd = E_OK; } else if (p_mtxcb->p_loctsk == p_runtsk) { ercd = E_OBJ; } else if (tmout == TMO_POL) { ercd = E_TMOUT; } else { p_runtsk->tstat = (TS_WAITING | TS_WAIT_MTX); wobj_make_wait_tmout((WOBJCB *) p_mtxcb, (WINFO_WOBJ *) &winfo_mtx, &tmevtb, tmout); dispatch(); ercd = winfo_mtx.winfo.wercd; } t_unlock_cpu(); error_exit: LOG_TLOC_MTX_LEAVE(ercd); return(ercd); }
uint_t mutex_calc_priority(TCB *p_tcb) { uint_t priority; QUEUE *p_queue; MTXCB *p_mtxcb; priority = p_tcb->bpriority; 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) && p_mtxcb->p_mtxinib->ceilpri < priority) { priority = p_mtxcb->p_mtxinib->ceilpri; } p_queue = p_queue->p_next; } return(priority); }
ER unl_mtx(ID mtxid) { MTXCB *p_mtxcb; bool_t dspreq = false; ER ercd; LOG_UNL_MTX_ENTER(mtxid); CHECK_TSKCTX_UNL(); CHECK_MTXID(mtxid); p_mtxcb = get_mtxcb(mtxid); t_lock_cpu(); if (p_mtxcb->p_loctsk != p_runtsk) { ercd = E_OBJ; } else { queue_delete(&(p_mtxcb->mutex_queue)); if (MTX_CEILING(p_mtxcb)) { if (mutex_drop_priority(p_runtsk, p_mtxcb->p_mtxinib->ceilpri)) { dspreq = true; } } if (mutex_release(p_mtxcb)) { dspreq = true; } if (dspreq) { dispatch(); } ercd = E_OK; } t_unlock_cpu(); error_exit: LOG_UNL_MTX_LEAVE(ercd); return(ercd); }
ER ploc_mtx(ID mtxid) { MTXCB *p_mtxcb; ER ercd; LOG_PLOC_MTX_ENTER(mtxid); CHECK_TSKCTX_UNL(); CHECK_MTXID(mtxid); p_mtxcb = get_mtxcb(mtxid); t_lock_cpu(); if (MTX_CEILING(p_mtxcb) && p_runtsk->bpriority < p_mtxcb->p_mtxinib->ceilpri) { ercd = E_ILUSE; } else if (p_mtxcb->p_loctsk == NULL) { (void) mutex_acquire(p_runtsk, p_mtxcb); /* * 優先度上限ミューテックスをロックした場合,p_runtskの優先度 * が上がる可能性があるが,ディスパッチが必要になることはない. */ assert(!(p_runtsk != p_schedtsk && dspflg)); ercd = E_OK; } else if (p_mtxcb->p_loctsk == p_runtsk) { ercd = E_OBJ; } else { ercd = E_TMOUT; } t_unlock_cpu(); error_exit: LOG_PLOC_MTX_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); }