/** * @brief Receives bytes as many as possible, without blocking the * calling task. * * rt_mbx_receive_wp receives at most @e msg_size of bytes of message * from the mailbox @e mbx then returns immediately. * * @param mbx is a pointer to a user allocated mailbox structure. * * @param msg points to a buffer provided by the caller. * * @param msg_size corresponds to the size of the message to be received. * * @return On success, the number of bytes not received is returned. On * failure a negative value is returned as described below: * - @b EINVAL: mbx points to not a valid mailbox. */ RTAI_SYSCALL_MODE int _rt_mbx_receive_wp(MBX *mbx, void *msg, int msg_size, int space) { unsigned long flags; RT_TASK *rt_current = RT_CURRENT; int size = msg_size; CHK_MBX_MAGIC; flags = rt_global_save_flags_and_cli(); if (mbx->rcvsem.count > 0 && mbx->avbs) { mbx->rcvsem.count = 0; if (mbx->rcvsem.type > 0) { mbx->rcvsem.owndby = rt_current; enqueue_resqel(&mbx->rcvsem.resq, rt_current); } rt_global_restore_flags(flags); msg_size = mbxget(mbx, (char **)(&msg), msg_size, space); mbx_signal(mbx); rt_sem_signal(&mbx->rcvsem); } else { rt_global_restore_flags(flags); } if (msg_size < size) { rt_wakeup_pollers(&mbx->poll_send, 0); } return msg_size; }
/** * @brief Receives a message with absolute timeout. * * rt_mbx_receive_until receives a message of @e msg_size bytes from * the mailbox @e mbx. The caller will be blocked until all bytes of * the message arrive, timeout expires or an error occurs. * * @param mbx is a pointer to a user allocated mailbox structure. * * @param msg points to a buffer provided by the caller. * * @param msg_size corresponds to the size of the message received. * * @param time is an absolute value of the timeout. * * @return On success, 0 is returned. * On failure a value is returned as described below: * - the number of bytes not received: an error is occured * in the queueing of all receiving tasks or the timeout has expired. * - @b EINVAL: mbx points to an invalid mailbox. * * See also: notes under rt_mbx_received_timed(). */ RTAI_SYSCALL_MODE int _rt_mbx_receive_until(MBX *mbx, void *msg, int msg_size, RTIME time, int space) { RT_TASK *rt_current = RT_CURRENT; int retval; CHK_MBX_MAGIC; if ((retval = rt_sem_wait_until(&mbx->rcvsem, time)) > 1) { return MBX_RET(msg_size, retval); } while (msg_size) { if ((retval = mbx_wait_until(mbx, &mbx->avbs, time, rt_current))) { rt_sem_signal(&mbx->rcvsem); retval = MBX_RET(msg_size, retval); rt_wakeup_pollers(&mbx->poll_recv, retval); return retval; } msg_size = mbxget(mbx, (char **)(&msg), msg_size, space); mbx_signal(mbx); } rt_sem_signal(&mbx->rcvsem); rt_wakeup_pollers(&mbx->poll_send, 0); return 0; }
/** * @brief Sends a message overwriting what already in the buffer * if there is no place for the message. * * rt_mbx_ovrwr_send sends the message @e msg of @e msg_size bytes * to the mailbox @e mbx overwriting what already in the mailbox * buffer if there is no place for the message. Useful for logging * purposes. It returns immediately and the caller is never blocked. * * @return On success, 0 is returned. On failure a negative value * is returned as described below: * - @b EINVAL: @e mbx points to an invalid mailbox. */ RTAI_SYSCALL_MODE int _rt_mbx_ovrwr_send(MBX *mbx, void *msg, int msg_size, int space) { unsigned long flags; RT_TASK *rt_current = RT_CURRENT; CHK_MBX_MAGIC; flags = rt_global_save_flags_and_cli(); if (mbx->sndsem.count > 0) { mbx->sndsem.count = 0; if (mbx->sndsem.type > 0) { mbx->sndsem.owndby = rt_current; enqueue_resqel(&mbx->sndsem.resq, rt_current); } rt_global_restore_flags(flags); msg_size = mbxovrwrput(mbx, (char **)(&msg), msg_size, space); mbx_signal(mbx); rt_sem_signal(&mbx->sndsem); } else { rt_global_restore_flags(flags); } return msg_size; }
/** * @brief Sends a message unconditionally. * * rt_mbx_send sends a message @e msg of @e msg_size bytes to the * mailbox @e mbx. The caller will be blocked until the whole message * is copied into the mailbox or an error occurs. Even if the message * can be sent in a single shot, the sending task can be blocked if * there is a task of higher priority waiting to receive from the * mailbox. * * @param mbx is a pointer to a user allocated mailbox structure. * * @param msg corresponds to the message to be sent. * * @param msg_size is the size of the message. * * @return On success, 0 is returned. * On failure a value is returned as described below: * - the number of bytes not received: an error is occured * in the queueing of all sending tasks. * - @b EINVAL: mbx points to an invalid mailbox. */ RTAI_SYSCALL_MODE int _rt_mbx_send(MBX *mbx, void *msg, int msg_size, int space) { RT_TASK *rt_current = RT_CURRENT; int retval; CHK_MBX_MAGIC; if ((retval = rt_sem_wait(&mbx->sndsem)) > 1) { return MBX_RET(msg_size, retval); } while (msg_size) { if ((retval = mbx_wait(mbx, &mbx->frbs, rt_current))) { rt_sem_signal(&mbx->sndsem); retval = MBX_RET(msg_size, retval); rt_wakeup_pollers(&mbx->poll_recv, retval); return retval; } msg_size = mbxput(mbx, (char **)(&msg), msg_size, space); mbx_signal(mbx); } rt_sem_signal(&mbx->sndsem); rt_wakeup_pollers(&mbx->poll_recv, 0); return 0; }