base/ipc/shm/shm.c

Go to the documentation of this file.
00001 /** 00002 * @ingroup shm 00003 * @file 00004 * 00005 * Implementation of the @ref shm "RTAI SHM module". 00006 * 00007 * @author Paolo Mantegazza 00008 * 00009 * @note Copyright &copy; 1999-2004 Paolo Mantegazza <mantegazza@aero.polimi.it> 00010 * 00011 * This program is free software; you can redistribute it and/or 00012 * modify it under the terms of the GNU General Public License as 00013 * published by the Free Software Foundation; either version 2 of the 00014 * License, or (at your option) any later version. 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU General Public License 00022 * along with this program; if not, write to the Free Software 00023 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00024 */ 00025 00026 00027 /** 00028 * @defgroup shm Unified RTAI real-time memory management. 00029 * 00030 *@{*/ 00031 00032 #define RTAI_SHM_MISC_MINOR 254 // The same minor used to mknod for major 10. 00033 00034 #include <linux/version.h> 00035 #include <linux/module.h> 00036 #include <linux/config.h> 00037 #include <linux/errno.h> 00038 #include <linux/mm.h> 00039 #include <linux/miscdevice.h> 00040 00041 #include <rtai_trace.h> 00042 #include <rtai_schedcore.h> 00043 #include <rtai_registry.h> 00044 #include "rtai_shm.h" 00045 00046 MODULE_LICENSE("GPL"); 00047 00048 #define ALIGN2PAGE(adr) ((void *)PAGE_ALIGN((unsigned long)adr)) 00049 #define RT_SHM_OP_PERM() (!(_rt_whoami()->is_hard)) 00050 00051 static int SUPRT[] = { 0, GFP_KERNEL, GFP_ATOMIC, GFP_DMA }; 00052 00053 static inline void *_rt_shm_alloc(unsigned long name, int size, int suprt) 00054 { 00055 void *adr; 00056 00057 // suprt = USE_GFP_ATOMIC; // to force some testing 00058 if (!(adr = rt_get_adr_cnt(name)) && size > 0 && suprt >= 0 && RT_SHM_OP_PERM()) { 00059 size = ((size - 1) & PAGE_MASK) + PAGE_SIZE; 00060 if ((adr = suprt ? rkmalloc(&size, SUPRT[suprt]) : rvmalloc(size))) { 00061 if (!rt_register(name, adr, suprt ? -size : size, 0)) { 00062 if (suprt) { 00063 rkfree(adr, size); 00064 } else { 00065 rvfree(adr, size); 00066 } 00067 return 0; 00068 } 00069 memset(ALIGN2PAGE(adr), 0, size); 00070 } 00071 } 00072 return ALIGN2PAGE(adr); 00073 } 00074 00075 static inline int _rt_shm_free(unsigned long name, int size) 00076 { 00077 void *adr; 00078 00079 if (size && (adr = rt_get_adr(name))) { 00080 if (RT_SHM_OP_PERM()) { 00081 if (!rt_drg_on_name_cnt(name) && name != GLOBAL_HEAP_ID) { 00082 if (size < 0) { 00083 rkfree(adr, -size); 00084 } else { 00085 rvfree(adr, size); 00086 } 00087 } 00088 } 00089 return abs(size); 00090 } 00091 return 0; 00092 } 00093 00094 /** 00095 * Allocate a chunk of memory to be shared inter-intra kernel modules and Linux 00096 * processes. 00097 * 00098 * @internal 00099 * 00100 * rt_shm_alloc is used to allocate shared memory. 00101 * 00102 * @param name is an unsigned long identifier; 00103 * 00104 * @param size is the amount of required shared memory; 00105 * 00106 * @param suprt is the kernel allocation method to be used, it can be: 00107 * - USE_VMALLOC, use vmalloc; 00108 * - USE_GFP_KERNEL, use kmalloc with GFP_KERNEL; 00109 * - USE_GFP_ATOMIC, use kmalloc with GFP_ATOMIC; 00110 * - USE_GFP_DMA, use kmalloc with GFP_DMA. 00111 * 00112 * Since @a name can be a clumsy identifier, services are provided to 00113 * convert 6 characters identifiers to unsigned long, and vice versa. 00114 * 00115 * @see nam2num() and num2nam(). 00116 * 00117 * It must be remarked that only the very first call does a real allocation, 00118 * any following call to allocate with the same name from anywhere will just 00119 * increase the usage count and maps the area to the user space, or return 00120 * the related pointer to the already allocated space in kernel space. 00121 * In any case the functions return a pointer to the allocated memory, 00122 * appropriately mapped to the memory space in use. So if one is really sure 00123 * that the named shared memory has been allocated already parameters size 00124 * and suprt are not used and can be assigned any value. 00125 * 00126 * @returns a valid address on succes, 0 on failure. 00127 * 00128 */ 00129 00130 void *rt_shm_alloc(unsigned long name, int size, int suprt) 00131 { 00132 TRACE_RTAI_SHM(TRACE_RTAI_EV_SHM_KMALLOC, name, size, 0); 00133 return _rt_shm_alloc(name, size, suprt); 00134 } 00135 00136 static int rt_shm_alloc_usp(unsigned long name, int size, int suprt) 00137 { 00138 TRACE_RTAI_SHM(TRACE_RTAI_EV_SHM_MALLOC, name, size, current->pid); 00139 00140 if (_rt_shm_alloc(name, size, suprt)) { 00141 ((current->mm)->mmap)->vm_private_data = (void *)name; 00142 return abs(rt_get_type(name)); 00143 } 00144 return 0; 00145 } 00146 00147 /** 00148 * Free a chunk of shared memory being shared inter-intra kernel modules and 00149 * Linux processes. 00150 * 00151 * @internal 00152 * 00153 * rt_shm_free is used to free a previously allocated shared memory. 00154 * 00155 * @param name is the unsigned long identifier used when the memory was 00156 * allocated; 00157 * 00158 * Analogously to what done by all the named allocation functions the freeing 00159 * calls have just the effect of decrementing a usage count, unmapping any 00160 * user space shared memory being freed, till the last is done, as that is the 00161 * one the really frees any allocated memory. 00162 * 00163 * @returns the size of the succesfully freed memory, 0 on failure. 00164 * 00165 */ 00166 00167 int rt_shm_free(unsigned long name) 00168 { 00169 TRACE_RTAI_SHM(TRACE_RTAI_EV_SHM_KFREE, name, 0, 0); 00170 return _rt_shm_free(name, rt_get_type(name)); 00171 } 00172 00173 static int rt_shm_size(unsigned long *arg) 00174 { 00175 int size; 00176 struct vm_area_struct *vma; 00177 00178 size = abs(rt_get_type(*arg)); 00179 for (vma = (current->mm)->mmap; vma; vma = vma->vm_next) { 00180 if (vma->vm_private_data == (void *)*arg && (vma->vm_end - vma->vm_start) == size) { 00181 *arg = vma->vm_start; 00182 return size; 00183 } 00184 } 00185 return 0; 00186 } 00187 00188 static void rtai_shm_vm_open(struct vm_area_struct *vma) 00189 { 00190 rt_get_adr_cnt((unsigned long)vma->vm_private_data); 00191 } 00192 00193 static void rtai_shm_vm_close(struct vm_area_struct *vma) 00194 { 00195 _rt_shm_free((unsigned long)vma->vm_private_data, rt_get_type((unsigned long)vma->vm_private_data)); 00196 } 00197 00198 static struct vm_operations_struct rtai_shm_vm_ops = { 00199 open: rtai_shm_vm_open, 00200 close: rtai_shm_vm_close 00201 }; 00202 00203 static void rt_set_heap(unsigned long, void *); 00204 00205 static int rtai_shm_f_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) 00206 { 00207 switch (cmd) { 00208 case SHM_ALLOC: { 00209 TRACE_RTAI_SHM(TRACE_RTAI_EV_SHM_MALLOC, ((unsigned long *)arg)[0], cmd, current->pid); 00210 return rt_shm_alloc_usp(((unsigned long *)arg)[0], ((int *)arg)[1], ((int *)arg)[2]); 00211 } 00212 case SHM_FREE: { 00213 TRACE_RTAI_SHM(TRACE_RTAI_EV_SHM_FREE, arg, cmd, current->pid); 00214 return _rt_shm_free(arg, rt_get_type(arg)); 00215 } 00216 case SHM_SIZE: { 00217 TRACE_RTAI_SHM(TRACE_RTAI_EV_SHM_GET_SIZE, arg, cmd, current->pid); 00218 return rt_shm_size((unsigned long *)((unsigned long *)arg)[0]); 00219 } 00220 case HEAP_SET: { 00221 rt_set_heap(((unsigned long *)arg)[0], (void *)((unsigned long *)arg)[1]); 00222 return 0; 00223 } 00224 } 00225 return 0; 00226 } 00227 00228 static int rtai_shm_f_mmap(struct file *file, struct vm_area_struct *vma) 00229 { 00230 unsigned long name; 00231 int size; 00232 if (!vma->vm_ops) { 00233 vma->vm_ops = &rtai_shm_vm_ops; 00234 vma->vm_flags |= VM_LOCKED; 00235 name = (unsigned long)(vma->vm_private_data = ((current->mm)->mmap)->vm_private_data); 00236 ((current->mm)->mmap)->vm_private_data = NULL; 00237 return (size = rt_get_type(name)) < 0 ? rkmmap(ALIGN2PAGE(rt_get_adr(name)), -size, vma) : rvmmap(rt_get_adr(name), size, vma); 00238 } 00239 return -EFAULT; 00240 } 00241 00242 static struct file_operations rtai_shm_fops = { 00243 ioctl: rtai_shm_f_ioctl, 00244 mmap: rtai_shm_f_mmap 00245 }; 00246 00247 static struct miscdevice rtai_shm_dev = 00248 { RTAI_SHM_MISC_MINOR, "RTAI_SHM", &rtai_shm_fops }; 00249 00250 static inline void *_rt_halloc(int size, struct rt_heap_t *heap) 00251 { 00252 void *mem_ptr = NULL; 00253 00254 if ((mem_ptr = rtheap_alloc(heap->heap, size, 0))) { 00255 mem_ptr = heap->uadr + (mem_ptr - heap->kadr); 00256 } 00257 return mem_ptr; 00258 } 00259 00260 static inline void _rt_hfree(void *addr, struct rt_heap_t *heap) 00261 { 00262 rtheap_free(heap->heap, heap->kadr + (addr - heap->uadr)); 00263 } 00264 00265 #define GLOBAL 0 00266 #define SPECIFIC 1 00267 00268 /** 00269 * Allocate a chunk of the global real time heap in kernel/user space. Since 00270 * it is not named there is no chance of retrieving and sharing it elsewhere. 00271 * 00272 * @internal 00273 * 00274 * rt_malloc is used to allocate a non sharable piece of the global real time 00275 * heap. 00276 * 00277 * @param size is the size of the requested memory in bytes; 00278 * 00279 * @returns the pointer to the allocated memory, 0 on failure. 00280 * 00281 */ 00282 00283 /** 00284 * Free a chunk of the global real time heap. 00285 * 00286 * @internal 00287 * 00288 * rt_free is used to free a previously allocated chunck of the global real 00289 * time heap. 00290 * 00291 * @param addr is the addr of the memory to be freed. 00292 * 00293 */ 00294 00295 /** 00296 * Allocate a chunk of the global real time heap in kernel/user space. Since 00297 * it is named it can be retrieved and shared everywhere. 00298 * 00299 * @internal 00300 * 00301 * rt_named_malloc is used to allocate a sharable piece of the global real 00302 * time heap. 00303 * 00304 * @param name is an unsigned long identifier; 00305 * 00306 * @param size is the amount of required shared memory; 00307 * 00308 * Since @a name can be a clumsy identifier, services are provided to 00309 * convert 6 characters identifiers to unsigned long, and vice versa. 00310 * 00311 * @see nam2num() and num2nam(). 00312 * 00313 * It must be remarked that only the very first call does a real allocation, 00314 * any subsequent call to allocate with the same name will just increase the 00315 * usage count and return the appropriate pointer to the already allocated 00316 * memory having the same name. So if one is really sure that the named chunk 00317 * has been allocated already the size parameter is not used and can be 00318 * assigned any value. 00319 * 00320 * @returns a valid address on succes, 0 on failure. 00321 * 00322 */ 00323 00324 void *rt_named_malloc(unsigned long name, int size) 00325 { 00326 void *mem_ptr; 00327 00328 if ((mem_ptr = rt_get_adr_cnt(name))) { 00329 return mem_ptr; 00330 } 00331 if ((mem_ptr = _rt_halloc(size, &rt_smp_linux_task->heap[GLOBAL]))) { 00332 if (rt_register(name, mem_ptr, IS_HPCK, 0)) { 00333 return mem_ptr; 00334 } 00335 rt_hfree(mem_ptr); 00336 } 00337 return NULL; 00338 } 00339 00340 /** 00341 * Free a named chunk of the global real time heap. 00342 * 00343 * @internal 00344 * 00345 * rt_named_free is used to free a previously allocated chunk of the global 00346 * real time heap. 00347 * 00348 * @param adr is the addr of the memory to be freed. 00349 * 00350 * Analogously to what done by all the named allocation functions the freeing 00351 * calls of named memory chunks have just the effect of decrementing its usage 00352 * count, any shared piece of the global heap being freed only when the last 00353 * is done, as that is the one the really frees any allocated memory. 00354 * So one must be carefull not to use rt_free on a named global heap chunk, 00355 * since it will force its unconditional immediate freeing. 00356 * 00357 */ 00358 00359 void rt_named_free(void *adr) 00360 { 00361 unsigned long name; 00362 00363 name = rt_get_name(adr); 00364 if (!rt_drg_on_name_cnt(name)) { 00365 _rt_hfree(adr, &rt_smp_linux_task->heap[GLOBAL]); 00366 } 00367 } 00368 00369 /* 00370 * we must care of this because LXRT callable functions are set as non 00371 * blocking, so they are called directly. 00372 */ 00373 #define RTAI_TASK(return_instr) \ 00374 do { \ 00375 if (!(task = _rt_whoami())->is_hard) { \ 00376 if (!(task = current->rtai_tskext(TSKEXT0))) { \ 00377 return_instr; \ 00378 } \ 00379 } \ 00380 } while (0) 00381 00382 static inline void *rt_halloc_typed(int size, int htype) 00383 { 00384 RT_TASK *task; 00385 00386 RTAI_TASK(return NULL); 00387 return _rt_halloc(size, &task->heap[htype]); 00388 } 00389 00390 static inline void rt_hfree_typed(void *addr, int htype) 00391 { 00392 RT_TASK *task; 00393 00394 RTAI_TASK(return); 00395 _rt_hfree(addr, &task->heap[htype]); 00396 } 00397 00398 static inline void *rt_named_halloc_typed(unsigned long name, int size, int htype) 00399 { 00400 RT_TASK *task; 00401 void *mem_ptr; 00402 00403 RTAI_TASK(return NULL); 00404 if ((mem_ptr = rt_get_adr_cnt(name))) { 00405 return task->heap[htype].uadr + (mem_ptr - task->heap[htype].kadr); 00406 } 00407 if ((mem_ptr = _rt_halloc(size, &task->heap[htype]))) { 00408 if (rt_register(name, task->heap[htype].kadr + (mem_ptr - task->heap[htype].uadr), IS_HPCK, 0)) { 00409 return mem_ptr; 00410 } 00411 _rt_hfree(mem_ptr, &task->heap[htype]); 00412 } 00413 return NULL; 00414 } 00415 00416 static inline void rt_named_hfree_typed(void *adr, int htype) 00417 { 00418 RT_TASK *task; 00419 unsigned long name; 00420 00421 RTAI_TASK(return); 00422 name = rt_get_name(task->heap[htype].kadr + (adr - task->heap[htype].uadr)); 00423 if (!rt_drg_on_name_cnt(name)) { 00424 _rt_hfree(adr, &task->heap[htype]); 00425 } 00426 } 00427 00428 /** 00429 * Allocate a chunk of a group real time heap in kernel/user space. Since 00430 * it is not named there is no chance to retrieve and share it elsewhere. 00431 * 00432 * @internal 00433 * 00434 * rt_halloc is used to allocate a non sharable piece of a group real time 00435 * heap. 00436 * 00437 * @param size is the size of the requested memory in bytes; 00438 * 00439 * A process/task must have opened the real time group heap to use and can use 00440 * just one real time group heap. Be careful and avoid opening more than one 00441 * group real time heap per process/task. If more than one is opened then just 00442 * the last will used. 00443 * 00444 * @returns the pointer to the allocated memory, 0 on failure. 00445 * 00446 */ 00447 00448 void *rt_halloc(int size) 00449 { 00450 return rt_halloc_typed(size, SPECIFIC); 00451 } 00452 00453 /** 00454 * Free a chunk of a group real time heap. 00455 * 00456 * @internal 00457 * 00458 * rt_hfree is used to free a previously allocated chunck of a group real 00459 * time heap. 00460 * 00461 * @param adr is the addr of the memory to be freed. 00462 * 00463 */ 00464 00465 void rt_hfree(void *adr) 00466 { 00467 rt_hfree_typed(adr, SPECIFIC); 00468 } 00469 00470 /** 00471 * Allocate a chunk of a group real time heap in kernel/user space. Since 00472 * it is named it can be retrieved and shared everywhere among the group 00473 * peers, i.e all processes/tasks that have opened the same group heap. 00474 * 00475 * @internal 00476 * 00477 * rt_named_halloc is used to allocate a sharable piece of a group real 00478 * time heap. 00479 * 00480 * @param name is an unsigned long identifier; 00481 * 00482 * @param size is the amount of required shared memory; 00483 * 00484 * Since @a name can be a clumsy identifier, services are provided to 00485 * convert 6 characters identifiers to unsigned long, and vice versa. 00486 * 00487 * @see nam2num() and num2nam(). 00488 * 00489 * A process/task must have opened the real time group heap to use and can use 00490 * just one real time group heap. Be careful and avoid opening more than one 00491 * group real time heap per process/task. If more than one is opened then just 00492 * the last will used. It must be remarked that only the very first call does 00493 * a real allocation, any subsequent call with the same name will just 00494 * increase the usage count and receive the appropriate pointer to the already 00495 * allocated memory having the same name. 00496 * 00497 * @returns a valid address on succes, 0 on failure. 00498 * 00499 */ 00500 00501 void *rt_named_halloc(unsigned long name, int size) 00502 { 00503 return rt_named_halloc_typed(name, size, SPECIFIC); 00504 } 00505 00506 /** 00507 * Free a chunk of a group real time heap. 00508 * 00509 * @internal 00510 * 00511 * rt_named_hfree is used to free a previously allocated chunk of the global 00512 * real time heap. 00513 * 00514 * @param adr is the address of the memory to be freed. 00515 * 00516 * Analogously to what done by all the named allocation functions the freeing 00517 * calls of named memory chunks have just the effect of decrementing a usage 00518 * count, any shared piece of the global heap being freed only when the last 00519 * is done, as that is the one the really frees any allocated memory. 00520 * So one must be carefull not to use rt_hfree on a named global heap chunk, 00521 * since it will force its unconditional immediate freeing. 00522 * 00523 */ 00524 00525 void rt_named_hfree(void *adr) 00526 { 00527 rt_named_hfree_typed(adr, SPECIFIC); 00528 } 00529 00530 extern rtheap_t rtai_global_heap; 00531 extern void *rtai_global_heap_adr; 00532 extern int rtai_global_heap_size; 00533 00534 static void *rt_malloc_usp(int size) 00535 { 00536 return rtai_global_heap_adr ? rt_halloc_typed(size, GLOBAL) : NULL; 00537 } 00538 00539 static void rt_free_usp(void *adr) 00540 { 00541 if (rtai_global_heap_adr) { 00542 rt_hfree_typed(adr, GLOBAL); 00543 } 00544 } 00545 00546 static void *rt_named_malloc_usp(unsigned long name, int size) 00547 { 00548 return rtai_global_heap_adr ? rt_named_halloc_typed(name, size, GLOBAL) : NULL; 00549 } 00550 00551 static void rt_named_free_usp(void *adr) 00552 { 00553 if (rtai_global_heap_adr) { 00554 rt_named_hfree_typed(adr, GLOBAL); 00555 } 00556 } 00557 00558 static void rt_set_heap(unsigned long name, void *adr) 00559 { 00560 void *heap, *hptr; 00561 int size; 00562 RT_TASK *task; 00563 00564 heap = rt_get_adr(name); 00565 hptr = ALIGN2PAGE(heap); 00566 size = ((abs(rt_get_type(name)) - sizeof(rtheap_t) - (hptr - heap)) & PAGE_MASK); 00567 heap = hptr + size; 00568 if (!atomic_cmpxchg((int *)hptr, 0, name)) { 00569 rtheap_init(heap, hptr, size, PAGE_SIZE); 00570 } 00571 RTAI_TASK(return); 00572 if (name == GLOBAL_HEAP_ID) { 00573 task->heap[GLOBAL].heap = &rtai_global_heap; 00574 task->heap[GLOBAL].kadr = rtai_global_heap_adr; 00575 task->heap[GLOBAL].uadr = adr; 00576 } else { 00577 task->heap[SPECIFIC].heap = heap; 00578 task->heap[SPECIFIC].kadr = hptr; 00579 task->heap[SPECIFIC].uadr = adr; 00580 } 00581 } 00582 00583 /** 00584 * Open/create a named group real time heap to be shared inter-intra kernel 00585 * modules and Linux processes. 00586 * 00587 * @internal 00588 * 00589 * rt_heap_open is used to allocate open/create a shared real time heap. 00590 * 00591 * @param name is an unsigned long identifier; 00592 * 00593 * @param size is the amount of required shared memory; 00594 * 00595 * @param suprt is the kernel allocation method to be used, it can be: 00596 * - USE_VMALLOC, use vmalloc; 00597 * - USE_GFP_KERNEL, use kmalloc with GFP_KERNEL; 00598 * - USE_GFP_ATOMIC, use kmalloc with GFP_ATOMIC; 00599 * - USE_GFP_DMA, use kmalloc with GFP_DMA. 00600 * 00601 * Since @a name can be a clumsy identifier, services are provided to 00602 * convert 6 characters identifiers to unsigned long, and vice versa. 00603 * 00604 * @see nam2num() and num2nam(). 00605 * 00606 * It must be remarked that only the very first open does a real allocation, 00607 * any subsequent one with the same name from anywhere will just map the area 00608 * to the user space, or return the related pointer to the already allocated 00609 * memory in kernel space. In any case the functions return a pointer to the 00610 * allocated memory, appropriately mapped to the memory space in use. 00611 * Be careful and avoid opening more than one group heap per process/task, if 00612 * more than one is opened then just the last will used. 00613 * 00614 * @returns a valid address on succes, 0 on failure. 00615 * 00616 */ 00617 00618 void *rt_heap_open(unsigned long name, int size, int suprt) 00619 { 00620 void *adr; 00621 if ((adr = rt_shm_alloc(name, ((size - 1) & PAGE_MASK) + PAGE_SIZE + sizeof(rtheap_t), suprt))) { 00622 rt_set_heap(name, adr); 00623 return adr; 00624 } 00625 return 0; 00626 } 00627 00628 struct rt_native_fun_entry rt_shm_entries[] = { 00629 { { 0, rt_shm_alloc_usp }, SHM_ALLOC }, 00630 { { 0, rt_shm_free }, SHM_FREE }, 00631 { { 0, rt_shm_size }, SHM_SIZE }, 00632 { { 0, rt_set_heap }, HEAP_SET}, 00633 { { 0, rt_halloc }, HEAP_ALLOC }, 00634 { { 0, rt_hfree }, HEAP_FREE }, 00635 { { 0, rt_named_halloc }, HEAP_NAMED_ALLOC }, 00636 { { 0, rt_named_hfree }, HEAP_NAMED_FREE }, 00637 { { 0, rt_malloc_usp }, MALLOC }, 00638 { { 0, rt_free_usp }, FREE }, 00639 { { 0, rt_named_malloc_usp }, NAMED_MALLOC }, 00640 { { 0, rt_named_free_usp }, NAMED_FREE }, 00641 { { 0, 0 }, 000 } 00642 }; 00643 00644 extern int set_rt_fun_entries(struct rt_native_fun_entry *entry); 00645 extern void reset_rt_fun_entries(struct rt_native_fun_entry *entry); 00646 00647 int __rtai_shm_init (void) 00648 { 00649 if (misc_register(&rtai_shm_dev) < 0) { 00650 printk("***** UNABLE TO REGISTER THE SHARED MEMORY DEVICE (miscdev minor: %d) *****\n", RTAI_SHM_MISC_MINOR); 00651 return -EBUSY; 00652 } 00653 #ifndef CONFIG_RTAI_MALLOC_VMALLOC 00654 printk("***** WARNING: GLOBAL HEAP NEITHER SHARABLE NOR USABLE FROM USER SPACE (use the vmalloc option for RTAI malloc) *****\n"); 00655 #else 00656 rt_register(GLOBAL_HEAP_ID, rtai_global_heap_adr, rtai_global_heap_size, 0); 00657 rt_smp_linux_task->heap[GLOBAL].heap = &rtai_global_heap; 00658 rt_smp_linux_task->heap[GLOBAL].kadr = 00659 rt_smp_linux_task->heap[GLOBAL].uadr = rtai_global_heap_adr; 00660 #endif 00661 return set_rt_fun_entries(rt_shm_entries); 00662 } 00663 00664 void __rtai_shm_exit (void) 00665 { 00666 extern int max_slots; 00667 int slot; 00668 struct rt_registry_entry entry; 00669 00670 rt_drg_on_name_cnt(GLOBAL_HEAP_ID); 00671 for (slot = 1; slot <= max_slots; slot++) { 00672 if (rt_get_registry_slot(slot, &entry)) { 00673 if (abs(entry.type) >= PAGE_SIZE) { 00674 char name[8]; 00675 while (_rt_shm_free(entry.name, entry.type)); 00676 num2nam(entry.name, name); 00677 rt_printk("\nSHM_CLEANUP_MODULE releases: '%s':0x%lx:%lu (%d).\n", name, entry.name, entry.name, entry.type); 00678 } 00679 } 00680 } 00681 reset_rt_fun_entries(rt_shm_entries); 00682 misc_deregister(&rtai_shm_dev); 00683 return; 00684 } 00685 00686 /*@}*/ 00687 00688 #ifndef CONFIG_RTAI_SHM_BUILTIN 00689 module_init(__rtai_shm_init); 00690 module_exit(__rtai_shm_exit); 00691 #endif /* !CONFIG_RTAI_SHL_BUILTIN */ 00692 00693 #ifdef CONFIG_KBUILD 00694 EXPORT_SYMBOL(rt_shm_alloc); 00695 EXPORT_SYMBOL(rt_shm_free); 00696 EXPORT_SYMBOL(rt_named_malloc); 00697 EXPORT_SYMBOL(rt_named_free); 00698 EXPORT_SYMBOL(rt_halloc); 00699 EXPORT_SYMBOL(rt_hfree); 00700 EXPORT_SYMBOL(rt_named_halloc); 00701 EXPORT_SYMBOL(rt_named_hfree); 00702 EXPORT_SYMBOL(rt_heap_open); 00703 #endif /* CONFIG_KBUILD */

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