OS_RESULT os_mbx_send (OS_ID mailbox, void *p_msg, U16 timeout) { /* Send message to a mailbox */ P_MCB p_MCB = mailbox; P_TCB p_TCB; tsk_lock(); m:if (p_MCB->p_lnk != NULL && p_MCB->count == 0) { /* A task is waiting for message */ p_TCB = os_get_first ((P_XCB)p_MCB); p_TCB->p_msg = p_msg; p_TCB->ret_val = OS_R_MBX; os_rmv_dly (p_TCB); os_dispatch (p_TCB); } else { /* Store message in mailbox queue */ if (p_MCB->count == p_MCB->size) { /* No free message entry, wait for one. If message queue is full, */ /* then no task is waiting for message. The 'p_MCB->p_lnk' list */ /* pointer can now be reused for send message waits task list. */ if (timeout == 0) { goto wto; } if (p_MCB->p_lnk != NULL) { os_put_prio ((P_XCB)p_MCB, os_runtask); } else { p_MCB->p_lnk = os_runtask; os_runtask->p_lnk = NULL; os_runtask->p_rlnk = (P_TCB)p_MCB; /* Signal the 'isr_mbx_receive ()' that the task is waiting */ /* to send a message */ p_MCB->isr_st = 1; } if (os_block(timeout, WAIT_MBX) == OS_R_TMO) { wto: tsk_unlock(); return (OS_R_TMO); } /* A message has been fetched, check the mailbox again. */ goto m; } /* Yes, there is a free entry in a mailbox. */ p_MCB->msg[p_MCB->first] = p_msg; _incw (&p_MCB->count); if (++p_MCB->first == p_MCB->size) { p_MCB->first = 0; } } tsk_unlock(); return (OS_R_OK); }
OS_RESULT os_mbx_wait (OS_ID mailbox, void **message, U16 timeout) { /* Receive a message; possibly wait for it */ P_MCB p_MCB = mailbox; P_TCB p_TCB; tsk_lock(); /* If a message is available in the fifo buffer */ /* remove it from the fifo buffer and return. */ if (p_MCB->count) { *message = p_MCB->msg[p_MCB->last]; _decw (&p_MCB->count); if (++p_MCB->last == p_MCB->size) { p_MCB->last = 0; } if (p_MCB->p_lnk != NULL) { /* A task is waiting to send message */ p_TCB = os_get_first ((P_XCB)p_MCB); os_rmv_dly (p_TCB); os_dispatch (p_TCB); } tsk_unlock(); return (OS_R_OK); } /* No message available: wait for one */ if (timeout == 0) { goto rto; } if (p_MCB->p_lnk != NULL) { os_put_prio ((P_XCB)p_MCB, os_runtask); } else { p_MCB->p_lnk = os_runtask; os_runtask->p_lnk = NULL; os_runtask->p_rlnk = (P_TCB)p_MCB; } if (os_block(timeout, WAIT_MBX) == OS_R_TMO) { rto:tsk_unlock(); *message = NULL; return (OS_R_TMO); } tsk_unlock(); *message = os_runtask->p_msg; return (OS_R_MBX); }
OS_RESULT os_mut_wait (OS_ID mutex, U16 timeout) { /* Wait for a mutex, continue when mutex is free. */ P_MUCB p_MCB = mutex; tsk_lock(); if (p_MCB->level == 0) { p_MCB->owner = os_runtask; p_MCB->prio = os_runtask->prio; goto inc; } if (p_MCB->owner == os_runtask) { /* OK, running task is the owner of this mutex. */ inc:p_MCB->level++; tsk_unlock(); return (OS_R_OK); } /* Mutex owned by another task, wait until released. */ if (timeout == 0) { goto rto; } /* Raise the owner task priority if lower than current priority. */ /* This priority inversion is called priority inheritance. */ if (p_MCB->prio < os_runtask->prio) { p_MCB->owner->prio = os_runtask->prio; os_resort_prio (p_MCB->owner); } if (p_MCB->p_lnk != NULL) { os_put_prio ((P_XCB)p_MCB, os_runtask); } else { p_MCB->p_lnk = os_runtask; os_runtask->p_lnk = NULL; os_runtask->p_rlnk = (P_TCB)p_MCB; } if (os_block(timeout, WAIT_MUT) == OS_R_TMO) { rto:tsk_unlock(); return (OS_R_TMO); } /* A mutex has been released. */ tsk_unlock(); return (OS_R_MUT); }
OS_RESULT os_evt_wait (U16 wait_flags, U16 timeout, BOOL and_wait) { /* Wait for one or more event flags with optional time-out. */ /* "wait_flags" identifies the flags to wait for. */ /* "timeout" is the time-out limit in system ticks (0xffff if no time-out) */ /* "and_wait" specifies the AND-ing of "wait_flags" as condition to be met */ /* to complete the wait. (OR-ing if set to 0). */ U32 block_state; tsk_lock(); if (and_wait) { /* Check for AND-connected events */ if ((os_runtask->events & wait_flags) == wait_flags) { os_runtask->events &= ~wait_flags; tsk_unlock(); return (OS_R_EVT); } block_state = WAIT_AND; } else { /* Check for OR-connected events */ if (os_runtask->events & wait_flags) { os_runtask->waits = os_runtask->events & wait_flags; os_runtask->events &= ~wait_flags; tsk_unlock(); return (OS_R_EVT); } block_state = WAIT_OR; } /* Task has to wait */ os_runtask->waits = wait_flags; if (os_block(timeout, (U8)block_state) == OS_R_TMO) { tsk_unlock(); return (OS_R_TMO); } tsk_unlock(); return (OS_R_EVT); }