/* * Wakeup task */ SYSCALL ER _tk_wup_tsk( ID tskid ) { TCB *tcb; TSTAT state; ER ercd = E_OK; CHECK_TSKID(tskid); CHECK_NONSELF(tskid); tcb = get_tcb(tskid); BEGIN_CRITICAL_SECTION; state = (TSTAT)tcb->state; if ( !task_alive(state) ) { ercd = ( state == TS_NONEXIST )? E_NOEXS: E_OBJ; } else if ( (state & TS_WAIT) != 0 && tcb->wspec == &wspec_slp ) { wait_release_ok(tcb); } else if ( tcb->wupcnt == INT_MAX ) { ercd = E_QOVR; } else { ++tcb->wupcnt; } END_CRITICAL_SECTION; return ercd; }
/* * Free mutex when task is terminated * Free all mutexes which the task holds. * Do not need to handle mutex list and priority of terminated task. * */ EXPORT void signal_all_mutex( TCB *tcb ) { MTXCB *mtxcb, *next_mtxcb; TCB *next_tcb; next_mtxcb = tcb->mtxlist; while ( (mtxcb = next_mtxcb) != NULL ) { next_mtxcb = mtxcb->mtxlist; if ( mtx_waited(mtxcb) ) { next_tcb = (TCB*)mtxcb->wait_queue.next; /* Wake wait task */ wait_release_ok(next_tcb); /* Change mutex get task */ mtxcb->mtxtsk = next_tcb; mtxcb->mtxlist = next_tcb->mtxlist; next_tcb->mtxlist = mtxcb; if ( (mtxcb->mtxatr & TA_CEILING) == TA_CEILING ) { if ( next_tcb->priority > mtxcb->ceilpri ) { /* Raise the priority for the task that got lock to the highest priority limit */ change_task_priority(next_tcb, mtxcb->ceilpri); } } } else { /* No wait task */ mtxcb->mtxtsk = NULL; } } }
SYSCALL INT _tk_rcv_mbf_u( ID mbfid, void *msg, TMO_U tmout ) { MBFCB *mbfcb; TCB *tcb; INT rcvsz; ER ercd = E_OK; CHECK_MBFID(mbfid); CHECK_TMOUT(tmout); CHECK_DISPATCH(); mbfcb = get_mbfcb(mbfid); BEGIN_CRITICAL_SECTION; if (mbfcb->mbfid == 0) { ercd = E_NOEXS; goto error_exit; } /* Check receive wait disable */ if ( is_diswai((GCB*)mbfcb, ctxtsk, TTW_RMBF) ) { ercd = E_DISWAI; goto error_exit; } if ( !mbf_empty(mbfcb) ) { /* Read from message buffer */ rcvsz = mbf_to_msg(mbfcb, msg); /* Accept message from sending task(s) */ mbf_wakeup(mbfcb); } else if ( !isQueEmpty(&mbfcb->send_queue) ) { /* Receive directly from send wait task */ tcb = (TCB*)mbfcb->send_queue.next; rcvsz = tcb->winfo.smbf.msgsz; memcpy(msg, tcb->winfo.smbf.msg, (UINT)rcvsz); wait_release_ok(tcb); mbf_wakeup(mbfcb); } else { ercd = E_TMOUT; if ( tmout != TMO_POL ) { /* Ready for receive wait */ ctxtsk->wspec = &wspec_rmbf; ctxtsk->wid = mbfid; ctxtsk->wercd = &ercd; ctxtsk->winfo.rmbf.msg = msg; ctxtsk->winfo.rmbf.p_msgsz = &rcvsz; make_wait(tmout, mbfcb->mbfatr); QueInsert(&ctxtsk->tskque, &mbfcb->recv_queue); } } error_exit: END_CRITICAL_SECTION; return ( ercd < E_OK )? ercd: rcvsz; }
/* * 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; }
/* * Send to mailbox */ SYSCALL ER _tk_snd_mbx( ID mbxid, T_MSG *pk_msg ) { MBXCB *mbxcb; TCB *tcb; ER ercd = E_OK; CHECK_MBXID(mbxid); mbxcb = get_mbxcb(mbxid); BEGIN_CRITICAL_SECTION; if (mbxcb->mbxid == 0) { ercd = E_NOEXS; goto error_exit; } if ( (mbxcb->mbxatr & TA_MPRI) != 0 ) { if ( ((T_MSG_PRI*)pk_msg)->msgpri <= 0 ) { ercd = E_PAR; goto error_exit; } } if ( !isQueEmpty(&mbxcb->wait_queue) ) { /* Directly send to receive wait task */ tcb = (TCB*)(mbxcb->wait_queue.next); *tcb->winfo.mbx.ppk_msg = pk_msg; wait_release_ok(tcb); } else { /* Connect message to queue */ if ( (mbxcb->mbxatr & TA_MPRI) != 0 ) { /* Connect message to queue following priority */ queue_insert_mpri((T_MSG_PRI*)pk_msg, &mbxcb->mq_head); } else { /* Connect to end of queue */ nextmsg(pk_msg) = NULL; if ( headmsg(mbxcb) == NULL ) { headmsg(mbxcb) = pk_msg; } else { nextmsg(mbxcb->mq_tail) = pk_msg; } mbxcb->mq_tail = pk_msg; } } error_exit: END_CRITICAL_SECTION; return ercd; }
/* * Accept message and release wait task, * as long as there are free message area. */ LOCAL void mbf_wakeup( MBFCB *mbfcb ) { TCB *top; INT msgsz; while ( !isQueEmpty(&mbfcb->send_queue) ) { top = (TCB*)mbfcb->send_queue.next; msgsz = top->winfo.smbf.msgsz; if ( !mbf_free(mbfcb, msgsz) ) { break; } /* Store a message from waiting task and release it */ msg_to_mbf(mbfcb, top->winfo.smbf.msg, msgsz); wait_release_ok(top); } }
/* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ Funtion :_bk_wup_tsk Input :struct task *task < task to wake up > Output :void Return :ER < result > Description :wake up a task for btron _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */ EXPORT ER _bk_wup_tsk(struct task *task) { ER ercd = E_OK; TSTAT state; state = (TSTAT)task->state; if ( !task_alive(state) ) { ercd = ( state == TS_NONEXIST )? E_NOEXS: E_OBJ; } else if ( (state & TS_WAIT) != 0 && task->wspec == &wspec_slp ) { wait_release_ok(task); } else if ( task->wupcnt == INT_MAX ) { ercd = E_QOVR; } else { ++task->wupcnt; } return(ercd); }
SYSCALL ER i_vsnd_tmb(ID tskid,T_MSG *pk_msg) { TCB *tcb; TSTAT state; ER ercd = E_OK; CHECK_TSKID(tskid); CHECK_TSKACV(tskid); CHECK_NONSELF(tskid); tcb = get_tcb(tskid); BEGIN_CRITICAL_SECTION; if ( !task_alive(state = tcb->state) ) { ercd = (state == TS_NONEXIST) ? E_NOEXS : E_OBJ; } else if ((state & TS_WAIT) && tcb->wspec == &wspec_tmb_tfifo) { *(tcb->winfo.tmb.ppk_msg) = pk_msg; wait_release_ok(tcb); } else { nextmsg(pk_msg) = (T_MSG *) 0; if (tcb->tmq_head) { nextmsg(tcb->tmq_tail) = pk_msg; } else { tcb->tmq_head = pk_msg; } tcb->tmq_tail = pk_msg; } END_CRITICAL_SECTION; return(ercd); }
/* * Allocate memory and release wait task, * as long as there are enough free memory. */ LOCAL void mpl_wakeup( MPLCB *mplcb ) { TCB *top; void *blk; INT blksz; while ( !isQueEmpty(&mplcb->wait_queue) ) { top = (TCB*)mplcb->wait_queue.next; blksz = top->winfo.mpl.blksz; /* Check free space */ if ( blksz > MaxFreeSize(mplcb) ) { break; } /* Get memory block */ blk = get_blk(mplcb, blksz); *top->winfo.mpl.p_blk = blk; /* Release wait task */ wait_release_ok(top); } }
/* * Reply rendezvous */ SYSCALL ER _tk_rpl_rdv( RNO rdvno, void *msg, INT rmsgsz ) { TCB *caltcb; ER ercd = E_OK; CHECK_RDVNO(rdvno); CHECK_PAR(rmsgsz >= 0); CHECK_INTSK(); caltcb = get_tcb(get_tskid_rdvno(rdvno)); BEGIN_CRITICAL_SECTION; if ( (caltcb->state & TS_WAIT) == 0 || caltcb->wspec != &wspec_rdv || rdvno != caltcb->winfo.rdv.rdvno ) { ercd = E_OBJ; goto error_exit; } #if CHK_PAR if ( rmsgsz > caltcb->winfo.rdv.maxrmsz ) { ercd = E_PAR; goto error_exit; } #endif /* Send message */ if ( rmsgsz > 0 ) { memcpy(caltcb->winfo.rdv.msg, msg, (UINT)rmsgsz); } *caltcb->winfo.rdv.p_rmsgsz = rmsgsz; wait_release_ok(caltcb); error_exit: END_CRITICAL_SECTION; return ercd; }
SYSCALL ER _tk_snd_mbf_u( ID mbfid, CONST void *msg, INT msgsz, TMO_U tmout ) { MBFCB *mbfcb; TCB *tcb; ER ercd = E_OK; CHECK_MBFID(mbfid); CHECK_PAR(msgsz > 0); CHECK_TMOUT(tmout); CHECK_DISPATCH_POL(tmout); mbfcb = get_mbfcb(mbfid); BEGIN_CRITICAL_SECTION; if ( mbfcb->mbfid == 0 ) { ercd = E_NOEXS; goto error_exit; } #if CHK_PAR if ( msgsz > mbfcb->maxmsz ) { ercd = E_PAR; goto error_exit; } #endif /* Check send wait disable */ if ( !in_indp() && is_diswai((GCB*)mbfcb, ctxtsk, TTW_SMBF) ) { ercd = E_DISWAI; goto error_exit; } if ( !isQueEmpty(&mbfcb->recv_queue) ) { /* Send directly to the receive wait task */ tcb = (TCB*)mbfcb->recv_queue.next; memcpy(tcb->winfo.rmbf.msg, msg, (UINT)msgsz); *tcb->winfo.rmbf.p_msgsz = msgsz; wait_release_ok(tcb); } else if ( (in_indp() || gcb_top_of_wait_queue((GCB*)mbfcb, ctxtsk) == ctxtsk) &&(mbf_free(mbfcb, msgsz)) ) { /* Store the message to message buffer */ msg_to_mbf(mbfcb, msg, msgsz); } else { ercd = E_TMOUT; if ( tmout != TMO_POL ) { /* Ready for send wait */ ctxtsk->wspec = ( (mbfcb->mbfatr & TA_TPRI) != 0 )? &wspec_smbf_tpri: &wspec_smbf_tfifo; ctxtsk->wercd = &ercd; ctxtsk->winfo.smbf.msg = msg; ctxtsk->winfo.smbf.msgsz = msgsz; gcb_make_wait_with_diswai((GCB*)mbfcb, tmout); } } error_exit: 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_cal_por_u( ID porid, UINT calptn, void *msg, INT cmsgsz, TMO_U 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; } /* Check rendezvous call wait disable */ if ( is_diswai((GCB*)porcb, ctxtsk, TTW_CAL) ) { ercd = E_DISWAI; goto error_exit; } /* Send message */ rdvno = gen_rdvno(ctxtsk); if ( cmsgsz > 0 ) { memcpy(tcb->winfo.acp.msg, msg, (UINT)cmsgsz); } *tcb->winfo.acp.p_rdvno = rdvno; *tcb->winfo.acp.p_cmsgsz = cmsgsz; wait_release_ok(tcb); /* Check rendezvous end wait disable */ if ( is_diswai((GCB*)porcb, ctxtsk, TTW_RDV) ) { ercd = E_DISWAI; goto error_exit; } /* Ready for rendezvous end wait */ ercd = E_TMOUT; ctxtsk->wspec = &wspec_rdv; ctxtsk->wid = 0; ctxtsk->wercd = &ercd; ctxtsk->winfo.rdv.rdvno = rdvno; ctxtsk->winfo.rdv.msg = msg; ctxtsk->winfo.rdv.maxrmsz = porcb->maxrmsz; ctxtsk->winfo.rdv.p_rmsgsz = &rmsgsz; make_wait(TMO_FEVR, porcb->poratr); QueInit(&ctxtsk->tskque); goto error_exit; } /* Ready for rendezvous call wait */ ctxtsk->wspec = ( (porcb->poratr & TA_TPRI) != 0 )? &wspec_cal_tpri: &wspec_cal_tfifo; ctxtsk->wercd = &ercd; ctxtsk->winfo.cal.calptn = calptn; ctxtsk->winfo.cal.msg = msg; ctxtsk->winfo.cal.cmsgsz = cmsgsz; ctxtsk->winfo.cal.p_rmsgsz = &rmsgsz; gcb_make_wait_with_diswai((GCB*)porcb, tmout); error_exit: END_CRITICAL_SECTION; return ( ercd < E_OK )? ercd: rmsgsz; }