/* * Get fixed size memory block */ SYSCALL ER tk_get_mpf_impl( ID mpfid, VP *p_blf, TMO tmout ) { MPFCB *mpfcb; FREEL *free; ER ercd = E_OK; CHECK_MPFID(mpfid); CHECK_TMOUT(tmout); CHECK_DISPATCH(); mpfcb = get_mpfcb(mpfid); knl_LockOBJ(&mpfcb->lock); if ( mpfcb->mpfid == 0 ) { ercd = E_NOEXS; goto error_exit; } /* If there is no space, ready for wait */ if ( mpfcb->frbcnt <= 0 ) { goto wait_mpf; } else { /* Get memory block */ if ( mpfcb->freelist != NULL ) { free = mpfcb->freelist; mpfcb->freelist = free->next; *p_blf = free; } else { *p_blf = mpfcb->unused; mpfcb->unused = (VB*)mpfcb->unused + mpfcb->blfsz; } mpfcb->frbcnt--; } error_exit: knl_UnlockOBJ(&mpfcb->lock); return ercd; wait_mpf: /* Ready for wait */ BEGIN_CRITICAL_SECTION; knl_ctxtsk->wspec = ( (mpfcb->mpfatr & TA_TPRI) != 0 )? &knl_wspec_mpf_tpri: &knl_wspec_mpf_tfifo; knl_ctxtsk->wercd = &ercd; knl_ctxtsk->winfo.mpf.p_blf = p_blf; knl_gcb_make_wait((GCB*)mpfcb, tmout); knl_UnlockOBJ(&mpfcb->lock); END_CRITICAL_SECTION; return ercd; }
/* * Event flag wait */ SYSCALL ER tk_wai_flg_impl( ID flgid, UINT waiptn, UINT wfmode, UINT *p_flgptn, TMO tmout ) { FLGCB *flgcb; ER ercd = E_OK; CHECK_FLGID(flgid); CHECK_PAR(waiptn != 0); CHECK_PAR((wfmode & ~(TWF_ORW|TWF_CLR|TWF_BITCLR)) == 0); CHECK_TMOUT(tmout); CHECK_DISPATCH(); flgcb = get_flgcb(flgid); BEGIN_CRITICAL_SECTION; if ( flgcb->flgid == 0 ) { ercd = E_NOEXS; goto error_exit; } if ( (flgcb->flgatr & TA_WMUL) == 0 && !isQueEmpty(&flgcb->wait_queue) ) { /* Disable multiple tasks wait */ ercd = E_OBJ; goto error_exit; } /* Meet condition for release wait? */ if ( knl_eventflag_cond(flgcb, waiptn, wfmode) ) { *p_flgptn = flgcb->flgptn; /* Clear event flag */ if ( (wfmode & TWF_BITCLR) != 0 ) { flgcb->flgptn &= ~waiptn; } if ( (wfmode & TWF_CLR) != 0 ) { flgcb->flgptn = 0; } } else { /* Ready for wait */ knl_ctxtsk->wspec = ( (flgcb->flgatr & TA_TPRI) != 0 )? &knl_wspec_flg_tpri: &knl_wspec_flg_tfifo; knl_ctxtsk->wercd = &ercd; knl_ctxtsk->winfo.flg.waiptn = waiptn; knl_ctxtsk->winfo.flg.wfmode = wfmode; knl_ctxtsk->winfo.flg.p_flgptn = p_flgptn; knl_gcb_make_wait((GCB*)flgcb, tmout); } error_exit: END_CRITICAL_SECTION; return ercd; }
/* * Wait on semaphore */ SYSCALL ER tk_wai_sem_impl( ID semid, INT cnt, TMO tmout ) { SEMCB *semcb; ER ercd = E_OK; CHECK_SEMID(semid); CHECK_PAR(cnt > 0); CHECK_TMOUT(tmout); CHECK_DISPATCH(); semcb = get_semcb(semid); BEGIN_CRITICAL_SECTION; if ( semcb->semid == 0 ) { ercd = E_NOEXS; goto error_exit; } #if CHK_PAR if ( cnt > semcb->maxsem ) { ercd = E_PAR; goto error_exit; } #endif if ( ((semcb->sematr & TA_CNT) != 0 || knl_gcb_top_of_wait_queue((GCB*)semcb, knl_ctxtsk) == knl_ctxtsk) && semcb->semcnt >= cnt ) { /* Get semaphore count */ semcb->semcnt -= cnt; } else { /* Ready for wait */ knl_ctxtsk->wspec = ( (semcb->sematr & TA_TPRI) != 0 )? &knl_wspec_sem_tpri: &knl_wspec_sem_tfifo; knl_ctxtsk->wercd = &ercd; knl_ctxtsk->winfo.sem.cnt = cnt; knl_gcb_make_wait((GCB*)semcb, tmout); } error_exit: END_CRITICAL_SECTION; return ercd; }
/* * Call rendezvous */ SYSCALL INT tk_cal_por_impl( ID porid, UINT calptn, VP msg, INT cmsgsz, TMO tmout ) { PORCB *porcb; TCB *tcb; QUEUE *queue; RNO rdvno; INT rmsgsz; ER ercd = E_OK; CHECK_PORID(porid); CHECK_PAR(calptn != 0); CHECK_PAR(cmsgsz >= 0); CHECK_TMOUT(tmout); CHECK_DISPATCH(); porcb = get_porcb(porid); BEGIN_CRITICAL_SECTION; if ( porcb->porid == 0 ) { ercd = E_NOEXS; goto error_exit; } #if CHK_PAR if ( cmsgsz > porcb->maxcmsz ) { ercd = E_PAR; goto error_exit; } #endif /* Search accept wait task */ queue = porcb->accept_queue.next; while ( queue != &porcb->accept_queue ) { tcb = (TCB*)queue; queue = queue->next; if ( (calptn & tcb->winfo.acp.acpptn) == 0 ) { continue; } /* Send message */ rdvno = knl_gen_rdvno(knl_ctxtsk); if ( cmsgsz > 0 ) { memcpy(tcb->winfo.acp.msg, msg, (UINT)cmsgsz); } *tcb->winfo.acp.p_rdvno = rdvno; *tcb->winfo.acp.p_cmsgsz = cmsgsz; knl_wait_release_ok(tcb); /* Ready for rendezvous end wait */ ercd = E_TMOUT; knl_ctxtsk->wspec = &knl_wspec_rdv; knl_ctxtsk->wid = 0; knl_ctxtsk->wercd = &ercd; knl_ctxtsk->winfo.rdv.rdvno = rdvno; knl_ctxtsk->winfo.rdv.msg = msg; knl_ctxtsk->winfo.rdv.maxrmsz = porcb->maxrmsz; knl_ctxtsk->winfo.rdv.p_rmsgsz = &rmsgsz; knl_make_wait(TMO_FEVR, porcb->poratr); QueInit(&knl_ctxtsk->tskque); goto error_exit; } /* Ready for rendezvous call wait */ knl_ctxtsk->wspec = ( (porcb->poratr & TA_TPRI) != 0 )? &knl_wspec_cal_tpri: &knl_wspec_cal_tfifo; knl_ctxtsk->wercd = &ercd; knl_ctxtsk->winfo.cal.calptn = calptn; knl_ctxtsk->winfo.cal.msg = msg; knl_ctxtsk->winfo.cal.cmsgsz = cmsgsz; knl_ctxtsk->winfo.cal.p_rmsgsz = &rmsgsz; knl_gcb_make_wait((GCB*)porcb, tmout); error_exit: END_CRITICAL_SECTION; return ( ercd < E_OK )? ercd: rmsgsz; }