📄 msg.c
字号:
* if any. rt_evdrp never blocks. * * @param task is a pointer to a @e RT_TASK structure. * * @param msg points to any 4 bytes word buffer provided by the * caller. * * @return a pointer to the sender task is returned upon success.<br> * 0 is returned if no message is available. * A special value is returned on other failure. The errors * are described below: * - @b 0: the sender task was killed before sending the message; * - @b 0xFFFF: @e task does not refer to a valid task. * * @note Since all the messaging functions return a task address * 0xFFFF could seem an inappropriate return value. However on all * the CPUs RTAI runs on 0xFFFF is not an address that can be used by * any RTAI task, so it is should be always safe. */RT_TASK *rt_evdrp(RT_TASK *task, unsigned int *msg){ DECLARE_RT_CURRENT; if (task && task->magic != RT_TASK_MAGIC) { return MSG_ERR; } ASSIGN_RT_CURRENT; if (!task) task = (rt_current->msg_queue.next)->task; if ((task->state & (RT_SCHED_SEND | RT_SCHED_RPC)) && task->msg_queue.task == rt_current) { *msg = task->msg; } else { task = (RT_TASK *)0; } return task;}/** * @ingroup msg * @anchor rt_receive * @brief Receive a message. * * rt_receive gets a message from the task specified by task. If task * is equal to 0, the caller accepts messages from any task. If there * is a pending message, rt_receive does not block but can be * preempted if the task that rt_sent the just received message has a * higher priority. The task will not block if it receives rpced messages * since rpcing tasks always waits for a returned message. Moreover it * inheredits the highest priority of any rpcing task waiting on the receive * queue. The receiving task will then recover its priority as explained in * rt_return. Otherwise the caller task is blocked waiting for any * message to be sent/rpced. * * @param task is a pointer to a @e RT_TASK structure. * * @param msg points to any 4 bytes word buffer provided by the * caller. * * @return a pointer to the sender task is returned upon success.<br> * 0 is returned if the caller is unblocked but no message has * been received (e.g. the task @e task was killed before sending the * message.)<br> * A special value is returned on other failure. The errors * are described below: * - @b 0: the sender task was killed before sending the message; * - @b 0xFFFF: @e task does not refer to a valid task. * * @note Since all the messaging functions return a task address * 0xFFFF could seem an inappropriate return value. However on all * the CPUs RTAI runs on 0xFFFF is not an address that can be used by * any RTAI task, so it is should be always safe. */RT_TASK *rt_receive(RT_TASK *task, unsigned int *msg){ DECLARE_RT_CURRENT; unsigned long flags; if (task && task->magic != RT_TASK_MAGIC) { return MSG_ERR; } flags = rt_global_save_flags_and_cli(); ASSIGN_RT_CURRENT; if (!task) task = (rt_current->msg_queue.next)->task; if ((task->state & (RT_SCHED_SEND | RT_SCHED_RPC)) && task->msg_queue.task == rt_current) { dequeue_blocked(task); rem_timed_task(task); *msg = task->msg; rt_current->msg_queue.task = task; if (task->state & RT_SCHED_SEND) { task->msg_queue.task = task; if (task->state != RT_SCHED_READY && (task->state &= ~(RT_SCHED_SEND | RT_SCHED_DELAYED)) == RT_SCHED_READY) { enq_ready_task(task); RT_SCHEDULE(task, cpuid); } } else if (task->state & RT_SCHED_RPC) { enqueue_blocked(task, &rt_current->ret_queue, 0); task->state = (task->state & ~(RT_SCHED_RPC | RT_SCHED_DELAYED)) | RT_SCHED_RETURN; } } else { rt_current->ret_queue.task = SOMETHING; rt_current->state |= RT_SCHED_RECEIVE; rem_ready_current(rt_current); rt_current->msg_queue.task = task != rt_current ? task : (RT_TASK *)0; rt_schedule(); *msg = rt_current->msg; } if (rt_current->ret_queue.task) { rt_current->ret_queue.task = NOTHING; task = (RT_TASK *)0; } else { task = rt_current->msg_queue.task; } rt_current->msg_queue.task = rt_current; rt_global_restore_flags(flags); if (task && (struct proxy_t *)task->stack_bottom) { if (((struct proxy_t *)task->stack_bottom)->receiver == rt_current) { rt_return(task, 0); } } return task;}/** * @ingroup msg * @anchor rt_receive_if * @brief Receive a message, only if the calling task is not blocked. * * rt_receive_if tries to get a message from the task specified by * task. If task is equal to 0, the caller accepts messages from any * task. The caller task is never blocked but can be preempted if the * task that rt_sent the just received message has a * higher priority. The task will not block if it receives rpced messages * since rpcing tasks always waits for a returned message. Moreover it * inheredits the highest priority of any rpcing task waiting on the receive * queue. The receiving task will then recover its priority as explained in * rt_return. Otherwise the caller task is blocked waiting for any * message to be sent/rpced. * * @param task is a pointer to the task structure. * * @param msg points to a buffer provided by the caller. * * @return a pointer to the sender task is returned upon success.<br> * A special value is returned on other failure. The errors are * described below: * - @b 0: there was no message to receive; * - @b 0xFFFF: @e task does not refer to a valid task. * * Since all the messaging functions return a task address 0xFFFF * could seem an inappropriate return value. However on all the CPUs * RTAI runs on 0xFFFF is not an address that can be used by any RTAI * task, so it is should be always safe. */RT_TASK *rt_receive_if(RT_TASK *task, unsigned int *msg){ DECLARE_RT_CURRENT; unsigned long flags; if (task && task->magic != RT_TASK_MAGIC) { return MSG_ERR; } flags = rt_global_save_flags_and_cli(); ASSIGN_RT_CURRENT; if (!task) task = (rt_current->msg_queue.next)->task; if ((task->state & (RT_SCHED_SEND | RT_SCHED_RPC)) && task->msg_queue.task == rt_current) { dequeue_blocked(task); rem_timed_task(task); *msg = task->msg; rt_current->msg_queue.task = task; if (task->state & RT_SCHED_SEND) { task->msg_queue.task = task; if (task->state != RT_SCHED_READY && (task->state &= ~(RT_SCHED_SEND | RT_SCHED_DELAYED)) == RT_SCHED_READY) { enq_ready_task(task); RT_SCHEDULE(task, cpuid); } } else if (task->state & RT_SCHED_RPC) { enqueue_blocked(task, &rt_current->ret_queue, 0); task->state = (task->state & ~(RT_SCHED_RPC | RT_SCHED_DELAYED)) | RT_SCHED_RETURN; } if (rt_current->ret_queue.task) { rt_current->ret_queue.task = NOTHING; task = (RT_TASK *)0; } else { task = rt_current->msg_queue.task; } rt_current->msg_queue.task = rt_current; } else { task = (RT_TASK *)0; } rt_global_restore_flags(flags); if (task && (struct proxy_t *)task->stack_bottom) { if (((struct proxy_t *)task->stack_bottom)->receiver == rt_current) { rt_return(task, 0); } } return task;}/** * @ingroup msg * @anchor rt_receive_until * @brief Receive a message with an absolute timeout. * * rt_receive_until receives a message from the task specified by * task. If task is equal to 0, the caller accepts messages from any * task. If there is a pending message, rt_receive does not block but * but can be preempted if the * task that rt_sent the just received message has a * higher priority. The task will not block if it receives rpced messages * since rpcing tasks always waits for a returned message. Moreover it * inheredits the highest priority of any rpcing task waiting on the receive * queue. The receiving task will then recover its priority as explained in * rt_return. Otherwise the caller task is blocked waiting for any * message to be sent/rpced. * In this case these functions return if: * a sender sends a message and has a lower priority; * any rpced message is received; * - timeout occurs; * - an error occurs (e.g. the sender task is killed.) * * @param task is a pointer to the task structure. * * @param msg points to a buffer provided by the caller. * * @param time is an absolute timout value. * * @return On success, a pointer to the sender task is returned. * On other failure, a special value is returned. The errors * are described below: * - @b 0: there was no message to receive. * - @b 0xFFFF: @e task does not refer to a valid task. * * @note Since all the messaging functions return a task address * 0xFFFF could seem an inappropriate return value. However on all * the CPUs RTAI runs on 0xFFFF is not an address that can be used by * any RTAI task, so it is should be always safe. * * See also: @ref rt_receive_timed(). */RT_TASK *rt_receive_until(RT_TASK *task, unsigned int *msg, RTIME time){ DECLARE_RT_CURRENT; unsigned long flags; if (task && task->magic != RT_TASK_MAGIC) { return MSG_ERR; } flags = rt_global_save_flags_and_cli(); ASSIGN_RT_CURRENT; if (!task) task = (rt_current->msg_queue.next)->task; if ((task->state & (RT_SCHED_SEND | RT_SCHED_RPC)) && task->msg_queue.task == rt_current) { dequeue_blocked(task); rem_timed_task(task); *msg = task->msg; rt_current->msg_queue.task = task; if (task->state & RT_SCHED_SEND) { task->msg_queue.task = task; if (task->state != RT_SCHED_READY && (task->state &= ~(RT_SCHED_SEND | RT_SCHED_DELAYED)) == RT_SCHED_READY) { enq_ready_task(task); RT_SCHEDULE(task, cpuid); } } else if (task->state & RT_SCHED_RPC) { enqueue_blocked(task, &rt_current->ret_queue, 0); task->state = (task->state & ~(RT_SCHED_RPC | RT_SCHED_DELAYED)) | RT_SCHED_RETURN; } } else { rt_current->ret_queue.task = SOMETHING; if ((rt_current->resume_time = time) > rt_time_h) { rt_current->state |= (RT_SCHED_RECEIVE | RT_SCHED_DELAYED); rem_ready_current(rt_current); rt_current->msg_queue.task = task != rt_current ? task : (RT_TASK *)0; enq_timed_task(rt_current); rt_schedule(); *msg = rt_current->msg; } } if (rt_current->ret_queue.task) { rt_current->ret_queue.task = NOTHING; task = (RT_TASK *)0; } else { task = rt_current->msg_queue.task; } rt_current->msg_queue.task = rt_current; rt_global_restore_flags(flags); if (task && (struct proxy_t *)task->stack_bottom) { if (((struct proxy_t *)task->stack_bottom)->receiver == rt_current) { rt_return(task, 0); } } return task;}/** * @ingroup msg * @anchor rt_receive_timed * @brief Receive a message with a relative timeout. * * rt_receive_timed receives a message from the task specified by * task. If task is equal to 0, the caller accepts messages from any * task. * If there is a pending message, rt_receive does not block but * but can be preempted if the * task that rt_sent the just received message has a * higher priority. The task will not block if it receives rpced messages * since rpcing tasks always waits for a returned message. Moreover it * inheredits the highest priority of any rpcing task waiting on the receive * queue. The receiving task will then recover its priority as explained in * rt_return. Otherwise the caller task is blocked waiting for any * message to be sent/rpced. * In this case these functions return if: * a sender sends a message and has a lower priority; * any rpced message is received; * - timeout occurs; * - an error occurs (e.g. the sender task is killed.) * * @param task is a pointer to the task structure. * * @param msg points to a buffer provided by the caller. * * @param delay is a timeout relative to the current time. * * @return On success, a pointer to the sender task is returned. * On other failure, a special value is returned. The errors * are described below: * - @b 0: there was no message to receive. * - @b 0xFFFF: @e task does not refer to a valid task. * * @note Since all the messaging functions return a task address * 0xFFFF could seem an inappropriate return value. However on all * the CPUs RTAI runs on 0xFFFF is not an address that can be used by * any RTAI task, so it is should be always safe. * * See also: @ref rt_receive_until(). */RT_TASK *rt_receive_timed(RT_TASK *task, unsigned int *msg, RTIME delay){ return rt_receive_until(task, msg, get_time() + delay);}/* ++++++++++++++++++++++++++ EXTENDED MESSAGES +++++++++++++++++++++++++++++++COPYRIGHT (C) 2003 Pierre Cloutier (pcloutier@poseidoncontrols.com) Paolo Mantegazza (mantegazza@aero.polimi.it)+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */#define SET_RPC_MCB() \ do { \ mcb.sbuf = smsg; \ mcb.sbytes = ssize; \ mcb.rbuf = rmsg; \ mcb.rbytes = rsize; \ } while (0)/** * @ingroup rpcx * @anchor rt_rpcx * @brief Make an extended remote procedure call
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -