base/ipc/netrpc/netrpc.c

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

Generated on Thu Nov 20 11:49:51 2008 for RTAI API by doxygen 1.3.8