/ README.LINUX_SERVER
README.LINUX_SERVER
  1         *** SERVING LINUX SYSCALLS IN RTAI HARD REAL TIME MODE ***
  2  
  3  The default RTAI way of dealing with Linux syscalls done while in hard real
  4  time consists in moving a task wanting to use Linux back to soft mode, 
  5  recovering it to hard real time again, as soon as possible, afterward. See the 
  6  related RTAI configuration helper for an explanation of the different available 
  7  modes to implement the "as soon as possible" above on various architectures.
  8  
  9  This README documents possible alternative ways to access Linux services from 
 10  hard real time RTAI applications in user space. Such a support is based on the 
 11  creation of a general purpose server thread that takes over Linux requests. 
 12  
 13  It must be noticed that if Linux is to be used synchronously at the very moment
 14  Linux is called the task becomes timed by Linux, wherever a Linux server is 
 15  used or not. So hard real time constraints cannot be satisfied anyhow. The use 
 16  of a Linux server has an advantage though. In fact it takes just two context 
 17  switches, in place of the four used by hard-soft-hard transitions. Moreover it 
 18  ensures that RTAI returns to hard real time immediately after the Linux syscall 
 19  has finished while, if the architecture does not support the immediate Linux 
 20  syscall mode reliably for all Linux syscalls, there will be the need to wait 
 21  for a call to an RTAI function to go back in RTAI hard real time fully. That 
 22  will add even far more latencies when a hard RTAI task does some processing 
 23  for a significant amount of time after the Linux syscall, without using any 
 24  RTAI service. So, provided it is allowed loosing real time, installing a 
 25  synchronous server might be the best way to interact with Linux anyhow.
 26  
 27  There are however instances in which Linux can be used asynchronously. In 
 28  such cases RTAI hard real time tasks might use Linux without loosing hard
 29  real time determinism. Such a capability can be implemented in many ways, 
 30  the one chosen by RTAI is based on a buffering of async Linux syscalls mated 
 31  either to an optional callback function or to inquiry mechanisms to help 
 32  implementing any user own async call policy. Beware of not reusing read/write 
 33  data buffers made available to async calls though. 
 34  If you do not want, or cannot, either inquire for or check async terminations, 
 35  to avoid running the risk of reusing an yet unserved buffer, use RTAI dynamic 
 36  memory or SCB to allocate them in real time, freeing them afterward, possibly 
 37  with the help of a support callback function. 
 38  Async support is a bit tricky but, provided one cares of what said above, it
 39  should work always when Linux syscalls arguments are fully contained in the 
 40  passed registers structure. That is not the case for a few Linux syscalls that 
 41  are multiplexed within a single framework, whereas libc can end in building a 
 42  hidden object on the stack, so that it is not assured it will be available at 
 43  the time the server uses it. On some archs a notable example of that is the 
 44  socketcall, but RTAI should already care of it appropriately. There remain 
 45  nonetheless the chance of other instances to be cared as well. So beware that 
 46  some async calls might not work with a few Linux services yet, in which case 
 47  you should let us know about it for a possible fix.
 48  Just to mention another typical care to be taken we notice that printf might
 49  work as it is but it will often crash. So the safe way to printf is as follows:
 50  - sprintf(buffer, format, args, ....);
 51  - write(STDOUT_FILENO, buffer, strlen(buffer));
 52  
 53  Provided the socketcall has been intercepted well you should be able to do many
 54  IO operations asynchronously, e.g.: dumping data directly to disk, Linux ipcs 
 55  and POSIX mq, fifos, pipes, serial and networked communications etc. etc. 
 56  In many applications one often requires RTAI specific IO drivers just to avoid 
 57  loosing real time for communications with non real time support/interface 
 58  processes and tasks. The async server should be of much help in such cases by 
 59  letting you use standard Linux, with the ensuing advantage of not needing any 
 60  special hard real time driver.
 61  
 62  Clearly what above does not impede you to set up your own async server to 
 63  which your hard real time task can be connected by using RTAI non blocking 
 64  communication functions, i.e. those ending with "_if". So the choice of the 
 65  most viable solution is left to you.
 66   
 67  How it works
 68  ------------
 69  
 70  By using the functions described below a server thread is created that will
 71  block waiting for parent task requests to Linux. Whenever the RTAI scheduler 
 72  intercepts a Linux syscall in hard real time mode it passes it to the server 
 73  thread and:
 74  - remains waiting for its execution if in sync mode;
 75  - returns immediately if in async mode.
 76  The server carries out the syscall and:
 77  - resumes the hard real time parent, returning what returned by Linux, if in 
 78  sync mode:
 79  - calls a callback function, if one has been made available, in async mode,
 80  returning an identifier.
 81  
 82  As said in sync mode real time is lost, but there will be two task switches per
 83  Linux service request only, while there will be four if no sync server is used.
 84  In async mode there is no need for any task switch, as the server will execute 
 85  in soft mode when there will be no RTAI real time activity any more.
 86  The need of passing syscall data to the server is responsible for most of the 
 87  penalty incurred by using a Linux server. 
 88  Let's stress once more that this is a far better alternative way to what the 
 89  RTAI scheduler will have to do anyhow, i.e. make you soft and recover hard mode 
 90  at the next RTAI proper service call, which will require four task switches, 
 91  keeping you in Linux hands from the Linux syscall till an RTAI function is 
 92  called again. 
 93  With a server instead you will stay soft just either till Linux has finished 
 94  servicing your request, when in sync mode, or kept working in real time, when
 95  in async mode.
 96  
 97  API Functions prototypes
 98  ------------------------
 99  
100  The available functions are:
101  
102  - void *rt_create_linux_syscall_server(RT_TASK *task, int mode, void 
103  (*callback_fun)(long, long), int nr_bufd_async_calls);
104  create a Linux syscall server for task, a NULL task means the current one; a 
105  non NULL return is the handle allowing you to link to the server for any 
106  further management request, see functions below, NULL indicates a failure in 
107  setting the server up; a NULL callback_fun is allowed. It will operate 
108  according to mode setting, either SYNC_LINUX_SYSCALL or ASYNC_LINUX_SYSCALL. 
109  Beware of using an appropriate nr_bufd_async_calls. If async requests overrun 
110  the latest will be discarded till some space is available again.
111  If a server exists already it is terminated and a new one replaces it.
112  
113  - void rt_destroy_linux_syscall(RT_TASK *task);
114  destroy the linux_syscall_server of task, if NULL use the current task. 
115  
116  - void *rt_sync_async_linux_syscall_server_create(RT_TASK *task, int mode, 
117    void (*callback_fun)(long, long), int nr_bufd_async_calls);
118  legacy interface, the same as: 
119  rt_create_linux_syscall_server(task, mode, callback_fun, nr_bufd_async_calls).
120  
121  - void *rt_linux_syscall_server_create(RT_TASK *task);
122  legacy call, the same as:
123  rt_create_linux_syscall_server(task, SYNC_LINUX_SYSCALL, NULL, 1).
124  
125  Notice that in sync mode Linux functions will return their usual values while 
126  that is not possible in async mode and what returned is an identifier, id, of 
127  that specific async call, a negative id meaning the call was not satisfied
128  because of a buffer overrun. When <= 0 ids can be used for monitoring async
129  calls execution, as explained below.
130  
131  - int rt_set_linux_syscall_mode(int mode, void (*callback_fun)(long, long);
132  to both switch between sync and async mode and change the call back function.
133  It returns EINVAL if there is no server or the mode setting is not correct.
134  
135  Notice that this is a legacy call, you'd better use:
136  
137  - int rt_linux_syscall_mode(struct linux_syscalls_list *syscalls, int mode);
138  to switch between sync and async mode; syscalls is the handle returned by
139  rt_sync_async_linux_syscall_server_create; mode can be: SYNC_LINUX_SYSCALL, 
140  ASYNC_LINUX_SYSCALL, LINUX_SYSCALL_GET_MODE.
141  The function returns the previous mode and LINUX_SYSCALL_GET_MODE can be used
142  to just inquire for it, in which case mode is discarded. EINVAL is returned if
143  syscalls is not a valid pointer. 
144  
145  - void *rt_linux_syscall_cbfun(struct linux_syscalls_list *syscalls, void (*cbfun)(long, long));
146  to change the callback function; syscalls is the handle returned by
147  rt_sync_async_linux_syscall_server_create; cbfun can be either a NULL, no 
148  callback will be used, a pointer to a true callback function, 
149  LINUX_SYSCALL_GET_CALLBACK.
150  The function returns the pointer to the previous callback function and 
151  LINUX_SYSCALL_GET_CALLBACK can be used to just inquire for it. EINVAL is 
152  returned if syscall is not a valid pointer 
153  
154  The callback function afford a notification control mechanism for async calls.
155  An alternative way to monitor async calls execution is given by the following
156  functions:
157  
158  - int rt_linux_syscall_status(struct linux_syscalls_list *syscalls, int id, int *retval);
159  syscalls is the handle returned from rt_sync_async_linux_syscall_server_create;
160  id is the value returned by the call to Linux, retval is a pointer to an int
161  that will receive the value returned by Linux after executing the related 
162  service.
163  It returns:
164  - EINVAL if syscalls is not a valid pointer or id < 0
165  - ENOENT if no id is found, meaning the function has been overwritten;
166  - ECANCELED when the function has call has been explicitly canceled by the 
167    user;
168  - EINPROGRESS when the function is pending waiting for execution;
169  - 0 when the function has been executed, in such a case retval, if not NULL,
170    will receive the value returned by Linux.
171  
172  - int rt_linux_syscall_cancel(struct linux_syscalls_list *syscalls, int id);
173  Syscalls is the handle returned from rt_sync_async_linux_syscall_server_create;
174  id is the value returned by the call to Linux.
175  It returns:
176  - EINVAL if syscalls is not a valid pointer or id < 0
177  - ENOENT if no id is found, meaning the function has been overwritten;
178  - -id when the function has been executed already;
179  - 0 if the function has been successfully canceled.
180  
181  Examples
182  -------
183  
184  They are in RTAI "showroom" CVS: linux_server and printer_server.
185  
186  Paolo.