/* * Create mutex */ SYSCALL ID _tk_cre_mtx( CONST T_CMTX *pk_cmtx ) { #if CHK_RSATR const ATR VALID_MTXATR = { TA_CEILING |TA_NODISWAI #if USE_OBJECT_NAME |TA_DSNAME #endif }; #endif MTXCB *mtxcb; ID mtxid; INT ceilpri; ER ercd; CHECK_RSATR(pk_cmtx->mtxatr, VALID_MTXATR); if ( (pk_cmtx->mtxatr & TA_CEILING) == TA_CEILING ) { CHECK_PRI(pk_cmtx->ceilpri); ceilpri = int_priority(pk_cmtx->ceilpri); } else { ceilpri = 0; } BEGIN_CRITICAL_SECTION; /* Get control block from FreeQue */ mtxcb = (MTXCB*)QueRemoveNext(&free_mtxcb); if ( mtxcb == NULL ) { ercd = E_LIMIT; } else { mtxid = ID_MTX(mtxcb - mtxcb_table); /* Initialize control block */ QueInit(&mtxcb->wait_queue); mtxcb->mtxid = mtxid; mtxcb->exinf = pk_cmtx->exinf; mtxcb->mtxatr = pk_cmtx->mtxatr; mtxcb->ceilpri = ceilpri; mtxcb->mtxtsk = NULL; mtxcb->mtxlist = NULL; #if USE_OBJECT_NAME if ( (pk_cmtx->mtxatr & TA_DSNAME) != 0 ) { strncpy((char*)mtxcb->name, (char*)pk_cmtx->dsname, (UINT)OBJECT_NAME_LENGTH); } #endif ercd = mtxid; } END_CRITICAL_SECTION; return ercd; }
/* * 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; }
/* * Change task priority */ SYSCALL ER _tk_chg_pri( ID tskid, PRI tskpri ) { TCB *tcb; INT priority; ER ercd; CHECK_TSKID_SELF(tskid); CHECK_PRI_INI(tskpri); tcb = get_tcb_self(tskid); BEGIN_CRITICAL_SECTION; if ( tcb->state == TS_NONEXIST ) { ercd = E_NOEXS; goto error_exit; } /* Conversion priority to internal expression */ if ( tskpri == TPRI_INI ) { priority = tcb->ipriority; } else { priority = int_priority(tskpri); } #ifdef NUM_MTXID /* Mutex priority change limit */ ercd = chg_pri_mutex(tcb, priority); if ( ercd < E_OK ) { goto error_exit; } tcb->bpriority = (UB)priority; priority = ercd; #else tcb->bpriority = priority; #endif /* Change priority */ change_task_priority(tcb, priority); ercd = E_OK; error_exit: END_CRITICAL_SECTION; return ercd; }
/* * Rotate ready queue */ SYSCALL ER _tk_rot_rdq( PRI tskpri ) { CHECK_PRI_RUN(tskpri); BEGIN_CRITICAL_SECTION; if ( tskpri == TPRI_RUN ) { if ( in_indp() ) { rotate_ready_queue_run(); } else { rotate_ready_queue(ctxtsk->priority); } } else { rotate_ready_queue(int_priority(tskpri)); } END_CRITICAL_SECTION; return E_OK; }
/* * Refer ready queue */ SYSCALL INT _td_rdy_que( PRI pri, ID list[], INT nent ) { QUEUE *q, *tskque; INT n = 0; CHECK_PRI(pri); BEGIN_DISABLE_INTERRUPT; tskque = &ready_queue.tskque[int_priority(pri)]; for ( q = tskque->next; q != tskque; q = q->next ) { if ( n++ < nent ) { *(list++) = ((TCB*)q)->tskid; } } END_DISABLE_INTERRUPT; return n; }
/* * Create task */ SYSCALL ID _tk_cre_tsk P1( CONST T_CTSK *pk_ctsk ) { #if CHK_RSATR const ATR VALID_TSKATR = { /* Valid value of task attribute */ TA_HLNG |TA_SSTKSZ |TA_USERSTACK |TA_TASKSPACE |TA_RESID |TA_RNG3 |TA_FPU |TA_COP0 |TA_COP1 |TA_COP2 |TA_COP3 |TA_GP #if USE_OBJECT_NAME |TA_DSNAME #endif }; #endif TCB *tcb; INT stksz, sstksz, sysmode, resid; void *stack = NULL, *sstack; ER ercd; CHECK_RSATR(pk_ctsk->tskatr, VALID_TSKATR); CHECK_PRI(pk_ctsk->itskpri); CHECK_NOCOP(pk_ctsk->tskatr); #if USE_SINGLE_STACK CHECK_NOSPT((pk_ctsk->tskatr & TA_USERSTACK) == 0); #endif #if CHK_PAR if ( (pk_ctsk->tskatr & TA_USERSTACK) != 0 ) { CHECK_PAR((pk_ctsk->tskatr & TA_RNG3) != TA_RNG0); CHECK_PAR(pk_ctsk->stksz == 0); } else { CHECK_PAR(pk_ctsk->stksz >= 0); } if ( (pk_ctsk->tskatr & TA_TASKSPACE) != 0 ) { CHECK_PAR(pk_ctsk->lsid >= 0 && pk_ctsk->lsid <= MAX_LSID); } #endif if ( (pk_ctsk->tskatr & TA_RESID) != 0 ) { CHECK_RESID(pk_ctsk->resid); resid = pk_ctsk->resid; } else { resid = SYS_RESID; /* System resource group */ } if ( (pk_ctsk->tskatr & TA_SSTKSZ) != 0 ) { CHECK_PAR(pk_ctsk->sstksz >= MIN_SYS_STACK_SIZE); sstksz = pk_ctsk->sstksz; } else { sstksz = default_sstksz; } if ( (pk_ctsk->tskatr & TA_RNG3) == TA_RNG0 ) { sysmode = 1; sstksz += pk_ctsk->stksz; stksz = 0; } else { sysmode = 0; #if USE_SINGLE_STACK sstksz += pk_ctsk->stksz; stksz = 0; #else stksz = pk_ctsk->stksz; #endif } /* Adjust stack size by 8 bytes */ sstksz = (sstksz + 7) / 8 * 8; stksz = (stksz + 7) / 8 * 8; /* Allocate system stack area */ sstack = IAmalloc((UINT)sstksz, TA_RNG0); if ( sstack == NULL ) { return E_NOMEM; } if ( stksz > 0 ) { /* Allocate user stack area */ stack = IAmalloc((UINT)stksz, pk_ctsk->tskatr); if ( stack == NULL ) { IAfree(sstack, TA_RNG0); return E_NOMEM; } } BEGIN_CRITICAL_SECTION; /* Get control block from FreeQue */ tcb = (TCB*)QueRemoveNext(&free_tcb); if ( tcb == NULL ) { ercd = E_LIMIT; goto error_exit; } /* Initialize control block */ tcb->exinf = pk_ctsk->exinf; tcb->tskatr = pk_ctsk->tskatr; tcb->task = pk_ctsk->task; tcb->ipriority = (UB)int_priority(pk_ctsk->itskpri); tcb->resid = resid; tcb->stksz = stksz; tcb->sstksz = sstksz; #if USE_OBJECT_NAME if ( (pk_ctsk->tskatr & TA_DSNAME) != 0 ) { STRNCPY((char*)tcb->name, (char*)pk_ctsk->dsname, OBJECT_NAME_LENGTH); } #endif #if TA_GP /* Set global pointer */ if ( (pk_ctsk->tskatr & TA_GP) != 0 ) { gp = pk_ctsk->gp; } tcb->gp = gp; #endif /* Set stack pointer */ if ( stksz > 0 ) { tcb->istack = (VB*)stack + stksz; } else { tcb->istack = pk_ctsk->stkptr; } tcb->isstack = (VB*)sstack + sstksz - RESERVE_SSTACK(tcb->tskatr); /* Set initial value of task operation mode */ tcb->isysmode = (B)sysmode; tcb->sysmode = (H)sysmode; /* Set initial value of task space */ if ( (pk_ctsk->tskatr & TA_TASKSPACE) != 0 ) { tcb->tskctxb.uatb = pk_ctsk->uatb; tcb->tskctxb.lsid = pk_ctsk->lsid; } else { tcb->tskctxb.uatb = NULL; tcb->tskctxb.lsid = 0; /* Task Space */ } /* make it to DORMANT state */ make_dormant(tcb); ercd = tcb->tskid; error_exit: END_CRITICAL_SECTION; if ( ercd < E_OK ) { IAfree(sstack, TA_RNG0); if ( stksz > 0 ) { IAfree(stack, pk_ctsk->tskatr); } } return ercd; }
/* * Create task */ SYSCALL ID tk_cre_tsk_impl P1( T_CTSK *pk_ctsk ) { #if CHK_RSATR const ATR VALID_TSKATR = { /* Valid value of task attribute */ TA_HLNG |TA_RNG3 |TA_USERBUF |TA_GP #if USE_OBJECT_NAME |TA_DSNAME #endif }; #endif TCB *tcb; W sstksz; VP stack; ER ercd; CHECK_RSATR(pk_ctsk->tskatr, VALID_TSKATR); #if !USE_IMALLOC /* TA_USERBUF must be specified if configured in no Imalloc */ CHECK_PAR((pk_ctsk->tskatr & TA_USERBUF) != 0); #endif CHECK_PRI(pk_ctsk->itskpri); CHECK_PAR(pk_ctsk->stksz >= MIN_SYS_STACK_SIZE); /* Adjust stack size by 8 bytes */ sstksz = (pk_ctsk->stksz + 7) / 8 * 8; #if USE_IMALLOC if ( (pk_ctsk->tskatr & TA_USERBUF) != 0 ) { /* Size of User buffer must be multiples of 8 */ if ( sstksz != pk_ctsk->stksz ) { return E_PAR; } /* Use user buffer */ stack = pk_ctsk->bufptr; } else { /* Allocate system stack area */ stack = knl_Imalloc((UW)sstksz); if ( stack == NULL ) { return E_NOMEM; } } #else /* Size of User buffer must be multiples of 8 */ if ( sstksz != pk_ctsk->stksz ) { return E_PAR; } /* Use user buffer */ stack = pk_ctsk->bufptr; #endif BEGIN_CRITICAL_SECTION; /* Get control block from FreeQue */ tcb = (TCB*)QueRemoveNext(&knl_free_tcb); if ( tcb == NULL ) { ercd = E_LIMIT; goto error_exit; } /* Initialize control block */ tcb->exinf = pk_ctsk->exinf; tcb->tskatr = pk_ctsk->tskatr & ~TA_RNG3; /* handling as TA_RNG0 */ tcb->task = pk_ctsk->task; tcb->ipriority = (UB)int_priority(pk_ctsk->itskpri); tcb->sstksz = sstksz; #if USE_OBJECT_NAME if ( (pk_ctsk->tskatr & TA_DSNAME) != 0 ) { strncpy((char*)tcb->name, (char*)pk_ctsk->dsname, OBJECT_NAME_LENGTH); } #endif #if TA_GP /* Set global pointer */ if ( (pk_ctsk->tskatr & TA_GP) != 0 ) { gp = pk_ctsk->gp; } tcb->gp = gp; #endif /* Set stack pointer */ tcb->isstack = (VB*)stack + sstksz; /* Set initial value of task operation mode */ tcb->isysmode = 1; tcb->sysmode = 1; /* make it to DORMANT state */ knl_make_dormant(tcb); ercd = tcb->tskid; error_exit: END_CRITICAL_SECTION; #if USE_IMALLOC if ( (ercd < E_OK) && ((pk_ctsk->tskatr & TA_USERBUF) == 0) ) { knl_Ifree(stack); } #endif return ercd; }