base/ipc/netrpc/netrpc.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 1999-2009 Paolo Mantegazza <mantegazza@aero.polimi.it>
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License as
00006  * published by the Free Software Foundation; either version 2 of the
00007  * License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017  */
00018 
00019 
00020 #include <linux/kernel.h>
00021 #include <linux/module.h>
00022 #include <linux/version.h>
00023 #include <linux/timer.h>
00024 #include <linux/unistd.h>
00025 #include <asm/uaccess.h>
00026 
00027 #include <net/ip.h>
00028 
00029 #include <rtai_schedcore.h>
00030 #include <rtai_prinher.h>
00031 #include <rtai_netrpc.h>
00032 #include <rtai_sem.h>
00033 #include <rtai_mbx.h>
00034 
00035 MODULE_LICENSE("GPL");
00036 
00037 #define COMPILE_ANYHOW  // RTNet is not available but we want to compile anyhow
00038 #include <rtdm.h>
00039 #include "rtnetP.h"
00040 
00041 /* ethernet support(s) we want to use: 1 -> DO, 0 -> DO NOT */
00042 
00043 #define SOFT_RTNET  1
00044 
00045 #ifdef CONFIG_RTAI_NETRPC_RTNET
00046 #define HARD_RTNET  1
00047 #else
00048 #define HARD_RTNET  0
00049 #endif
00050 
00051 /* end of ethernet support(s) we want to use */
00052 
00053 #if HARD_RTNET
00054 #ifndef COMPILE_ANYHOW
00055 #include <rtnet.h>  // must be the true RTNet header file
00056 #endif
00057 #define MSG_SOFT  0
00058 #define MSG_HARD  1
00059 #define hard_rt_socket              rt_dev_socket
00060 #define hard_rt_bind                rt_dev_bind
00061 #define hard_rt_close               rt_dev_close
00062 #define hard_rt_socket_callback     hard_rt_socket_callback
00063 #define hard_rt_recvfrom            rt_dev_recvfrom
00064 #define hard_rt_sendto              rt_dev_sendto
00065 #else
00066 #define MSG_SOFT 0
00067 #define MSG_HARD 0
00068 #define hard_rt_socket(a, b, c)     portslot[i].socket[0]
00069 #define hard_rt_bind(a, b, c)
00070 #define hard_rt_close(a)
00071 #define hard_rt_socket_callback     soft_rt_socket_callback
00072 #define hard_rt_recvfrom            soft_rt_recvfrom
00073 #define hard_rt_sendto              soft_rt_sendto
00074 #endif
00075 
00076 #define LOCALHOST  "127.0.0.1"
00077 
00078 #define BASEPORT  (NETRPC_BASEPORT)
00079 
00080 #define NETRPC_STACK_SIZE  6000
00081 
00082 static unsigned long MaxStubs = MAX_STUBS;
00083 RTAI_MODULE_PARM(MaxStubs, ulong);
00084 static int MaxStubsMone;
00085 
00086 static unsigned long MaxSocks = MAX_SOCKS;
00087 RTAI_MODULE_PARM(MaxSocks, ulong);
00088 
00089 static int StackSize = NETRPC_STACK_SIZE;
00090 RTAI_MODULE_PARM(StackSize, int);
00091 
00092 static char *ThisNode = LOCALHOST;
00093 RTAI_MODULE_PARM(ThisNode, charp);
00094 
00095 static char *ThisSoftNode = 0;
00096 RTAI_MODULE_PARM(ThisSoftNode, charp);
00097 
00098 static char *ThisHardNode = 0;
00099 RTAI_MODULE_PARM(ThisHardNode, charp);
00100 
00101 #define MAX_DFUN_EXT  16
00102 static struct rt_fun_entry *rt_net_rpc_fun_ext[MAX_DFUN_EXT];
00103 
00104 static unsigned long this_node[2];
00105 
00106 #define PRTSRVNAME  0xFFFFFFFF
00107 struct portslot_t { struct portslot_t *p; long task; int indx, place, socket[2], hard; unsigned long long owner; SEM sem; void *msg; struct sockaddr_in addr; MBX *mbx; unsigned long name;  RTIME timeout; int recovered; };
00108 static spinlock_t portslot_lock = SPIN_LOCK_UNLOCKED;
00109 static volatile int portslotsp;
00110 
00111 static spinlock_t stub_lock = SPIN_LOCK_UNLOCKED;
00112 static volatile int stubssp = 1;
00113 
00114 
00115 static struct portslot_t *portslot;
00116 static struct sockaddr_in SPRT_ADDR;
00117 struct recovery_msg { int hard, priority; unsigned long long owner; struct sockaddr addr; };
00118 static struct { int in, out; struct recovery_msg *msg; } recovery;
00119 static spinlock_t recovery_lock = SPIN_LOCK_UNLOCKED;
00120 
00121 #if HARD_RTNET
00122 int hard_rt_socket_callback(int fd, void *func, void *arg)
00123 {
00124     struct rtnet_callback args = { func, arg };
00125     return(rt_dev_ioctl(fd, RTNET_RTIOC_CALLBACK, &args));
00126 }
00127 #endif
00128 
00129 static inline struct portslot_t *get_portslot(void)
00130 {
00131     unsigned long flags;
00132 
00133     flags = rt_spin_lock_irqsave(&portslot_lock);
00134     if (portslotsp < MaxSocks) {
00135         struct portslot_t *p;
00136         p = portslot[portslotsp++].p;
00137         rt_spin_unlock_irqrestore(flags, &portslot_lock);
00138         return p;
00139     }
00140     rt_spin_unlock_irqrestore(flags, &portslot_lock);
00141     return 0;
00142 }
00143 
00144 static inline int gvb_portslot(struct portslot_t *portslotp)
00145 {
00146     unsigned long flags;
00147 
00148     flags = rt_spin_lock_irqsave(&portslot_lock);
00149     if (portslotsp > MaxStubs) {
00150         struct portslot_t *tmp_p;
00151         int tmp_place;
00152         tmp_p = portslot[--portslotsp].p;
00153         tmp_place = portslotp->place;
00154         portslotp->place = portslotsp;
00155         portslot[portslotsp].p = portslotp;
00156         tmp_p->place = tmp_place;
00157         portslot[tmp_place].p = tmp_p;
00158         rt_spin_unlock_irqrestore(flags, &portslot_lock);
00159         return 0;
00160     }
00161     rt_spin_unlock_irqrestore(flags, &portslot_lock);
00162     return -EINVAL;
00163 }
00164 
00165 static inline void check_portslot(unsigned long node, int port, struct portslot_t **p)
00166 {
00167 //  unsigned long flags;
00168     int i;
00169     struct portslot_t *p_old;
00170     
00171     p_old = *p; 
00172 //  flags = rt_spin_lock_irqsave(&portslot_lock);
00173     for (i = MaxStubs; i < portslotsp; i++) {
00174         if (portslot[i].p->addr.sin_port == htons(port) && portslot[i].p->addr.sin_addr.s_addr == node) {
00175             *p = portslot[i].p;
00176             break;
00177         }   
00178     }
00179 //  rt_spin_unlock_irqrestore(flags, &portslot_lock);
00180     if (p_old != *p)    {
00181         gvb_portslot(p_old);
00182     }
00183     
00184 }
00185 
00186 #define NETRPC_TIMER_FREQ 50
00187 static struct timer_list timer;
00188 static SEM timer_sem;
00189 
00190 static void timer_fun(unsigned long none)
00191 {
00192     if (timer_sem.count < 0) {
00193         rt_sem_signal(&timer_sem);
00194         timer.expires = jiffies + HZ/NETRPC_TIMER_FREQ;
00195         add_timer(&timer);
00196     }
00197 }
00198 
00199 static int (*encode)(struct portslot_t *portslotp, void *msg, int size, int where);
00200 static int (*decode)(struct portslot_t *portslotp, void *msg, int size, int where);
00201 
00202 void set_netrpc_encoding(void *encode_fun, void *decode_fun, void *ext)
00203 {
00204     encode = encode_fun;
00205     decode = decode_fun;
00206     rt_net_rpc_fun_ext[1] = ext;
00207 }
00208 
00209 struct req_rel_msg { long long op, port, priority, hard; unsigned long long owner, name, rem_node, chkspare;};
00210 
00211 struct par_t { long long mach, priority, base_priority, argsize, rsize, fun_ext_timed, type; unsigned long long owner, partypes; long a[1]; };
00212 
00213 struct reply_t { long long wsize, w2size, myport; unsigned long long retval; char msg[1], msg1[1]; };
00214 
00215 static inline int argconv(void *ain, void *aout, int send_mach, int argsize, unsigned int partypes)
00216 {
00217 #define recv_mach  (sizeof(long))
00218     int argsizeout;
00219     if (send_mach == recv_mach) {
00220         memcpy(aout, ain, argsize);
00221         return argsize;
00222     }
00223     argsizeout = 0;
00224     if (send_mach == 4 && recv_mach == 8) {
00225         long *out = aout;
00226         int *in = ain;
00227         while (argsize) {
00228             argsize -= 4;
00229             argsizeout += 8;
00230             switch(partypes & WDWMSK) {
00231                 case SINT: 
00232                     *out++ = *in++;
00233                     break;
00234                 case UINT:
00235                     *out++ = (unsigned int)*in++;
00236                     break;
00237                 case VADR:
00238                     *out++ = reset_kadr(*in++);
00239                     break;
00240                 case RTIM: 
00241                     *out++ = (long)*in++;
00242                     in++;
00243                     argsize -= 4;
00244                     break;
00245             }
00246             partypes >>= WDW;
00247         }
00248     } else {
00249         unsigned long *out = aout;
00250         unsigned long long *in = ain;
00251         while (argsize) {
00252             argsize -= 8;
00253             argsizeout += 4;
00254             switch(partypes & WDWMSK) {
00255                 case SINT: 
00256                 case UINT:
00257                 case VADR:
00258                     *out++ = *in++;
00259                     break;
00260                 case RTIM: 
00261                     *((unsigned long long *)out++) = *in++;
00262                     out++;
00263                     argsizeout += 4;
00264                     break;
00265             }
00266             partypes >>= WDW;
00267         }
00268     }
00269     return argsizeout;
00270 #undef recv_mach
00271 }
00272 
00273 static void net_resume_task(int sock, struct portslot_t *p)
00274 {
00275     int all_ok;
00276     RT_TASK *my;
00277     my = _rt_whoami();
00278     all_ok = 1;
00279     if ((p->indx > 0) && (p->indx < MaxStubs)) {
00280         if (!((p->task) && (p->hard == my->is_hard))) {
00281             all_ok = 0;
00282         }
00283     }
00284     if (all_ok) {
00285         rt_sem_signal(&p->sem);
00286     } else {
00287         long i;
00288         unsigned long flags;
00289         struct par_t *par;
00290         char msg[MAX_MSG_SIZE];
00291         struct sockaddr *addr;
00292         par = (void *)msg;
00293         addr = (struct sockaddr*)&p->addr;
00294         
00295         if (my->is_hard) {
00296             while (hard_rt_recvfrom(p->socket[1], msg, MAX_MSG_SIZE, 0, addr, (void *)&i) == -EAGAIN);
00297         } else {
00298             soft_rt_recvfrom(p->socket[0], msg, MAX_MSG_SIZE, 0, addr, &i);
00299         }
00300         
00301         flags = rt_spin_lock_irqsave(&recovery_lock);
00302         recovery.msg[recovery.in].priority = par->priority;
00303         recovery.msg[recovery.in].owner = par->owner;
00304         recovery.msg[recovery.in].addr = *addr;
00305         recovery.msg[recovery.in].hard = my->is_hard;
00306         recovery.in = (recovery.in + 1) & MaxStubsMone;
00307         rt_spin_unlock_irqrestore(flags, &recovery_lock);
00308         rt_sem_signal(&portslot[0].sem);
00309     }
00310 }
00311 
00312 int get_min_tasks_cpuid(void);
00313 int set_rtext(RT_TASK *, int, int, void(*)(void), unsigned int, void *);
00314 int clr_rtext(RT_TASK *);
00315 void rt_schedule_soft(RT_TASK *);
00316 
00317 static inline int soft_rt_fun_call(RT_TASK *task, void *fun, void *arg)
00318 {
00319     union { long long ll; long l; } retval;
00320     task->fun_args[0] = (long)arg;
00321     ((struct fun_args *)task->fun_args)->fun = fun;
00322     rt_schedule_soft(task);
00323     retval.ll = task->retval;
00324     return (int)retval.l;
00325 }
00326 
00327 static inline long long soft_rt_genfun_call(RT_TASK *task, void *fun, void *args, int argsize)
00328 {
00329     memcpy(task->fun_args, args, argsize);
00330     ((struct fun_args *)task->fun_args)->fun = fun;
00331     rt_schedule_soft(task);
00332     return task->retval;
00333 }
00334 
00335 extern void rt_daemonize(void);
00336 static void thread_fun(RT_TASK *task)
00337 {
00338     if (!set_rtext(task, task->fun_args[3], 0, 0, get_min_tasks_cpuid(), 0)) {
00339         rt_daemonize();
00340         sigfillset(&current->blocked);
00341         rtai_set_linux_task_priority(current, SCHED_FIFO, MIN_LINUX_RTPRIO);
00342         soft_rt_fun_call(task, rt_task_suspend, task);
00343         ((void (*)(long))task->fun_args[1])(task->fun_args[2]);
00344         task->fun_args[1] = 0;
00345     }
00346 }
00347 
00348 static int soft_kthread_init(RT_TASK *task, long fun, long arg, int priority)
00349 {
00350     task->magic = task->state = 0;
00351     (task->fun_args = (long *)(task + 1))[1] = fun;
00352     task->fun_args[2] = arg;
00353     task->fun_args[3] = priority;
00354     if (kernel_thread((void *)thread_fun, task, 0) > 0) {
00355         while (task->state != (RT_SCHED_READY | RT_SCHED_SUSPENDED)) {
00356             current->state = TASK_INTERRUPTIBLE;
00357             schedule_timeout(HZ/NETRPC_TIMER_FREQ);
00358         }
00359         return 0;
00360     }
00361     return -ENOEXEC;
00362 }
00363 
00364 static int soft_kthread_delete(RT_TASK *task)
00365 {
00366     task->fun_args[1] = 1;
00367     while (task->fun_args[1]) {
00368         rt_task_masked_unblock(task, ~RT_SCHED_READY);
00369         current->state = TASK_INTERRUPTIBLE;
00370         schedule_timeout(HZ/NETRPC_TIMER_FREQ);
00371     }
00372         clr_rtext(task);
00373     return 0;
00374 }
00375 
00376 #define ADRSZ  sizeof(struct sockaddr)
00377 
00378 static inline int get_stub(unsigned long long owner)
00379 {
00380     unsigned long flags;
00381     int i;
00382     
00383     flags = rt_spin_lock_irqsave(&stub_lock);
00384     if (stubssp < MaxStubsMone) {
00385         struct portslot_t *p;
00386         i = 1;
00387         while(((p = portslot[i].p)->owner != owner) && (i < stubssp)) {
00388             i++;
00389         }
00390         if (p->owner != owner) {
00391             p = portslot[stubssp++].p;
00392             p->owner = owner;
00393         }
00394         rt_spin_unlock_irqrestore(flags, &stub_lock);
00395         return p->indx;
00396     }
00397     rt_spin_unlock_irqrestore(flags, &stub_lock);
00398     return 0;
00399 }
00400 
00401 static inline int gvb_stub(int slot, unsigned long long owner)
00402 {
00403     unsigned long flags;
00404     RT_TASK *task;
00405 
00406     flags = rt_spin_lock_irqsave(&stub_lock);
00407     if (stubssp > 1) {
00408         if (slot > 0 && slot < MaxStubs) {
00409             if (portslot[slot].owner == owner) {
00410                 struct portslot_t *tmp_p;
00411                 int tmp_place;
00412                 task = (RT_TASK *)portslot[slot].task;
00413                 portslot[slot].task = 0;
00414                 portslot[slot].owner = 0;
00415                 tmp_p = portslot[--stubssp].p;
00416                 tmp_place = portslot[slot].place;
00417                 portslot[slot].place = stubssp;
00418                 portslot[stubssp].p = &portslot[slot];
00419                 tmp_p->place = tmp_place;
00420                 portslot[tmp_place].p = tmp_p;
00421                 slot += BASEPORT;
00422                 rt_spin_unlock_irqrestore(flags, &stub_lock);
00423                 if (task->is_hard) {
00424                     rt_task_delete(task);
00425                 } else {
00426                     soft_kthread_delete(task);
00427                 }
00428                 kfree(task);
00429             } else {
00430                 slot = !portslot[slot].owner ? slot + BASEPORT : -ENXIO;
00431                 rt_spin_unlock_irqrestore(flags, &stub_lock);
00432             }
00433         } else {
00434             rt_spin_unlock_irqrestore(flags, &stub_lock);
00435         }       
00436         return slot;
00437     }
00438     rt_spin_unlock_irqrestore(flags, &stub_lock);
00439     return -EINVAL;
00440 }
00441 
00442 static inline int find_stub(unsigned long long owner)
00443 {
00444     unsigned long flags;
00445     int i;
00446     struct portslot_t *p;
00447     i = 1;
00448     flags = rt_spin_lock_irqsave(&stub_lock);
00449     while(((p = portslot[i].p)->owner != owner) && (i < stubssp)) {
00450         i++;
00451     }
00452     rt_spin_unlock_irqrestore(flags, &stub_lock);
00453     return p->owner != owner ? 0 : p->indx;
00454 }
00455 
00456 static void soft_stub_fun(struct portslot_t *portslotp)
00457 {
00458     char msg[MAX_MSG_SIZE];
00459     struct sockaddr *addr;
00460     RT_TASK *task;
00461     SEM *sem;
00462         struct par_t *par;
00463     long wsize, w2size, sock;
00464     long *ain;
00465     long type;
00466 
00467     addr = (struct sockaddr *)&portslotp->addr;
00468     sock = portslotp->socket[0];
00469     sem  = &portslotp->sem;
00470     ain = (par = (void *)msg)->a;
00471     task = (RT_TASK *)portslotp->task;
00472     sprintf(current->comm, "SFTSTB-%ld", sock);
00473     
00474 recvrys:
00475 
00476     while (soft_rt_fun_call(task, rt_sem_wait, sem) < RTE_LOWERR) {
00477         wsize = soft_rt_recvfrom(sock, msg, MAX_MSG_SIZE, 0, addr, &w2size);
00478         if (decode) {
00479             decode(portslotp, msg, wsize, RPC_SRV);
00480         }
00481         if (portslotp->owner != par->owner) {
00482             unsigned long flags;
00483             
00484             flags = rt_spin_lock_irqsave(&recovery_lock);
00485             recovery.msg[recovery.in].priority = par->priority;
00486             recovery.msg[recovery.in].owner = par->owner;
00487             recovery.msg[recovery.in].addr = *addr;
00488             recovery.msg[recovery.in].hard = 0;
00489             recovery.in = (recovery.in + 1) & MaxStubsMone;
00490             rt_spin_unlock_irqrestore(flags, &recovery_lock);
00491             rt_sem_signal(&portslot[0].sem);
00492         } else {
00493             int argsize; 
00494             long a[par->argsize/sizeof(long) + 1];
00495             if(par->priority >= 0 && par->priority < RT_SCHED_LINUX_PRIORITY) {
00496                 if ((wsize = par->priority) < task->priority) {
00497                     task->priority = wsize;
00498                     rtai_set_linux_task_priority(task->lnxtsk, task->lnxtsk->policy, wsize >= MAX_LINUX_RTPRIO ? MIN_LINUX_RTPRIO : MAX_LINUX_RTPRIO - wsize);
00499                 }
00500                 task->base_priority = par->base_priority;
00501             }
00502             argsize = argconv(ain, a, par->mach, par->argsize, par->partypes);
00503             type = par->type;
00504             if (par->rsize) {
00505                 a[USP_RBF1(type) - 1] = (long)((char *)ain + par->argsize);
00506             }
00507             if (NEED_TO_W(type)) {
00508                 wsize = USP_WSZ1(type);
00509                 wsize = wsize ? a[wsize - 1] : par->mach; //sizeof(long);
00510             } else {
00511                 wsize = 0;
00512             }
00513             if (NEED_TO_W2ND(type)) {
00514                 w2size = USP_WSZ2(type);
00515                 w2size = w2size ? a[w2size - 1] : par->mach; //sizeof(long);
00516             } else {
00517                 w2size = 0;
00518             }
00519             do {
00520                 struct msg_t { struct reply_t arg; char bufspace[wsize + w2size]; } arg;
00521                 arg.arg.myport = 0;
00522                 if (wsize > 0) {
00523                     arg.arg.wsize = wsize;
00524                     a[USP_WBF1(type) - 1] = (long)arg.arg.msg;
00525                 } else {
00526                     arg.arg.wsize = 0;
00527                 }
00528                 if (w2size > 0) {
00529                     arg.arg.w2size = w2size;
00530                     a[USP_WBF2(type) - 1] = (long)(arg.arg.msg + arg.arg.wsize);
00531                 } else {
00532                     arg.arg.w2size = 0;
00533                 }
00534 #ifndef NETRPC_ALIGN_RTIME
00535                 if ((wsize = TIMED(par->fun_ext_timed) - 1) >= 0) {
00536 #else
00537                 if ((wsize = TIMED(par->fun_ext_timed)) > 0) {
00538                     wsize += (NETRPC_ALIGN_RTIME(wsize) - 1);
00539 #endif
00540                     *((long long *)(a + wsize)) = nano2count(*((long long *)(a + wsize)));
00541                 }
00542                 arg.arg.retval = soft_rt_genfun_call(task, rt_net_rpc_fun_ext[EXT(par->fun_ext_timed)][FUN(par->fun_ext_timed)].fun, a, argsize);
00543                 soft_rt_sendto(sock, &arg, encode ? encode(portslotp, &arg, sizeof(struct msg_t), RPC_RTR) : sizeof(struct msg_t), 0, addr, ADRSZ);
00544             } while (0);
00545         }
00546     }
00547     if (portslotp->recovered) {
00548         struct reply_t arg;
00549         portslotp->recovered = 0;
00550         arg.myport = sock + BASEPORT;
00551         arg.retval = portslotp->owner;
00552         soft_rt_sendto(sock, &arg, encode ? encode(portslotp, &arg, sizeof(struct reply_t), RPC_RTR) : sizeof(struct reply_t), 0, addr, ADRSZ);
00553         goto recvrys;
00554     }
00555 //  soft_rt_fun_call(task, rt_task_suspend, task);
00556 }
00557 
00558 static void hard_stub_fun(struct portslot_t *portslotp)
00559 {
00560     char msg[MAX_MSG_SIZE];
00561     struct sockaddr *addr;
00562     RT_TASK *task;
00563     SEM *sem;
00564     struct par_t *par;
00565     long wsize, w2size, sock;
00566     long *ain;
00567     long type;
00568 
00569     addr = (struct sockaddr *)&portslotp->addr;
00570     sock = portslotp->socket[1];
00571     sem  = &portslotp->sem;
00572     ain = (par = (void *)msg)->a;
00573     task = (RT_TASK *)portslotp->task;
00574     if (task->lnxtsk) {
00575         sprintf(current->comm, "HRDSTB-%ld", sock);
00576     }
00577     
00578 recvryh:
00579 
00580     while (rt_sem_wait(sem) < RTE_LOWERR) {
00581         wsize = hard_rt_recvfrom(sock, msg, MAX_MSG_SIZE, 0, addr, (void *)&w2size);
00582         if (decode) {
00583             decode(portslotp, msg, wsize, RPC_SRV);
00584         }
00585         if (portslotp->owner != par->owner) {
00586             unsigned long flags;
00587 
00588             flags = rt_spin_lock_irqsave(&recovery_lock);
00589             recovery.msg[recovery.in].priority = par->priority;
00590             recovery.msg[recovery.in].owner = par->owner;
00591             recovery.msg[recovery.in].addr = *addr;
00592             recovery.msg[recovery.in].hard = 1;
00593             recovery.in = (recovery.in + 1) & MaxStubsMone;
00594             rt_spin_unlock_irqrestore(flags, &recovery_lock);
00595             rt_sem_signal(&portslot[0].sem);
00596         } else {
00597             int argsize;
00598             long a[par->argsize/sizeof(long) + 1];
00599             if(par->priority >= 0 && par->priority < RT_SCHED_LINUX_PRIORITY) {
00600                 if ((wsize = par->priority) < task->priority) {
00601                     task->priority = wsize;
00602                 }
00603                 task->base_priority = par->base_priority;
00604             }
00605             argsize = argconv(ain, a, par->mach, par->argsize, par->partypes);
00606             type = par->type;
00607             if (par->rsize) {
00608                 a[USP_RBF1(type) - 1] = (long)((char *)ain + par->argsize);
00609             }
00610             if (NEED_TO_W(type)) {
00611                 wsize = USP_WSZ1(type);
00612                 wsize = wsize ? a[wsize - 1] : par->mach; //sizeof(long);
00613             } else {
00614                 wsize = 0;
00615             }
00616             if (NEED_TO_W2ND(type)) {
00617                 w2size = USP_WSZ2(type);
00618                 w2size = w2size ? a[w2size - 1] : par->mach; //sizeof(long);
00619             } else {
00620                 w2size = 0;
00621             }
00622             do {
00623                 struct msg_t { struct reply_t arg; char bufspace[wsize + w2size]; } arg;
00624                 arg.arg.myport = 0;
00625                 if (wsize > 0) {
00626                     arg.arg.wsize = wsize;
00627                     a[USP_WBF1(type) - 1] = (long)arg.arg.msg;
00628                 } else {
00629                     arg.arg.wsize = 0;
00630                 }
00631                 if (w2size > 0) {
00632                     arg.arg.w2size = w2size;
00633                     a[USP_WBF2(type) - 1] = (long)(arg.arg.msg + arg.arg.wsize);
00634                 } else {
00635                     arg.arg.w2size = 0;
00636                 }
00637 #ifndef NETRPC_ALIGN_RTIME
00638                 if ((wsize = TIMED(par->fun_ext_timed) - 1) >= 0) {
00639 #else
00640                 if ((wsize = TIMED(par->fun_ext_timed)) > 0) {
00641                     wsize += (NETRPC_ALIGN_RTIME(wsize) - 1);
00642 #endif
00643                     *((long long *)(a + wsize)) = nano2count(*((long long *)(a + wsize)));
00644                 }
00645                 arg.arg.retval = ((long long (*)(long, ...))rt_net_rpc_fun_ext[EXT(par->fun_ext_timed)][FUN(par->fun_ext_timed)].fun)(RTAI_FUN_A);
00646                 hard_rt_sendto(sock, &arg, encode ? encode(portslotp, &arg, sizeof(struct msg_t), RPC_RTR) : sizeof(struct msg_t), 0, addr, ADRSZ);
00647             } while (0);
00648         }
00649     }
00650     if (portslotp->recovered) {
00651         struct reply_t arg;
00652         portslotp->recovered = 0;
00653         arg.myport = sock + BASEPORT;
00654         arg.retval = portslotp->owner;
00655         hard_rt_sendto(sock, &arg, encode ? encode(portslotp, &arg, sizeof(struct reply_t), RPC_RTR) : sizeof(struct reply_t), 0, addr, ADRSZ);
00656         goto recvryh;
00657     }
00658     rt_task_suspend(task);
00659 }
00660 
00661 static void port_server_fun(RT_TASK *port_server)
00662 {
00663     short recovered;
00664     long i, rsize;
00665     RT_TASK *task;
00666     struct sockaddr *addr;
00667     struct req_rel_msg msg;
00668 
00669     addr = (struct sockaddr *)&portslot[0].addr;
00670     sprintf(current->comm, "PRTSRV");
00671 
00672     while (soft_rt_fun_call(port_server, rt_sem_wait, &portslot[0].sem) < RTE_LOWERR) {
00673         if (recovery.out != recovery.in) {
00674             recovered = 1;
00675             msg.priority = recovery.msg[recovery.out].priority;
00676             msg.hard = recovery.msg[recovery.out].hard;
00677             msg.owner = recovery.msg[recovery.out].owner;
00678             msg.name = TSK_FRM_WNR(recovery.msg[recovery.out].owner);
00679             *addr = recovery.msg[recovery.out].addr;
00680             msg.op = 0;
00681             msg.port = 0;
00682             recovery.out = (recovery.out + 1) & MaxStubsMone;
00683         } else {
00684             recovered = 0;
00685             rsize = soft_rt_recvfrom(portslot[0].socket[0], &msg, sizeof(msg), 0, addr, &i);
00686             if (decode) {
00687                 decode(&portslot[0], &msg, rsize, PRT_SRV);
00688             }
00689         }
00690         if (msg.op) {
00691             msg.port = gvb_stub(msg.op - BASEPORT, msg.owner);
00692             goto ret;
00693         }
00694         if (!(msg.port = get_stub(msg.owner))) {
00695             msg.port = -ENODEV;
00696             goto ret;
00697         }
00698         if (!portslot[msg.port].task) {
00699             if ((task = kmalloc(sizeof(RT_TASK) + 2*sizeof(struct fun_args), GFP_KERNEL))) {
00700                 if ((msg.hard ? rt_task_init(task, (void *)hard_stub_fun, (long)(portslot + msg.port), StackSize + 2*MAX_MSG_SIZE, msg.priority, 0, NULL) : soft_kthread_init(task, (long)soft_stub_fun, (long)(portslot + msg.port), msg.priority < BASE_SOFT_PRIORITY ? msg.priority + BASE_SOFT_PRIORITY : msg.priority))) {
00701                     kfree(task);
00702                     task = 0;
00703                 }
00704             }
00705             if (!task) {
00706                 portslot[msg.port].owner = 0;
00707                 msg.port = -ENOMEM;
00708                 goto ret;
00709             }
00710             portslot[msg.port].name = msg.name;
00711             portslot[msg.port].task = (long)task;
00712             if (msg.hard) { 
00713                 portslot[msg.port].hard = MSG_HARD;
00714             } else {
00715                 portslot[msg.port].hard = MSG_SOFT;
00716             }
00717             portslot[msg.port].sem.count = 0;
00718             portslot[msg.port].sem.queue.prev = portslot[msg.port].sem.queue.next = &portslot[msg.port].sem.queue;
00719             portslot[msg.port].addr = portslot[0].addr;
00720             rt_task_resume(task);
00721         }
00722         portslot[msg.port].recovered = recovered;
00723         msg.rem_node = this_node[msg.hard];
00724         msg.port += BASEPORT;
00725         msg.chkspare = sizeof(long);
00726 ret:
00727         if (recovered) {
00728             rt_task_masked_unblock((RT_TASK *)portslot[msg.port-BASEPORT].task,~RT_SCHED_READY);
00729         } else {
00730             soft_rt_sendto(portslot[0].socket[0], &msg, encode ? encode(&portslot[0], &msg, sizeof(msg), PRT_RTR) : sizeof(msg), 0, addr, ADRSZ);
00731         }
00732     }
00733 //soft_rt_fun_call(port_server, rt_task_suspend, port_server);
00734 }
00735 
00736 static int mod_timer_srq;
00737 
00738 RTAI_SYSCALL_MODE int rt_send_req_rel_port(unsigned long node, int op, unsigned long id, MBX *mbx, int hard)
00739 {
00740     RT_TASK *task;
00741     long i, msgsize;
00742     struct portslot_t *portslotp;
00743     struct req_rel_msg msg;
00744 
00745     op >>= PORT_SHF;
00746     if (!node || (op && (op < MaxStubs || op >= MaxSocks))) {
00747         return -EINVAL;
00748     }
00749     if (!(portslotp = get_portslot())) {
00750         return -ENODEV;
00751     }
00752     portslotp->name = PRTSRVNAME;
00753     portslotp->addr = SPRT_ADDR;
00754     portslotp->addr.sin_addr.s_addr = node;
00755     task = _rt_whoami();
00756     if (op) {
00757         msg.op = ntohs(portslot[op].addr.sin_port);
00758         id = portslot[op].name;
00759         hard = portslot[op].hard;
00760     } else {
00761         msg.op = 0;
00762         if (!id) {
00763             id = (unsigned long)task;
00764         }
00765     }
00766     msg.port = portslotp->sem.count = 0;
00767     portslotp->sem.queue.prev = portslotp->sem.queue.next = &portslotp->sem.queue;
00768     msg.hard = hard ? MSG_HARD : MSG_SOFT;
00769     msg.name = id;
00770     msg.owner = OWNER(this_node[0], id);
00771     msg.rem_node = 0;
00772     msg.priority = task->base_priority;
00773     msgsize = encode ? encode(&portslot[0], &msg, sizeof(msg), PRT_REQ) : sizeof(msg);
00774     for (i = 0; i < NETRPC_TIMER_FREQ && !portslotp->sem.count; i++) {
00775         soft_rt_sendto(portslotp->socket[0], &msg, msgsize, 0, (void *)&portslotp->addr, ADRSZ);
00776         rt_pend_linux_srq(mod_timer_srq);
00777         rt_sem_wait(&timer_sem);
00778     }
00779     if (portslotp->sem.count >= 1) {
00780         msgsize = soft_rt_recvfrom(portslotp->socket[0], &msg, sizeof(msg), 0, (void *)&portslotp->addr, &i);   
00781         if (decode) {
00782             decode(&portslot[0], &msg, msgsize, PRT_RCV);
00783         }
00784         if (msg.port > 0) {
00785             if (op) {
00786                 portslot[op].task = 0;
00787                 gvb_portslot(portslot + op);
00788                 gvb_portslot(portslotp);
00789                 return op;
00790             } else {
00791                 check_portslot(node, msg.port, &portslotp);
00792                 portslotp->sem.count = 0;
00793                 portslotp->sem.queue.prev = portslotp->sem.queue.next = &portslotp->sem.queue;
00794                 portslotp->hard = msg.hard;
00795                 portslotp->owner = msg.owner;
00796                 portslotp->name = msg.name;
00797                 portslotp->addr.sin_port = htons(msg.port);
00798                 portslotp->mbx  = mbx;
00799                 portslotp->recovered = 1;
00800                 portslotp->addr.sin_addr.s_addr = msg.rem_node; 
00801                 if (msg.chkspare == 4) {
00802                     return (portslotp->indx << PORT_SHF);
00803                 } else {
00804                     return (portslotp->indx << PORT_SHF) + PORT_INC;
00805                 }
00806             }
00807         }
00808     }
00809     gvb_portslot(portslotp);
00810     return msg.port ? msg.port : -ETIMEDOUT;
00811 }
00812 
00813 RTAI_SYSCALL_MODE int rt_set_netrpc_timeout(int port, RTIME timeout)
00814 {
00815     portslot[port >> PORT_SHF].timeout = timeout;
00816     return 0;
00817 }
00818 
00819 RTAI_SYSCALL_MODE RT_TASK *rt_find_asgn_stub(unsigned long long owner, int asgn)
00820 {
00821     int i;
00822     i = asgn ? get_stub(owner) : find_stub(owner);
00823     return i > 0 ? (RT_TASK *)portslot[i].task : 0;
00824 }
00825 
00826 RTAI_SYSCALL_MODE int rt_rel_stub(unsigned long long owner)
00827 {
00828     int i;
00829     i = find_stub(owner);
00830     if (i)
00831     {
00832     i = gvb_stub(i,owner);  
00833     return i;
00834     } else {
00835     return -ESRCH;
00836     }
00837 }
00838 
00839 RTAI_SYSCALL_MODE int rt_waiting_return(unsigned long node, int port)
00840 {
00841     struct portslot_t *portslotp;
00842     portslotp = portslot + (abs(port) >> PORT_SHF);
00843     return portslotp->task < 0 && !portslotp->sem.count;
00844 }
00845 
00846 #if 0
00847 
00848 static inline void mbx_send_if(MBX *mbx, void *sendmsg, int msg_size)
00849 {
00850 #define MOD_SIZE(indx) ((indx) < mbx->size ? (indx) : (indx) - mbx->size)
00851 
00852     unsigned long flags;
00853     int tocpy, avbs;
00854     char *msg;
00855 
00856     if (!mbx) {
00857         return;
00858     }
00859     msg = sendmsg;
00860     if (msg_size <= mbx->frbs) {
00861         RT_TASK *task;
00862         avbs = mbx->avbs;
00863         while (msg_size > 0 && mbx->frbs) {
00864             if ((tocpy = mbx->size - mbx->lbyte) > msg_size) {
00865                 tocpy = msg_size;
00866             }
00867             if (tocpy > mbx->frbs) {
00868                 tocpy = mbx->frbs;
00869             }
00870             memcpy(mbx->bufadr + mbx->lbyte, msg, tocpy);
00871             flags = rt_spin_lock_irqsave(&mbx->lock);
00872             mbx->frbs -= tocpy;
00873             rt_spin_unlock_irqrestore(flags, &mbx->lock);
00874             avbs += tocpy;
00875             msg_size -= tocpy;
00876             *msg += tocpy;
00877             mbx->lbyte = MOD_SIZE(mbx->lbyte + tocpy);
00878         }
00879         mbx->avbs = avbs;
00880         flags = rt_global_save_flags_and_cli();
00881         if ((task = mbx->waiting_task)) {
00882             rem_timed_task(task);
00883             mbx->waiting_task = (void *)0;
00884                     if (task->state != RT_SCHED_READY && (task->state &= ~(RT_SCHED_MBXSUSP | RT_SCHED_DELAYED)) == RT_SCHED_READY) {
00885                             enq_ready_task(task);
00886                 rt_schedule();
00887                 }
00888         }
00889         rt_global_restore_flags(flags);
00890     }
00891 }
00892 
00893 #else
00894 
00895 static inline void mbx_signal(MBX *mbx)
00896 {
00897     unsigned long flags;
00898     RT_TASK *task;
00899 
00900     flags = rt_global_save_flags_and_cli();
00901     if ((task = mbx->waiting_task)) {
00902         rem_timed_task(task);
00903         task->blocked_on  = NULL;
00904         mbx->waiting_task = NULL;
00905         if (task->state != RT_SCHED_READY && (task->state &= ~(RT_SCHED_MBXSUSP | RT_SCHED_DELAYED)) == RT_SCHED_READY) {
00906             enq_ready_task(task);
00907             RT_SCHEDULE(task, rtai_cpuid());
00908         }
00909     }
00910     rt_global_restore_flags(flags);
00911 }
00912 
00913 #define MOD_SIZE(indx) ((indx) < mbx->size ? (indx) : (indx) - mbx->size)
00914 
00915 static inline void mbxput(MBX *mbx, char **msg, int msg_size)
00916 {
00917     unsigned long flags;
00918     int tocpy;
00919 
00920     while (msg_size > 0 && mbx->frbs) {
00921         if ((tocpy = mbx->size - mbx->lbyte) > msg_size) {
00922             tocpy = msg_size;
00923         }
00924         if (tocpy > mbx->frbs) {
00925             tocpy = mbx->frbs;
00926         }
00927         memcpy(mbx->bufadr + mbx->lbyte, *msg, tocpy);
00928         flags = rt_spin_lock_irqsave(&(mbx->lock));
00929         mbx->frbs -= tocpy;
00930         mbx->avbs += tocpy;
00931         rt_spin_unlock_irqrestore(flags, &(mbx->lock));
00932         msg_size -= tocpy;
00933         *msg     += tocpy;
00934         mbx->lbyte = MOD_SIZE(mbx->lbyte + tocpy);
00935     }
00936 }
00937 
00938 static void mbx_send_if(MBX *mbx, void *msg, int msg_size)
00939 {
00940     unsigned long flags;
00941     RT_TASK *rt_current;
00942 
00943     if (!mbx || mbx->magic != RT_MBX_MAGIC) {
00944         return;
00945     }
00946 
00947     flags = rt_global_save_flags_and_cli();
00948     rt_current = RT_CURRENT;
00949     if (mbx->sndsem.count > 0 && msg_size <= mbx->frbs) {
00950         mbx->sndsem.count = 0;
00951         if (mbx->sndsem.type > 0) {
00952             mbx->sndsem.owndby = rt_current;
00953             enqueue_resqel(&mbx->sndsem.resq, rt_current);
00954         }
00955         rt_global_restore_flags(flags);
00956         mbxput(mbx, (char **)(&msg), msg_size);
00957         mbx_signal(mbx);
00958         rt_sem_signal(&mbx->sndsem);
00959     }
00960     rt_global_restore_flags(flags);
00961 }
00962 
00963 #endif
00964 
00965 #define RETURN_ERR(err) \
00966     do { \
00967         union { long long ll; long l; } retval; \
00968         retval.l = err; \
00969         return retval.ll; \
00970     } while (0)
00971 
00972 RTAI_SYSCALL_MODE long long _rt_net_rpc(long fun_ext_timed, long type, void *args, int argsize, int space, unsigned long partypes)
00973 {
00974     char msg[MAX_MSG_SIZE];
00975     struct reply_t *reply;
00976     long rsize, port;
00977     struct portslot_t *portslotp;
00978 
00979     if ((port = PORT(fun_ext_timed)) > 0) {
00980         port >>= PORT_SHF;
00981         if ((portslotp = portslot + port)->task < 0) {
00982             long i;
00983             struct sockaddr addr;
00984             
00985             if (portslotp->timeout) {
00986                 if(rt_sem_wait_timed(&portslotp->sem,portslotp->timeout) == RTE_TIMOUT)
00987                     RETURN_ERR(RTE_NETIMOUT);
00988             } else {
00989                 rt_sem_wait(&portslotp->sem);
00990             }
00991             if ((rsize = portslotp->hard ? hard_rt_recvfrom(portslotp->socket[1], msg, MAX_MSG_SIZE, 0, &addr, (void *)&i) : soft_rt_recvfrom(portslotp->socket[0], msg, MAX_MSG_SIZE, 0, &addr, &i))) {
00992                 if (decode) {
00993                     rsize = decode(portslotp, msg, rsize, RPC_RCV);
00994                 }
00995                 if((reply = (void *)msg)->myport) {
00996                     if (reply->myport < 0) {
00997                         RETURN_ERR(-RTE_CHGPORTERR);    
00998                     }
00999                     portslotp->addr.sin_port = htons(reply->myport);
01000                     portslotp->sem.count = 0;
01001                     portslotp->sem.queue.prev = portslotp->sem.queue.next = &portslotp->sem.queue;
01002                     portslotp->owner = reply->retval;
01003                     portslotp->name = (unsigned long)(_rt_whoami());
01004                     RETURN_ERR(-RTE_CHGPORTOK);
01005                 }
01006                 mbx_send_if(portslotp->mbx, msg, offsetof(struct reply_t, msg) + reply->wsize + reply->w2size);
01007 //              mbx_send_if(portslotp->mbx, msg, rsize);
01008             }
01009             portslotp->task = 1;
01010         }
01011         portslotp->msg = msg;
01012     } else {
01013         port = -(abs(port) >> PORT_SHF);
01014         if ((portslotp = portslot - port)->task < 0) {
01015             if (!rt_sem_wait_if(&portslotp->sem)) {
01016                 return 0;
01017             } else {
01018                 long i;
01019                 struct sockaddr addr;
01020                 
01021                 if ((rsize = portslotp->hard ? hard_rt_recvfrom(portslotp->socket[1], msg, MAX_MSG_SIZE, 0, &addr, (void *)&i) : soft_rt_recvfrom(portslotp->socket[0], msg, MAX_MSG_SIZE, 0, &addr, &i))) {
01022                     if (decode) {
01023                         rsize = decode(portslotp, msg, rsize, RPC_RCV);
01024                     }
01025                         if((reply = (void *)msg)->myport) {
01026                             if (reply->myport < 0) {
01027                                 RETURN_ERR(-RTE_CHGPORTERR);
01028                             }
01029 
01030                                 portslotp->addr.sin_port = htons(reply->myport);
01031                                 portslotp->sem.count = 0;
01032                                 portslotp->sem.queue.prev = portslotp->sem.queue.next = &portslotp->sem.queue;
01033                                 portslotp->owner = reply->retval;
01034                                 portslotp->name = (unsigned long)(_rt_whoami());
01035                                 RETURN_ERR(-RTE_CHGPORTOK);
01036                         }
01037                     mbx_send_if(portslotp->mbx, msg, offsetof(struct reply_t, msg) + reply->wsize + reply->w2size);
01038 //                  mbx_send_if(portslotp->mbx, msg, rsize);
01039                 }
01040             }
01041         } else {
01042             portslotp->task = -1;
01043         }
01044     }
01045     if (FUN(fun_ext_timed) == SYNC_NET_RPC) {
01046         RETURN_ERR(1);
01047     }
01048     if (NEED_TO_R(type)) {
01049         rsize = USP_RSZ1(type);
01050         rsize = rsize ? ((long *)args)[rsize - 1] : sizeof(long);
01051     } else {
01052         rsize = 0;
01053     }
01054     do {
01055         struct par_t *arg;
01056         RT_TASK *task;
01057 
01058         arg = (void *)msg;
01059         arg->priority = (task = _rt_whoami())->priority;
01060         arg->base_priority = task->base_priority;
01061         arg->argsize = argsize;
01062         arg->rsize = rsize;
01063         arg->fun_ext_timed = fun_ext_timed;
01064         arg->type = type;
01065         arg->owner = portslotp->owner;
01066         arg->partypes = partypes;
01067         memcpy(arg->a, args, argsize);
01068         if (rsize > 0) {
01069             if (space) {
01070                 memcpy((char *)arg->a + argsize, (void *)((long *)args + USP_RBF1(type) - 1)[0], rsize);
01071             } else {
01072                 rt_copy_from_user((char *)arg->a + argsize, (void *)((long *)args + USP_RBF1(type) - 1)[0], rsize);
01073             }
01074         }
01075         rsize = sizeof(struct par_t) - sizeof(long) + argsize + rsize;
01076         if (encode) {
01077             rsize = encode(portslotp, msg, rsize, RPC_REQ);
01078         }
01079         arg->mach = sizeof(long);
01080         if (portslotp->hard) {
01081             hard_rt_sendto(portslotp->socket[1], msg, rsize, 0, (struct sockaddr *)&portslotp->addr, ADRSZ);
01082         } else  {
01083             soft_rt_sendto(portslotp->socket[0], msg, rsize, 0, (struct sockaddr *)&portslotp->addr, ADRSZ);
01084         }
01085     } while (0);
01086     if (port > 0) {
01087         struct sockaddr addr;
01088 
01089         if (portslotp->timeout) {
01090             if(rt_sem_wait_timed(&portslotp->sem,portslotp->timeout) == RTE_TIMOUT)
01091                 RETURN_ERR(-RTE_NETIMOUT);
01092         } else {
01093             rt_sem_wait(&portslotp->sem);
01094         }
01095         rsize = portslotp->hard ? hard_rt_recvfrom(portslotp->socket[1], msg, MAX_MSG_SIZE, 0, &addr, (void *)&port) : soft_rt_recvfrom(portslotp->socket[0], msg, MAX_MSG_SIZE, 0, &addr, &port);
01096         if (decode) {
01097             decode(portslotp, portslotp->msg, rsize, RPC_RCV);
01098         }
01099         if((reply = (void *)msg)->myport) {
01100             if (reply->myport < 0) {
01101                 RETURN_ERR(-RTE_CHGPORTERR);    
01102             }
01103             portslotp->addr.sin_port = htons(reply->myport);
01104             portslotp->sem.count = 0;
01105             portslotp->sem.queue.prev = portslotp->sem.queue.next = &portslotp->sem.queue;
01106             portslotp->owner = reply->retval;
01107             portslotp->name = (unsigned long)(_rt_whoami());
01108             RETURN_ERR(-RTE_CHGPORTOK);
01109         } else {
01110             if (reply->wsize) {
01111                 if (space) {
01112                     memcpy((char *)(*((long *)args + USP_WBF1(type) - 1)), reply->msg, reply->wsize);
01113                 } else {
01114                     rt_copy_to_user((char *)(*((long *)args + USP_WBF1(type) - 1)), reply->msg, reply->wsize);
01115                 }
01116                 if (reply->w2size) {
01117                     if (space) {
01118                         memcpy((char *)(*((long *)args + USP_WBF2(type) - 1)), reply->msg + reply->wsize, reply->w2size);
01119                     } else {
01120                         rt_copy_to_user((char *)(*((long *)args + USP_WBF2(type) - 1)), reply->msg + reply->wsize, reply->w2size);
01121                     }
01122                 }
01123             }
01124 
01125             return reply->retval;
01126         }
01127     }
01128     return 0;
01129 }
01130 
01131 int rt_get_net_rpc_ret(MBX *mbx, unsigned long long *retval, void *msg1, int *msglen1, void *msg2, int *msglen2, RTIME timeout, int type)
01132 {
01133     struct reply_t reply;
01134     int ret;
01135 
01136     if ((ret = ((int (*)(MBX *, ...))rt_net_rpc_fun_ext[NET_RPC_EXT][type].fun)(mbx, &reply, offsetof(struct reply_t, msg), timeout))) {
01137         return ret;
01138     }
01139     *retval = reply.retval;
01140     if (reply.wsize) {
01141         if (*msglen1 > reply.wsize) {
01142             *msglen1 = reply.wsize;
01143         }
01144         _rt_mbx_receive(mbx, &msg1, *msglen1, 1);
01145     } else {
01146         *msglen1 = 0;
01147     }
01148     if (reply.w2size) {
01149         if (*msglen2 > reply.w2size) {
01150             *msglen2 = reply.w2size;
01151         }
01152         _rt_mbx_receive(mbx, &msg2, *msglen2, 1);
01153     } else {
01154         *msglen2 = 0;
01155     }
01156     return 0;
01157 }
01158 
01159 RTAI_SYSCALL_MODE unsigned long ddn2nl(const char *ddn)
01160 {
01161     int p, n, c;
01162     union { unsigned long l; char c[4]; } u;
01163 
01164     p = n = 0;
01165     while ((c = *ddn++)) {
01166         if (c != '.') {
01167             n = n*10 + c - '0';
01168         } else {
01169             if (n > 0xFF) {
01170                 return 0;
01171             }
01172             u.c[p++] = n;
01173             n = 0;
01174         }
01175     }
01176     u.c[3] = n;
01177 
01178     return u.l;
01179 }
01180 
01181 RTAI_SYSCALL_MODE unsigned long rt_set_this_node(const char *ddn, unsigned long node, int hard)
01182 {
01183     return this_node[hard ? MSG_HARD : MSG_SOFT] = ddn ? ddn2nl(ddn) : node;
01184 }
01185 
01186 #ifdef CONFIG_RTAI_RT_POLL
01187 
01188 RTAI_SYSCALL_MODE int rt_poll_netrpc(struct rt_poll_s *pdsa1, struct rt_poll_s *pdsa2, unsigned long pdsa_size, RTIME timeout)
01189 {
01190     int retval = pdsa_size/sizeof(struct rt_poll_s);
01191     if (sizeof(long) == 8 && !((unsigned long)pdsa1[0].what & 0xFFFFFFFF00000000ULL)) {
01192         int i;
01193         for (i = 0; i < retval; i++) {
01194             pdsa1[i].what = (void *)reset_kadr((unsigned long)pdsa1[i].what);
01195         }
01196     }
01197     retval = _rt_poll(pdsa1, retval, timeout, 1);
01198     memcpy(pdsa2, pdsa1, pdsa_size);
01199     return retval;
01200 }
01201 
01202 EXPORT_SYMBOL(rt_poll_netrpc);
01203 
01204 #endif
01205 
01206 /* +++++++++++++++++++++++++++ NETRPC ENTRIES +++++++++++++++++++++++++++++++ */
01207 
01208 struct rt_native_fun_entry rt_netrpc_entries[] = {
01209     { { 1, _rt_net_rpc           },  NETRPC },
01210     { { 0, rt_set_netrpc_timeout },  SET_NETRPC_TIMEOUT },
01211     { { 1, rt_send_req_rel_port  },  SEND_REQ_REL_PORT },
01212     { { 0, ddn2nl                },  DDN2NL },
01213     { { 0, rt_set_this_node      },  SET_THIS_NODE },
01214     { { 0, rt_find_asgn_stub     },  FIND_ASGN_STUB },
01215     { { 0, rt_rel_stub           },  REL_STUB },
01216     { { 0, rt_waiting_return     },  WAITING_RETURN },
01217 #ifdef CONFIG_RTAI_RT_POLL
01218     { { 1, rt_poll_netrpc        },  RT_POLL_NETRPC },
01219 #endif
01220     { { 0, 0 },                     000 }
01221 };
01222 
01223 extern int set_rt_fun_entries(struct rt_native_fun_entry *entry);
01224 extern void reset_rt_fun_entries(struct rt_native_fun_entry *entry);
01225 
01226 static RT_TASK *port_server;
01227 
01228 static int init_softrtnet(void);
01229 static void cleanup_softrtnet(void);
01230 
01231 void do_mod_timer(void)
01232 {
01233     mod_timer(&timer, jiffies + HZ/NETRPC_TIMER_FREQ);
01234 }
01235 
01236 static struct sock_t *socks;
01237 
01238 int soft_rt_socket(int domain, int type, int protocol)
01239 {
01240     int i;
01241     for (i = 0; i < MaxSocks; i++) {
01242         if (!cmpxchg(&socks[i].opnd, 0, 1)) {
01243             return i;
01244         }
01245     }
01246     return -1;
01247 }
01248 
01249 int soft_rt_close(int sock)
01250 {
01251     if (sock >= 0 && sock < MaxSocks) {
01252         return socks[sock].opnd = 0;
01253     }
01254     return -1;
01255 }
01256 
01257 int soft_rt_bind(int sock, struct sockaddr *addr, int addrlen)
01258 {
01259     return 0;
01260 }
01261 
01262 int soft_rt_socket_callback(int sock, int (*func)(int sock, void *arg), void *arg)
01263 {
01264     if (sock >= 0 && sock < MaxSocks && func > 0) {
01265         socks[sock].callback = func;
01266         socks[sock].arg      = arg;
01267         return 0;
01268     }
01269     return -1;
01270 }
01271 
01272 static int MaxSockSrq;
01273 static struct { int srq, in, out, *sockindx; } sysrq;
01274 static spinlock_t sysrq_lock = SPIN_LOCK_UNLOCKED;
01275 
01276 int soft_rt_sendto(int sock, const void *msg, int msglen, unsigned int sflags, struct sockaddr *to, int tolen)
01277 {
01278     unsigned long flags;
01279     if (sock >= 0 && sock < MaxSocks) {
01280         if (msglen > MAX_MSG_SIZE) {
01281             msglen = MAX_MSG_SIZE;
01282         }
01283         memcpy(socks[sock].msg, msg, socks[sock].tosend = msglen);
01284         memcpy(&socks[sock].addr, to, tolen);
01285         flags = rt_spin_lock_irqsave(&sysrq_lock);
01286         sysrq.sockindx[sysrq.in] = sock;
01287             sysrq.in = (sysrq.in + 1) & MaxSockSrq;
01288         rt_spin_unlock_irqrestore(flags, &sysrq_lock);
01289         rt_pend_linux_srq(sysrq.srq);
01290         return msglen;
01291     }
01292     return -1;
01293 }
01294 
01295 int soft_rt_recvfrom(int sock, void *msg, int msglen, unsigned int flags, struct sockaddr *from, long *fromlen)
01296 {
01297     if (sock >= 0 && sock < MaxSocks) {
01298         if (msglen > socks[sock].recvd) {
01299             msglen = socks[sock].recvd;
01300         }
01301         memcpy(msg, socks[sock].msg, msglen);
01302         if (from && fromlen) {
01303             memcpy(from, &socks[sock].addr, socks[sock].addrlen);
01304             *fromlen = socks[sock].addrlen;
01305         }
01306         return msglen;
01307     }
01308     return -1;
01309 }
01310 
01311 #include <linux/unistd.h>
01312 #include <linux/poll.h>
01313 #include <linux/net.h>
01314 
01315 int errno;
01316 
01317 #define SYSCALL_BGN() \
01318     do { int retval; mm_segment_t svdfs = get_fs(); set_fs(KERNEL_DS)
01319 #define SYSCALL_END() \
01320     set_fs(svdfs); return retval; } while (0)
01321 
01322 #ifdef __NR_socketcall
01323 
01324 extern void *sys_call_table[];
01325 
01326 //static _syscall3(int, poll, struct pollfd *, ufds, unsigned int, nfds, int, timeout)
01327 static inline int kpoll(struct pollfd *ufds, unsigned int nfds, int timeout)
01328 {
01329     SYSCALL_BGN();
01330     retval = ((asmlinkage int (*)(struct pollfd *, ... ))sys_call_table[__NR_poll])(ufds, nfds, timeout);
01331 //  retval = poll(ufds, nfds, timeout);
01332     SYSCALL_END();
01333 }
01334 
01335 //static _syscall2(int, socketcall, int, call, void *, args)
01336 static inline int ksocketcall(int call, void *args)
01337 {
01338     SYSCALL_BGN();
01339     retval = ((asmlinkage int (*)(int, ... ))sys_call_table[__NR_socketcall])(call, args);
01340 //  retval = socketcall(call, args);
01341     SYSCALL_END();
01342 }
01343 
01344 static inline int ksocket(int family, int type, int protocol)
01345 {
01346     struct { int family; int type; int protocol; } args = { family, type, protocol };
01347     return ksocketcall(SYS_SOCKET, &args);
01348 }
01349 
01350 static inline int kbind(int fd, struct sockaddr *umyaddr, int addrlen)
01351 {
01352     struct { int fd; struct sockaddr *umyaddr; int addrlen; } args = { fd, umyaddr, addrlen };
01353     return ksocketcall(SYS_BIND, &args);
01354 }
01355 
01356 static inline int kconnect(int fd, struct sockaddr *serv_addr, int addrlen)
01357 {
01358     struct { int fd; struct sockaddr *serv_addr; int addrlen; } args = { fd, serv_addr, addrlen };
01359     return ksocketcall(SYS_CONNECT, &args);
01360 }
01361 
01362 static inline int klisten(int fd, int backlog)
01363 {
01364     struct { int fd; int backlog; } args = { fd, backlog };
01365     return ksocketcall(SYS_LISTEN, &args);
01366 }
01367 
01368 static inline int kaccept(int fd, struct sockaddr *upeer_sockaddr, int *upeer_addrlen)
01369 {
01370     struct { int fd; struct sockaddr *upeer_sockaddr; int *upeer_addrlen; } args = { fd, upeer_sockaddr, upeer_addrlen };
01371     return ksocketcall(SYS_ACCEPT, &args);
01372 }
01373 
01374 static inline int kgetsockname(int fd, struct sockaddr *usockaddr, int *usockaddr_len)
01375 {
01376     struct { int fd; struct sockaddr *usockaddr; int *usockaddr_len; } args = { fd, usockaddr, usockaddr_len };
01377     return ksocketcall(SYS_GETSOCKNAME, &args);
01378 }
01379 
01380 static inline int kgetpeername(int fd, struct sockaddr *usockaddr, int *usockaddr_len)
01381 {
01382     struct { int fd; struct sockaddr *usockaddr; int *usockaddr_len; } args = { fd, usockaddr, usockaddr_len };
01383     return ksocketcall(SYS_GETPEERNAME, &args);
01384 }
01385 
01386 static inline int ksocketpair(int family, int type, int protocol, int *usockvec)
01387 {
01388     struct { int family; int type; int protocol; int *usockvec; } args = { family, type, protocol, usockvec };
01389     return ksocketcall(SYS_SOCKETPAIR, &args);
01390 }
01391 
01392 static inline int ksendto(int fd, void *buff, size_t len, unsigned flags, struct sockaddr *addr, int addr_len)
01393 {
01394     struct { int fd; void *buff; size_t len; unsigned flags; struct sockaddr *addr; int addr_len; } args = { fd, buff, len, flags, addr, addr_len };
01395     return ksocketcall(SYS_SENDTO, &args);
01396 }
01397 
01398 static inline int krecvfrom(int fd, void *ubuf, size_t len, unsigned flags, struct sockaddr *addr, int *addr_len)
01399 {
01400     struct { int fd; void *ubuf; size_t len; unsigned flags; struct sockaddr *addr; int *addr_len; } args = { fd, ubuf, len, flags, addr, addr_len };
01401     return ksocketcall(SYS_RECVFROM, &args);
01402 }
01403 
01404 static inline int kshutdown(int fd, int how)
01405 {
01406     struct { int fd; int how; } args = { fd, how };
01407     return ksocketcall(SYS_SHUTDOWN, &args);
01408 }
01409 
01410 static inline int ksetsockopt(int fd, int level, int optname, void *optval, int optlen)
01411 {
01412     struct { int fd; int level; int optname; void *optval; int optlen; } args = { fd, level, optname, optval, optlen };
01413     return ksocketcall(SYS_SETSOCKOPT, &args);
01414 }
01415 
01416 static inline int kgetsockopt(int fd, int level, int optname, char *optval, int *optlen)
01417 {
01418     struct { int fd; int level; int optname; void *optval; int *optlen; } args = { fd, level, optname, optval, optlen };
01419     return ksocketcall(SYS_GETSOCKOPT, &args);
01420 }
01421 
01422 static inline int ksendmsg(int fd, struct msghdr *msg, unsigned flags)
01423 {
01424     struct { int fd; struct msghdr *msg; unsigned flags; } args = { fd, msg, flags };
01425     return ksocketcall(SYS_SENDMSG, &args);
01426 }
01427 
01428 static inline int krecvmsg(int fd, struct msghdr *msg, unsigned flags)
01429 {
01430     struct { int fd; struct msghdr *msg; unsigned flags; } args = { fd, msg, flags };
01431     return ksocketcall(SYS_RECVMSG, &args);
01432 }
01433 
01434 #else
01435 
01436 #if 0  // just for compiling
01437 #define __NR_socket       1
01438 #define __NR_bind         1
01439 #define __NR_connect      1
01440 #define __NR_accept       1
01441 #define __NR_listen       1
01442 #define __NR_getsockname  1
01443 #define __NR_getpeername  1
01444 #define __NR_socketpair   1
01445 #define __NR_sendto       1
01446 #define __NR_recvfrom     1
01447 #define __NR_shutdown     1
01448 #define __NR_setsockopt   1
01449 #define __NR_getsockopt   1
01450 #define __NR_sendmsg      1
01451 #define __NR_recvmsg      1
01452 #endif
01453 
01454 extern void *sys_call_table[];
01455 
01456 //static _syscall3(int, poll, struct pollfd *, ufds, unsigned int, nfds, int, timeout)
01457 static inline int kpoll(struct pollfd *ufds, unsigned int nfds, int timeout)
01458 {
01459     SYSCALL_BGN();
01460     retval = ((int (*)(void *, unsigned int, int))sys_call_table[__NR_poll])(ufds, nfds, timeout);
01461 //  retval = poll(ufds, nfds, timeout);
01462     SYSCALL_END();
01463 }
01464 
01465 //static _syscall3(int, socket, int, family, int, type, int, protocol)
01466 static inline int ksocket(int family, int type, int protocol)
01467 {
01468     SYSCALL_BGN();
01469     retval = ((int (*)(int, int, int))sys_call_table[__NR_socket])(family, type, protocol);
01470 //  retval = socket(family, type, protocol);
01471     SYSCALL_END();
01472 }
01473 
01474 //static _syscall3(int, bind, int, fd, struct sockaddr *, umyaddr, int, addrlen)
01475 static inline int kbind(int fd, struct sockaddr *umyaddr, int addrlen)
01476 {
01477     SYSCALL_BGN();
01478     retval = ((int (*)(int, struct sockaddr *, int))sys_call_table[__NR_bind])(fd, umyaddr, addrlen);
01479 //  retval = bind(fd, umyaddr, addrlen);
01480     SYSCALL_END();
01481 }
01482 
01483 //static _syscall3(int, connect, int, fd, struct sockaddr *, serv_addr, int, addrlen)
01484 static inline int kconnect(int fd, struct sockaddr *serv_addr, int addrlen)
01485 {
01486     SYSCALL_BGN();
01487     retval = ((int (*)(int, struct sockaddr *, int))sys_call_table[__NR_connect])(fd, serv_addr, addrlen);
01488 //  retval = connect(fd, serv_addr, addrlen);
01489     SYSCALL_END();
01490 }
01491 
01492 //static _syscall2(int, listen, int, fd, int, backlog)
01493 static inline int klisten(int fd, int backlog)
01494 {
01495     SYSCALL_BGN();
01496     retval = ((int (*)(int, int))sys_call_table[__NR_listen])(fd, backlog);
01497 //  retval = listen(fd, backlog);
01498     SYSCALL_END();
01499 }
01500 
01501 //static _syscall3(int, accept, int, fd, struct sockaddr *, upeer_sockaddr, int *, upeer_addrlen)
01502 static inline int kaccept(int fd, struct sockaddr *upeer_sockaddr, int *upeer_addrlen)
01503 {
01504     SYSCALL_BGN();
01505     retval = ((int (*)(int, struct sockaddr *, int *))sys_call_table[__NR_accept])(fd, upeer_sockaddr, upeer_addrlen);
01506 //  retval = accept(fd, upeer_sockaddr, upeer_addrlen);
01507     SYSCALL_END();
01508 }
01509 
01510 //static _syscall3(int, getsockname, int, fd, struct sockaddr *, usockaddr, int *, uaddr_len)
01511 static inline int kgetsockname(int fd, struct sockaddr *usockaddr, int *usockaddr_len)
01512 {
01513     SYSCALL_BGN();
01514     retval = ((int (*)(int, struct sockaddr *, int *))sys_call_table[__NR_getsockname])(fd, usockaddr, usockaddr_len);
01515 //  retval = getsockname(fd, usockaddr, usockaddr_len);
01516     SYSCALL_END();
01517 }
01518 
01519 //static _syscall3(int, getpeername, int, fd, struct sockaddr *, usockaddr, int *, uaddr_len)
01520 static inline int kgetpeername(int fd, struct sockaddr *usockaddr, int *usockaddr_len)
01521 {
01522     SYSCALL_BGN();
01523     retval = ((int (*)(int, struct sockaddr *, int *))sys_call_table[__NR_getpeername])(fd, usockaddr, usockaddr_len);
01524 //  retval = getpeername(fd, usockaddr, usockaddr_len);
01525     SYSCALL_END();
01526 }
01527 
01528 //static _syscall4(int, socketpair, int, family, int, type, int, protocol, int, usockvec[2])
01529 static inline int ksocketpair(int family, int type, int protocol, int *usockvec)
01530 {
01531     SYSCALL_BGN();
01532     retval = ((int (*)(int, int, int, int *))sys_call_table[__NR_socketpair])(family, type, protocol, usockvec);
01533 //  retval = socketpair(family, type, protocol, usockvec);
01534     SYSCALL_END();
01535 }
01536 
01537 //static _syscall6(int, sendto, int, fd, void *, ubuf, size_t, len, unsigned, flags, struct sockaddr *, addr, int, addr_len)
01538 static inline int ksendto(int fd, void *buff, size_t len, unsigned flags, struct sockaddr *addr, int addr_len)
01539 {
01540     SYSCALL_BGN();
01541     retval = ((int (*)(int, void *, size_t, unsigned, struct sockaddr *, int))sys_call_table[__NR_sendto])(fd, buff, len, flags, addr, addr_len);
01542 //  retval = sendto(fd, buff, len, flags, addr, addr_len);
01543     SYSCALL_END();
01544 }
01545 
01546 //static _syscall6(int, recvfrom, int, fd, void *, ubuf, size_t, len, unsigned, flags, struct sockaddr *, addr, int *, addr_len)
01547 static inline int krecvfrom(int fd, void *ubuf, size_t len, unsigned flags, struct sockaddr *addr, int *addr_len)
01548 {
01549     SYSCALL_BGN();
01550     retval = ((int (*)(int, void *, size_t, unsigned, struct sockaddr *, int *))sys_call_table[__NR_recvfrom])(fd, ubuf, len, flags, addr, addr_len);
01551 //  retval = recvfrom(fd, ubuf, len, flags, addr, addr_len);
01552     SYSCALL_END();
01553 }
01554 
01555 //static _syscall2(int, shutdown, int, fd, int, how)
01556 static inline int kshutdown(int fd, int how)
01557 {
01558     SYSCALL_BGN();
01559     retval = ((int (*)(int, int))sys_call_table[__NR_shutdown])(fd, how);
01560 //  retval = shutdown(fd, how);
01561     SYSCALL_END();
01562 }
01563 
01564 //static _syscall5(int, setsockopt, int, fd, int, level, int, optname, void *, optval, int, optlen)
01565 static inline int ksetsockopt(int fd, int level, int optname, void *optval, int optlen)
01566 {
01567     SYSCALL_BGN();
01568     retval = ((int (*)(int, int, int, void *, int))sys_call_table[__NR_setsockopt])(fd, level, optname, optval, optlen);
01569 //  retval = setsockopt(fd, level, optname, optval, optlen);
01570     SYSCALL_END();
01571 }
01572 
01573 //static _syscall5(int, getsockopt, int, fd, int, level, int, optname, char *, optval, int *, optlen)
01574 static inline int kgetsockopt(int fd, int level, int optname, char *optval, int *optlen)
01575 {
01576     SYSCALL_BGN();
01577     retval = ((int (*)(int, int, int, void *, int *))sys_call_table[__NR_getsockopt])(fd, level, optname, optval, optlen);
01578 //  retval = getsockopt(fd, level, optname, optval, optlen);
01579     SYSCALL_END();
01580 }
01581 
01582 //static _syscall3(int, sendmsg, int, fd, struct msghdr *, msg, unsigned, flags)
01583 static inline int ksendmsg(int fd, struct msghdr *msg, unsigned flags)
01584 {
01585     SYSCALL_BGN();
01586     retval = ((int (*)(int, struct msghdr *, unsigned))sys_call_table[__NR_sendmsg])(fd, msg, flags);
01587 //  retval = sendmsg(fd, msg, flags);
01588     SYSCALL_END();
01589 }
01590 
01591 //static _syscall3(int, recvmsg, int, fd, struct msghdr *, msg, unsigned, flags)
01592 static inline int krecvmsg(int fd, struct msghdr *msg, unsigned flags)
01593 {
01594     SYSCALL_BGN();
01595     retval = ((int (*)(int, struct msghdr *, unsigned))sys_call_table[__NR_recvmsg])(fd, msg, flags);
01596 //  retval = recvmsg(fd, msg, flags);
01597     SYSCALL_END();
01598 }
01599 
01600 #endif
01601 
01602 static inline int ksend(int fd, void *buff, size_t len, unsigned flags)
01603 {
01604         return ksendto(fd, buff, len, flags, NULL, 0);
01605 }
01606 
01607 static inline int krecv(int fd, void *ubuf, size_t size, unsigned flags)
01608 {
01609     return krecvfrom(fd, ubuf, size, flags, NULL, NULL);
01610 }
01611 
01612 #ifndef DECLARE_MUTEX_LOCKED
01613 #ifndef __DECLARE_SEMAPHORE_GENERIC
01614 #define DECLARE_MUTEX_LOCKED(name) \
01615     struct semaphore name = __SEMAPHORE_INITIALIZER(name, 0)
01616 #else
01617 #define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
01618 #endif
01619 #endif
01620 static DECLARE_MUTEX_LOCKED(mtx);
01621 static unsigned long end_softrtnet;
01622 
01623 static void send_thread(void)
01624 {
01625     int i;
01626 
01627     sprintf(current->comm, "SNDSRV");
01628     rtai_set_linux_task_priority(current,SCHED_FIFO,MAX_LINUX_RTPRIO);
01629     sigfillset(&current->blocked);
01630     while (!end_softrtnet) {
01631         i = down_interruptible(&mtx);
01632         while (sysrq.out != sysrq.in) {
01633             i = sysrq.sockindx[sysrq.out];
01634             ksendto(socks[i].sock, socks[i].msg, socks[i].tosend, MSG_DONTWAIT, &socks[i].addr, ADRSZ);
01635             sysrq.out = (sysrq.out + 1) & MaxSockSrq;
01636         }
01637     }
01638     set_bit(1, &end_softrtnet);
01639 }
01640 
01641 static struct pollfd *pollv;
01642 static struct task_struct *recv_handle;
01643 
01644 static void recv_thread(void)
01645 {
01646     int i, nevents;
01647 
01648     recv_handle = current;
01649     sprintf(current->comm, "RCVSRV");
01650     rtai_set_linux_task_priority(current,SCHED_RR,MAX_LINUX_RTPRIO);
01651     sigfillset(&current->blocked);
01652     while (!end_softrtnet) {
01653         if ((nevents = kpoll(pollv, MaxSocks, 1000)) > 0) {
01654             i = -1;
01655             do {
01656                 while (!pollv[++i].revents);
01657                 if ((socks[i].recvd = krecvfrom(socks[i].sock, socks[i].msg, MAX_MSG_SIZE, MSG_DONTWAIT, &socks[i].addr, &socks[i].addrlen)) > 0) {
01658                     socks[i].callback(i, socks[i].arg);
01659                 }
01660             } while (--nevents);
01661         }
01662     }
01663     set_bit(2, &end_softrtnet);
01664 }
01665 
01666 static void softrtnet_hdl(void)
01667 {
01668     up(&mtx);
01669 }
01670 
01671 static int init_softrtnet(void)
01672 {
01673     int i;
01674     for (i = 8*sizeof(unsigned long) - 1; !test_bit(i, &MaxSocks); i--);
01675     MaxSockSrq = ((1 << i) != MaxSocks ? 1 << (i + 1) : MaxSocks) - 1;
01676     if ((sysrq.srq = rt_request_srq(0xbadbeef2, softrtnet_hdl, 0)) < 0) {
01677         printk("SOFT RTNet: no sysrq available.\n");
01678         return sysrq.srq;
01679     }
01680     if (!(sysrq.sockindx = (int *)kmalloc((MaxSockSrq + 1)*sizeof(int), GFP_KERNEL))) {
01681         printk("SOFT RTNet: no memory available for socket queus.\n");
01682         return -ENOMEM;
01683     }
01684     if (!(socks = (struct sock_t *)kmalloc(MaxSocks*sizeof(struct sock_t), GFP_KERNEL))) {
01685         kfree(sysrq.sockindx);
01686         printk("SOFT RTNet: no memory available for socks.\n");
01687         return -ENOMEM;
01688     }
01689     if (!(pollv = (struct pollfd *)kmalloc(MaxSocks*sizeof(struct pollfd), GFP_KERNEL))) {
01690         kfree(sysrq.sockindx);
01691         kfree(socks);
01692         printk("SOFT RTNet: no memory available for polling.\n");
01693         return -ENOMEM;
01694     }
01695     memset(socks, 0, MaxSocks*sizeof(struct sock_t));
01696     for (i = 0; i < MaxSocks; i++) {
01697         SPRT_ADDR.sin_port = htons(BASEPORT + i);
01698         if ((socks[i].sock = ksocket(AF_INET, SOCK_DGRAM, 0)) < 0 || kbind(socks[i].sock, (struct sockaddr *)&SPRT_ADDR, ADRSZ) < 0) {
01699             rt_free_srq(sysrq.srq);
01700             kfree(socks);
01701             kfree(pollv);
01702             kfree(sysrq.sockindx);
01703             printk("SOFT RTNet: unable to set up Linux support sockets.\n");
01704             return -ESOCKTNOSUPPORT;
01705         }
01706         socks[i].addrlen = ADRSZ;
01707         pollv[i].fd     = socks[i].sock;
01708         pollv[i].events = POLLIN;
01709     }
01710     if (kernel_thread((void *)send_thread, 0, 0) <= 0 || kernel_thread((void *)recv_thread, 0, 0) <= 0) {
01711             kfree(sysrq.sockindx);
01712             kfree(socks);
01713             kfree(pollv);
01714             printk("SOFT RTNet: unable to set up Linux support kernel threads.\n");
01715             return -EINVAL;
01716     }
01717     while (!recv_handle) {
01718         current->state = TASK_INTERRUPTIBLE;
01719         schedule_timeout(HZ/2);
01720     }
01721     return 0;
01722 }
01723 
01724 static void cleanup_softrtnet(void)
01725 {
01726     int i;
01727     rt_free_srq(sysrq.srq);
01728     end_softrtnet = 1;
01729 /* watch out: dirty trick, but we are sure the thread will do nothing more. */
01730 //  sigemptyset(&recv_handle->blocked);
01731 //  send_sig(SIGKILL, recv_handle, 1);
01732 /* watch out: end of the dirty trick. */
01733     softrtnet_hdl();
01734     while (end_softrtnet < 7) {
01735         current->state = TASK_INTERRUPTIBLE;
01736         schedule_timeout(HZ/2);
01737     }
01738     for (i = 0; i < MaxSocks; i++) {
01739         kshutdown(socks[i].sock, 2);
01740     }
01741     kfree(sysrq.sockindx);
01742     kfree(socks);
01743     kfree(pollv);
01744 }
01745 
01746 /*
01747  * this is a thing to make available externally what it should not,
01748  * needed to check the working of a user message processing addon
01749  */
01750 void **rt_net_rpc_fun_hook = (void *)rt_net_rpc_fun_ext;
01751 
01752 int __rtai_netrpc_init(void)
01753 {
01754     int i;
01755 
01756     MaxStubsMone = MaxStubs - 1;
01757     if ((mod_timer_srq = rt_request_srq(0xbadbeef1, do_mod_timer, 0)) < 0) {
01758         printk("MOD_TIMER: no sysrq available.\n");
01759         return mod_timer_srq;
01760     }
01761     if (!(recovery.msg = (struct recovery_msg *)kmalloc((MaxStubs)*sizeof(struct recovery_msg), GFP_KERNEL))) {
01762         printk("Init MODULE no memory for recovery queue.\n");
01763         rt_free_srq(mod_timer_srq);
01764         return -ENOMEM;
01765     }
01766     MaxSocks += MaxStubs;
01767     SPRT_ADDR.sin_family = AF_INET;
01768     SPRT_ADDR.sin_addr.s_addr = htonl(INADDR_ANY);
01769     if (init_softrtnet()) {
01770         return 1;
01771     }
01772     rt_net_rpc_fun_ext[NET_RPC_EXT] = rt_fun_lxrt;
01773     set_rt_fun_entries(rt_netrpc_entries);
01774     if (!(portslot = kmalloc(MaxSocks*sizeof(struct portslot_t), GFP_KERNEL))) {
01775         printk("KMALLOC FAILED ALLOCATING PORT SLOTS\n");
01776     }
01777     if (!ThisSoftNode) {
01778         ThisSoftNode = ThisNode;
01779     }
01780     if (!ThisHardNode) {
01781         ThisHardNode = ThisNode;
01782     }
01783     this_node[0] = ddn2nl(ThisSoftNode);
01784     this_node[1] = ddn2nl(ThisHardNode);
01785 
01786     for (i = 0; i < MaxSocks; i++) {
01787         portslot[i].p = portslot + i;
01788         portslot[i].indx = portslot[i].place = i;
01789         SPRT_ADDR.sin_port = htons(BASEPORT + i);
01790         portslot[i].addr = SPRT_ADDR;
01791         portslot[i].socket[0] = soft_rt_socket(AF_INET, SOCK_DGRAM, 0);
01792         soft_rt_bind(portslot[i].socket[0], (struct sockaddr *)&SPRT_ADDR, ADRSZ);
01793         portslot[i].socket[1] = hard_rt_socket(AF_INET, SOCK_DGRAM, 0);
01794         hard_rt_bind(portslot[i].socket[1], (struct sockaddr *)&SPRT_ADDR, ADRSZ);
01795         soft_rt_socket_callback(portslot[i].socket[0], (void *)net_resume_task, &portslot[i].p);
01796         hard_rt_socket_callback(portslot[i].socket[1], (void *)net_resume_task, &portslot[i].p);
01797         portslot[i].owner = 0;
01798         rt_typed_sem_init(&portslot[i].sem, 0, BIN_SEM | FIFO_Q);
01799         portslot[i].task = 0;
01800         portslot[i].timeout = 0;
01801     }
01802     SPRT_ADDR.sin_port = htons(BASEPORT);
01803     portslotsp = MaxStubs;
01804     portslot[0].hard = 0;
01805     portslot[0].name = PRTSRVNAME;
01806     portslot[0].owner = OWNER(this_node[0], (unsigned long)port_server);
01807     port_server = kmalloc(sizeof(RT_TASK) + 3*sizeof(struct fun_args), GFP_KERNEL);
01808     soft_kthread_init(port_server, (long)port_server_fun, (long)port_server, RT_SCHED_LOWEST_PRIORITY);
01809     portslot[0].task = (long)port_server;
01810     rt_task_resume(port_server);
01811     rt_typed_sem_init(&timer_sem, 0, BIN_SEM | FIFO_Q);
01812     init_timer(&timer);
01813     timer.function = timer_fun;
01814     return 0 ;
01815 }
01816 
01817 void __rtai_netrpc_exit(void)
01818 {
01819     int i;
01820 
01821     reset_rt_fun_entries(rt_netrpc_entries);
01822     del_timer(&timer);
01823     rt_sem_delete(&timer_sem);
01824     for (i = 0; i < MaxStubs; i++) {
01825         if (portslot[i].task) {
01826             if (portslot[i].hard) {
01827                 rt_task_delete((RT_TASK *)portslot[i].task);
01828             } else {
01829                 soft_kthread_delete((RT_TASK *)portslot[i].task);
01830                 kfree((RT_TASK *)portslot[i].task);
01831             }
01832         }
01833     }
01834     for (i = 0; i < MaxSocks; i++) {
01835         rt_sem_delete(&portslot[i].sem);
01836         soft_rt_close(portslot[i].socket[0]);
01837         hard_rt_close(portslot[i].socket[1]);
01838     }
01839     kfree(portslot);
01840     cleanup_softrtnet();
01841     rt_free_srq(mod_timer_srq);
01842     return;
01843 }
01844 
01845 #ifndef CONFIG_RTAI_NETRPC_BUILTIN
01846 module_init(__rtai_netrpc_init);
01847 module_exit(__rtai_netrpc_exit);
01848 #endif /* !CONFIG_RTAI_NETRPC_BUILTIN */
01849 
01850 EXPORT_SYMBOL(set_netrpc_encoding);
01851 EXPORT_SYMBOL(rt_send_req_rel_port);
01852 EXPORT_SYMBOL(rt_find_asgn_stub);
01853 EXPORT_SYMBOL(rt_rel_stub);
01854 EXPORT_SYMBOL(rt_waiting_return);
01855 EXPORT_SYMBOL(_rt_net_rpc);
01856 EXPORT_SYMBOL(rt_get_net_rpc_ret);
01857 EXPORT_SYMBOL(rt_set_this_node);
01858 EXPORT_SYMBOL(rt_set_netrpc_timeout);
01859 
01860 
01861 #ifdef SOFT_RTNET
01862 EXPORT_SYMBOL(soft_rt_socket);
01863 EXPORT_SYMBOL(soft_rt_close);
01864 EXPORT_SYMBOL(soft_rt_bind);
01865 EXPORT_SYMBOL(soft_rt_socket_callback);
01866 EXPORT_SYMBOL(soft_rt_sendto);
01867 EXPORT_SYMBOL(soft_rt_recvfrom);
01868 EXPORT_SYMBOL(ddn2nl);
01869 #endif /* SOFT_RTNET */
01870 
01871 EXPORT_SYMBOL(rt_net_rpc_fun_hook);

Generated on Tue Feb 2 17:46:05 2010 for RTAI API by  doxygen 1.4.7