/* * Object unlock * It may be called from a critical section. */ EXPORT void knl_UnlockOBJ( OBJLOCK *loc ) { TCB *tcb; BEGIN_CRITICAL_SECTION; knl_ctxtsk->klocked = FALSE; knl_ready_queue.klocktsk = NULL; tcb = (TCB*)QueRemoveNext(&loc->wtskq); if ( tcb == NULL ) { /* Free lock */ loc->wtskq.next = NULL; } else { /* Wake lock wait task */ tcb->klockwait = FALSE; tcb->klocked = TRUE; knl_ready_queue_insert_top(&knl_ready_queue, tcb); } knl_schedtsk = knl_ready_queue_top(&knl_ready_queue); if ( knl_ctxtsk != knl_schedtsk ) { knl_dispatch_request(); } END_CRITICAL_SECTION; }
/* * Get open management block */ LOCAL OpnCB* newOpnCB( DevCB *devcb, INT unitno, UINT omode, ResCB *rescb ) { OpnCB *opncb; /* Get space in open management block */ opncb = (OpnCB*)QueRemoveNext(&knl_FreeOpnCB); if ( opncb == NULL ) { return NULL; /* No space */ } /* Register as open device */ QueInsert(&opncb->q, &devcb->openq); QueInsert(&opncb->resq, &rescb->openq); opncb->devcb = devcb; opncb->unitno = unitno; opncb->omode = omode; QueInit(&opncb->requestq); opncb->waitone = 0; opncb->nwaireq = 0; opncb->abort_tskid = 0; opncb->resid = 0; /* Indicate that open processing is not completed */ return opncb; }
/* * 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; }
/* * Create rendezvous port */ SYSCALL ID _tk_cre_por( CONST T_CPOR *pk_cpor ) { #if CHK_RSATR const ATR VALID_PORATR = { TA_TPRI |TA_NODISWAI #if USE_OBJECT_NAME |TA_DSNAME #endif }; #endif PORCB *porcb; ID porid; ER ercd; CHECK_RSATR(pk_cpor->poratr, VALID_PORATR); CHECK_PAR(pk_cpor->maxcmsz >= 0); CHECK_PAR(pk_cpor->maxrmsz >= 0); CHECK_INTSK(); BEGIN_CRITICAL_SECTION; /* Get control block from FreeQue */ porcb = (PORCB*)QueRemoveNext(&free_porcb); if ( porcb == NULL ) { ercd = E_LIMIT; } else { porid = ID_POR(porcb - porcb_table); /* Initialize control block */ QueInit(&porcb->call_queue); porcb->porid = porid; porcb->exinf = pk_cpor->exinf; porcb->poratr = pk_cpor->poratr; QueInit(&porcb->accept_queue); porcb->maxcmsz = pk_cpor->maxcmsz; porcb->maxrmsz = pk_cpor->maxrmsz; #if USE_OBJECT_NAME if ( (pk_cpor->poratr & TA_DSNAME) != 0 ) { strncpy((char*)porcb->name, (char*)pk_cpor->dsname, OBJECT_NAME_LENGTH); } #endif ercd = porid; } END_CRITICAL_SECTION; return ercd; }
/* * processing of INP_KEY */ LOCAL BOOL execINP_KEY( InnerEvent *evt, ReceiveData *msg ) { KeyTop keytop; UW kbsel; KeyState *ks; if ( msg->head.cmd.err != DEV_OK ) { /* resetting key state due to error */ kpAllResetKeyMap(); if ( isQueEmpty(&StatMach.useq) ) return FALSE; kpExecKeyStateMachine((KeyState*)StatMach.useq.next, evt, msg); return !isQueEmpty(&StatMach.useq); } keytop = toKeyTop(&msg->kb); /* look for KeyState that matches keytop */ ks = (KeyState*)QueSearch(&StatMach.useq, &StatMach.useq, keytop.w, offsetof(KeyState, keytop.w)); kbsel = ( ks == (KeyState*)&StatMach.useq )? kpMgrInfo.kpState.stat.kbsel: ks->kbsel; /* change keymap */ kpSetOrResetKeyMap(keytop, kbsel, msg->kb.stat.press); if ( ks == (KeyState*)&StatMach.useq ) { /* search empty KeyState */ ks = (KeyState*)QueRemoveNext(&StatMach.freq); if ( ks == NULL ) return FALSE; /* initialize KeyState */ ks->keytop = keytop; ks->kbsel = kbsel; ks->state = ( kpGetKeyKind(keytop) <= NormalKey )? KS_RELEASE: SS_RELEASE; memset(&ks->u, 0, sizeof(ks->u)); QueInsert((QUEUE*)ks, &StatMach.useq); } /* execute the state machine */ kpExecKeyStateMachine(ks, evt, msg); return FALSE; }
/* * Create semaphore */ SYSCALL ID tk_cre_sem_impl( T_CSEM *pk_csem ) { #if CHK_RSATR const ATR VALID_SEMATR = { TA_TPRI |TA_CNT #if USE_OBJECT_NAME |TA_DSNAME #endif }; #endif SEMCB *semcb; ID semid; ER ercd; CHECK_RSATR(pk_csem->sematr, VALID_SEMATR); CHECK_PAR(pk_csem->isemcnt >= 0); CHECK_PAR(pk_csem->maxsem > 0); CHECK_PAR(pk_csem->maxsem >= pk_csem->isemcnt); BEGIN_CRITICAL_SECTION; /* Get control block from FreeQue */ semcb = (SEMCB*)QueRemoveNext(&knl_free_semcb); if ( semcb == NULL ) { ercd = E_LIMIT; } else { semid = ID_SEM(semcb - knl_semcb_table); /* Initialize control block */ QueInit(&semcb->wait_queue); semcb->semid = semid; semcb->exinf = pk_csem->exinf; semcb->sematr = pk_csem->sematr; semcb->semcnt = pk_csem->isemcnt; semcb->maxsem = pk_csem->maxsem; #if USE_OBJECT_NAME if ( (pk_csem->sematr & TA_DSNAME) != 0 ) { strncpy((char*)semcb->name, (char*)pk_csem->dsname, OBJECT_NAME_LENGTH); } #endif ercd = semid; } END_CRITICAL_SECTION; return ercd; }
/* * Get request management block */ LOCAL ReqCB* newReqCB( OpnCB *opncb ) { ReqCB *reqcb; /* Get space in request management block */ reqcb = (ReqCB*)QueRemoveNext(&knl_FreeReqCB); if ( reqcb == NULL ) { return NULL; /* No space */ } /* Register as requested open device */ QueInsert(&reqcb->q, &opncb->requestq); reqcb->opncb = opncb; return reqcb; }
/* * Create mailbox */ SYSCALL ID _tk_cre_mbx( CONST T_CMBX *pk_cmbx ) { #if CHK_RSATR const ATR VALID_MBXATR = { TA_MPRI |TA_TPRI |TA_NODISWAI #if USE_OBJECT_NAME |TA_DSNAME #endif }; #endif MBXCB *mbxcb; ID mbxid; ER ercd; CHECK_RSATR(pk_cmbx->mbxatr, VALID_MBXATR); BEGIN_CRITICAL_SECTION; /* Get control block from FreeQue */ mbxcb = (MBXCB*)QueRemoveNext(&free_mbxcb); if ( mbxcb == NULL ) { ercd = E_LIMIT; } else { mbxid = ID_MBX(mbxcb - mbxcb_table); /* Initialize control block */ QueInit(&mbxcb->wait_queue); mbxcb->mbxid = mbxid; mbxcb->exinf = pk_cmbx->exinf; mbxcb->mbxatr = pk_cmbx->mbxatr; mbxcb->mq_head.msgque[0] = NULL; #if USE_OBJECT_NAME if ( (pk_cmbx->mbxatr & TA_DSNAME) != 0 ) { STRNCPY((char*)mbxcb->name, (char*)pk_cmbx->dsname, OBJECT_NAME_LENGTH); } #endif ercd = mbxid; } END_CRITICAL_SECTION; return ercd; }
/* * Create event flag */ SYSCALL ID tk_cre_flg_impl( T_CFLG *pk_cflg ) { #if CHK_RSATR const ATR VALID_FLGATR = { TA_TPRI |TA_WMUL #if USE_OBJECT_NAME |TA_DSNAME #endif }; #endif FLGCB *flgcb; ID flgid; ER ercd; CHECK_RSATR(pk_cflg->flgatr, VALID_FLGATR); BEGIN_CRITICAL_SECTION; /* Get control block from FreeQue */ flgcb = (FLGCB*)QueRemoveNext(&knl_free_flgcb); if ( flgcb == NULL ) { ercd = E_LIMIT; } else { flgid = ID_FLG(flgcb - knl_flgcb_table); /* Initialize control block */ QueInit(&flgcb->wait_queue); flgcb->flgid = flgid; flgcb->exinf = pk_cflg->exinf; flgcb->flgatr = pk_cflg->flgatr; flgcb->flgptn = pk_cflg->iflgptn; #if USE_OBJECT_NAME if ( (pk_cflg->flgatr & TA_DSNAME) != 0 ) { strncpy((char*)flgcb->name, (char*)pk_cflg->dsname, OBJECT_NAME_LENGTH); } #endif ercd = flgid; } END_CRITICAL_SECTION; return ercd; }
/* * Create message buffer */ SYSCALL ID _tk_cre_mbf( CONST T_CMBF *pk_cmbf ) { #if CHK_RSATR const ATR VALID_MBFATR = { TA_TPRI |TA_NODISWAI #if USE_OBJECT_NAME |TA_DSNAME #endif }; #endif MBFCB *mbfcb; ID mbfid; INT bufsz; VB *msgbuf; ER ercd; CHECK_RSATR(pk_cmbf->mbfatr, VALID_MBFATR); CHECK_PAR(pk_cmbf->bufsz >= 0); CHECK_PAR(pk_cmbf->maxmsz > 0); bufsz = (INT)ROUNDSZ(pk_cmbf->bufsz); if ( bufsz > 0 ) { msgbuf = Imalloc((UINT)bufsz); if ( msgbuf == NULL ) { return E_NOMEM; } } else { msgbuf = NULL; } BEGIN_CRITICAL_SECTION; /* Get control block from FreeQue */ mbfcb = (MBFCB*)QueRemoveNext(&free_mbfcb); if ( mbfcb == NULL ) { ercd = E_LIMIT; } else { mbfid = ID_MBF(mbfcb - mbfcb_table); /* Initialize control block */ QueInit(&mbfcb->send_queue); mbfcb->mbfid = mbfid; mbfcb->exinf = pk_cmbf->exinf; mbfcb->mbfatr = pk_cmbf->mbfatr; QueInit(&mbfcb->recv_queue); mbfcb->buffer = msgbuf; mbfcb->bufsz = mbfcb->frbufsz = bufsz; mbfcb->maxmsz = pk_cmbf->maxmsz; mbfcb->head = mbfcb->tail = 0; #if USE_OBJECT_NAME if ( (pk_cmbf->mbfatr & TA_DSNAME) != 0 ) { strncpy((char*)mbfcb->name, (char*)pk_cmbf->dsname, OBJECT_NAME_LENGTH); } #endif ercd = mbfid; } END_CRITICAL_SECTION; if ( ercd < E_OK && msgbuf != NULL ) { Ifree(msgbuf); } return ercd; }
/* * 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; }
/* * Fetch from the free queue * When DRQ is obtained, execute a return in the state of executing "LockGDI()". */ LOCAL ER gdi_getDRQ( DRQ **p_drq, T_DEVREQ *req, TMO tmout, GDI gdi ) { DRQ *drq; SYSTIM stime, ctime; TMO tmo = tmout; INT rw; UINT ptn, waiptn; ER err; rw = ( req->cmd == TDC_READ )? 0 : 1; waiptn = ( rw == 0 )? FREEQ_RD: FREEQ_WR; if ( tmout != TMO_FEVR ) { err = tk_get_otm(&stime); if ( err < E_OK ) goto err_ret1; } /* Lock for DRQ : This required in order to ensure that only one task waits the event flag for the same pattern */ err = LockDRQ(gdi, rw, tmo); if ( err < E_OK ) goto err_ret1; for ( ;; ) { /* Fetch one from the free queue */ LockGDI(gdi); if ( gdi->preq[rw] < gdi->limit ) { drq = (DRQ*)QueRemoveNext(&gdi->freeq); if ( drq != NULL ) break; /* Obtained */ } UnlockGDI(gdi); /* Remaining waiting time */ if ( tmout != TMO_FEVR ) { err = tk_get_otm(&ctime); if ( err < E_OK ) goto err_ret2; tmo = tmout - (ctime.lo - stime.lo); if ( tmo <= 0 ) { err = E_TMOUT; goto err_ret2; } } /* Wait for DRQ to be returned to the free queue */ err = tk_wai_flg(gdi->flgid, waiptn, TWF_ORW | TWF_BITCLR, &ptn, tmo); if ( err < E_OK ) { if ( err == E_DISWAI ) err = E_ABORT; goto err_ret2; } } /* UnLock for DRQ */ UnlockDRQ(gdi, rw); gdi->preq[rw]++; /* Set the device request to DRQ */ drq->req = req; if ( req->exinf != NULL ) { /* There is the task that waits for completion (gdi_waitfn) */ drq->wtid = *(ID*)req->exinf; } req->exinf = drq; *p_drq = drq; return E_OK; /* Return while executing "LockGDI()" */ err_ret2: UnlockDRQ(gdi, rw); err_ret1: DEBUG_PRINT(("gdi_getDRQ err = %d\n", err)); return err; }
/* * Create variable size memory pool */ SYSCALL ID _tk_cre_mpl( CONST T_CMPL *pk_cmpl ) { #if CHK_RSATR const ATR VALID_MPLATR = { TA_TPRI |TA_RNG3 |TA_NODISWAI #if USE_OBJECT_NAME |TA_DSNAME #endif }; #endif MPLCB *mplcb; ID mplid; INT mplsz; void *mempool; ER ercd; CHECK_RSATR(pk_cmpl->mplatr, VALID_MPLATR); CHECK_PAR(pk_cmpl->mplsz > 0 && pk_cmpl->mplsz <= MAX_ALLOCATE); CHECK_DISPATCH(); mplsz = roundSize(pk_cmpl->mplsz); /* Allocate memory for memory pool */ mempool = IAmalloc((UINT)mplsz + sizeof(QUEUE)*2, pk_cmpl->mplatr); if ( mempool == NULL ) { return E_NOMEM; } BEGIN_CRITICAL_SECTION; /* Get control block from FreeQue */ mplcb = (MPLCB*)QueRemoveNext(&free_mplcb); if ( mplcb == NULL ) { ercd = E_LIMIT; } else { mplid = ID_MPL(mplcb - mplcb_table); /* Initialize control block */ QueInit(&mplcb->wait_queue); mplcb->mplid = mplid; mplcb->exinf = pk_cmpl->exinf; mplcb->mplatr = pk_cmpl->mplatr; mplcb->mplsz = mplsz; #if USE_OBJECT_NAME if ( (pk_cmpl->mplatr & TA_DSNAME) != 0 ) { strncpy((char*)mplcb->name, (char*)pk_cmpl->dsname, OBJECT_NAME_LENGTH); } #endif /* Initialize memory pool */ init_mempool(mplcb, mempool, mplsz + (INT)sizeof(QUEUE)*2); ercd = mplid; } END_CRITICAL_SECTION; if ( ercd < E_OK ) { IAfree(mempool, pk_cmpl->mplatr); } return ercd; }
/* * Create fixed size memory pool */ SYSCALL ID tk_cre_mpf_impl( T_CMPF *pk_cmpf ) { #if CHK_RSATR const ATR VALID_MPFATR = { TA_TPRI |TA_RNG3 |TA_USERBUF #if USE_OBJECT_NAME |TA_DSNAME #endif }; #endif MPFCB *mpfcb; ID mpfid; W blfsz, mpfsz; VP mempool; CHECK_RSATR(pk_cmpf->mpfatr, VALID_MPFATR); CHECK_PAR(pk_cmpf->mpfcnt > 0); CHECK_PAR(pk_cmpf->blfsz > 0); #if !USE_IMALLOC /* TA_USERBUF must be specified if configured in no Imalloc */ CHECK_PAR((pk_cmpf->mpfatr & TA_USERBUF) != 0); #endif CHECK_DISPATCH(); blfsz = (W)MINSZ(pk_cmpf->blfsz); mpfsz = blfsz * pk_cmpf->mpfcnt; #if USE_IMALLOC if ( (pk_cmpf->mpfatr & TA_USERBUF) != 0 ) { /* Size of user buffer must be multiples of sizeof(FREEL) */ if ( blfsz != pk_cmpf->blfsz ) { return E_PAR; } /* Use user buffer */ mempool = pk_cmpf->bufptr; } else { /* Allocate memory for memory pool */ mempool = knl_Imalloc((UW)mpfsz); if ( mempool == NULL ) { return E_NOMEM; } } #else /* Size of user buffer must be larger than sizeof(FREEL) */ if ( blfsz != pk_cmpf->blfsz ) { return E_PAR; } /* Use user buffer */ mempool = pk_cmpf->bufptr; #endif /* Get control block from FreeQue */ DISABLE_INTERRUPT; mpfcb = (MPFCB*)QueRemoveNext(&knl_free_mpfcb); ENABLE_INTERRUPT; if ( mpfcb == NULL ) { #if USE_IMALLOC if ( (pk_cmpf->mpfatr & TA_USERBUF) == 0 ) { knl_Ifree(mempool); } #endif return E_LIMIT; } knl_LockOBJ(&mpfcb->lock); mpfid = ID_MPF(mpfcb - knl_mpfcb_table); /* Initialize control block */ QueInit(&mpfcb->wait_queue); mpfcb->exinf = pk_cmpf->exinf; mpfcb->mpfatr = pk_cmpf->mpfatr; mpfcb->mpfcnt = mpfcb->frbcnt = pk_cmpf->mpfcnt; mpfcb->blfsz = blfsz; mpfcb->mpfsz = mpfsz; mpfcb->unused = mpfcb->mempool = mempool; mpfcb->freelist = NULL; #if USE_OBJECT_NAME if ( (pk_cmpf->mpfatr & TA_DSNAME) != 0 ) { strncpy((char*)mpfcb->name, (char*)pk_cmpf->dsname, OBJECT_NAME_LENGTH); } #endif mpfcb->mpfid = mpfid; /* Set ID after completion */ knl_UnlockOBJ(&mpfcb->lock); return mpfid; }
/* * 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; }