00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
#include <linux/module.h>
00027 
#include <linux/kernel.h>
00028 
#include <linux/config.h>
00029 
#include <linux/version.h>
00030 
#include <linux/errno.h>
00031 
#include <linux/slab.h>
00032 
#include <linux/unistd.h>
00033 
#include <linux/mman.h>
00034 
#include <asm/uaccess.h>
00035 
00036 
#include <rtai_sched.h>
00037 
#include <rtai_lxrt.h>
00038 
#include <rtai_sem.h>
00039 
#include <rtai_mbx.h>
00040 
#include <rtai_rwl.h>
00041 
#include <rtai_spl.h>
00042 
00043 
#include <asm/rtai_fpu.h>
00044 
#include <rtai_registry.h>
00045 
#include <rtai_proxies.h>
00046 
#include <rtai_msg.h>
00047 
#include <rtai_schedcore.h>
00048 
00049 #define MAX_FUN_EXT  16
00050 static struct rt_fun_entry *
rt_fun_ext[
MAX_FUN_EXT];
00051 
00052 
00053 
00054 
00055 #define USRLAND_MAX_MSG_SIZE  128  // Default max message size, used here only.
00056 
00057 
#ifdef CONFIG_RTAI_TRACE
00058 
00059 
00060 
00061 
void trace_true_lxrt_rtai_syscall_entry(
void);
00062 
void trace_true_lxrt_rtai_syscall_exit(
void);
00063 
00064 
#endif 
00065 
00066 
int get_min_tasks_cpuid(
void);
00067 
00068 
int set_rtext(
RT_TASK *task,
00069           
int priority,
00070           
int uses_fpu,
00071           
void(*signal)(
void),
00072           
unsigned int cpuid,
00073           
struct task_struct *relink);
00074 
00075 
int clr_rtext(
RT_TASK *task);
00076 
00077 
void steal_from_linux(
RT_TASK *task);
00078 
00079 
void give_back_to_linux(
RT_TASK *task, 
int);
00080 
00081 
void rt_schedule_soft(
RT_TASK *task);
00082 
00083 
void *
rt_get_lxrt_fun_entry(
int index);
00084 
00085 static inline void lxrt_typed_sem_init(
SEM *sem, 
int count, 
int type)
00086 {
00087     ((int (*)(
SEM *, 
int, 
int))
rt_get_lxrt_fun_entry(
TYPED_SEM_INIT))(sem, 
count, type);
00088 }
00089 
00090 static inline int lxrt_typed_mbx_init(
MBX *mbx, 
int bufsize, 
int type)
00091 {
00092     
return ((int (*)(
MBX *, 
int, 
int))
rt_get_lxrt_fun_entry(
TYPED_MBX_INIT))(mbx, bufsize, type);
00093 }
00094 
00095 static inline int lxrt_rwl_init(
RWL *rwl)
00096 {
00097     
return ((int (*)(
RWL *))
rt_get_lxrt_fun_entry(
RWL_INIT))(rwl);
00098 }
00099 
00100 static inline int lxrt_spl_init(
SPL *spl)
00101 {
00102     
return ((int (*)(
SPL *))
rt_get_lxrt_fun_entry(
SPL_INIT))(spl);
00103 }
00104 
00105 static inline int lxrt_Proxy_detach(pid_t pid)
00106 {
00107     
return ((int (*)(
int))
rt_get_lxrt_fun_entry(
PROXY_DETACH))(
pid);
00108 }
00109 
00110 static inline int GENERIC_DELETE(
int index, 
void *object)
00111 {
00112     
return ((int (*)(
void *))
rt_get_lxrt_fun_entry(index))(object);
00113 }
00114              
00115 #define lxrt_sem_delete(sem)        GENERIC_DELETE(SEM_DELETE, sem)
00116 #define lxrt_named_sem_delete(sem)  GENERIC_DELETE(NAMED_SEM_DELETE, sem)
00117 #define lxrt_rwl_delete(rwl)        GENERIC_DELETE(RWL_DELETE, rwl)
00118 #define lxrt_named_rwl_delete(rwl)  GENERIC_DELETE(NAMED_RWL_DELETE, rwl)
00119 #define lxrt_spl_delete(spl)        GENERIC_DELETE(SPL_DELETE, spl)
00120 #define lxrt_named_spl_delete(spl)  GENERIC_DELETE(NAMED_SPL_DELETE, spl)
00121 #define lxrt_mbx_delete(mbx)        GENERIC_DELETE(MBX_DELETE, mbx)
00122 #define lxrt_named_mbx_delete(mbx)  GENERIC_DELETE(NAMED_MBX_DELETE, mbx)
00123 
00124 static inline void lxrt_resume(
void *fun, 
int narg, 
long *arg, 
unsigned long type, 
RT_TASK *rt_task)
00125 {
00126     
if (NEED_TO_RW(type)) {
00127         
int rsize, r2size, wsize, w2size, msg_size;
00128         
long *wmsg_adr, *w2msg_adr, *fun_args;
00129         
00130         rsize = r2size = wsize = w2size = 0 ;
00131         wmsg_adr = w2msg_adr = NULL;
00132         fun_args = arg - 1;
00133         
if (NEED_TO_R(type)) {          
00134             rsize = USP_RSZ1(type);
00135             rsize = rsize ? fun_args[rsize] : 
sizeof(
long);
00136             
if (NEED_TO_R2ND(type)) {
00137                 r2size = USP_RSZ2(type);
00138                 r2size = r2size ? fun_args[r2size] : 
sizeof(
long);
00139             }
00140         }
00141         
if (NEED_TO_W(type)) {
00142             wsize = USP_WSZ1(type);
00143             wsize = wsize ? fun_args[wsize] : 
sizeof(
long);
00144             
if (NEED_TO_W2ND(type)) {
00145                 w2size = USP_WSZ2(type);
00146                 w2size = w2size ? fun_args[w2size] : 
sizeof(
long);
00147             }
00148         }
00149         
if ((msg_size = rsize > wsize ? rsize : wsize) > 0) {
00150             
if (msg_size > rt_task->max_msg_size[0]) {
00151                 
rt_free(rt_task->msg_buf[0]);
00152                 rt_task->max_msg_size[0] = (msg_size << 7)/100;
00153                 rt_task->msg_buf[0] = 
rt_malloc(rt_task->max_msg_size[0]);
00154             }
00155             
if (rsize) {            
00156                 
long *buf_arg = fun_args + USP_RBF1(type);
00157                 rt_copy_from_user(rt_task->msg_buf[0], (
long *)buf_arg[0], rsize);
00158                 buf_arg[0] = (
long)rt_task->msg_buf[0];
00159             }
00160             
if (wsize) {
00161                 
long *buf_arg = fun_args + USP_WBF1(type);
00162                 wmsg_adr = (
long *)buf_arg[0];
00163                 buf_arg[0] = (
long)rt_task->msg_buf[0];
00164             }
00165         }
00166         
if ((msg_size = r2size > w2size ? r2size : w2size) > 0) {
00167             
if (msg_size > rt_task->max_msg_size[1]) {
00168                 
rt_free(rt_task->msg_buf[1]);
00169                 rt_task->max_msg_size[1] = (msg_size << 7)/100;
00170                 rt_task->msg_buf[1] = 
rt_malloc(rt_task->max_msg_size[1]);
00171             }
00172             
if (r2size) {
00173                 
long *buf_arg = fun_args + USP_RBF2(type);
00174                 rt_copy_from_user(rt_task->msg_buf[1], (
long *)buf_arg[0], r2size);
00175                 buf_arg[0] = (
long)rt_task->msg_buf[1];
00176                 }
00177             
if (w2size) {
00178                 
long *buf_arg = fun_args + USP_WBF2(type);
00179                 w2msg_adr = (
long *)buf_arg[0];
00180                         buf_arg[0] = (
long)rt_task->msg_buf[1];
00181                 }
00182         }
00183         
if (
likely(rt_task->is_hard > 0)) {
00184             rt_task->retval = ((
long long (*)(
unsigned long, ...))fun)(RTAI_FUN_ARGS);
00185             
if (
unlikely(!rt_task->is_hard)) {
00186 
extern void rt_schedule_soft_tail(
RT_TASK *rt_task, 
int cpuid);
00187                 
rt_schedule_soft_tail(rt_task, rt_task->runnable_on_cpus);
00188             }
00189         } 
else {
00190             
struct fun_args *funarg;
00191             memcpy(funarg = (
void *)rt_task->fun_args, arg, narg);
00192             funarg->fun = fun;
00193             
rt_schedule_soft(rt_task);
00194         }
00195         
if (wsize) {
00196             rt_copy_to_user(wmsg_adr, rt_task->msg_buf[0], wsize);
00197             
if (w2size) {
00198                 rt_copy_to_user(w2msg_adr, rt_task->msg_buf[1], w2size);
00199             }
00200         }
00201     } 
else if (
likely(rt_task->is_hard > 0)) {
00202         rt_task->retval = ((
long long (*)(
unsigned long, ...))fun)(RTAI_FUN_ARGS);
00203         
if (
unlikely(!rt_task->is_hard)) {
00204 
extern void rt_schedule_soft_tail(
RT_TASK *rt_task, 
int cpuid);
00205             
rt_schedule_soft_tail(rt_task, rt_task->runnable_on_cpus);
00206         }
00207     } 
else {
00208         
struct fun_args *funarg;
00209         memcpy(funarg = (
void *)rt_task->fun_args, arg, narg);
00210         funarg->fun = fun;
00211         
rt_schedule_soft(rt_task);
00212     }
00213 }
00214 
00215 static inline RT_TASK* 
__task_init(
unsigned long name, 
int prio, 
int stack_size, 
int max_msg_size, 
int cpus_allowed)
00216 {
00217     
void *msg_buf0, *msg_buf1;
00218     
RT_TASK *rt_task;
00219 
00220     
if (
rt_get_adr(name)) {
00221         
return 0;
00222     }
00223     
if (prio > 
RT_SCHED_LOWEST_PRIORITY) {
00224         prio = 
RT_SCHED_LOWEST_PRIORITY;
00225     }
00226     
if (!max_msg_size) {
00227         max_msg_size = 
USRLAND_MAX_MSG_SIZE;
00228     }
00229     
if (!(msg_buf0 = 
rt_malloc(max_msg_size))) {
00230         
return 0;
00231     }
00232     
if (!(msg_buf1 = 
rt_malloc(max_msg_size))) {
00233         
rt_free(msg_buf0);
00234         
return 0;
00235     }
00236     rt_task = 
rt_malloc(
sizeof(
RT_TASK) + 3*
sizeof(
struct fun_args)); 
00237     
if (rt_task) {
00238         rt_task->magic = 0;
00239         
if (num_online_cpus() > 1 && cpus_allowed) {
00240         cpus_allowed = hweight32(cpus_allowed) > 1 ? 
get_min_tasks_cpuid() : 
ffnz(cpus_allowed);
00241         } 
else {
00242         cpus_allowed = smp_processor_id();
00243         }
00244         
if (!
set_rtext(rt_task, prio, 0, 0, cpus_allowed, 0)) {
00245             rt_task->fun_args = (
long *)((
struct fun_args *)(rt_task + 1));
00246         rt_task->msg_buf[0] = msg_buf0;
00247         rt_task->msg_buf[1] = msg_buf1;
00248         rt_task->max_msg_size[0] =
00249         rt_task->max_msg_size[1] = max_msg_size;
00250         
if (
rt_register(name, rt_task, 
IS_TASK, 0)) {
00251             
return rt_task;
00252         } 
else {
00253             
clr_rtext(rt_task);
00254         }
00255         }
00256         
rt_free(rt_task);
00257     }
00258     
rt_free(msg_buf0);
00259     
rt_free(msg_buf1);
00260     
return 0;
00261 }
00262 
00263 static int __task_delete(
RT_TASK *rt_task)
00264 {
00265     
struct task_struct *process;
00266     
if (rt_task->linux_syscall_server) {
00267         
rt_task_masked_unblock(rt_task->linux_syscall_server, ~
RT_SCHED_READY);
00268     }
00269     
if (current == rt_task->lnxtsk && rt_task->is_hard > 0) {
00270         
give_back_to_linux(rt_task, 0);
00271     }
00272     
if (
clr_rtext(rt_task)) {
00273         
return -EFAULT;
00274     }
00275     
rt_free(rt_task->msg_buf[0]);
00276     
rt_free(rt_task->msg_buf[1]);
00277     
rt_free(rt_task);
00278     
if ((process = rt_task->lnxtsk)) {
00279         process->rtai_tskext(
TSKEXT0) = process->rtai_tskext(
TSKEXT1) = 0;
00280     }
00281     
return (!
rt_drg_on_adr(rt_task)) ? -ENODEV : 0;
00282 }
00283 
00284 
00285 
#ifdef ECHO_SYSW
00286 
#define SYSW_DIAG_MSG(x) x
00287 
#else
00288 #define SYSW_DIAG_MSG(x)
00289 
#endif
00290 
00291 static inline long long handle_lxrt_request (
unsigned int lxsrq, 
long *arg, 
RT_TASK *task)
00292 {
00293 
#define larg ((struct arg *)arg)
00294 
00295     
union {
unsigned long name; 
RT_TASK *rt_task; 
SEM *sem; 
MBX *mbx; 
RWL *rwl; 
SPL *spl; } arg0;
00296     
int srq;
00297 
00298     
srq = 
SRQ(lxsrq);
00299     
if (
likely(
srq < 
MAX_LXRT_FUN)) {
00300         
unsigned long type;
00301         
struct rt_fun_entry *funcm;
00302 
00303 
00304 
00305 
00306 
00307 
00308         funcm = 
rt_fun_ext[
INDX(lxsrq)];
00309         
if (
unlikely(!funcm)) {
00310             
rt_printk(
"BAD: null rt_fun_ext[%d]\n", 
INDX(lxsrq));
00311             
return -ENOSYS;
00312         }
00313         type = funcm[
srq].type;
00314         
if (
likely(type)) {
00315             
if (
unlikely(
task->is_hard < 0)) {
00316                 
SYSW_DIAG_MSG(
rt_printk(
"GOING BACK TO HARD (SYSLXRT, RESUME), PID = %d.\n", current->pid););
00317                 
steal_from_linux(
task);
00318                 
SYSW_DIAG_MSG(
rt_printk(
"GONE BACK TO HARD (SYSLXRT),  PID = %d.\n", current->pid););
00319             }
00320             
lxrt_resume(funcm[
srq].fun, 
NARG(lxsrq), arg, type, 
task);
00321             
return task->retval;
00322         } 
else {
00323             
if (
unlikely(
task && 
task->is_hard < 0)) {
00324                 
SYSW_DIAG_MSG(
rt_printk(
"GOING BACK TO HARD (SYSLXRT, DIRECT), PID = %d.\n", current->pid););
00325                 
steal_from_linux(
task);
00326                 
SYSW_DIAG_MSG(
rt_printk(
"GONE BACK TO HARD (SYSLXRT),  PID = %d.\n", current->pid););
00327             }
00328             
return ((
long long (*)(
unsigned long, ...))funcm[
srq].fun)(RTAI_FUN_ARGS);
00329             }
00330     }
00331 
00332     arg0.name = arg[0];
00333     
switch (
srq) {
00334         
case LXRT_GET_ADR: {
00335             
return (
unsigned long)
rt_get_adr(arg0.name);
00336         }
00337 
00338         
case LXRT_GET_NAME: {
00339             
return rt_get_name((
void *)arg0.name);
00340         }
00341 
00342         
case LXRT_TASK_INIT: {
00343             
struct arg { 
unsigned long name; 
int prio, stack_size, max_msg_size, cpus_allowed; };
00344             
return (
unsigned long) 
__task_init(arg0.name, 
larg->prio, 
larg->stack_size, 
larg->max_msg_size, 
larg->cpus_allowed);
00345         }
00346 
00347         
case LXRT_TASK_DELETE: {
00348             
return __task_delete(arg0.rt_task ? arg0.rt_task : 
task);
00349         }
00350 
00351         
case LXRT_SEM_INIT: {
00352             
if (
rt_get_adr(arg0.name)) {
00353                 
return 0;
00354             }
00355             
if ((arg0.sem = 
rt_malloc(
sizeof(
SEM)))) {
00356                 
struct arg { 
unsigned long name; 
int cnt; 
int typ; };
00357                 
lxrt_typed_sem_init(arg0.sem, 
larg->cnt, 
larg->typ);
00358                 
if (
rt_register(
larg->name, arg0.sem, 
IS_SEM, current)) {
00359                     
return arg0.name;
00360                 } 
else {
00361                     
rt_free(arg0.sem);
00362                 }
00363             }
00364             
return 0;
00365         }
00366 
00367         
case LXRT_SEM_DELETE: {
00368             
if (
lxrt_sem_delete(arg0.sem)) {
00369                 
return -EFAULT;
00370             }
00371             
rt_free(arg0.sem);
00372             
return rt_drg_on_adr(arg0.sem);
00373         }
00374 
00375         
case LXRT_MBX_INIT: {
00376             
if (
rt_get_adr(arg0.name)) {
00377                 
return 0;
00378             }
00379             
if ((arg0.mbx = 
rt_malloc(
sizeof(
MBX)))) {
00380                 
struct arg { 
unsigned long name; 
int size; 
int qtype; };
00381                 
if (
lxrt_typed_mbx_init(arg0.mbx, 
larg->size, 
larg->qtype) < 0) {
00382                     
rt_free(arg0.mbx);
00383                     
return 0;
00384                 }
00385                 
if (
rt_register(
larg->name, arg0.mbx, 
IS_MBX, current)) {
00386                     
return arg0.name;
00387                 } 
else {
00388                     
rt_free(arg0.mbx);
00389                 }
00390             }
00391             
return 0;
00392         }
00393 
00394         
case LXRT_MBX_DELETE: {
00395             
if (
lxrt_mbx_delete(arg0.mbx)) {
00396                 
return -EFAULT;
00397             }
00398             
rt_free(arg0.mbx);
00399             
return rt_drg_on_adr(arg0.mbx);
00400         }
00401 
00402         
case LXRT_RWL_INIT: {
00403             
if (
rt_get_adr(arg0.name)) {
00404                 
return 0;
00405             }
00406             
if ((arg0.rwl = 
rt_malloc(
sizeof(
RWL)))) {
00407                 
struct arg { 
unsigned long name; };
00408                 
lxrt_rwl_init(arg0.rwl);
00409                 
if (
rt_register(
larg->name, arg0.rwl, 
IS_SEM, current)) {
00410                     
return arg0.name;
00411                 } 
else {
00412                     
rt_free(arg0.rwl);
00413                 }
00414             }
00415             
return 0;
00416         }
00417 
00418         
case LXRT_RWL_DELETE: {
00419             
if (
lxrt_rwl_delete(arg0.rwl)) {
00420                 
return -EFAULT;
00421             }
00422             
rt_free(arg0.rwl);
00423             
return rt_drg_on_adr(arg0.rwl);
00424         }
00425 
00426         
case LXRT_SPL_INIT: {
00427             
if (
rt_get_adr(arg0.name)) {
00428                 
return 0;
00429             }
00430             
if ((arg0.spl = 
rt_malloc(
sizeof(
SPL)))) {
00431                 
struct arg { 
unsigned long name; };
00432                 
lxrt_spl_init(arg0.spl);
00433                 
if (
rt_register(
larg->name, arg0.spl, 
IS_SEM, current)) {
00434                     
return arg0.name;
00435                 } 
else {
00436                     
rt_free(arg0.spl);
00437                 }
00438             }
00439             
return 0;
00440         }
00441 
00442         
case LXRT_SPL_DELETE: {
00443             
if (
lxrt_spl_delete(arg0.spl)) {
00444                 
return -EFAULT;
00445             }
00446             
rt_free(arg0.spl);
00447             
return rt_drg_on_adr(arg0.spl);
00448         }
00449 
00450         
case MAKE_HARD_RT: {
00451             
if (!
task || 
task->is_hard) {
00452                  
return 0;
00453             }
00454             
steal_from_linux(
task);
00455             
return 0;
00456         }
00457 
00458         
case MAKE_SOFT_RT: {
00459             
if (!
task || !
task->is_hard) {
00460                 
return 0;
00461             }
00462             
if (
task->is_hard < 0) {
00463                 
task->is_hard = 0;
00464             } 
else {
00465                 
give_back_to_linux(
task, 0);
00466             }
00467             
return 0;
00468         }
00469         
case PRINT_TO_SCREEN: {
00470             
struct arg { 
char *display; 
int nch; };
00471             
return rtai_print_to_screen(
"%s", 
larg->display);
00472         }
00473 
00474         
case PRINTK: {
00475             
struct arg { 
char *display; 
int nch; };
00476             
return rt_printk(
"%s", 
larg->display);
00477         }
00478 
00479         
case NONROOT_HRT: {
00480             current->cap_effective |= ((1 << CAP_IPC_LOCK)  |
00481                            (1 << CAP_SYS_RAWIO) | 
00482                            (1 << CAP_SYS_NICE));
00483             
return 0;
00484         }
00485 
00486         
case RT_BUDDY: {
00487             
return task && current->rtai_tskext(
TSKEXT1) == current ? (
unsigned long)(
task) : 0;
00488         }
00489 
00490         
case HRT_USE_FPU: {
00491             
struct arg { 
RT_TASK *
task; 
int use_fpu; };
00492             
if(!
larg->use_fpu) {
00493                 
clear_lnxtsk_uses_fpu((
larg->task)->lnxtsk);
00494             } 
else {
00495                 
init_fpu((
larg->task)->lnxtsk);
00496             }
00497             
return 0;
00498         }
00499 
00500                 
case GET_USP_FLAGS: {
00501                         
return arg0.rt_task->usp_flags;
00502                 }
00503                 
case SET_USP_FLAGS: {
00504                         
struct arg { 
RT_TASK *
task; 
unsigned long flags; };
00505                         arg0.rt_task->usp_flags = 
larg->flags;
00506                         arg0.rt_task->force_soft = (arg0.rt_task->is_hard > 0) && (
larg->flags & arg0.rt_task->usp_flags_mask & 
FORCE_SOFT);
00507                         
return 0;
00508                 }
00509 
00510                 
case GET_USP_FLG_MSK: {
00511                         
return arg0.rt_task->usp_flags_mask;
00512                 }
00513 
00514                 
case SET_USP_FLG_MSK: {
00515                         
task->usp_flags_mask = arg0.name;
00516                         
task->force_soft = (
task->is_hard > 0) && (
task->usp_flags & arg0.name & 
FORCE_SOFT);
00517                         
return 0;
00518                 }
00519 
00520                 
case FORCE_TASK_SOFT: {
00521             
extern void rt_do_force_soft(
RT_TASK *rt_task);
00522                         
struct task_struct *ltsk;
00523                         
if ((ltsk = find_task_by_pid(arg0.name)))  {
00524                                 
if ((arg0.rt_task = ltsk->rtai_tskext(
TSKEXT0))) {
00525                     
if ((arg0.rt_task->force_soft = (arg0.rt_task->is_hard > 0) && 
FORCE_SOFT)) {
00526                         
rt_do_force_soft(arg0.rt_task);
00527                     }
00528                                         
return (
unsigned long)arg0.rt_task;
00529                                 }
00530                         }
00531                         
return 0;
00532                 }
00533 
00534         
case IS_HARD: {
00535             
return arg0.rt_task->is_hard;
00536         }
00537         
case GET_EXECTIME: {
00538             
struct arg { 
RT_TASK *
task; 
RTIME *exectime; };
00539             
if ((
larg->task)->exectime[0] && (
larg->task)->exectime[1]) {
00540                 
larg->exectime[0] = (
larg->task)->exectime[0]; 
00541                 
larg->exectime[1] = (
larg->task)->exectime[1]; 
00542                 
larg->exectime[2] = 
rdtsc(); 
00543             }
00544                         
return 0;
00545         }
00546         
case GET_TIMEORIG: {
00547             
struct arg { 
RTIME *time_orig; };
00548             
rt_gettimeorig(
larg->time_orig);
00549                         
return 0;
00550         }
00551 
00552         
case LINUX_SERVER_INIT: {
00553 
extern RT_TASK *lxrt_init_linux_server(
RT_TASK *master_task);
00554 
00555             arg0.rt_task->linux_syscall_server = 
__task_init((
unsigned long)arg0.rt_task, arg0.rt_task->base_priority >= BASE_SOFT_PRIORITY ? arg0.rt_task->base_priority - BASE_SOFT_PRIORITY : arg0.rt_task->base_priority, 0, 0, 1 << arg0.rt_task->runnable_on_cpus);
00556             
rt_task_resume(arg0.rt_task);
00557             
return (
long)arg0.rt_task->linux_syscall_server;
00558         }
00559 
00560             
default: {
00561             
rt_printk(
"RTAI/LXRT: Unknown srq #%d\n", 
srq);
00562             
return -ENOSYS;
00563         }
00564     }
00565     
return 0;
00566 }
00567 
00568 static inline void force_soft(
RT_TASK *task)
00569 {
00570     
if (
unlikely(
task->force_soft)) {
00571         
task->force_soft = 0;
00572         
task->usp_flags &= ~
FORCE_SOFT;
00573         
give_back_to_linux(
task, 0);
00574     }
00575 }
00576 
00577 
extern int FASTCALL(do_signal(
struct pt_regs *regs, sigset_t *oldset));
00578 static inline int rt_do_signal(
struct pt_regs *regs, 
RT_TASK *task)
00579 {
00580     
if (
unlikely(
task->unblocked)) {
00581         
int retval = 
task->unblocked < 0;
00582         
if (
task->is_hard > 0) {
00583             
give_back_to_linux(
task, -1);
00584         }
00585         
task->unblocked = 0;
00586 
#if LINUX_VERSION_CODE < KERNEL_VERSION(0,0,0)
00587 
        if (
likely(regs->LINUX_SYSCALL_NR < 
RTAI_SYSCALL_NR)) {
00588             
unsigned long saved_eax = regs->LINUX_SYSCALL_RETREG;
00589             regs->LINUX_SYSCALL_RETREG = -EINTR;
00590             do_signal(regs, NULL);
00591             regs->LINUX_SYSCALL_RETREG = saved_eax;
00592             
if (
task->is_hard < 0) {
00593                 
steal_from_linux(
task);
00594             }
00595         }
00596 
#endif
00597 
        return retval;
00598     }
00599     
return 1;
00600 }
00601 
00602 long long rtai_lxrt_invoke (
unsigned int lxsrq, 
void *arg, 
struct pt_regs *regs)
00603 {
00604     
long long retval;
00605     
RT_TASK *
task;
00606 
00607 
#ifdef CONFIG_RTAI_TRACE
00608 
    trace_true_lxrt_rtai_syscall_entry();
00609 
#endif 
00610 
00611     
if (
likely((
task = current->rtai_tskext(
TSKEXT0)) != NULL)) {
00612         
if (
unlikely(
rt_do_signal(regs, 
task))) {
00613             
force_soft(
task);
00614         }
00615     }
00616     retval = 
handle_lxrt_request(lxsrq, arg, 
task);
00617     
if (
likely(
task != NULL)) {
00618         
if (
unlikely(
rt_do_signal(regs, 
task))) {
00619             
force_soft(
task);
00620         } 
else {
00621             
task->system_data_ptr = regs;
00622             retval = -
RT_EINTR;
00623         }
00624     }
00625 
00626 
#ifdef CONFIG_RTAI_TRACE
00627 
    trace_true_lxrt_rtai_syscall_exit();
00628 
#endif 
00629 
00630     
return retval;
00631 }
00632 
00633 int set_rt_fun_ext_index(
struct rt_fun_entry *fun, 
int idx)
00634 {
00635     
if (idx > 0 && idx < 
MAX_FUN_EXT && !
rt_fun_ext[idx]) {
00636         
rt_fun_ext[idx] = fun;
00637         
return 0;
00638     }
00639     
return -EACCES;
00640 }
00641 
00642 void reset_rt_fun_ext_index( 
struct rt_fun_entry *fun, 
int idx)
00643 {
00644     
if (idx > 0 && idx < 
MAX_FUN_EXT && 
rt_fun_ext[idx] == fun) {
00645         
rt_fun_ext[idx] = 0;
00646     }
00647 }
00648 
00649 void linux_process_termination(
void)
00650 
00651 {
00652     
extern int max_slots;
00653     
unsigned long numid;
00654     
char name[8];
00655     
RT_TASK *task2delete;
00656     
struct rt_registry_entry entry;
00657     
int slot;
00658 
00659 
00660 
00661 
00662     
if (!(numid = 
is_process_registered(current))) {
00663         
return;
00664     }
00665     
for (slot = 1; slot <= 
max_slots; slot++) {
00666         
if (!
rt_get_registry_slot(slot, &entry) || entry.
tsk != current || 
rt_drg_on_name_cnt(entry.
name) <= 0) {
00667             
continue;
00668         }
00669         
num2nam(entry.
name, name);
00670         entry.
tsk = 0;
00671             
switch (entry.
type) {
00672             
case IS_SEM:
00673                 
rt_printk(
"LXRT releases SEM %s\n", name);
00674                 
lxrt_sem_delete(entry.
adr);
00675                 
rt_free(entry.
adr);
00676                 
break;
00677             
case IS_RWL:
00678                 
rt_printk(
"LXRT releases RWL %s\n", name);
00679                 
lxrt_rwl_delete(entry.
adr);
00680                 
rt_free(entry.
adr);
00681                 
break;
00682             
case IS_SPL:
00683                 
rt_printk(
"LXRT releases SPL %s\n", name);
00684                 
lxrt_spl_delete(entry.
adr);
00685                 
rt_free(entry.
adr);
00686                 
break;
00687             
case IS_MBX:
00688                 
rt_printk(
"LXRT releases MBX %s\n", name);
00689                 
lxrt_mbx_delete(entry.
adr);
00690                 
rt_free(entry.
adr);
00691                 
break;
00692             
case IS_PRX:
00693                 numid = rttask2pid(entry.
adr);
00694                 
rt_printk(
"LXRT releases PROXY PID %lu\n", numid);
00695                 
lxrt_Proxy_detach(numid);
00696                 
break;
00697             
case IS_TASK:
00698                 
rt_printk(
"LXRT deregisters task %s %d\n", name, ((
RT_TASK *)entry.
adr)->lnxtsk->pid);
00699                 
break;
00700         }
00701     }
00702     
if ((task2delete = current->rtai_tskext(
TSKEXT0))) {
00703         
if (!
clr_rtext(task2delete)) {
00704             
rt_drg_on_adr(task2delete); 
00705             
rt_printk(
"LXRT releases PID %d (ID: %s).\n", current->pid, current->comm);
00706             
rt_free(task2delete->msg_buf[0]);
00707             
rt_free(task2delete->msg_buf[1]);
00708             
rt_free(task2delete);
00709             current->rtai_tskext(
TSKEXT0) = current->rtai_tskext(
TSKEXT1) = 0;
00710         }
00711     }
00712 }
00713 
00714 void init_fun_ext (
void)
00715 {
00716     
RT_TASK *rt_linux_tasks[
NR_RT_CPUS];
00717     
rt_fun_ext[0] = 
rt_fun_lxrt;
00718     
rt_get_base_linux_task(rt_linux_tasks);
00719     rt_linux_tasks[0]->task_trap_handler[0] = (
void *)
set_rt_fun_ext_index;
00720     rt_linux_tasks[0]->task_trap_handler[1] = (
void *)
reset_rt_fun_ext_index;
00721 }