SYSCALL INT _tk_dis_wai( ID tskid, UINT waitmask ) { TCB *tcb; UINT tskwait = 0; ER ercd = E_OK; CHECK_TSKID_SELF(tskid); CHECK_PAR(((waitmask & ~WAIT_PATTERN) == 0)&&((waitmask & WAIT_PATTERN) != 0)); tcb = get_tcb_self(tskid); BEGIN_CRITICAL_SECTION; if ( tcb->state == TS_NONEXIST ) { ercd = E_NOEXS; goto error_exit; } /* Update wait disable mask */ tcb->waitmask = waitmask; if ( (tcb->state & TS_WAIT) != 0 ) { tskwait = tcb->wspec->tskwait; if ( (tskwait & waitmask) != 0 && !tcb->nodiswai ) { /* Free wait */ wait_release_ng(tcb, E_DISWAI); tskwait = 0; } } error_exit: END_CRITICAL_SECTION; return ( ercd < E_OK )? (INT)ercd: (INT)tskwait; }
/* * Release wait */ SYSCALL ER _tk_rel_wai( ID tskid ) { TCB *tcb; TSTAT state; ER ercd = E_OK; CHECK_TSKID(tskid); tcb = get_tcb(tskid); BEGIN_CRITICAL_SECTION; state = (TSTAT)tcb->state; if ( (state & TS_WAIT) == 0 ) { ercd = ( state == TS_NONEXIST )? E_NOEXS: E_OBJ; } else { wait_release_ng(tcb, E_RLWAI); } END_CRITICAL_SECTION; return ercd; }
/* * Forward Rendezvous to Other Port */ SYSCALL ER _tk_fwd_por( ID porid, UINT calptn, RNO rdvno, void *msg, INT cmsgsz ) { PORCB *porcb; TCB *caltcb, *tcb; QUEUE *queue; RNO new_rdvno; ER ercd = E_OK; CHECK_PORID(porid); CHECK_PAR(calptn != 0); CHECK_RDVNO(rdvno); CHECK_PAR(cmsgsz >= 0); CHECK_INTSK(); porcb = get_porcb(porid); caltcb = get_tcb(get_tskid_rdvno(rdvno)); 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 if ( (caltcb->state & TS_WAIT) == 0 || caltcb->wspec != &wspec_rdv || rdvno != caltcb->winfo.rdv.rdvno ) { ercd = E_OBJ; goto error_exit; } if ( porcb->maxrmsz > caltcb->winfo.rdv.maxrmsz ) { ercd = E_OBJ; goto error_exit; } #if CHK_PAR if ( cmsgsz > caltcb->winfo.rdv.maxrmsz ) { 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; } /* Check rendezvous accept wait disable */ if ( is_diswai((GCB*)porcb, caltcb, TTW_CAL) ) { wait_release_ng(caltcb, E_DISWAI); ercd = E_DISWAI; goto error_exit; } /* Send message */ new_rdvno = gen_rdvno(caltcb); if ( cmsgsz > 0 ) { memcpy(tcb->winfo.acp.msg, msg, (UINT)cmsgsz); } *tcb->winfo.acp.p_rdvno = new_rdvno; *tcb->winfo.acp.p_cmsgsz = cmsgsz; wait_release_ok(tcb); /* Check rendezvous end wait disable */ if ( is_diswai((GCB*)porcb, caltcb, TTW_RDV) ) { wait_release_ng(caltcb, E_DISWAI); ercd = E_DISWAI; goto error_exit; } /* Change rendezvous end wait of the other task */ caltcb->winfo.rdv.rdvno = new_rdvno; caltcb->winfo.rdv.msg = caltcb->winfo.cal.msg; caltcb->winfo.rdv.maxrmsz = porcb->maxrmsz; caltcb->winfo.rdv.p_rmsgsz = caltcb->winfo.cal.p_rmsgsz; caltcb->nodiswai = ( (porcb->poratr & TA_NODISWAI) != 0 )? TRUE: FALSE; goto error_exit; } /* Check rendezvous accept wait disable */ if ( is_diswai((GCB*)porcb, caltcb, TTW_CAL) ) { wait_release_ng(caltcb, E_DISWAI); ercd = E_DISWAI; goto error_exit; } /* Change the other task to rendezvous call wait */ caltcb->wspec = ( (porcb->poratr & TA_TPRI) != 0 )? &wspec_cal_tpri: &wspec_cal_tfifo; caltcb->wid = porid; caltcb->winfo.cal.calptn = calptn; caltcb->winfo.cal.msg = caltcb->winfo.rdv.msg; caltcb->winfo.cal.cmsgsz = cmsgsz; caltcb->winfo.cal.p_rmsgsz = caltcb->winfo.rdv.p_rmsgsz; caltcb->nodiswai = ( (porcb->poratr & TA_NODISWAI) != 0 )? TRUE: FALSE; timer_insert(&caltcb->wtmeb, TMO_FEVR, (CBACK)wait_release_tmout, caltcb); if ( (porcb->poratr & TA_TPRI) != 0 ) { queue_insert_tpri(caltcb, &porcb->call_queue); } else { QueInsert(&caltcb->tskque, &porcb->call_queue); } if ( cmsgsz > 0 ) { memcpy(caltcb->winfo.cal.msg, msg, (UINT)cmsgsz); } error_exit: END_CRITICAL_SECTION; return ercd; }
SYSCALL INT _tk_acp_por_u( ID porid, UINT acpptn, RNO *p_rdvno, void *msg, TMO_U tmout ) { PORCB *porcb; TCB *tcb; QUEUE *queue; RNO rdvno; INT cmsgsz; ER ercd = E_OK; CHECK_PORID(porid); CHECK_PAR(acpptn != 0); CHECK_TMOUT(tmout); CHECK_DISPATCH(); porcb = get_porcb(porid); BEGIN_CRITICAL_SECTION; if ( porcb->porid == 0 ) { ercd = E_NOEXS; goto error_exit; } /* Search call wait task */ queue = porcb->call_queue.next; while ( queue != &porcb->call_queue ) { tcb = (TCB*)queue; queue = queue->next; if ( (acpptn & tcb->winfo.cal.calptn) == 0 ) { continue; } /* Check rendezvous accept wait disable */ if ( is_diswai((GCB*)porcb, ctxtsk, TTW_ACP) ) { ercd = E_DISWAI; goto error_exit; } /* Receive message */ *p_rdvno = rdvno = gen_rdvno(tcb); cmsgsz = tcb->winfo.cal.cmsgsz; if ( cmsgsz > 0 ) { memcpy(msg, tcb->winfo.cal.msg, (UINT)cmsgsz); } /* Check rendezvous end wait disable */ if ( is_diswai((GCB*)porcb, tcb, TTW_RDV) ) { wait_release_ng(tcb, E_DISWAI); goto error_exit; } wait_cancel(tcb); /* Make the other task at rendezvous end wait state */ tcb->wspec = &wspec_rdv; tcb->wid = 0; tcb->winfo.rdv.rdvno = rdvno; tcb->winfo.rdv.msg = tcb->winfo.cal.msg; tcb->winfo.rdv.maxrmsz = porcb->maxrmsz; tcb->winfo.rdv.p_rmsgsz = tcb->winfo.cal.p_rmsgsz; timer_insert(&tcb->wtmeb, TMO_FEVR, (CBACK)wait_release_tmout, tcb); QueInit(&tcb->tskque); goto error_exit; } /* Check rendezvous accept wait disable */ if ( is_diswai((GCB*)porcb, ctxtsk, TTW_ACP) ) { ercd = E_DISWAI; goto error_exit; } ercd = E_TMOUT; if ( tmout != TMO_POL ) { /* Ready for rendezvous accept wait */ ctxtsk->wspec = &wspec_acp; ctxtsk->wid = porid; ctxtsk->wercd = &ercd; ctxtsk->winfo.acp.acpptn = acpptn; ctxtsk->winfo.acp.msg = msg; ctxtsk->winfo.acp.p_rdvno = p_rdvno; ctxtsk->winfo.acp.p_cmsgsz = &cmsgsz; make_wait(tmout, porcb->poratr); QueInsert(&ctxtsk->tskque, &porcb->accept_queue); } error_exit: END_CRITICAL_SECTION; return ( ercd < E_OK )? ercd: cmsgsz; }