/* * Refer mutex wait queue */ SYSCALL INT _td_mtx_que( ID mtxid, ID list[], INT nent ) { MTXCB *mtxcb; QUEUE *q; ER ercd = E_OK; CHECK_MTXID(mtxid); mtxcb = get_mtxcb(mtxid); BEGIN_DISABLE_INTERRUPT; if ( mtxcb->mtxid == 0 ) { ercd = E_NOEXS; } else { INT n = 0; for ( q = mtxcb->wait_queue.next; q != &mtxcb->wait_queue; q = q->next ) { if ( n++ < nent ) { *list++ = ((TCB*)q)->tskid; } } ercd = n; } END_DISABLE_INTERRUPT; return ercd; }
/* * Delete mutex */ SYSCALL ER _tk_del_mtx( ID mtxid ) { MTXCB *mtxcb; ER ercd = E_OK; CHECK_MTXID(mtxid); mtxcb = get_mtxcb(mtxid); BEGIN_CRITICAL_SECTION; if ( mtxcb->mtxid == 0 ) { ercd = E_NOEXS; } else { /* If there is a task that holds mutex to delete, * delete the mutex from the list * and adjust the task priority if necessary. */ if ( mtxcb->mtxtsk != NULL ) { release_mutex(mtxcb->mtxtsk, mtxcb); } /* Free wait state of task (E_DLT) */ wait_delete(&mtxcb->wait_queue); /* Return to FreeQue */ QueInsert(&mtxcb->wait_queue, &free_mtxcb); mtxcb->mtxid = 0; } END_CRITICAL_SECTION; return ercd; }
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); }
ER sac_mtx(ID mtxid, const ACVCT *p_acvct) { MTXCB *p_mtxcb; MTXINIB *p_mtxinib; ER ercd; LOG_SAC_MTX_ENTER(mtxid, p_acvct); CHECK_TSKCTX_UNL(); CHECK_ID(VALID_MTXID(mtxid)); CHECK_MACV_READ(p_acvct, ACVCT); 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.acptn3)) { ercd = E_OACV; } else if (MTXID(p_mtxcb) <= tmax_smtxid) { ercd = E_OBJ; } else { p_mtxinib = (MTXINIB *)(p_mtxcb->p_mtxinib); p_mtxinib->acvct = *p_acvct; ercd = E_OK; } unlock_cpu(); error_exit: LOG_SAC_MTX_LEAVE(ercd); return(ercd); }
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 ref_mtx(ID mtxid, T_RMTX *pk_rmtx) { MTXCB *p_mtxcb; ER ercd; LOG_REF_MTX_ENTER(mtxid, pk_rmtx); CHECK_TSKCTX_UNL(); CHECK_ID(VALID_MTXID(mtxid)); CHECK_MACV_WRITE(pk_rmtx, T_RMTX); 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.acptn4)) { ercd = E_OACV; } else { pk_rmtx->htskid = (p_mtxcb->p_loctsk != NULL) ? TSKID(p_mtxcb->p_loctsk) : TSK_NONE; pk_rmtx->wtskid = wait_tskid(&(p_mtxcb->wait_queue)); ercd = E_OK; } unlock_cpu(); error_exit: LOG_REF_MTX_LEAVE(ercd, pk_rmtx); return(ercd); }
/* * Unlock mutex */ SYSCALL ER _tk_unl_mtx( ID mtxid ) { MTXCB *mtxcb; TCB *tcb; ER ercd = E_OK; CHECK_MTXID(mtxid); CHECK_INTSK(); mtxcb = get_mtxcb(mtxid); BEGIN_CRITICAL_SECTION; if ( mtxcb->mtxid == 0 ) { ercd = E_NOEXS; goto error_exit; } if ( mtxcb->mtxtsk != ctxtsk ) { ercd = E_ILUSE; /* This is not locked by its own task */ goto error_exit; } /* Delete the mutex from the list, and adjust its own task priority if necessary. */ release_mutex(ctxtsk, mtxcb); if ( mtx_waited(mtxcb) ) { tcb = (TCB*)mtxcb->wait_queue.next; /* Release wait */ wait_release_ok(tcb); /* Change mutex get task */ mtxcb->mtxtsk = tcb; mtxcb->mtxlist = tcb->mtxlist; tcb->mtxlist = mtxcb; if ( (mtxcb->mtxatr & TA_CEILING) == TA_CEILING ) { if ( tcb->priority > mtxcb->ceilpri ) { /* Raise the priority of the task that got lock to the highest priority limit */ change_task_priority(tcb, mtxcb->ceilpri); } } } else { /* No wait task */ mtxcb->mtxtsk = NULL; } error_exit: END_CRITICAL_SECTION; return ercd; }
/* * Processing if the wait task is released (For TA_INHERIT only) */ LOCAL void mtx_rel_wai( TCB *tcb ) { MTXCB *mtxcb; TCB *mtxtsk; mtxcb = get_mtxcb(tcb->wid); mtxtsk = mtxcb->mtxtsk; if ( mtxtsk->priority == tcb->priority ) { /* Since the highest priority of the lock wait task might become lower, adjust this priority */ reset_priority(mtxtsk); } }
/* * Limit the priority change by mutex at task priority change * 1.If the 'tcb' task locks mutex, cannot set lower priority than the * highest priority in all mutexes which hold lock. In such case, * return the highest priority of locked mutex. * 2.If mutex with TA_CEILING attribute is locked or waiting to be locked, * cannot set higher priority than the lowest within the highest * priority limit of mutex with TA_CEILING attribute. * In this case, return E_ILUSE. * 3.Other than above, return the 'priority'. */ EXPORT INT chg_pri_mutex( TCB *tcb, INT priority ) { MTXCB *mtxcb; INT hi_pri, low_pri, pri; hi_pri = priority; low_pri = int_priority(MIN_PRI); /* Mutex lock wait */ if ( (tcb->state & TS_WAIT) != 0 && (tcb->wspec->tskwait & TTW_MTX) != 0 ) { mtxcb = get_mtxcb(tcb->wid); if ( (mtxcb->mtxatr & TA_CEILING) == TA_CEILING ) { pri = mtxcb->ceilpri; if ( pri > low_pri ) { low_pri = pri; } } } /* Locked Mutex */ pri = hi_pri; for ( mtxcb = tcb->mtxlist; mtxcb != NULL; mtxcb = mtxcb->mtxlist ) { switch ( mtxcb->mtxatr & TA_CEILING ) { case TA_CEILING: pri = mtxcb->ceilpri; if ( pri > low_pri ) { low_pri = pri; } break; case TA_INHERIT: if ( mtx_waited(mtxcb) ) { pri = mtx_head_pri(mtxcb); } break; default: /* TA_TFIFO, TA_TPRI */ /* nothing to do */ break; } if ( pri < hi_pri ) { hi_pri = pri; } } if ( priority < low_pri ) { return E_ILUSE; } return hi_pri; }
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); }
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); }
ER ini_mtx(ID mtxid) { MTXCB *p_mtxcb, **pp_prevmtx; TCB *p_loctsk; ER ercd; LOG_INI_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.acptn3)) { ercd = E_OACV; } else { init_wait_queue(&(p_mtxcb->wait_queue)); p_loctsk = p_mtxcb->p_loctsk; if (p_loctsk != NULL) { p_mtxcb->p_loctsk = NULL; pp_prevmtx = &(p_loctsk->p_lastmtx); while (*pp_prevmtx != NULL) { if (*pp_prevmtx == p_mtxcb) { *pp_prevmtx = p_mtxcb->p_prevmtx; break; } pp_prevmtx = &((*pp_prevmtx)->p_prevmtx); } mutex_drop_priority(p_loctsk, p_mtxcb); } if (p_runtsk != p_schedtsk) { dispatch(); } ercd = E_OK; } unlock_cpu(); error_exit: LOG_INI_MTX_LEAVE(ercd); return(ercd); }
ER del_mtx(ID mtxid) { MTXCB *p_mtxcb; MTXINIB *p_mtxinib; const DOMINIB *p_dominib; ER ercd; LOG_DEL_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.acptn3)) { ercd = E_OACV; } else if (MTXID(p_mtxcb) <= tmax_smtxid) { ercd = E_OBJ; } else { init_wait_queue(&(p_mtxcb->wait_queue)); p_mtxinib = (MTXINIB *)(p_mtxcb->p_mtxinib); p_dominib = get_atrdominib(p_mtxinib->mtxatr); p_mtxinib->mtxatr = TA_NOEXS; queue_insert_prev(&(p_dominib->p_domcb->free_mtxcb), &(p_mtxcb->wait_queue)); if (p_runtsk != p_schedtsk) { dispatch(); } ercd = E_OK; } unlock_cpu(); error_exit: LOG_DEL_MTX_LEAVE(ercd); return(ercd); }
/* * Refer mutex state */ SYSCALL ER _tk_ref_mtx( ID mtxid, T_RMTX *pk_rmtx ) { MTXCB *mtxcb; ER ercd = E_OK; CHECK_MTXID(mtxid); mtxcb = get_mtxcb(mtxid); BEGIN_CRITICAL_SECTION; if ( mtxcb->mtxid == 0 ) { ercd = E_NOEXS; } else { pk_rmtx->exinf = mtxcb->exinf; pk_rmtx->htsk = ( mtxcb->mtxtsk != NULL )? mtxcb->mtxtsk->tskid: 0; pk_rmtx->wtsk = wait_tskid(&mtxcb->wait_queue); } END_CRITICAL_SECTION; return ercd; }
ER ref_mtx(ID mtxid, T_RMTX *pk_rmtx) { MTXCB *p_mtxcb; ER ercd; LOG_REF_MTX_ENTER(mtxid, pk_rmtx); CHECK_TSKCTX_UNL(); CHECK_MTXID(mtxid); p_mtxcb = get_mtxcb(mtxid); t_lock_cpu(); pk_rmtx->htskid = (p_mtxcb->p_loctsk != NULL) ? TSKID(p_mtxcb->p_loctsk) : TSK_NONE; pk_rmtx->wtskid = wait_tskid(&(p_mtxcb->wait_queue)); ercd = E_OK; t_unlock_cpu(); error_exit: LOG_REF_MTX_LEAVE(ercd, pk_rmtx); return(ercd); }
/* * Refer mutex state */ SYSCALL ER _td_ref_mtx( ID mtxid, TD_RMTX *pk_rmtx ) { MTXCB *mtxcb; ER ercd = E_OK; CHECK_MTXID(mtxid); mtxcb = get_mtxcb(mtxid); BEGIN_DISABLE_INTERRUPT; if ( mtxcb->mtxid == 0 ) { ercd = E_NOEXS; } else { pk_rmtx->exinf = mtxcb->exinf; pk_rmtx->htsk = ( mtxcb->mtxtsk != NULL )? mtxcb->mtxtsk->tskid: 0; pk_rmtx->wtsk = wait_tskid(&mtxcb->wait_queue); } END_DISABLE_INTERRUPT; return ercd; }
/* * Processing if the priority of wait task changes */ LOCAL void mtx_chg_pri( TCB *tcb, INT oldpri ) { MTXCB *mtxcb; TCB *mtxtsk; mtxcb = get_mtxcb(tcb->wid); gcb_change_priority((GCB*)mtxcb, tcb); if ( (mtxcb->mtxatr & TA_CEILING) == TA_INHERIT ) { mtxtsk = mtxcb->mtxtsk; if ( mtxtsk->priority > tcb->priority ) { /* Since the highest priority of the lock wait task became higher, raise the lock get task priority higher */ change_task_priority(mtxtsk, tcb->priority); } else if ( mtxtsk->priority == oldpri ) { /* Since the highest priority of the lock wait task might become lower, adjust this priority */ reset_priority(mtxtsk); } } }
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); }
EXPORT ER mutex_getname(ID id, UB **name) { MTXCB *mtxcb; ER ercd = E_OK; CHECK_MTXID(id); BEGIN_DISABLE_INTERRUPT; mtxcb = get_mtxcb(id); if ( mtxcb->mtxid == 0 ) { ercd = E_NOEXS; goto error_exit; } if ( (mtxcb->mtxatr & TA_DSNAME) == 0 ) { ercd = E_OBJ; goto error_exit; } *name = mtxcb->name; error_exit: END_DISABLE_INTERRUPT; return ercd; }
ER unl_mtx(ID mtxid) { MTXCB *p_mtxcb; ER ercd; LOG_UNL_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 (p_mtxcb != p_runtsk->p_lastmtx) { ercd = E_OBJ; } else { p_runtsk->p_lastmtx = p_mtxcb->p_prevmtx; mutex_drop_priority(p_runtsk, p_mtxcb); mutex_release(p_mtxcb); if (p_runtsk != p_schedtsk) { dispatch(); } ercd = E_OK; } unlock_cpu(); error_exit: LOG_UNL_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); }
SYSCALL ER _tk_loc_mtx_u( ID mtxid, TMO_U tmout ) { MTXCB *mtxcb; TCB *mtxtsk; ATR mtxatr; ER ercd = E_OK; CHECK_MTXID(mtxid); CHECK_TMOUT(tmout); CHECK_DISPATCH(); mtxcb = get_mtxcb(mtxid); BEGIN_CRITICAL_SECTION; if ( mtxcb->mtxid == 0 ) { ercd = E_NOEXS; goto error_exit; } if ( mtxcb->mtxtsk == ctxtsk ) { ercd = E_ILUSE; /* Multiplexed lock */ goto error_exit; } mtxatr = mtxcb->mtxatr & TA_CEILING; if ( mtxatr == TA_CEILING ) { if ( ctxtsk->bpriority < mtxcb->ceilpri ) { /* Violation of highest priority limit */ ercd = E_ILUSE; goto error_exit; } } /* Check wait disable */ if ( is_diswai((GCB*)mtxcb, ctxtsk, TTW_MTX) ) { ercd = E_DISWAI; goto error_exit; } mtxtsk = mtxcb->mtxtsk; if ( mtxtsk == NULL ) { /* Get lock */ mtxcb->mtxtsk = ctxtsk; mtxcb->mtxlist = ctxtsk->mtxlist; ctxtsk->mtxlist = mtxcb; if ( mtxatr == TA_CEILING ) { if ( ctxtsk->priority > mtxcb->ceilpri ) { /* Raise its own task to the highest priority limit */ change_task_priority(ctxtsk, mtxcb->ceilpri); } } } else { ercd = E_TMOUT; if ( tmout == TMO_POL ) { goto error_exit; } if ( mtxatr == TA_INHERIT ) { if ( mtxtsk->priority > ctxtsk->priority ) { /* Raise the priority of task during locking to the same priority as its own task */ change_task_priority(mtxtsk, ctxtsk->priority); } } /* Ready for wait */ ctxtsk->wspec = ( mtxatr == TA_TFIFO )? &wspec_mtx_tfifo: ( mtxatr == TA_INHERIT )? &wspec_mtx_inherit: &wspec_mtx_tpri; ctxtsk->wercd = &ercd; ctxtsk->wid = mtxcb->mtxid; make_wait(tmout, mtxcb->mtxatr); if ( mtxatr == TA_TFIFO ) { QueInsert(&ctxtsk->tskque, &mtxcb->wait_queue); } else { queue_insert_tpri(ctxtsk, &mtxcb->wait_queue); } } error_exit: END_CRITICAL_SECTION; return ercd; }