📄 msg.c
字号:
(!task->msg_queue.task || task->msg_queue.task == rt_current)) { rt_current->msg = task->msg = to_do; task->msg_queue.task = rt_current; task->ret_queue.task = NOTHING; rem_timed_task(task); if (task->state != RT_SCHED_READY && (task->state &= ~(RT_SCHED_RECEIVE | RT_SCHED_DELAYED)) == RT_SCHED_READY) { enq_ready_task(task); } enqueue_blocked(rt_current, &task->ret_queue, 0); rt_current->state |= RT_SCHED_RETURN; } else { rt_current->msg = to_do; enqueue_blocked(rt_current, &task->msg_queue, 0); rt_current->state |= RT_SCHED_RPC; } task->owndres += RPCINC; pass_prio(task, rt_current); rem_ready_current(rt_current); rt_current->msg_queue.task = task; RT_SCHEDULE_BOTH(task, cpuid); if (rt_current->msg_queue.task == rt_current) { *result = rt_current->msg; } else { rt_current->msg_queue.task = rt_current; task = (RT_TASK *)0; } rt_global_restore_flags(flags); return task;}/** * @ingroup rpc * @anchor rt_rpc_if * @brief Make a remote procedure call, only if the calling task will * not be blocked. * * rt_rpc_if tries to make a Remote Procedure Call (RPC). If the * receiver task is ready to accept a message rt_rpc_if sends the * message @e msg then it always block until a return is received. In * this case the caller task is blocked and queued up * in priority order while the receiver * inheredits the blocked sender priority if it is higher (lower in value) * than its. * If the receiver is not ready * rt_rpc_if returns immediately. The receiver task may get the * message with any rt_receive function. It can send the answer with * @ref rt_return(). * * @param task pointer to a RT_TASK structure. * * @param msg message to send. * * @param reply points to a buffer provided by the caller. * * @return On success, task (the pointer to the task that received the * message) is returned. If message has not been sent, 0 is * returned. On other failure, a special value is returned as * described below: * - @b 0: The task @e task was not ready to receive the message or * it was killed before sending the reply. * - @b 0xFFFF: @e task does not refer to a valid task. * * See also: notes under @ref rt_rpc(). * * @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 safe always. */RT_TASK *rt_rpc_if(RT_TASK *task, unsigned int to_do, unsigned int *result){ DECLARE_RT_CURRENT; unsigned long flags; if (task->magic != RT_TASK_MAGIC) { return MSG_ERR; } flags = rt_global_save_flags_and_cli(); ASSIGN_RT_CURRENT; if ((task->state & RT_SCHED_RECEIVE) && (!task->msg_queue.task || task->msg_queue.task == rt_current)) { rt_current->msg = task->msg = to_do; task->msg_queue.task = rt_current; task->ret_queue.task = NOTHING; rem_timed_task(task); if (task->state != RT_SCHED_READY && (task->state &= ~(RT_SCHED_RECEIVE | RT_SCHED_DELAYED)) == RT_SCHED_READY) { enq_ready_task(task); } enqueue_blocked(rt_current, &task->ret_queue, 0); rt_current->state |= RT_SCHED_RETURN; task->owndres += RPCINC; pass_prio(task, rt_current); rem_ready_current(rt_current); rt_current->msg_queue.task = task; RT_SCHEDULE_BOTH(task, cpuid); if (rt_current->msg_queue.task == rt_current) { *result = rt_current->msg; } else { rt_current->msg_queue.task = rt_current; task = (RT_TASK *)0; } } else { task = (RT_TASK *)0; } rt_global_restore_flags(flags); return task;}/** * @ingroup rpc * @anchor rt_rpc_until * @brief Make a remote procedure call with an absolute timeout. * * rt_rpc_until makes a Remote Procedure Call. It sends the message @e * msg to the task @e task then always waits until a return is * received or a timeout occurs. So the caller task is always blocked * and queued up in priority order while the receiver * inheredits the blocked sender priority if it is higher (lower in value) * than its. * The receiver task may get the message with any @ref * rt_receive() function. It can send the answer with @ref rt_return(). * * @param task pointer to a RT_TASK structure. * * @param msg message to send. * * @param reply points to a buffer provided by the caller. * * @param time is an absolute timeout value. * * @return On success, task (the pointer to the task that received the * message) is returned. If message has not been sent or no answer * arrived, 0 is returned. * On other failure, a special value is returned as described below: * - @b 0: The message could not be sent or the answer did not arrived * in time. * - @b 0xFFFF: @e task does not refer to a valid task. * * See also: @ref rt_receive(), @ref rt_return(), @ref rt_isrpc(). * * @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.<br> * See also the notes under @ref rt_rpc(). */RT_TASK *rt_rpc_until(RT_TASK *task, unsigned int to_do, unsigned int *result, RTIME time){ DECLARE_RT_CURRENT; unsigned long flags; if (task->magic != RT_TASK_MAGIC) { return MSG_ERR; } flags = rt_global_save_flags_and_cli(); ASSIGN_RT_CURRENT; if ((task->state & RT_SCHED_RECEIVE) && (!task->msg_queue.task || task->msg_queue.task == rt_current)) { rt_current->msg = task->msg = to_do; task->msg_queue.task = rt_current; task->ret_queue.task = NOTHING; rem_timed_task(task); if (task->state != RT_SCHED_READY && (task->state &= ~(RT_SCHED_RECEIVE | RT_SCHED_DELAYED)) == RT_SCHED_READY) { enq_ready_task(task); } enqueue_blocked(rt_current, &task->ret_queue, 0); rt_current->state |= (RT_SCHED_RETURN | RT_SCHED_DELAYED); } else { if ((rt_current->resume_time = time) <= rt_time_h) { rt_global_restore_flags(flags); return (RT_TASK *)0; } rt_current->msg = to_do; enqueue_blocked(rt_current, &task->msg_queue, 0); rt_current->state |= (RT_SCHED_RPC | RT_SCHED_DELAYED); } task->owndres += RPCINC; pass_prio(task, rt_current); rem_ready_current(rt_current); rt_current->msg_queue.task = task; enq_timed_task(rt_current); RT_SCHEDULE_BOTH(task, cpuid); if (rt_current->msg_queue.task == rt_current) { *result = rt_current->msg; } else { dequeue_blocked(rt_current); rt_current->msg_queue.task = rt_current; task = (RT_TASK *)0; } rt_global_restore_flags(flags); return task;}/** * @ingroup rpc * @anchor rt_rpc_timed * @brief Make a remote procedure call with a relative timeout. * * rt_rpc_timed makes a Remote Procedure Call. It sends the message @e * msg to the task @e task then always waits until a return is * received or a timeout occurs. So the caller task is always blocked * and queued up in priority order while the receiver * inheredits the blocked sender priority if it is higher (lower in value) * than its. * The receiver task may get the message with any @ref * rt_receive() function. It can send the answer with @ref rt_return(). * * @param task pointer to a RT_TASK structure. * * @param msg message to send. * * @param reply points to a buffer provided by the caller. * * @param delay is a timeout relative to the current time. * * @return On success, task (the pointer to the task that received the * message) is returned. If message has not been sent or no answer * arrived, 0 is returned. * On other failure, a special value is returned as described below: * - @b 0: The message could not be sent or the answer did not arrived * in time. * - @b 0xFFFF: @e task does not refer to a valid task. * * See also: @ref rt_receive(), @ref rt_return(), @ref rt_isrpc(). * * @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.<br> * See also the notes under @ref rt_rpc(). */RT_TASK *rt_rpc_timed(RT_TASK *task, unsigned int to_do, unsigned int *result, RTIME delay){ return rt_rpc_until(task, to_do, result, get_time() + delay);}/* ++++++++++++++++++++++++++++++ RPC_RETURN +++++++++++++++++++++++++++++++ *//** * @ingroup rpc * @anchor rt_isrpc * @brief Check if sender waits for reply or not. * * After receiving a message, by calling rt_isrpc a task can figure * out whether the sender task @e task is waiting for a reply or * not. Such an inquiry may be needed when a server task * must provide services to both rt_sends (FIXME) and rt_rtcs. * No answer is required if the message is sent by an @e rt_send function * or the sender called @ref rt_rpc_timed() or @ref rt_rpc_until() but it * is already timed out. * * @param task pointer to a task structure. * * @return If the task waits for a return reply, a nonzero value is returned. * Otherwise 0 is returned. * * @note rt_isrpc does not perform any check on pointer task. rt_isrpc * cannot figure out what RPC result the sender is waiting for.<br> * @ref rt_return() is intelligent enough to not send an answer to a * task which is not waiting for it. Therefore using rt_isrpc might not * be necessary. */int rt_isrpc(RT_TASK *task){ return task->state & RT_SCHED_RETURN;}/** * @ingroup rpc * @anchor rt_return * @brief Return (sends) the result back to the task that made the * related remote procedure call. * * rt_return sends the result @e result to the task @e task. If the task * calling rt_rpc is not waiting the answer (i.e. killed or * timed out) this return message is silently discarded. The returning task * tries to release any previously inheredited priority inherediting the * highest priority of any rpcing task still waiting for * a return, but only if does not own a resource semaphore. In the latter * case it will keep the eighest inheredited priority till it has released * the resource ownership and no further message is waiting for a return. * That means that in the case priority inheritance is coming only * from rpced messages the task will return to its base priority when no * further message is queued for a return. Such a scheme automatically * sets a dynamic priority ceiling in the case priorities are * inheredited both from intertask messaging and resource semaphores * ownership. * * @return On success, task (the pointer to the task that is got the * reply) is returned. If the reply message has not been sent, 0 is * returned. On other failure, a special value is returned as * described below: * - @b 0: The reply message was not delivered. * - @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: notes under @ref rt_rpc(). */RT_TASK *rt_return(RT_TASK *task, unsigned int result){ DECLARE_RT_CURRENT; unsigned long flags; if (task->magic != RT_TASK_MAGIC) { return MSG_ERR; } flags = rt_global_save_flags_and_cli(); ASSIGN_RT_CURRENT; if ((task->state & RT_SCHED_RETURN) && task->msg_queue.task == rt_current) { int sched; dequeue_blocked(task); if (rt_current->owndres & RPCHLF) { rt_current->owndres -= RPCINC; } if (!rt_current->owndres) { sched = renq_current(rt_current, rt_current->base_priority); } else if (!(rt_current->owndres & SEMHLF)) { int priority; sched = renq_current(rt_current, rt_current->base_priority > (priority = ((rt_current->msg_queue.next)->task)->priority) ? priority : rt_current->base_priority); } else { sched = 0; } task->msg = result; task->msg_queue.task = task; rem_timed_task(task); if (task->state != RT_SCHED_READY && (task->state &= ~(RT_SCHED_RETURN | RT_SCHED_DELAYED)) == RT_SCHED_READY) { enq_ready_task(task); if (sched) { RT_SCHEDULE_BOTH(task, cpuid); } else { RT_SCHEDULE(task, cpuid); } } else if (sched) { rt_schedule(); } } else { task = (RT_TASK *)0; } rt_global_restore_flags(flags); return task;}/* ++++++++++++++++++++++++++++++ RECEIVES +++++++++++++++++++++++++++++++++ *//** * @ingroup msg * @anchor rt_evdrp * @brief Eavedrop (spy) the content of a message. * * rt_evdrp spies the content of a message from the task specified by @e task * while leaving it on the queue. To actually receive the message any of the * rt_receive function must be used specifically. If task * is equal to 0, the caller eavdrops the first message of its receive queue,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -