base/sched/sys.c

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

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