00001 /** 00002 * @file 00003 * Message handling functions. 00004 * @author Paolo Mantegazza 00005 * 00006 * @note Copyright (C) 1999-2003 Paolo Mantegazza 00007 * <mantegazza@aero.polimi.it> [ Specific COPYRIGHTS follow along the 00008 * code ] 00009 * 00010 * This program is free software; you can redistribute it and/or 00011 * modify it under the terms of the GNU General Public License as 00012 * published by the Free Software Foundation; either version 2 of the 00013 * License, or (at your option) any later version. 00014 * 00015 * This program is distributed in the hope that it will be useful, 00016 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00018 * GNU General Public License for more details. 00019 * 00020 * You should have received a copy of the GNU General Public License 00021 * along with this program; if not, write to the Free Software 00022 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00023 * 00024 * @ingroup msg 00025 * @ingroup rpc 00026 */ 00027 00028 /** 00029 * @ingroup sched 00030 * @defgroup msg Message handling functions 00031 */ 00032 00033 /** 00034 * @ingroup sched 00035 * @defgroup rpc Remote procedure call functions 00036 */ 00037 00038 #include <linux/kernel.h> 00039 #include <linux/module.h> 00040 #include <linux/errno.h> 00041 #include <linux/version.h> 00042 00043 #include <rtai_schedcore.h> 00044 #include <rtai_prinher.h> 00045 00046 MODULE_LICENSE("GPL"); 00047 00048 /* +++++++++++++++++++++++ SHORT INTERTASK MESSAGES +++++++++++++++++++++++++ */ 00049 00050 #define TASK_INVAL ((RT_TASK *)RTE_OBJINV) 00051 00052 #define msg_not_sent() \ 00053 do { \ 00054 void *retp; \ 00055 if ((retp = rt_current->blocked_on) != RTP_OBJREM) { \ 00056 set_task_prio_from_resq(task); \ 00057 dequeue_blocked(rt_current); \ 00058 task = (void *)(long)(CONFIG_RTAI_USE_NEWERR ? ((likely(retp > RTP_HIGERR) ? RTE_TIMOUT : RTE_UNBLKD)) : 0); \ 00059 } else { \ 00060 rt_current->prio_passed_to = NULL; \ 00061 task = (void *)(long)(CONFIG_RTAI_USE_NEWERR ? RTE_OBJREM : 0); \ 00062 } \ 00063 rt_current->msg_queue.task = rt_current; \ 00064 } while (0) 00065 00066 #define msg_not_received() \ 00067 do { \ 00068 rt_current->ret_queue.task = NULL; \ 00069 task = (void *)(long)(CONFIG_RTAI_USE_NEWERR ? (((void *)rt_current->blocked_on != RTP_UNBLKD) ? RTE_TIMOUT : RTE_UNBLKD) : 0); \ 00070 } while (0) 00071 00072 /* ++++++++++++++++++++++++++ TASK POINTERS CHECKS +++++++++++++++++++++++++ */ 00073 00074 #define CHECK_SENDER_MAGIC(task) \ 00075 do { if (task->magic != RT_TASK_MAGIC) return TASK_INVAL; } while (0) 00076 00077 #define CHECK_RECEIVER_MAGIC(task) \ 00078 do { if (task && task->magic != RT_TASK_MAGIC) return TASK_INVAL; } while (0) 00079 00080 /* +++++++++++++++++++++++++++++ ASYNC SENDS ++++++++++++++++++++++++++++++++ */ 00081 00082 /** 00083 * @ingroup msg 00084 * @anchor rt_send 00085 * @brief Send a message. 00086 * 00087 * rt_send sends the message @e msg to the task @e task. If the 00088 * receiver task is ready to get the message rt_send does not block 00089 * the sending task, but its execution can be preempted if the 00090 * receiving task has a higher priority. Otherwise the caller task is 00091 * blocked and queued up in priority order on the receive list of the sent 00092 * task. 00093 * 00094 * @param task is a pointer to a task structure. 00095 * 00096 * @param msg corresponds to the message that has to be sent. 00097 * 00098 * @return On success, the pointer to the task that received the message is 00099 * returned.<br> 00100 * 0 is returned if the caller is unblocked but the message has not 00101 * been sent, e.g. the task @e task was killed before receiving the 00102 * message.<br> 00103 * A special value is returned as described below in case of 00104 * a failure: 00105 * - @b 0xFFFF: @e task does not refer to a valid task. 00106 * 00107 * @note Since all the messaging functions return a task address 00108 * 0xFFFF could seem an inappropriate return value. However on all the 00109 * CPUs RTAI runs on 0xFFFF is not an address that can be used by any 00110 * RTAI task, so it is should be safe always. 00111 */ 00112 RTAI_SYSCALL_MODE RT_TASK *rt_send(RT_TASK *task, unsigned long msg) 00113 { 00114 DECLARE_RT_CURRENT; 00115 unsigned long flags; 00116 00117 CHECK_SENDER_MAGIC(task); 00118 00119 flags = rt_global_save_flags_and_cli(); 00120 ASSIGN_RT_CURRENT; 00121 if ((task->state & RT_SCHED_RECEIVE) && 00122 (!task->msg_queue.task || task->msg_queue.task == rt_current)) { 00123 task->msg = msg; 00124 task->msg_queue.task = rt_current; 00125 task->ret_queue.task = NULL; 00126 rem_timed_task(task); 00127 if (task->state != RT_SCHED_READY && (task->state &= ~(RT_SCHED_RECEIVE | RT_SCHED_DELAYED)) == RT_SCHED_READY) { 00128 enq_ready_task(task); 00129 RT_SCHEDULE(task, cpuid); 00130 } 00131 } else { 00132 rt_current->msg = msg; 00133 rt_current->msg_queue.task = task; 00134 enqueue_blocked(rt_current, &task->msg_queue, 0); 00135 rt_current->state |= RT_SCHED_SEND; 00136 enqueue_resqtsk(task); 00137 pass_prio(task, rt_current); 00138 rem_ready_current(rt_current); 00139 rt_schedule(); 00140 } 00141 if (rt_current->msg_queue.task != rt_current) { 00142 msg_not_sent(); 00143 } 00144 rt_global_restore_flags(flags); 00145 return task; 00146 } 00147 00148 00149 /** 00150 * @ingroup msg 00151 * @anchor rt_send_if 00152 * @brief Send a message, only if the calling task will not be blocked. 00153 * 00154 * rt_send_if sends the message @e msg to the task @e task if the 00155 * latter is ready to receive, so that the caller task is never 00156 * blocked, but its execution can be preempted if the receiving task is 00157 * ready to receive and has a higher priority. 00158 * 00159 * @param task is a pointer to a task structure. 00160 * 00161 * @param msg corresponds to the message that has to be sent. 00162 * 00163 * @return the pointer to the task @e task that received the message 00164 * is returned upon success.<br> 00165 * @e 0 is returned if the message has not been sent.<br> 00166 * A special value @e 0xFFFF is returned upon failure.<br><br> 00167 * The errors are described below: 00168 * - @b 0: the task @e task was not ready to receive the message. 00169 * - @b 0xFFFF: @e task does not refer to a valid task. 00170 * 00171 * @note Since all the messaging functions return a task address, 00172 * 0xFFFF could seem an inappropriate return value. However on all the 00173 * CPUs RTAI runs on 0xFFFF is not an address that can be used by any 00174 * RTAI task, so it is should be safe always. (FIXME) 00175 */ 00176 RTAI_SYSCALL_MODE RT_TASK *rt_send_if(RT_TASK *task, unsigned long msg) 00177 { 00178 DECLARE_RT_CURRENT; 00179 unsigned long flags; 00180 00181 CHECK_SENDER_MAGIC(task); 00182 00183 flags = rt_global_save_flags_and_cli(); 00184 ASSIGN_RT_CURRENT; 00185 if ((task->state & RT_SCHED_RECEIVE) && 00186 (!task->msg_queue.task || task->msg_queue.task == rt_current)) { 00187 task->msg = msg; 00188 task->msg_queue.task = rt_current; 00189 task->ret_queue.task = NULL; 00190 rem_timed_task(task); 00191 if (task->state != RT_SCHED_READY && (task->state &= ~(RT_SCHED_RECEIVE | RT_SCHED_DELAYED)) == RT_SCHED_READY) { 00192 enq_ready_task(task); 00193 RT_SCHEDULE(task, cpuid); 00194 } 00195 if (rt_current->msg_queue.task != rt_current) { 00196 rt_current->msg_queue.task = rt_current; 00197 task = NULL; 00198 } 00199 } else { 00200 task = NULL; 00201 } 00202 rt_global_restore_flags(flags); 00203 return task; 00204 } 00205 00206 00207 /** 00208 * @ingroup msg 00209 * @anchor rt_send_until 00210 * brief Send a message with an absolute timeout. 00211 * 00212 * rt_send_until sends the message @e msg to the task @e task. If the 00213 * receiver task is ready to get the message, this function does not 00214 * block the sending task, but its execution can be preempted if the 00215 * receiving task has a higher priority. Otherwise the caller task is 00216 * blocked and queued up in priority order on the receive list of the sent 00217 * task. 00218 * In this case the function returns if: 00219 * - the caller task is in the first place of the waiting queue and 00220 * the receiver gets the message and has a lower priority; 00221 * - a timeout occurs; 00222 * - an error occurs (e.g. the receiver task is killed). 00223 * 00224 * @param task is a pointer to a task structure. 00225 * 00226 * @param msg corresponds to the message that has to be sent. 00227 * 00228 * @param time is the absolute timeout value. 00229 * 00230 * @return the pointer to the task that received the message is 00231 * returned on success i.e. the message received before timeout 00232 * expiration.<br> 00233 * 0 is returned if the message has not been sent. 00234 * A special value is returned on other failure. The errors 00235 * are described below: 00236 * - @b 0: operation timed out, message was not delivered; 00237 * - @b 0xFFFF: @e task does not refer to a valid task. 00238 * 00239 * See also: @ref rt_send_timed(). 00240 * 00241 * @note Since all the messaging functions return a task address 00242 * 0xFFFF could seem an inappropriate return value. However on all 00243 * the CPUs RTAI runs on 0xFFFF is not an address that can be used by 00244 * any RTAI task, so it is should be safe always. 00245 */ 00246 RTAI_SYSCALL_MODE RT_TASK *rt_send_until(RT_TASK *task, unsigned long msg, RTIME time) 00247 { 00248 DECLARE_RT_CURRENT; 00249 unsigned long flags; 00250 00251 CHECK_SENDER_MAGIC(task); 00252 00253 flags = rt_global_save_flags_and_cli(); 00254 ASSIGN_RT_CURRENT; 00255 if ((task->state & RT_SCHED_RECEIVE) && 00256 (!task->msg_queue.task || task->msg_queue.task == rt_current)) { 00257 task->msg = msg; 00258 task->msg_queue.task = rt_current; 00259 task->ret_queue.task = NULL; 00260 rem_timed_task(task); 00261 if (task->state != RT_SCHED_READY && (task->state &= ~(RT_SCHED_RECEIVE | RT_SCHED_DELAYED)) == RT_SCHED_READY) { 00262 enq_ready_task(task); 00263 RT_SCHEDULE(task, cpuid); 00264 } 00265 } else { 00266 rt_current->msg_queue.task = task; 00267 if ((rt_current->resume_time = time) > rt_time_h) { 00268 rt_current->msg = msg; 00269 enqueue_blocked(rt_current, &task->msg_queue, 0); 00270 rt_current->state |= (RT_SCHED_SEND | RT_SCHED_DELAYED); 00271 enqueue_resqtsk(task); 00272 pass_prio(task, rt_current); 00273 rem_ready_current(rt_current); 00274 enq_timed_task(rt_current); 00275 rt_schedule(); 00276 } else { 00277 rt_current->queue.prev = rt_current->queue.next = &rt_current->queue; 00278 } 00279 } 00280 if (rt_current->msg_queue.task != rt_current) { 00281 msg_not_sent(); 00282 } 00283 rt_global_restore_flags(flags); 00284 return task; 00285 } 00286 00287 00288 /** 00289 * @ingroup msg 00290 * @anchor rt_send_timed 00291 * brief Send a message with a relative timeout. 00292 * 00293 * rt_send_timed sends the message @e msg to the task @e task. If the 00294 * receiver task is ready to get the message, this function does not 00295 * block the sending task, but its execution can be preempted if the 00296 * receiving task has a higher priority. Otherwise the caller task is 00297 * blocked and queued up in priority order on the receive list of the sent 00298 * task. 00299 * In this case the function returns if: 00300 * - the caller task is in the first place of the waiting queue and 00301 * the receiver gets the message and has a lower priority; 00302 * - a timeout occurs; 00303 * - an error occurs (e.g. the receiver task is killed). 00304 * 00305 * @param task is a pointer to a task structure. 00306 * 00307 * @param msg corresponds to the message that has to be sent. 00308 * 00309 * @param delay is the timeout relative to the current time. 00310 * 00311 * @return on success, the pointer to the task that received the 00312 * message i.e. the message received before timeout expiration.<br> 00313 * 0 if the message has not been sent.<br> 00314 * A special value on other failure. The errors 00315 * are described below: 00316 * - @b 0: operation timed out, message was not delivered; 00317 * - @b 0xFFFF: @e task does not refer to a valid task. 00318 * 00319 * See also: @ref rt_send_until(). 00320 * 00321 * @note Since all the messaging functions return a task address 00322 * 0xFFFF could seem an inappropriate return value. However on all 00323 * the CPUs RTAI runs on 0xFFFF is not an address that can be used by 00324 * any RTAI task, so it is should be safe always. (FIXME) 00325 */ 00326 00327 RTAI_SYSCALL_MODE RT_TASK *rt_send_timed(RT_TASK *task, unsigned long msg, RTIME delay) 00328 { 00329 return rt_send_until(task, msg, get_time() + delay); 00330 } 00331 00332 /* ++++++++++++++++++++++++++++++++ RPCS +++++++++++++++++++++++++++++++++++ */ 00333 00334 /** 00335 * @ingroup rpc 00336 * @anchor rt_rpc 00337 * @brief Make a remote procedure call 00338 * 00339 * rt_rpc makes a Remote Procedure Call (RPC). rt_rpc is used for 00340 * synchronous inter task messaging as it sends the message @e msg to the 00341 * task @e task and blocks waiting until a return is 00342 * received from the called task. So the caller task is always blocked 00343 * and queued up in priority order while the receiver 00344 * inheredits the blocked sender priority if it is higher (lower in value) 00345 * than its. 00346 * The receiver task may get the message with any 00347 * rt_receive function. It can send an answer with @ref rt_return(). 00348 * 00349 * @param task pointer to a RT_TASK structure. 00350 * 00351 * @param msg message to send. 00352 * 00353 * @param reply points to a buffer provided by the caller were the 00354 * returned result message, any 4 bytes integer, is to be place. 00355 * 00356 * @return On success, task (the pointer to the task that received the 00357 * message) is returned. If the message has not been sent (e.g. the 00358 * task @e task was killed before receiving the message) 0 is returned. 00359 * On other failure, a special value is returned as described below: 00360 * - @b 0: the receiver task was killed before receiving the message. 00361 * - @b 0xFFFF: @e task does not refer to a valid task. 00362 * 00363 * See also: rt_receive_*, @ref rt_return(), @ref rt_isrpc(). 00364 * 00365 * @note Since all the messaging functions return a task address, 00366 * 0xFFFF could seem an inappropriate return value. However on 00367 * all the CPUs RTAI runs on, 0xFFFF is not an address that can 00368 * be used by any RTAI task, so it is should be always safe.<br> 00369 * The trio @ref rt_rpc(), @ref rt_receive(), @ref rt_return() 00370 * implement functions similar to its peers send-receive-replay 00371 * found in QNX, except that in RTAI only four bytes messages 00372 * contained in any integer can be exchanged. That's so because 00373 * it is more efficient and often enough. If you need to pass 00374 * arbitrarely long messages see the extended intertask messaging 00375 * functions. Moreover note also that we prefer 00376 * the idea of calling a function by using a message and then 00377 * wait for a return value since it is believed to give a better 00378 * idea of what is meant for synchronous message passing. For 00379 * a more truly QNX like way of inter task messaging use the support 00380 * of the upper cased functions: rt_Send-rt_Recieve-rt_Reply. 00381 */ 00382 RTAI_SYSCALL_MODE RT_TASK *rt_rpc(RT_TASK *task, unsigned long to_do, void *result) 00383 { 00384 00385 DECLARE_RT_CURRENT; 00386 unsigned long flags; 00387 00388 CHECK_SENDER_MAGIC(task); 00389 00390 flags = rt_global_save_flags_and_cli(); 00391 ASSIGN_RT_CURRENT; 00392 if ((task->state & RT_SCHED_RECEIVE) && 00393 (!task->msg_queue.task || task->msg_queue.task == rt_current)) { 00394 rt_current->msg = task->msg = to_do; 00395 task->msg_queue.task = rt_current; 00396 task->ret_queue.task = NULL; 00397 rem_timed_task(task); 00398 if (task->state != RT_SCHED_READY && (task->state &= ~(RT_SCHED_RECEIVE | RT_SCHED_DELAYED)) == RT_SCHED_READY) { 00399 enq_ready_task(task); 00400 } 00401 enqueue_blocked(rt_current, &task->ret_queue, 0); 00402 rt_current->state |= RT_SCHED_RETURN; 00403 } else { 00404 rt_current->msg = to_do; 00405 enqueue_blocked(rt_current, &task->msg_queue, 0); 00406 rt_current->state |= RT_SCHED_RPC; 00407 } 00408 enqueue_resqtsk(task); 00409 pass_prio(task, rt_current); 00410 rem_ready_current(rt_current); 00411 rt_current->msg_queue.task = task; 00412 RT_SCHEDULE_BOTH(task, cpuid); 00413 if (rt_current->msg_queue.task == rt_current) { 00414 *(unsigned long *)result = rt_current->msg; 00415 } else { 00416 msg_not_sent(); 00417 } 00418 rt_global_restore_flags(flags); 00419 return task; 00420 } 00421 00422 00423 /** 00424 * @ingroup rpc 00425 * @anchor rt_rpc_if 00426 * @brief Make a remote procedure call, only if the calling task will 00427 * not be blocked. 00428 * 00429 * rt_rpc_if tries to make a Remote Procedure Call (RPC). If the 00430 * receiver task is ready to accept a message rt_rpc_if sends the 00431 * message @e msg then it always block until a return is received. In 00432 * this case the caller task is blocked and queued up 00433 * in priority order while the receiver 00434 * inheredits the blocked sender priority if it is higher (lower in value) 00435 * than its. 00436 * If the receiver is not ready 00437 * rt_rpc_if returns immediately. The receiver task may get the 00438 * message with any rt_receive function. It can send the answer with 00439 * @ref rt_return(). 00440 * 00441 * @param task pointer to a RT_TASK structure. 00442 * 00443 * @param msg message to send. 00444 * 00445 * @param reply points to a buffer provided by the caller. 00446 * 00447 * @return On success, task (the pointer to the task that received the 00448 * message) is returned. If message has not been sent, 0 is 00449 * returned. On other failure, a special value is returned as 00450 * described below: 00451 * - @b 0: The task @e task was not ready to receive the message or 00452 * it was killed before sending the reply. 00453 * - @b 0xFFFF: @e task does not refer to a valid task. 00454 * 00455 * See also: notes under @ref rt_rpc(). 00456 * 00457 * @note Since all the messaging functions return a task address, 00458 * 0xFFFF could seem an inappropriate return value. However on 00459 * all the CPUs RTAI runs on, 0xFFFF is not an address that can 00460 * be used by any RTAI task, so it is should be safe always. 00461 */ 00462 RTAI_SYSCALL_MODE RT_TASK *rt_rpc_if(RT_TASK *task, unsigned long to_do, void *result) 00463 { 00464 DECLARE_RT_CURRENT; 00465 unsigned long flags; 00466 00467 CHECK_SENDER_MAGIC(task); 00468 00469 flags = rt_global_save_flags_and_cli(); 00470 ASSIGN_RT_CURRENT; 00471 if ((task->state & RT_SCHED_RECEIVE) && 00472 (!task->msg_queue.task || task->msg_queue.task == rt_current)) { 00473 rt_current->msg = task->msg = to_do; 00474 task->msg_queue.task = rt_current; 00475 task->ret_queue.task = NULL; 00476 rem_timed_task(task); 00477 if (task->state != RT_SCHED_READY && (task->state &= ~(RT_SCHED_RECEIVE | RT_SCHED_DELAYED)) == RT_SCHED_READY) { 00478 enq_ready_task(task); 00479 } 00480 enqueue_blocked(rt_current, &task->ret_queue, 0); 00481 rt_current->state |= RT_SCHED_RETURN; 00482 enqueue_resqtsk(task); 00483 pass_prio(task, rt_current); 00484 rem_ready_current(rt_current); 00485 rt_current->msg_queue.task = task; 00486 RT_SCHEDULE_BOTH(task, cpuid); 00487 if (rt_current->msg_queue.task == rt_current) { 00488 *(unsigned long *)result = rt_current->msg; 00489 } else { 00490 msg_not_sent(); 00491 } 00492 } else { 00493 task = NULL; 00494 } 00495 rt_global_restore_flags(flags); 00496 return task; 00497 } 00498 00499 00500 /** 00501 * @ingroup rpc 00502 * @anchor rt_rpc_until 00503 * @brief Make a remote procedure call with an absolute timeout. 00504 * 00505 * rt_rpc_until makes a Remote Procedure Call. It sends the message @e 00506 * msg to the task @e task then always waits until a return is 00507 * received or a timeout occurs. So the caller task is always blocked 00508 * and queued up in priority order while the receiver 00509 * inheredits the blocked sender priority if it is higher (lower in value) 00510 * than its. 00511 * The receiver task may get the message with any @ref 00512 * rt_receive() function. It can send the answer with @ref rt_return(). 00513 * 00514 * @param task pointer to a RT_TASK structure. 00515 * 00516 * @param msg message to send. 00517 * 00518 * @param reply points to a buffer provided by the caller. 00519 * 00520 * @param time is an absolute timeout value. 00521 * 00522 * @return On success, task (the pointer to the task that received the 00523 * message) is returned. If message has not been sent or no answer 00524 * arrived, 0 is returned. 00525 * On other failure, a special value is returned as described below: 00526 * - @b 0: The message could not be sent or the answer did not arrived 00527 * in time. 00528 * - @b 0xFFFF: @e task does not refer to a valid task. 00529 * 00530 * See also: @ref rt_receive(), @ref rt_return(), @ref rt_isrpc(). 00531 * 00532 * @note Since all the messaging functions return a task address, 0xFFFF 00533 * could seem an inappropriate return value. However on all the CPUs 00534 * RTAI runs on, 0xFFFF is not an address that can be used by any RTAI 00535 * task, so it is should be always safe.<br> 00536 * See also the notes under @ref rt_rpc(). 00537 */ 00538 RTAI_SYSCALL_MODE RT_TASK *rt_rpc_until(RT_TASK *task, unsigned long to_do, void *result, RTIME time) 00539 { 00540 DECLARE_RT_CURRENT; 00541 unsigned long flags; 00542 00543 CHECK_SENDER_MAGIC(task); 00544 00545 flags = rt_global_save_flags_and_cli(); 00546 ASSIGN_RT_CURRENT; 00547 if ((rt_current->resume_time = time) <= rt_time_h) { 00548 rt_global_restore_flags(flags); 00549 return (RT_TASK *)0; 00550 } 00551 if ((task->state & RT_SCHED_RECEIVE) && 00552 (!task->msg_queue.task || task->msg_queue.task == rt_current)) { 00553 rt_current->msg = task->msg = to_do; 00554 task->msg_queue.task = rt_current; 00555 task->ret_queue.task = NULL; 00556 rem_timed_task(task); 00557 if (task->state != RT_SCHED_READY && (task->state &= ~(RT_SCHED_RECEIVE | RT_SCHED_DELAYED)) == RT_SCHED_READY) { 00558 enq_ready_task(task); 00559 } 00560 enqueue_blocked(rt_current, &task->ret_queue, 0); 00561 rt_current->state |= (RT_SCHED_RETURN | RT_SCHED_DELAYED); 00562 } else { 00563 rt_current->msg = to_do; 00564 enqueue_blocked(rt_current, &task->msg_queue, 0); 00565 rt_current->state |= (RT_SCHED_RPC | RT_SCHED_DELAYED); 00566 } 00567 enqueue_resqtsk(task); 00568 pass_prio(task, rt_current); 00569 rem_ready_current(rt_current); 00570 rt_current->msg_queue.task = task; 00571 enq_timed_task(rt_current); 00572 RT_SCHEDULE_BOTH(task, cpuid); 00573 if (rt_current->msg_queue.task == rt_current) { 00574 *(unsigned long *)result = rt_current->msg; 00575 } else { 00576 msg_not_sent(); 00577 } 00578 rt_global_restore_flags(flags); 00579 return task; 00580 } 00581 00582 00583 /** 00584 * @ingroup rpc 00585 * @anchor rt_rpc_timed 00586 * @brief Make a remote procedure call with a relative timeout. 00587 * 00588 * rt_rpc_timed makes a Remote Procedure Call. It sends the message @e 00589 * msg to the task @e task then always waits until a return is 00590 * received or a timeout occurs. So the caller task is always blocked 00591 * and queued up in priority order while the receiver 00592 * inheredits the blocked sender priority if it is higher (lower in value) 00593 * than its. 00594 * The receiver task may get the message with any @ref 00595 * rt_receive() function. It can send the answer with @ref rt_return(). 00596 * 00597 * @param task pointer to a RT_TASK structure. 00598 * 00599 * @param msg message to send. 00600 * 00601 * @param reply points to a buffer provided by the caller. 00602 * 00603 * @param delay is a timeout relative to the current time. 00604 * 00605 * @return On success, task (the pointer to the task that received the 00606 * message) is returned. If message has not been sent or no answer 00607 * arrived, 0 is returned. 00608 * On other failure, a special value is returned as described below: 00609 * - @b 0: The message could not be sent or the answer did not arrived 00610 * in time. 00611 * - @b 0xFFFF: @e task does not refer to a valid task. 00612 * 00613 * See also: @ref rt_receive(), @ref rt_return(), @ref rt_isrpc(). 00614 * 00615 * @note Since all the messaging functions return a task address, 0xFFFF 00616 * could seem an inappropriate return value. However on all the CPUs 00617 * RTAI runs on, 0xFFFF is not an address that can be used by any RTAI 00618 * task, so it is should be always safe.<br> 00619 * See also the notes under @ref rt_rpc(). 00620 */ 00621 RTAI_SYSCALL_MODE RT_TASK *rt_rpc_timed(RT_TASK *task, unsigned long to_do, void *result, RTIME delay) 00622 { 00623 return rt_rpc_until(task, to_do, result, get_time() + delay); 00624 } 00625 00626 /* ++++++++++++++++++++++++++++++ RPC_RETURN +++++++++++++++++++++++++++++++ */ 00627 00628 /** 00629 * @ingroup rpc 00630 * @anchor rt_isrpc 00631 * @brief Check if sender waits for reply or not. 00632 * 00633 * After receiving a message, by calling rt_isrpc a task can figure 00634 * out whether the sender task @e task is waiting for a reply or 00635 * not. Such an inquiry may be needed when a server task 00636 * must provide services to both rt_sends (FIXME) and rt_rtcs. 00637 * No answer is required if the message is sent by an @e rt_send function 00638 * or the sender called @ref rt_rpc_timed() or @ref rt_rpc_until() but it 00639 * is already timed out. 00640 * 00641 * @param task pointer to a task structure. 00642 * 00643 * @return If the task waits for a return reply, a nonzero value is returned. 00644 * Otherwise 0 is returned. 00645 * 00646 * @note rt_isrpc does not perform any check on pointer task. rt_isrpc 00647 * cannot figure out what RPC result the sender is waiting for.<br> 00648 * @ref rt_return() is intelligent enough to not send an answer to a 00649 * task which is not waiting for it. Therefore using rt_isrpc might not 00650 * be necessary. 00651 */ 00652 RTAI_SYSCALL_MODE int rt_isrpc(RT_TASK *task) 00653 { 00654 return task->state & RT_SCHED_RETURN; 00655 } 00656 00657 00658 /** 00659 * @ingroup rpc 00660 * @anchor rt_return 00661 * @brief Return (sends) the result back to the task that made the 00662 * related remote procedure call. 00663 * 00664 * rt_return sends the result @e result to the task @e task. If the task 00665 * calling rt_rpc is not waiting the answer (i.e. killed or 00666 * timed out) this return message is silently discarded. The returning task 00667 * tries to release any previously inheredited priority inherediting the 00668 * highest priority of any rpcing task still waiting for 00669 * a return, but only if does not own a resource semaphore. In the latter 00670 * case it will keep the eighest inheredited priority till it has released 00671 * the resource ownership and no further message is waiting for a return. 00672 * That means that in the case priority inheritance is coming only 00673 * from rpced messages the task will return to its base priority when no 00674 * further message is queued for a return. Such a scheme automatically 00675 * sets a dynamic priority ceiling in the case priorities are 00676 * inheredited both from intertask messaging and resource semaphores 00677 * ownership. 00678 * 00679 * @return On success, task (the pointer to the task that is got the 00680 * reply) is returned. If the reply message has not been sent, 0 is 00681 * returned. On other failure, a special value is returned as 00682 * described below: 00683 * - @b 0: The reply message was not delivered. 00684 * - @b 0xFFFF: @e task does not refer to a valid task. 00685 * 00686 * @note Since all the messaging functions return a task address, 00687 * 0xFFFF could seem an inappropriate return value. However on all the 00688 * CPUs RTAI runs on, 0xFFFF is not an address that can be used by any 00689 * RTAI task, so it is should be always safe. 00690 * 00691 * See also: notes under @ref rt_rpc(). 00692 */ 00693 RTAI_SYSCALL_MODE RT_TASK *rt_return(RT_TASK *task, unsigned long result) 00694 { 00695 DECLARE_RT_CURRENT; 00696 unsigned long flags; 00697 00698 CHECK_SENDER_MAGIC(task); 00699 00700 flags = rt_global_save_flags_and_cli(); 00701 ASSIGN_RT_CURRENT; 00702 if ((task->state & RT_SCHED_RETURN) && task->msg_queue.task == rt_current) { 00703 int sched; 00704 dequeue_blocked(task); 00705 sched = set_current_prio_from_resq(rt_current); 00706 task->msg = result; 00707 task->msg_queue.task = task; 00708 rem_timed_task(task); 00709 if (task->state != RT_SCHED_READY && (task->state &= ~(RT_SCHED_RETURN | RT_SCHED_DELAYED)) == RT_SCHED_READY) { 00710 enq_ready_task(task); 00711 if (sched) { 00712 RT_SCHEDULE_BOTH(task, cpuid); 00713 } else { 00714 RT_SCHEDULE(task, cpuid); 00715 } 00716 } else if (sched) { 00717 rt_schedule(); 00718 } 00719 } else { 00720 task = NULL; 00721 } 00722 rt_global_restore_flags(flags); 00723 return task; 00724 } 00725 00726 /* ++++++++++++++++++++++++++++++ RECEIVES +++++++++++++++++++++++++++++++++ */ 00727 00728 /** 00729 * @ingroup msg 00730 * @anchor rt_evdrp 00731 * @brief Eavedrop (spy) the content of a message. 00732 * 00733 * rt_evdrp spies the content of a message from the task specified by @e task 00734 * while leaving it on the queue. To actually receive the message any of the 00735 * rt_receive function must be used specifically. If task 00736 * is equal to 0, the caller eavdrops the first message of its receive queue, 00737 * if any. rt_evdrp never blocks. 00738 * 00739 * @param task is a pointer to a @e RT_TASK structure. 00740 * 00741 * @param msg points to any 4 bytes word buffer provided by the 00742 * caller. 00743 * 00744 * @return a pointer to the sender task is returned upon success.<br> 00745 * 0 is returned if no message is available. 00746 * A special value is returned on other failure. The errors 00747 * are described below: 00748 * - @b 0: the sender task was killed before sending the message; 00749 * - @b 0xFFFF: @e task does not refer to a valid task. 00750 * 00751 * @note Since all the messaging functions return a task address 00752 * 0xFFFF could seem an inappropriate return value. However on all 00753 * the CPUs RTAI runs on 0xFFFF is not an address that can be used by 00754 * any RTAI task, so it is should be always safe. 00755 */ 00756 RTAI_SYSCALL_MODE RT_TASK *rt_evdrp(RT_TASK *task, void *msg) 00757 { 00758 DECLARE_RT_CURRENT; 00759 00760 CHECK_RECEIVER_MAGIC(task); 00761 00762 ASSIGN_RT_CURRENT; 00763 if (!task) task = (rt_current->msg_queue.next)->task; 00764 if ((task->state & (RT_SCHED_SEND | RT_SCHED_RPC)) && task->msg_queue.task == rt_current) { 00765 *(unsigned long *)msg = task->msg; 00766 } else { 00767 task = NULL; 00768 } 00769 return task; 00770 } 00771 00772 00773 /** 00774 * @ingroup msg 00775 * @anchor rt_receive 00776 * @brief Receive a message. 00777 * 00778 * rt_receive gets a message from the task specified by task. If task 00779 * is equal to 0, the caller accepts messages from any task. If there 00780 * is a pending message, rt_receive does not block but can be 00781 * preempted if the task that rt_sent the just received message has a 00782 * higher priority. The task will not block if it receives rpced messages 00783 * since rpcing tasks always waits for a returned message. Moreover it 00784 * inheredits the highest priority of any rpcing task waiting on the receive 00785 * queue. The receiving task will then recover its priority as explained in 00786 * rt_return. Otherwise the caller task is blocked waiting for any 00787 * message to be sent/rpced. 00788 * 00789 * @param task is a pointer to a @e RT_TASK structure. 00790 * 00791 * @param msg points to any 4 bytes word buffer provided by the 00792 * caller. 00793 * 00794 * @return a pointer to the sender task is returned upon success.<br> 00795 * 0 is returned if the caller is unblocked but no message has 00796 * been received (e.g. the task @e task was killed before sending the 00797 * message.)<br> 00798 * A special value is returned on other failure. The errors 00799 * are described below: 00800 * - @b 0: the sender task was killed before sending the message; 00801 * - @b 0xFFFF: @e task does not refer to a valid task. 00802 * 00803 * @note Since all the messaging functions return a task address 00804 * 0xFFFF could seem an inappropriate return value. However on all 00805 * the CPUs RTAI runs on 0xFFFF is not an address that can be used by 00806 * any RTAI task, so it is should be always safe. 00807 */ 00808 RTAI_SYSCALL_MODE RT_TASK *rt_receive(RT_TASK *task, void *msg) 00809 { 00810 DECLARE_RT_CURRENT; 00811 unsigned long flags; 00812 00813 CHECK_RECEIVER_MAGIC(task); 00814 00815 flags = rt_global_save_flags_and_cli(); 00816 ASSIGN_RT_CURRENT; 00817 if (!task) task = (rt_current->msg_queue.next)->task; 00818 if ((task->state & (RT_SCHED_SEND | RT_SCHED_RPC)) && task->msg_queue.task == rt_current) { 00819 dequeue_blocked(task); 00820 rem_timed_task(task); 00821 *(unsigned long *)msg = task->msg; 00822 rt_current->msg_queue.task = task; 00823 if (task->state & RT_SCHED_SEND) { 00824 int sched; 00825 task->msg_queue.task = task; 00826 sched = set_current_prio_from_resq(rt_current); 00827 if (task->state != RT_SCHED_READY && (task->state &= ~(RT_SCHED_SEND | RT_SCHED_DELAYED)) == RT_SCHED_READY) { 00828 enq_ready_task(task); 00829 if (sched) { 00830 RT_SCHEDULE_BOTH(task, cpuid); 00831 } else { 00832 RT_SCHEDULE(task, cpuid); 00833 } 00834 } 00835 } else if (task->state & RT_SCHED_RPC) { 00836 enqueue_blocked(task, &rt_current->ret_queue, 0); 00837 task->state = (task->state & ~(RT_SCHED_RPC | RT_SCHED_DELAYED)) | RT_SCHED_RETURN; 00838 } 00839 } else { 00840 rt_current->ret_queue.task = RTP_HIGERR; 00841 rt_current->state |= RT_SCHED_RECEIVE; 00842 rem_ready_current(rt_current); 00843 rt_current->msg_queue.task = task != rt_current ? task : (RT_TASK *)0; 00844 rt_schedule(); 00845 *(unsigned long *)msg = rt_current->msg; 00846 } 00847 if (rt_current->ret_queue.task) { 00848 msg_not_received(); 00849 } else { 00850 task = rt_current->msg_queue.task; 00851 } 00852 rt_current->msg_queue.task = rt_current; 00853 rt_global_restore_flags(flags); 00854 if ((unsigned long)task > RTE_HIGERR && (struct proxy_t *)task->stack_bottom) { 00855 if (((struct proxy_t *)task->stack_bottom)->receiver == rt_current) { 00856 rt_return(task, 0); 00857 } 00858 } 00859 return task; 00860 } 00861 00862 00863 /** 00864 * @ingroup msg 00865 * @anchor rt_receive_if 00866 * @brief Receive a message, only if the calling task is not blocked. 00867 * 00868 * rt_receive_if tries to get a message from the task specified by 00869 * task. If task is equal to 0, the caller accepts messages from any 00870 * task. The caller task is never blocked but can be preempted if the 00871 * task that rt_sent the just received message has a 00872 * higher priority. The task will not block if it receives rpced messages 00873 * since rpcing tasks always waits for a returned message. Moreover it 00874 * inheredits the highest priority of any rpcing task waiting on the receive 00875 * queue. The receiving task will then recover its priority as explained in 00876 * rt_return. Otherwise the caller task is blocked waiting for any 00877 * message to be sent/rpced. 00878 * 00879 * @param task is a pointer to the task structure. 00880 * 00881 * @param msg points to a buffer provided by the caller. 00882 * 00883 * @return a pointer to the sender task is returned upon success.<br> 00884 * A special value is returned on other failure. The errors are 00885 * described below: 00886 * - @b 0: there was no message to receive; 00887 * - @b 0xFFFF: @e task does not refer to a valid task. 00888 * 00889 * Since all the messaging functions return a task address 0xFFFF 00890 * could seem an inappropriate return value. However on all the CPUs 00891 * RTAI runs on 0xFFFF is not an address that can be used by any RTAI 00892 * task, so it is should be always safe. 00893 */ 00894 RTAI_SYSCALL_MODE RT_TASK *rt_receive_if(RT_TASK *task, void *msg) 00895 { 00896 DECLARE_RT_CURRENT; 00897 unsigned long flags; 00898 00899 CHECK_RECEIVER_MAGIC(task); 00900 00901 flags = rt_global_save_flags_and_cli(); 00902 ASSIGN_RT_CURRENT; 00903 if (!task) task = (rt_current->msg_queue.next)->task; 00904 if ((task->state & (RT_SCHED_SEND | RT_SCHED_RPC)) && task->msg_queue.task == rt_current) { 00905 dequeue_blocked(task); 00906 rem_timed_task(task); 00907 *(unsigned long *)msg = task->msg; 00908 rt_current->msg_queue.task = task; 00909 if (task->state & RT_SCHED_SEND) { 00910 int sched; 00911 task->msg_queue.task = task; 00912 sched = set_current_prio_from_resq(rt_current); 00913 if (task->state != RT_SCHED_READY && (task->state &= ~(RT_SCHED_SEND | RT_SCHED_DELAYED)) == RT_SCHED_READY) { 00914 enq_ready_task(task); 00915 if (sched) { 00916 RT_SCHEDULE_BOTH(task, cpuid); 00917 } else { 00918 RT_SCHEDULE(task, cpuid); 00919 } 00920 } 00921 } else if (task->state & RT_SCHED_RPC) { 00922 enqueue_blocked(task, &rt_current->ret_queue, 0); 00923 task->state = (task->state & ~(RT_SCHED_RPC | RT_SCHED_DELAYED)) | RT_SCHED_RETURN; 00924 } 00925 if (rt_current->ret_queue.task) { 00926 rt_current->ret_queue.task = NULL; 00927 task = NULL; 00928 } else { 00929 task = rt_current->msg_queue.task; 00930 } 00931 rt_current->msg_queue.task = rt_current; 00932 } else { 00933 task = NULL; 00934 } 00935 rt_global_restore_flags(flags); 00936 if ((unsigned long)task > RTE_HIGERR && (struct proxy_t *)task->stack_bottom) { 00937 if (((struct proxy_t *)task->stack_bottom)->receiver == rt_current) { 00938 rt_return(task, 0); 00939 } 00940 } 00941 return task; 00942 } 00943 00944 00945 /** 00946 * @ingroup msg 00947 * @anchor rt_receive_until 00948 * @brief Receive a message with an absolute timeout. 00949 * 00950 * rt_receive_until receives a message from the task specified by 00951 * task. If task is equal to 0, the caller accepts messages from any 00952 * task. If there is a pending message, rt_receive does not block but 00953 * but can be preempted if the 00954 * task that rt_sent the just received message has a 00955 * higher priority. The task will not block if it receives rpced messages 00956 * since rpcing tasks always waits for a returned message. Moreover it 00957 * inheredits the highest priority of any rpcing task waiting on the receive 00958 * queue. The receiving task will then recover its priority as explained in 00959 * rt_return. Otherwise the caller task is blocked waiting for any 00960 * message to be sent/rpced. 00961 * In this case these functions return if: 00962 * a sender sends a message and has a lower priority; 00963 * any rpced message is received; 00964 * - timeout occurs; 00965 * - an error occurs (e.g. the sender task is killed.) 00966 * 00967 * @param task is a pointer to the task structure. 00968 * 00969 * @param msg points to a buffer provided by the caller. 00970 * 00971 * @param time is an absolute timout value. 00972 * 00973 * @return On success, a pointer to the sender task is returned. 00974 * On other failure, a special value is returned. The errors 00975 * are described below: 00976 * - @b 0: there was no message to receive. 00977 * - @b 0xFFFF: @e task does not refer to a valid task. 00978 * 00979 * @note Since all the messaging functions return a task address 00980 * 0xFFFF could seem an inappropriate return value. However on all 00981 * the CPUs RTAI runs on 0xFFFF is not an address that can be used by 00982 * any RTAI task, so it is should be always safe. 00983 * 00984 * See also: @ref rt_receive_timed(). 00985 */ 00986 RTAI_SYSCALL_MODE RT_TASK *rt_receive_until(RT_TASK *task, void *msg, RTIME time) 00987 { 00988 DECLARE_RT_CURRENT; 00989 unsigned long flags; 00990 00991 CHECK_RECEIVER_MAGIC(task); 00992 00993 flags = rt_global_save_flags_and_cli(); 00994 ASSIGN_RT_CURRENT; 00995 if (!task) task = (rt_current->msg_queue.next)->task; 00996 if ((task->state & (RT_SCHED_SEND | RT_SCHED_RPC)) && task->msg_queue.task == rt_current) { 00997 dequeue_blocked(task); 00998 rem_timed_task(task); 00999 *(unsigned long *)msg = task->msg; 01000 rt_current->msg_queue.task = task; 01001 if (task->state & RT_SCHED_SEND) { 01002 int sched; 01003 task->msg_queue.task = task; 01004 sched = set_current_prio_from_resq(rt_current); 01005 if (task->state != RT_SCHED_READY && (task->state &= ~(RT_SCHED_SEND | RT_SCHED_DELAYED)) == RT_SCHED_READY) { 01006 enq_ready_task(task); 01007 if (sched) { 01008 RT_SCHEDULE_BOTH(task, cpuid); 01009 } else { 01010 RT_SCHEDULE(task, cpuid); 01011 } 01012 } 01013 } else if (task->state & RT_SCHED_RPC) { 01014 enqueue_blocked(task, &rt_current->ret_queue, 0); 01015 task->state = (task->state & ~(RT_SCHED_RPC | RT_SCHED_DELAYED)) | RT_SCHED_RETURN; 01016 } 01017 } else { 01018 rt_current->ret_queue.task = RTP_HIGERR; 01019 if ((rt_current->resume_time = time) > rt_time_h) { 01020 rt_current->state |= (RT_SCHED_RECEIVE | RT_SCHED_DELAYED); 01021 rem_ready_current(rt_current); 01022 rt_current->msg_queue.task = task != rt_current ? task : (RT_TASK *)0; 01023 enq_timed_task(rt_current); 01024 rt_schedule(); 01025 *(unsigned long *)msg = rt_current->msg; 01026 } 01027 } 01028 if (rt_current->ret_queue.task) { 01029 msg_not_received(); 01030 } else { 01031 task = rt_current->msg_queue.task; 01032 } 01033 rt_current->msg_queue.task = rt_current; 01034 rt_global_restore_flags(flags); 01035 if ((unsigned long)task > RTE_HIGERR && (struct proxy_t *)task->stack_bottom) { 01036 if (((struct proxy_t *)task->stack_bottom)->receiver == rt_current) { 01037 rt_return(task, 0); 01038 } 01039 } 01040 return task; 01041 } 01042 01043 01044 /** 01045 * @ingroup msg 01046 * @anchor rt_receive_timed 01047 * @brief Receive a message with a relative timeout. 01048 * 01049 * rt_receive_timed receives a message from the task specified by 01050 * task. If task is equal to 0, the caller accepts messages from any 01051 * task. 01052 * If there is a pending message, rt_receive does not block but 01053 * but can be preempted if the 01054 * task that rt_sent the just received message has a 01055 * higher priority. The task will not block if it receives rpced messages 01056 * since rpcing tasks always waits for a returned message. Moreover it 01057 * inheredits the highest priority of any rpcing task waiting on the receive 01058 * queue. The receiving task will then recover its priority as explained in 01059 * rt_return. Otherwise the caller task is blocked waiting for any 01060 * message to be sent/rpced. 01061 * In this case these functions return if: 01062 * a sender sends a message and has a lower priority; 01063 * any rpced message is received; 01064 * - timeout occurs; 01065 * - an error occurs (e.g. the sender task is killed.) 01066 * 01067 * @param task is a pointer to the task structure. 01068 * 01069 * @param msg points to a buffer provided by the caller. 01070 * 01071 * @param delay is a timeout relative to the current time. 01072 * 01073 * @return On success, a pointer to the sender task is returned. 01074 * On other failure, a special value is returned. The errors 01075 * are described below: 01076 * - @b 0: there was no message to receive. 01077 * - @b 0xFFFF: @e task does not refer to a valid task. 01078 * 01079 * @note Since all the messaging functions return a task address 01080 * 0xFFFF could seem an inappropriate return value. However on all 01081 * the CPUs RTAI runs on 0xFFFF is not an address that can be used by 01082 * any RTAI task, so it is should be always safe. 01083 * 01084 * See also: @ref rt_receive_until(). 01085 */ 01086 RTAI_SYSCALL_MODE RT_TASK *rt_receive_timed(RT_TASK *task, void *msg, RTIME delay) 01087 { 01088 return rt_receive_until(task, msg, get_time() + delay); 01089 } 01090 01091 /* ++++++++++++++++++++++++++ EXTENDED MESSAGES +++++++++++++++++++++++++++++++ 01092 COPYRIGHT (C) 2003 Pierre Cloutier (pcloutier@poseidoncontrols.com) 01093 Paolo Mantegazza (mantegazza@aero.polimi.it) 01094 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ 01095 01096 #define SET_RPC_MCB() \ 01097 do { \ 01098 mcb.sbuf = smsg; \ 01099 mcb.sbytes = ssize; \ 01100 mcb.rbuf = rmsg; \ 01101 mcb.rbytes = rsize; \ 01102 } while (0) 01103 01104 /** 01105 * @ingroup rpc 01106 * @anchor rt_rpcx 01107 * @brief Make an extended remote procedure call 01108 * 01109 * rt_rpcx makes an extended Remote Procedure Call (RPC). rt_rpcx is used for 01110 * synchronous inter task messaging. It sends an arbitrary @e smsg of size 01111 * @e ssize bytes to the task @e task then it always blocks waiting until a 01112 * message, of size @e rsize bytes at most, is returned in @e rmsg from the 01113 * called task. If the returned message is greater tha rsize it will be 01114 * truncated. So the caller task is always blocked on the receiver priority 01115 * queue while the receiver inheredits the blocked sender priority if it is 01116 * higher (lower in value) than its. The receiver task may get the message 01117 * with any rt_receivex function. It can send an answer with @ref rt_returnx(). 01118 * 01119 * @param task pointer to the RT_TASK structure of the receiver. 01120 * 01121 * @param smsg points to the message to be sent. 01122 * 01123 * @param rmsg points to the message to be returned by the receiver. 01124 * 01125 * @param ssize size of the message to be sent. 01126 * 01127 * @param rsize maximum allowed size for the message to be received. 01128 * 01129 * @return On success, task (the pointer to the task that received the 01130 * message) is returned. If the message has not been sent (e.g. the 01131 * task @e task was killed before receiving the message) 0 is returned. 01132 * 01133 * See also: rt_receivex_*, @ref rt_returnx(), @ref rt_isrpc(). 01134 * 01135 * @note The trio @ref rt_rpcx(), @ref rt_receivex(), @ref rt_returnx() 01136 * implements functions similar to its peers send-receive-reply 01137 * found in QNX. For a even greater compatibility see 01138 * rt_Send-rt_Receive-rt_Reply. 01139 */ 01140 RTAI_SYSCALL_MODE RT_TASK *rt_rpcx(RT_TASK *task, void *smsg, void *rmsg, int ssize, int rsize) 01141 { 01142 if (task) { 01143 struct mcb_t mcb; 01144 SET_RPC_MCB(); 01145 return rt_rpc(task, (unsigned long)&mcb, &mcb.rbytes); 01146 } 01147 return 0; 01148 } 01149 01150 01151 /** 01152 * @ingroup rpc 01153 * @anchor rt_rpcx_if 01154 * @brief Make an extended remote procedure call, only if the calling task 01155 * will not be blocked. 01156 * 01157 * rt_rpcx_if tries to make an extended Remote Procedure Call (RPC). If the 01158 * receiver task is ready to accept a message rt_rpcx_if sends the 01159 * message as it will be done by rt_rpcx. 01160 * If the receiver is not ready rt_rpcx_if returns immediately. The receiver 01161 * task may get the message with any rt_receivex function. It can send the 01162 * answer with * @ref rt_returnx(). 01163 * 01164 * @param task pointer to the RT_TASK structure of the receiver. 01165 * 01166 * @param smsg points to the message to be sent. 01167 * 01168 * @param rmsg points to the message to be returned by the receiver. 01169 * 01170 * @param ssize size of the message to be sent. 01171 * 01172 * @param rsize maximum allowed size for the message to be received. 01173 * 01174 * @return On success, task (the pointer to the task that received the 01175 * message) is returned. If message has not been sent, 0 is 01176 * returned. On other failure, a special value is returned as 01177 * described below: 01178 * - @b 0: The task @e task was not ready to receive the message or 01179 * it was killed before sending the reply. 01180 * - @b 0xFFFF: @e task does not refer to a valid task. 01181 * 01182 * See also: notes under @ref rt_rpc(). 01183 * 01184 * @note Since all the messaging functions return a task address, 01185 * 0xFFFF could seem an inappropriate return value. However on 01186 * all the CPUs RTAI runs on, 0xFFFF is not an address that can 01187 * be used by any RTAI task, so it is should be always safe. 01188 */ 01189 RTAI_SYSCALL_MODE RT_TASK *rt_rpcx_if(RT_TASK *task, void *smsg, void *rmsg, int ssize, int rsize) 01190 { 01191 if (task) { 01192 struct mcb_t mcb; 01193 SET_RPC_MCB(); 01194 return rt_rpc_if(task, (unsigned long)&mcb, &mcb.rbytes); 01195 } 01196 return 0; 01197 } 01198 01199 01200 /** 01201 * @ingroup rpc 01202 * @anchor rt_rpcx_until 01203 * @brief Make an extended remote procedure call with absolute timeout. 01204 * 01205 * rt_rpcx_until makes an extended Remote Procedure Call (RPC). 01206 * It sends an arbitrary @e smsg of size @e ssize bytes to the task @e task 01207 * then it always blocks waiting until a message, of size @e rsize bytes at 01208 * most, is returned in @e rmsg from the called task or a timeout occurs. 01209 * If the returned message is greater tha rsize it will be truncated. 01210 * So the caller task is always blocked on the receiver priority queue while 01211 * the receiver inheredits the blocked sender priority if it is higher 01212 * (lower in value) than its. The receiver task may get the message with any 01213 * rt_receivex function. It can send an answer with @ref rt_returnx(). 01214 * 01215 * @param task pointer to the RT_TASK structure of the receiver. 01216 * 01217 * @param smsg points to the message to be sent. 01218 * 01219 * @param rmsg points to the message to be returned by the receiver. 01220 * 01221 * @param ssize size of the message to be sent. 01222 * 01223 * @param rsize maximum allowed size for the message to be received. 01224 * 01225 * @param time is an absolute timeout value. 01226 * 01227 * @return On success, task (the pointer to the task that received the 01228 * message) is returned. If message has not been sent or no answer 01229 * arrived, 0 is returned. 01230 * On other failure, a special value is returned as described below: 01231 * - @b 0: The message could not be sent or the answer did not arrived 01232 * in time. 01233 * - @b 0xFFFF: @e task does not refer to a valid task. 01234 * 01235 * See also: @ref rt_receive(), @ref rt_return(), @ref rt_isrpc(). 01236 * 01237 * @note Since all the messaging functions return a task address, 0xFFFF 01238 * could seem an inappropriate return value. However on all the CPUs 01239 * RTAI runs on, 0xFFFF is not an address that can be used by any RTAI 01240 * task, so it is should be always safe.<br> 01241 * See also the notes under @ref rt_rpc(). 01242 */ 01243 RTAI_SYSCALL_MODE RT_TASK *rt_rpcx_until(RT_TASK *task, void *smsg, void *rmsg, int ssize, int rsize, RTIME time) 01244 { 01245 if (task) { 01246 struct mcb_t mcb; 01247 SET_RPC_MCB(); 01248 return rt_rpc_until(task, (unsigned long)&mcb, &mcb.rbytes, time); 01249 } 01250 return 0; 01251 } 01252 01253 01254 /** 01255 * @ingroup rpc 01256 * @anchor rt_rpcx_timed 01257 * @brief Make an extended remote procedure call with a relative timeout. 01258 * 01259 * rt_rpcx_timed makes an extended Remote Procedure Call (RPC). 01260 * It sends an arbitrary @e smsg of size @e ssize bytes to the task @e task 01261 * then it always blocks waiting until a message, of size @e rsize bytes at 01262 * most, is returned in @e rmsg from the called task or a timeout occurs. 01263 * If the returned message is greater tha rsize it will be truncated. 01264 * So the caller task is always blocked on the receiver priority queue while 01265 * the receiver inheredits the blocked sender priority if it is higher 01266 * (lower in value) than its. The receiver task may get the message with any 01267 * rt_receivex function. It can send an answer with @ref rt_returnx(). 01268 * 01269 * @param task pointer to the RT_TASK structure of the receiver. 01270 * 01271 * @param smsg points to the message to be sent. 01272 * 01273 * @param rmsg points to the message to be returned by the receiver. 01274 * 01275 * @param ssize size of the message to be sent. 01276 * 01277 * @param rsize maximum allowed size for the message to be received. 01278 * 01279 * @param delay is the relative timeout. 01280 * 01281 * @return On success, task (the pointer to the task that received the 01282 * message) is returned. If message has not been sent or no answer 01283 * arrived, 0 is returned. 01284 * On other failure, a special value is returned as described below: 01285 * - @b 0: The message could not be sent or the answer did not arrived 01286 * in time. 01287 * - @b 0xFFFF: @e task does not refer to a valid task. 01288 * 01289 * See also: @ref rt_receive(), @ref rt_return(), @ref rt_isrpc(). 01290 * 01291 * @note Since all the messaging functions return a task address, 0xFFFF 01292 * could seem an inappropriate return value. However on all the CPUs 01293 * RTAI runs on, 0xFFFF is not an address that can be used by any RTAI 01294 * task, so it is should be always safe.<br> 01295 * See also the notes under @ref rt_rpc(). 01296 */ 01297 RTAI_SYSCALL_MODE RT_TASK *rt_rpcx_timed(RT_TASK *task, void *smsg, void *rmsg, int ssize, int rsize, RTIME delay) 01298 { 01299 if (task) { 01300 struct mcb_t mcb; 01301 SET_RPC_MCB(); 01302 return rt_rpc_timed(task, (unsigned long)&mcb, &mcb.rbytes, delay); 01303 } 01304 return 0; 01305 } 01306 01307 #define task_mcb (task->mcb) 01308 #define SET_SEND_MCB() \ 01309 do { \ 01310 task_mcb.sbuf = msg; \ 01311 task_mcb.sbytes = size; \ 01312 task_mcb.rbuf = 0; \ 01313 task_mcb.rbytes = 0; \ 01314 } while (0) 01315 01316 /** 01317 * @ingroup msg 01318 * @anchor rt_sendx 01319 * @brief Send an extended message. 01320 * 01321 * rt_sendx sends an arbitrary message @e msg of size @e size bytes to the task 01322 * @e task. If the 01323 * receiver task is ready to get the message rt_sendx does not block 01324 * the sending task, but its execution can be preempted if the 01325 * receiving task has a higher priority. Otherwise the caller task is 01326 * blocked and queued up in priority order on the receive list of the sent 01327 * task. 01328 * 01329 * @param task is a pointer to a task structure. 01330 * 01331 * @param msg points to the message to be sent. 01332 * 01333 * @param size size of the message to be sent. 01334 * 01335 * @return On success, the pointer to the task that received the message is 01336 * returned.<br> 01337 * 0 is returned if the caller is unblocked but the message has not 01338 * been sent, e.g. the task @e task was killed before receiving the 01339 * message.<br> 01340 * A special value is returned as described below in case of 01341 * a failure: 01342 * - @b 0xFFFF: @e task does not refer to a valid task. 01343 * 01344 * @note Since all the messaging functions return a task address 01345 * 0xFFFF could seem an inappropriate return value. However on all the 01346 * CPUs RTAI runs on 0xFFFF is not an address that can be used by any 01347 * RTAI task, so it is should be safe always. 01348 */ 01349 RTAI_SYSCALL_MODE RT_TASK *rt_sendx(RT_TASK *task, void *msg, int size) 01350 { 01351 if (task) { 01352 SET_SEND_MCB(); 01353 return rt_send(task, (unsigned long)&task_mcb); 01354 } 01355 return 0; 01356 } 01357 01358 01359 /** 01360 * @ingroup msg 01361 * @anchor rt_sendx_if 01362 * @brief Send an extended message, only if the calling task will not be 01363 * blocked. 01364 * 01365 * rt_sendx_if sends an arbitrary message @e msg of size @e size bytes to the 01366 * task @e task if the latter is ready to receive. So the caller task in never 01367 * blocked but its execution can be preempted if the 01368 * receiving task has a higher priority. 01369 * 01370 * @param task is a pointer to a task structure. 01371 * 01372 * @param msg points to the message to be sent. 01373 * 01374 * @param size size of the message to be sent. 01375 * 01376 * @return On success, the pointer to the task that received the message is 01377 * returned.<br> 01378 * 0 is returned if the caller is unblocked but the message has not 01379 * been sent, e.g. the task @e task was killed before receiving the 01380 * message.<br> 01381 * A special value is returned as described below in case of 01382 * a failure: 01383 * - @b 0xFFFF: @e task does not refer to a valid task. 01384 * 01385 * @note Since all the messaging functions return a task address 01386 * 0xFFFF could seem an inappropriate return value. However on all the 01387 * CPUs RTAI runs on 0xFFFF is not an address that can be used by any 01388 * RTAI task, so it is should be safe always. 01389 */ 01390 RTAI_SYSCALL_MODE RT_TASK *rt_sendx_if(RT_TASK *task, void *msg, int size) 01391 { 01392 if (task) { 01393 SET_SEND_MCB(); 01394 return rt_send_if(task, (unsigned long)&task_mcb); 01395 } 01396 return 0; 01397 } 01398 01399 01400 /** 01401 * @ingroup msg 01402 * @anchor rt_sendx_until 01403 * @brief Send an extended message with absolute timeout. 01404 * 01405 * rt_sendx_until sends an arbitrary message @e msg of size @e size bytes to 01406 * the task @e task. If the 01407 * receiver task is ready to get the message rt_sendx_until does not block 01408 * the sending task, but its execution can be preempted if the 01409 * receiving task has a higher priority. Otherwise the caller task is 01410 * blocked and queued up in priority order on the receive list of the sent 01411 * task. 01412 * In this case the function returns if: 01413 * - the caller task is in the first place of the waiting queue and 01414 * the receiver gets the message and has a lower priority; 01415 * - a timeout occurs; 01416 * - an error occurs (e.g. the receiver task is killed). 01417 * 01418 * @param task is a pointer to a task structure. 01419 * 01420 * @param msg points to the message to be sent. 01421 * 01422 * @param size size of the message to be sent. 01423 * 01424 * @param time is an absolute timeout value. 01425 * 01426 * @return On success, the pointer to the task that received the message is 01427 * returned.<br> 01428 * 0 is returned if the caller is unblocked but the message has not 01429 * been sent, e.g. the task @e task was killed before receiving the 01430 * message.<br> 01431 * A special value is returned as described below in case of 01432 * a failure: 01433 * - @b 0: operation timed out, message was not delivered; 01434 * - @b 0xFFFF: @e task does not refer to a valid task. 01435 * 01436 * @note Since all the messaging functions return a task address 01437 * 0xFFFF could seem an inappropriate return value. However on all the 01438 * CPUs RTAI runs on 0xFFFF is not an address that can be used by any 01439 * RTAI task, so it is should be safe always. 01440 */ 01441 RTAI_SYSCALL_MODE RT_TASK *rt_sendx_until(RT_TASK *task, void *msg, int size, RTIME time) 01442 { 01443 if (task) { 01444 SET_SEND_MCB(); 01445 return rt_send_until(task, (unsigned long)&task_mcb, time); 01446 } 01447 return 0; 01448 } 01449 01450 01451 /** 01452 * @ingroup msg 01453 * @anchor rt_sendx_timed 01454 * @brief Send an extended message with relative timeout. 01455 * 01456 * rt_sendx_until sends an arbitrary message @e msg of size @e size bytes to 01457 * the task @e task. If the 01458 * receiver task is ready to get the message rt_sendx_until does not block 01459 * the sending task, but its execution can be preempted if the 01460 * receiving task has a higher priority. Otherwise the caller task is 01461 * blocked and queued up in priority order on the receive list of the sent 01462 * task. 01463 * In this case the function returns if: 01464 * - the caller task is in the first place of the waiting queue and 01465 * the receiver gets the message and has a lower priority; 01466 * - a timeout occurs; 01467 * - an error occurs (e.g. the receiver task is killed). 01468 * 01469 * @param task is a pointer to a task structure. 01470 * 01471 * @param msg points to the message to be sent. 01472 * 01473 * @param size size of the message to be sent. 01474 * 01475 * @param delay is r timeout elative to the current time. 01476 * 01477 * @return On success, the pointer to the task that received the message is 01478 * returned.<br> 01479 * 0 is returned if the caller is unblocked but the message has not 01480 * been sent, e.g. the task @e task was killed before receiving the 01481 * message.<br> 01482 * A special value is returned as described below in case of 01483 * a failure: 01484 * - @b 0: operation timed out, message was not delivered; 01485 * - @b 0xFFFF: @e task does not refer to a valid task. 01486 * 01487 * @note Since all the messaging functions return a task address 01488 * 0xFFFF could seem an inappropriate return value. However on all the 01489 * CPUs RTAI runs on 0xFFFF is not an address that can be used by any 01490 * RTAI task, so it is should be safe always. 01491 */ 01492 RTAI_SYSCALL_MODE RT_TASK *rt_sendx_timed(RT_TASK *task, void *msg, int size, RTIME delay) 01493 { 01494 if (task) { 01495 SET_SEND_MCB(); 01496 return rt_send_timed(task, (unsigned long)&task_mcb, delay); 01497 } 01498 return 0; 01499 } 01500 01501 01502 /** 01503 * @ingroup rpc 01504 * @anchor rt_returnx 01505 * @brief Return (sends) an extended result back to the task that made the 01506 * related extended remote procedure call. 01507 * 01508 * rt_returns sends the result @e msg of size @e size to the task @e task. 01509 * If the task calling rt_rpcx is not waiting the answer (i.e. killed or 01510 * timed out) this return message is silently discarded. The returning task 01511 * tries to release any previously inheredited priority inherediting the 01512 * highest priority of any rpcing task still waiting for 01513 * a return, but only if does not own a resource semaphore. In the latter 01514 * case it will keep the eighest inheredited priority till it has released 01515 * the resource ownership and no further message is waiting for a return. 01516 * That means that in the case priority inheritance is coming only 01517 * from rpced messages the task will return to its base priority when no 01518 * further message is queued for a return. Such a scheme automatically 01519 * sets a dynamic priority ceiling in the case priorities are 01520 * inheredited both from intertask messaging and resource semaphores 01521 * ownership. 01522 * 01523 * @return On success, task (the pointer to the task that is got the 01524 * reply) is returned. If the reply message has not been sent, 0 is 01525 * returned. On other failure, a special value is returned as 01526 * described below: 01527 * - @b 0: The reply message was not delivered. 01528 * - @b 0xFFFF: @e task does not refer to a valid task. 01529 * 01530 * @note Since all the messaging functions return a task address, 01531 * 0xFFFF could seem an inappropriate return value. However on all the 01532 * CPUs RTAI runs on, 0xFFFF is not an address that can be used by any 01533 * RTAI task, so it is should be always safe. 01534 * 01535 * See also: notes under @ref rt_rpcx(). 01536 */ 01537 RTAI_SYSCALL_MODE RT_TASK *rt_returnx(RT_TASK *task, void *msg, int size) 01538 { 01539 if (task) { 01540 struct mcb_t *mcb; 01541 if ((mcb = (struct mcb_t *)task->msg)->rbytes < size) { 01542 size = mcb->rbytes; 01543 } 01544 if (size) { 01545 memcpy(mcb->rbuf, msg, size); 01546 } 01547 return rt_return(task, 0); 01548 } 01549 return 0; 01550 } 01551 01552 #define DO_RCV_MSG() \ 01553 do { \ 01554 if ((*len = size <= mcb->sbytes ? size : mcb->sbytes)) { \ 01555 memcpy(msg, mcb->sbuf, *len); \ 01556 } \ 01557 } while (0) 01558 01559 01560 /** 01561 * @ingroup msg 01562 * @anchor rt_evdrpx 01563 * @brief Eavedrop (spy) the content of an extended message. 01564 * 01565 * rt_evdrpx spies the content of a message from the task specified by @e task 01566 * while leaving it on the queue. To actually receive the message any of the 01567 * rt_receivex function must be used specifically. If task 01568 * is equal to 0, the caller eavdrops the first message of its receive queue, 01569 * if any. rt_evdrpix never blocks. 01570 * 01571 * @param task is a pointer to a @e RT_TASK structure. 01572 * 01573 * @param msg points to the message to be eavedropped, without receive. 01574 * 01575 * @param size size of the message to be eavedropped. 01576 * 01577 * @param len is a pointer to an integer to be set to the actual len of the 01578 * eavedropped message. 01579 * 01580 * @return a pointer to the sender task is returned upon success.<br> 01581 * 0 is returned if no message is available. 01582 * A special value is returned on other failure. The errors 01583 * are described below: 01584 * - @b 0: the sender task was killed before sending the message; 01585 * - @b 0xFFFF: @e task does not refer to a valid task. 01586 * 01587 * @note Since all the messaging functions return a task address 01588 * 0xFFFF could seem an inappropriate return value. However on all 01589 * the CPUs RTAI runs on 0xFFFF is not an address that can be used by 01590 * any RTAI task, so it is should be always safe. 01591 */ 01592 RTAI_SYSCALL_MODE RT_TASK *rt_evdrpx(RT_TASK *task, void *msg, int size, long *len) 01593 { 01594 struct mcb_t *mcb; 01595 if ((task = rt_evdrp(task, (unsigned long *)&mcb))) { 01596 DO_RCV_MSG(); 01597 return task; 01598 } 01599 return 0; 01600 } 01601 01602 01603 /** 01604 * @ingroup msg 01605 * @anchor rt_receivex 01606 * @brief Receive an extended message. 01607 * 01608 * rt_receivex gets an extended message @a msg of size @a size from the task 01609 * specified by @e task task. If task 01610 * is equal to 0, the caller accepts messages from any task. If there 01611 * is a pending message, rt_receivex does not block but can be 01612 * preempted if the task that rt_sent the just received message has a 01613 * higher priority. The task will not block if it receives rpcxed messages 01614 * since rpcxing tasks always wait for a returned message. Moreover it 01615 * inheredits the highest priority of any rpcxing task waiting on the receive 01616 * queue. The receiving task will then recover its priority as explained in 01617 * rt_returnx. Otherwise the caller task is blocked waiting for any 01618 * message to be sentx/rpcxed. 01619 * 01620 * @param task is a pointer to a @e RT_TASK structure. 01621 * 01622 * @param msg points to the message to be eavedropped, without receive. 01623 * 01624 * @param size size of the message to be eavedropped. 01625 * 01626 * @param len is a pointer to an integer to be set to the actual len of the 01627 * eavedropped message. 01628 * 01629 * @return a pointer to the sender task is returned upon success.<br> 01630 * 0 is returned if the caller is unblocked but no message has 01631 * been received (e.g. the task @e task was killed before sending the 01632 * message.)<br> 01633 * A special value is returned on other failure. The errors 01634 * are described below: 01635 * - @b 0: the sender task was killed before sending the message; 01636 * - @b 0xFFFF: @e task does not refer to a valid task. 01637 * 01638 * @note Since all the messaging functions return a task address 01639 * 0xFFFF could seem an inappropriate return value. However on all 01640 * the CPUs RTAI runs on 0xFFFF is not an address that can be used by 01641 * any RTAI task, so it is should be always safe. 01642 */ 01643 RTAI_SYSCALL_MODE RT_TASK *rt_receivex(RT_TASK *task, void *msg, int size, long *len) 01644 { 01645 struct mcb_t *mcb; 01646 if ((task = rt_receive(task, (unsigned long *)&mcb))) { 01647 DO_RCV_MSG(); 01648 return task; 01649 } 01650 return 0; 01651 } 01652 01653 01654 /** 01655 * @ingroup msg 01656 * @anchor rt_receivex_if 01657 * @brief Receive an extended message, only if the calling task is not blocked. 01658 * 01659 * rt_receivex gets an extended message @a msg of size @a size from the task 01660 * specified by @e task task. If task 01661 * is equal to 0, the caller accepts messages from any task. The caller task 01662 * is never blocked but can be preempted if the task that rt_sentx the just 01663 * received message has a higher priority. 01664 * The task will not block if it receives rpcxed messages 01665 * since rpcxing tasks always wait for a returned message. Moreover it 01666 * inheredits the highest priority of any rpcxing task waiting on the receive 01667 * queue. The receiving task will then recover its priority as explained in 01668 * rt_returnx. Otherwise the caller task is blocked waiting for any 01669 * message to be sentx/rpcxed. 01670 * 01671 * @param task is a pointer to a @e RT_TASK structure. 01672 * 01673 * @param msg points to the message to be eavedropped, without receive. 01674 * 01675 * @param size size of the message to be eavedropped. 01676 * 01677 * @param len is a pointer to an integer to be set to the actual len of the 01678 * eavedropped message. 01679 * 01680 * @return a pointer to the sender task is returned upon success.<br> 01681 * 0 is returned if the caller is unblocked but no message has 01682 * been received (e.g. the task @e task was killed before sending the 01683 * message.)<br> 01684 * A special value is returned on other failure. The errors 01685 * are described below: 01686 * - @b 0: the sender task was killed before sending the message; 01687 * - @b 0xFFFF: @e task does not refer to a valid task. 01688 * 01689 * @note Since all the messaging functions return a task address 01690 * 0xFFFF could seem an inappropriate return value. However on all 01691 * the CPUs RTAI runs on 0xFFFF is not an address that can be used by 01692 * any RTAI task, so it is should be always safe. 01693 */ 01694 RTAI_SYSCALL_MODE RT_TASK *rt_receivex_if(RT_TASK *task, void *msg, int size, long *len) 01695 { 01696 struct mcb_t *mcb; 01697 if ((task = rt_receive_if(task, (unsigned long *)&mcb))) { 01698 DO_RCV_MSG(); 01699 return task; 01700 } 01701 return 0; 01702 } 01703 01704 01705 /** 01706 * @ingroup msg 01707 * @anchor rt_receivex_until 01708 * @brief Receive an extended message with an absolute timeout. 01709 * 01710 * rt_receivex_until gets an extended message @a msg of size @a size from the 01711 * task specified by @e task task. If task is equal to 0, the caller accepts 01712 * messages from any task. If there is a pending message, rt_receivex does not 01713 * block but can be preempted if the task that rt_sent the just received message 01714 * has a higher priority. The task will not block if it receives rpcxed messages 01715 * since rpcxing tasks always wait for a returned message. Moreover it 01716 * inheredits the highest priority of any rpcxing task waiting on the receive 01717 * queue. The receiving task will then recover its priority as explained in 01718 * rt_returnx. Otherwise the caller task is blocked waiting for any message to 01719 * be sentx/rpcxed. 01720 * 01721 * In this case these functions return if: 01722 * a sender sendxs a message and has a lower priority; 01723 * any rpcxed message is received; 01724 * - timeout occurs; 01725 * - an error occurs (e.g. the sender task is killed.) 01726 * @param task is a pointer to a @e RT_TASK structure. 01727 * 01728 * @param msg points to the message to be eavedropped, without receive. 01729 * 01730 * @param size size of the message to be eavedropped. 01731 * 01732 * @param len is a pointer to an integer to be set to the actual len of the 01733 * eavedropped message. 01734 * 01735 * @param time is an absolute timout value. 01736 * 01737 * @return a pointer to the sender task is returned upon success.<br> 01738 * 0 is returned if the caller is unblocked but no message has 01739 * been received (e.g. the task @e task was killed before sending the 01740 * message.)<br> 01741 * A special value is returned on other failure. The errors 01742 * are described below: 01743 * - @b 0: the sender task was killed before sending the message; 01744 * - @b 0xFFFF: @e task does not refer to a valid task. 01745 * 01746 * @note Since all the messaging functions return a task address 01747 * 0xFFFF could seem an inappropriate return value. However on all 01748 * the CPUs RTAI runs on 0xFFFF is not an address that can be used by 01749 * any RTAI task, so it is should be always safe. 01750 */ 01751 RTAI_SYSCALL_MODE RT_TASK *rt_receivex_until(RT_TASK *task, void *msg, int size, long *len, RTIME time) 01752 { 01753 struct mcb_t *mcb; 01754 if ((task = rt_receive_until(task, (unsigned long *)&mcb, time))) { 01755 DO_RCV_MSG(); 01756 return task; 01757 } 01758 return 0; 01759 } 01760 01761 01762 /** 01763 * @ingroup msg 01764 * @anchor rt_receivex_timed 01765 * @brief Receive an extended message with a relative timeout. 01766 * 01767 * rt_receivex_until gets an extended message @a msg of size @a size from the 01768 * task specified by @e task task. If task is equal to 0, the caller accepts 01769 * messages from any task. If there is a pending message, rt_receivex does not 01770 * block but can be preempted if the task that rt_sent the just received message 01771 * has a higher priority. The task will not block if it receives rpcxed messages 01772 * since rpcxing tasks always wait for a returned message. Moreover it 01773 * inheredits the highest priority of any rpcxing task waiting on the receive 01774 * queue. The receiving task will then recover its priority as explained in 01775 * rt_returnx. Otherwise the caller task is blocked waiting for any message to 01776 * be sentx/rpcxed. 01777 * 01778 * In this case these functions return if: 01779 * a sender sendxs a message and has a lower priority; 01780 * any rpcxed message is received; 01781 * - timeout occurs; 01782 * - an error occurs (e.g. the sender task is killed.) 01783 * @param task is a pointer to a @e RT_TASK structure. 01784 * 01785 * @param msg points to the message to be eavedropped, without receive. 01786 * 01787 * @param size size of the message to be eavedropped. 01788 * 01789 * @param len is a pointer to an integer to be set to the actual len of the 01790 * eavedropped message. 01791 * 01792 * @param delay is a timeout relative to the current time. 01793 * 01794 * @return a pointer to the sender task is returned upon success.<br> 01795 * 0 is returned if the caller is unblocked but no message has 01796 * been received (e.g. the task @e task was killed before sending the 01797 * message.)<br> 01798 * A special value is returned on other failure. The errors 01799 * are described below: 01800 * - @b 0: the sender task was killed before sending the message; 01801 * - @b 0xFFFF: @e task does not refer to a valid task. 01802 * 01803 * @note Since all the messaging functions return a task address 01804 * 0xFFFF could seem an inappropriate return value. However on all 01805 * the CPUs RTAI runs on 0xFFFF is not an address that can be used by 01806 * any RTAI task, so it is should be always safe. 01807 */ 01808 RTAI_SYSCALL_MODE RT_TASK *rt_receivex_timed(RT_TASK *task, void *msg, int size, long *len, RTIME delay) 01809 { 01810 struct mcb_t *mcb; 01811 if ((task = rt_receive_timed(task, (unsigned long *)&mcb, delay))) { 01812 DO_RCV_MSG(); 01813 return task; 01814 } 01815 return 0; 01816 } 01817 01818 /* +++++++++++++++++++++++++++++++ PROXIES ++++++++++++++++++++++++++++++++++ */ 01819 01820 // What any proxy is supposed to do, raw RTAI implementation. 01821 static void proxy_task(RT_TASK *me) 01822 { 01823 struct proxy_t *my; 01824 unsigned long ret; 01825 01826 my = (struct proxy_t *)me->stack_bottom; 01827 while (1) { 01828 while (my->nmsgs) { 01829 atomic_dec((atomic_t *)&my->nmsgs); 01830 rt_rpc(my->receiver, *((unsigned long *)my->msg), &ret); 01831 } 01832 rt_task_suspend(me); 01833 } 01834 } 01835 01836 // Create a raw proxy agent task. 01837 RT_TASK *__rt_proxy_attach(void (*agent)(long), RT_TASK *task, void *msg, int nbytes, int priority) 01838 { 01839 RT_TASK *proxy, *rt_current; 01840 struct proxy_t *my; 01841 01842 rt_current = _rt_whoami(); 01843 if (!task) { 01844 task = rt_current; 01845 } 01846 01847 if (task->magic != RT_TASK_MAGIC) { 01848 return 0; 01849 } 01850 01851 if (!(proxy = rt_malloc(sizeof(RT_TASK)))) { 01852 return 0; 01853 } 01854 01855 if (priority == -1 && (priority = rt_current->base_priority) == RT_SCHED_LINUX_PRIORITY) { 01856 priority = RT_SCHED_LOWEST_PRIORITY; 01857 } 01858 if (rt_kthread_init(proxy, agent, (long)proxy, PROXY_MIN_STACK_SIZE + nbytes + sizeof(struct proxy_t), priority, 0, 0)) { 01859 rt_free(proxy); 01860 return 0; 01861 } 01862 01863 my = (struct proxy_t *)(proxy->stack_bottom); 01864 my->receiver = task ; 01865 my->msg = ((char *)(proxy->stack_bottom)) + sizeof(struct proxy_t); 01866 my->nmsgs = 0; 01867 my->nbytes = nbytes; 01868 if (msg && nbytes) { 01869 memcpy(my->msg, msg, nbytes); 01870 } 01871 01872 // agent is at *(proxy->stack + 2) 01873 return proxy; 01874 } 01875 01876 // Create a raw proxy task. 01877 RTAI_SYSCALL_MODE RT_TASK *rt_proxy_attach(RT_TASK *task, void *msg, int nbytes, int prio) 01878 { 01879 return __rt_proxy_attach((void *)proxy_task, task, msg, nbytes, prio); 01880 } 01881 01882 // Delete a proxy task (a simplified specific rt_task_delete). 01883 // Note: a self delete will not do the rt_free() call. 01884 RTAI_SYSCALL_MODE int rt_proxy_detach(RT_TASK *proxy) 01885 { 01886 if (!rt_task_delete(proxy)) { 01887 rt_free(proxy); 01888 return 0; 01889 } 01890 return -EINVAL; 01891 } 01892 01893 // Trigger a proxy. 01894 RTAI_SYSCALL_MODE RT_TASK *rt_trigger(RT_TASK *proxy) 01895 { 01896 struct proxy_t *his; 01897 01898 his = (struct proxy_t *)(proxy->stack_bottom); 01899 if (his && proxy->magic == RT_TASK_MAGIC) { 01900 atomic_inc((atomic_t *)&his->nmsgs); 01901 rt_task_resume(proxy); 01902 return his->receiver; 01903 } 01904 return (RT_TASK *)0; 01905 } 01906 01907 #if 1 //def CONFIG_RTAI_INTERNAL_LXRT_SUPPORT 01908 01909 /* ++++++++++++ ANOTHER API SET FOR EXTENDED INTERTASK MESSAGES +++++++++++++++ 01910 COPYRIGHT (C) 2003 Pierre Cloutier (pcloutier@poseidoncontrols.com) 01911 Paolo Mantegazza (mantegazza@aero.polimi.it) 01912 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ 01913 01914 #include <asm/uaccess.h> 01915 01916 #include "rtai_registry.h" 01917 #include "rtai_msg.h" 01918 01919 RTAI_SYSCALL_MODE int rt_Send(pid_t pid, void *smsg, void *rmsg, size_t ssize, size_t rsize) 01920 { 01921 RT_TASK *task; 01922 if ((task = pid2rttask(pid))) { 01923 MSGCB cb; 01924 RT_TASK *replier; 01925 unsigned long replylen; 01926 cb.cmd = SYNCMSG; 01927 cb.sbuf = smsg; 01928 cb.sbytes = ssize; 01929 cb.rbuf = rmsg; 01930 cb.rbytes = rsize; 01931 if (!(replier = rt_rpc(task, (unsigned long)&cb, &replylen))) { 01932 return -EINVAL; 01933 } else if (replier != task) { 01934 return -ESRCH; 01935 } 01936 return replylen ; 01937 } 01938 return -ESRCH; 01939 } 01940 01941 RTAI_SYSCALL_MODE pid_t rt_Receive(pid_t pid, void *msg, size_t maxsize, size_t *msglen) 01942 { 01943 RT_TASK *task; 01944 MSGCB *cb; 01945 if ((task = rt_receive(pid ? pid2rttask(pid) : 0, (void *)&cb))) { 01946 if ((pid = rttask2pid(task))) { 01947 *msglen = maxsize <= cb->sbytes ? maxsize : cb->sbytes; 01948 if (*msglen) { 01949 memcpy(msg, cb->sbuf, *msglen); 01950 } 01951 return pid; 01952 } 01953 return -ESRCH; 01954 } 01955 return -EINVAL; 01956 } 01957 01958 RTAI_SYSCALL_MODE pid_t rt_Creceive(pid_t pid, void *msg, size_t maxsize, size_t *msglen, RTIME delay) 01959 { 01960 RT_TASK *task; 01961 MSGCB *cb; 01962 task = pid ? pid2rttask(pid) : 0; 01963 if (delay) { 01964 task = rt_receive_timed(task, (void *)&cb, delay); 01965 } else { 01966 task = rt_receive_if(task, (void *)&cb); 01967 } 01968 if (task) { 01969 if ((pid = rttask2pid(task))) { 01970 *msglen = maxsize <= cb->sbytes ? maxsize : cb->sbytes; 01971 if (*msglen) { 01972 memcpy(msg, cb->sbuf, *msglen); 01973 } 01974 return pid; 01975 } 01976 return 0; 01977 } 01978 return 0; 01979 } 01980 01981 RTAI_SYSCALL_MODE int rt_Reply(pid_t pid, void *msg, size_t size) 01982 { 01983 RT_TASK *task; 01984 if ((task = pid2rttask(pid))) { 01985 MSGCB *cb; 01986 if ((cb = (MSGCB *)task->msg)->cmd == SYNCMSG) { 01987 unsigned long retlen; 01988 RT_TASK *retask; 01989 if ((retlen = size <= cb->rbytes ? size : cb->rbytes)) { 01990 memcpy(cb->rbuf, msg, retlen); 01991 } 01992 if (!(retask = rt_return(task, retlen))) { 01993 return -EINVAL; 01994 } else if (retask != task) { 01995 return -ESRCH; 01996 } 01997 return 0; 01998 } 01999 return -EPERM; 02000 } 02001 return -ESRCH; 02002 } 02003 02004 static void Proxy_Task(RT_TASK *me) 02005 { 02006 struct proxy_t *my; 02007 MSGCB cb; 02008 unsigned long replylen; 02009 my = (struct proxy_t *)me->stack_bottom; 02010 cb.cmd = PROXY; 02011 cb.sbuf = my->msg; 02012 cb.sbytes = my->nbytes; 02013 cb.rbuf = &replylen; 02014 cb.rbytes = sizeof(replylen); 02015 while(1) { 02016 while (my->nmsgs) { 02017 atomic_dec((atomic_t *)&my->nmsgs); 02018 rt_rpc(my->receiver, (unsigned long)(&cb), &replylen); 02019 } 02020 rt_task_suspend(me); 02021 } 02022 } 02023 02024 RTAI_SYSCALL_MODE pid_t rt_Proxy_attach(pid_t pid, void *msg, int nbytes, int prio) 02025 { 02026 RT_TASK *task; 02027 return (task = __rt_proxy_attach((void *)Proxy_Task, pid ? pid2rttask(pid) : 0, msg, nbytes, prio)) ? (task->lnxtsk)->pid : -ENOMEM; 02028 } 02029 02030 RTAI_SYSCALL_MODE int rt_Proxy_detach(pid_t pid) 02031 { 02032 RT_TASK *proxy; 02033 if (!rt_task_delete(proxy = pid2rttask(pid))) { 02034 rt_free(proxy); 02035 return 0; 02036 } 02037 return -EINVAL; 02038 } 02039 02040 RTAI_SYSCALL_MODE pid_t rt_Trigger(pid_t pid) 02041 { 02042 RT_TASK *proxy; 02043 struct proxy_t *his; 02044 if ((proxy = pid2rttask(pid))) { 02045 his = (struct proxy_t *)(proxy->stack_bottom); 02046 if (his && proxy->magic == RT_TASK_MAGIC) { 02047 atomic_inc((atomic_t *)&his->nmsgs); 02048 rt_task_resume(proxy); 02049 return rttask2pid(his->receiver); 02050 } 02051 return -EINVAL; 02052 } 02053 return -ESRCH; 02054 } 02055 02056 02057 RTAI_SYSCALL_MODE pid_t rt_Name_attach(const char *argname) 02058 { 02059 RT_TASK *task; 02060 task = current->rtai_tskext(TSKEXT0) ? (RT_TASK *)current->rtai_tskext(TSKEXT0) : _rt_whoami(); 02061 if (current->comm[0] != 'U' && current->comm[1] != ':') { 02062 rt_strncpy_from_user(task->task_name, argname, RTAI_MAX_NAME_LENGTH); 02063 } else { 02064 strncpy(task->task_name, argname, RTAI_MAX_NAME_LENGTH); 02065 } 02066 task->task_name[RTAI_MAX_NAME_LENGTH - 1] = 0; 02067 return strnlen(task->task_name, RTAI_MAX_NAME_LENGTH) > (RTAI_MAX_NAME_LENGTH - 1) ? -EINVAL : task->lnxtsk ? ((struct task_struct *)current->rtai_tskext(TSKEXT1))->pid : (long)task; 02068 } 02069 02070 RTAI_SYSCALL_MODE pid_t rt_Name_locate(const char *arghost, const char *argname) 02071 { 02072 extern RT_TASK rt_smp_linux_task[]; 02073 int cpuid; 02074 RT_TASK *task; 02075 for (cpuid = 0; cpuid < num_online_cpus(); cpuid++) { 02076 task = &rt_smp_linux_task[cpuid]; 02077 while ((task = task->next)) { 02078 if (!strncmp(argname, task->task_name, RTAI_MAX_NAME_LENGTH - 1)) { 02079 return (struct task_struct *)(task->lnxtsk) ? ((struct task_struct *)(task->lnxtsk)->rtai_tskext(TSKEXT1))->pid : (long)task; 02080 02081 } 02082 } 02083 } 02084 return strlen(argname) <= 6 && (task = rt_get_adr(nam2num(argname))) ? rttask2pid(task) : 0; 02085 } 02086 02087 RTAI_SYSCALL_MODE int rt_Name_detach(pid_t pid) 02088 { 02089 if (pid <= PID_MAX_LIMIT) { 02090 if (pid != ((struct task_struct *)current->rtai_tskext(TSKEXT1))->pid ) { 02091 return -EINVAL; 02092 } 02093 ((RT_TASK *)current->rtai_tskext(TSKEXT0))->task_name[0] = 0; 02094 } else { 02095 ((RT_TASK *)(long)pid)->task_name[0] = 0; 02096 } 02097 return 0; 02098 } 02099 02100 #endif /* CONFIG_RTAI_INTERNAL_LXRT_SUPPORT */ 02101 02102 /* +++++++++++++++++++++ INTERTASK MESSAGES ENTRIES +++++++++++++++++++++++++ */ 02103 02104 struct rt_native_fun_entry rt_msg_entries[] = { 02105 { { 1, rt_send }, SENDMSG }, 02106 { { 1, rt_send_if }, SEND_IF }, 02107 { { 1, rt_send_until }, SEND_UNTIL }, 02108 { { 1, rt_send_timed }, SEND_TIMED }, 02109 { { UW1(2, 0), rt_evdrp }, EVDRP }, 02110 { { UW1(2, 0), rt_receive }, RECEIVEMSG }, 02111 { { UW1(2, 0), rt_receive_if }, RECEIVE_IF }, 02112 { { UW1(2, 0), rt_receive_until }, RECEIVE_UNTIL }, 02113 { { UW1(2, 0), rt_receive_timed }, RECEIVE_TIMED }, 02114 { { UW1(3, 0), rt_rpc }, RPCMSG }, 02115 { { UW1(3, 0), rt_rpc_if }, RPC_IF }, 02116 { { UW1(3, 0), rt_rpc_until }, RPC_UNTIL }, 02117 { { UW1(3, 0), rt_rpc_timed }, RPC_TIMED }, 02118 { { 0, rt_isrpc }, ISRPC }, 02119 { { 1, rt_return }, RETURNMSG }, 02120 { { UR1(2, 4) | UW1(3, 5), rt_rpcx }, RPCX }, 02121 { { UR1(2, 4) | UW1(3, 5), rt_rpcx_if }, RPCX_IF }, 02122 { { UR1(2, 4) | UW1(3, 5), rt_rpcx_until }, RPCX_UNTIL }, 02123 { { UR1(2, 4) | UW1(3, 5), rt_rpcx_timed }, RPCX_TIMED }, 02124 { { UR1(2, 3), rt_sendx }, SENDX }, 02125 { { UR1(2, 3), rt_sendx_if }, SENDX_IF }, 02126 { { UR1(2, 3), rt_sendx_until }, SENDX_UNTIL }, 02127 { { UR1(2, 3), rt_sendx_timed }, SENDX_TIMED }, 02128 { { UR1(2, 3), rt_returnx }, RETURNX }, 02129 { { UW1(2, 3) | UW2(4, 0), rt_evdrpx }, EVDRPX }, 02130 { { UW1(2, 3) | UW2(4, 0), rt_receivex }, RECEIVEX }, 02131 { { UW1(2, 3) | UW2(4, 0), rt_receivex_if }, RECEIVEX_IF }, 02132 { { UW1(2, 3) | UW2(4, 0), rt_receivex_until }, RECEIVEX_UNTIL }, 02133 { { UW1(2, 3) | UW2(4, 0), rt_receivex_timed }, RECEIVEX_TIMED }, 02134 { { UR1(2, 3), rt_proxy_attach }, PROXY_ATTACH }, 02135 { { 1, rt_proxy_detach }, PROXY_DETACH }, 02136 { { 1, rt_trigger }, PROXY_TRIGGER }, 02137 { { UR1(2, 4) | UW1(3, 5), rt_Send }, RT_SEND }, 02138 { { UW1(2, 3) | UW2(4, 0), rt_Receive }, RT_RECEIVE }, 02139 { { UW1(2, 3) | UW2(4, 0), rt_Creceive }, RT_CRECEIVE }, 02140 { { UR1(2, 3), rt_Reply }, RT_REPLY }, 02141 { { UR1(2, 3), rt_Proxy_attach }, RT_PROXY_ATTACH }, 02142 { { 1, rt_Proxy_detach }, RT_PROXY_DETACH }, 02143 { { 1, rt_Trigger }, RT_TRIGGER }, 02144 { { 1, rt_Name_attach }, RT_NAME_ATTACH }, 02145 { { 0, rt_Name_locate }, RT_NAME_LOCATE }, 02146 { { 1, rt_Name_detach }, RT_NAME_DETACH }, 02147 { { 0, 0 }, 000 } 02148 }; 02149 02150 int __rtai_msg_init (void) 02151 { 02152 return set_rt_fun_entries(rt_msg_entries); 02153 } 02154 02155 void __rtai_msg_exit (void) 02156 { 02157 reset_rt_fun_entries(rt_msg_entries); 02158 } 02159 02160 #ifndef CONFIG_RTAI_MSG_BUILTIN 02161 module_init(__rtai_msg_init); 02162 module_exit(__rtai_msg_exit); 02163 #endif /* !CONFIG_RTAI_MSG_BUILTIN */ 02164 02165 #ifdef CONFIG_KBUILD 02166 EXPORT_SYMBOL(rt_send); 02167 EXPORT_SYMBOL(rt_send_if); 02168 EXPORT_SYMBOL(rt_send_until); 02169 EXPORT_SYMBOL(rt_send_timed); 02170 EXPORT_SYMBOL(rt_rpc); 02171 EXPORT_SYMBOL(rt_rpc_if); 02172 EXPORT_SYMBOL(rt_rpc_until); 02173 EXPORT_SYMBOL(rt_rpc_timed); 02174 EXPORT_SYMBOL(rt_isrpc); 02175 EXPORT_SYMBOL(rt_return); 02176 EXPORT_SYMBOL(rt_evdrp); 02177 EXPORT_SYMBOL(rt_receive); 02178 EXPORT_SYMBOL(rt_receive_if); 02179 EXPORT_SYMBOL(rt_receive_until); 02180 EXPORT_SYMBOL(rt_receive_timed); 02181 EXPORT_SYMBOL(rt_rpcx); 02182 EXPORT_SYMBOL(rt_rpcx_if); 02183 EXPORT_SYMBOL(rt_rpcx_until); 02184 EXPORT_SYMBOL(rt_rpcx_timed); 02185 EXPORT_SYMBOL(rt_sendx); 02186 EXPORT_SYMBOL(rt_sendx_if); 02187 EXPORT_SYMBOL(rt_sendx_until); 02188 EXPORT_SYMBOL(rt_sendx_timed); 02189 EXPORT_SYMBOL(rt_returnx); 02190 EXPORT_SYMBOL(rt_evdrpx); 02191 EXPORT_SYMBOL(rt_receivex); 02192 EXPORT_SYMBOL(rt_receivex_if); 02193 EXPORT_SYMBOL(rt_receivex_until); 02194 EXPORT_SYMBOL(rt_receivex_timed); 02195 02196 EXPORT_SYMBOL(__rt_proxy_attach); 02197 EXPORT_SYMBOL(rt_proxy_attach); 02198 EXPORT_SYMBOL(rt_proxy_detach); 02199 EXPORT_SYMBOL(rt_trigger); 02200 02201 EXPORT_SYMBOL(rt_Send); 02202 EXPORT_SYMBOL(rt_Receive); 02203 EXPORT_SYMBOL(rt_Creceive); 02204 EXPORT_SYMBOL(rt_Reply); 02205 EXPORT_SYMBOL(rt_Proxy_attach); 02206 EXPORT_SYMBOL(rt_Proxy_detach); 02207 EXPORT_SYMBOL(rt_Trigger); 02208 EXPORT_SYMBOL(rt_Name_attach); 02209 EXPORT_SYMBOL(rt_Name_locate); 02210 EXPORT_SYMBOL(rt_Name_detach); 02211 #endif /* CONFIG_KBUILD */