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/errno.h>
00037 #include <linux/fs.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 RTAI_SYSCALL_MODE 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->rtai_tskext(TSKEXT1) = (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 RTAI_SYSCALL_MODE 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 RTAI_SYSCALL_MODE 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 #ifdef CONFIG_RTAI_MALLOC
00204 static RTAI_SYSCALL_MODE void rt_set_heap(unsigned long, void *);
00205 #endif
00206 
00207 static int rtai_shm_f_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
00208 {
00209     switch (cmd) {
00210         case SHM_ALLOC: {
00211             TRACE_RTAI_SHM(TRACE_RTAI_EV_SHM_MALLOC, ((unsigned long *)arg)[0], cmd, current->pid);
00212             return rt_shm_alloc_usp(((unsigned long *)arg)[0], ((long *)arg)[1], ((long *)arg)[2]);
00213         }
00214         case SHM_FREE: {
00215             TRACE_RTAI_SHM(TRACE_RTAI_EV_SHM_FREE, arg, cmd, current->pid);
00216             return _rt_shm_free(arg, rt_get_type(arg)); 
00217         }
00218         case SHM_SIZE: {
00219             TRACE_RTAI_SHM(TRACE_RTAI_EV_SHM_GET_SIZE, arg, cmd, current->pid);
00220             return rt_shm_size((unsigned long *)((unsigned long *)arg)[0]);
00221         }
00222 #ifdef CONFIG_RTAI_MALLOC
00223         case HEAP_SET: {
00224             rt_set_heap(((unsigned long *)arg)[0], (void *)((unsigned long *)arg)[1]);
00225             return 0;
00226         }
00227 #endif
00228     }
00229     return 0;
00230 }
00231 
00232 static int rtai_shm_f_mmap(struct file *file, struct vm_area_struct *vma)
00233 {
00234     unsigned long name;
00235     int size;
00236     if (!vma->vm_ops) {
00237         vma->vm_ops = &rtai_shm_vm_ops;
00238         vma->vm_flags |= VM_LOCKED;
00239         name = (unsigned long)(vma->vm_private_data = current->rtai_tskext(TSKEXT1));
00240         current->rtai_tskext(TSKEXT1) = current->rtai_tskext(TSKEXT0) ? current : NULL;
00241         return (size = rt_get_type(name)) < 0 ? rkmmap(ALIGN2PAGE(rt_get_adr(name)), -size, vma) : rvmmap(rt_get_adr(name), size, vma);
00242     }
00243     return -EFAULT;
00244 }
00245 
00246 static struct file_operations rtai_shm_fops = {
00247     ioctl:  rtai_shm_f_ioctl,
00248     mmap:   rtai_shm_f_mmap
00249 };
00250 
00251 static struct miscdevice rtai_shm_dev = 
00252     { RTAI_SHM_MISC_MINOR, "rtai_shm", &rtai_shm_fops };
00253 
00254 #ifdef CONFIG_RTAI_MALLOC
00255 
00256 static inline void *_rt_halloc(int size, struct rt_heap_t *heap)
00257 {
00258     void *mem_ptr = NULL;
00259 
00260     if ((mem_ptr = rtheap_alloc(heap->heap, size, 0))) {
00261         mem_ptr = heap->uadr + (mem_ptr - heap->kadr);
00262     }
00263     return mem_ptr;
00264 }
00265 
00266 static inline void _rt_hfree(void *addr, struct rt_heap_t *heap)
00267 {
00268     rtheap_free(heap->heap, heap->kadr + (addr - heap->uadr));
00269 }
00270 
00271 #define GLOBAL    0
00272 #define SPECIFIC  1
00273 
00274 /**
00275  * Allocate a chunk of the global real time heap in kernel/user space. Since 
00276  * it is not named there is no chance of retrieving and sharing it elsewhere.
00277  *
00278  * @internal
00279  * 
00280  * rt_malloc is used to allocate a non sharable piece of the global real time 
00281  * heap.
00282  *
00283  * @param size is the size of the requested memory in bytes;
00284  *
00285  * @returns the pointer to the allocated memory, 0 on failure.
00286  *
00287  */
00288 
00289 /**
00290  * Free a chunk of the global real time heap.
00291  *
00292  * @internal
00293  * 
00294  * rt_free is used to free a previously allocated chunck of the global real 
00295  * time heap.
00296  *
00297  * @param addr is the addr of the memory to be freed.
00298  *
00299  */
00300 
00301 /**
00302  * Allocate a chunk of the global real time heap in kernel/user space. Since 
00303  * it is named it can be retrieved and shared everywhere.
00304  *
00305  * @internal
00306  * 
00307  * rt_named_malloc is used to allocate a sharable piece of the global real 
00308  * time heap.
00309  *
00310  * @param name is an unsigned long identifier;
00311  * 
00312  * @param size is the amount of required shared memory;
00313  * 
00314  * Since @a name can be a clumsy identifier, services are provided to
00315  * convert 6 characters identifiers to unsigned long, and vice versa.
00316  * 
00317  * @see nam2num() and num2nam().
00318  * 
00319  * It must be remarked that only the very first call does a real allocation,
00320  * any subsequent call to allocate with the same name will just increase the
00321  * usage count and return the appropriate pointer to the already allocated 
00322  * memory having the same name. So if one is really sure that the named chunk 
00323  * has been allocated already the size parameter is not used and can be 
00324  * assigned any value.
00325  *
00326  * @returns a valid address on succes, 0 on failure.
00327  *
00328  */
00329 
00330 void *rt_named_malloc(unsigned long name, int size)
00331 {
00332     void *mem_ptr;
00333 
00334     if ((mem_ptr = rt_get_adr_cnt(name))) {
00335         return mem_ptr;
00336     }
00337     if ((mem_ptr = _rt_halloc(size, &rt_smp_linux_task->heap[GLOBAL]))) {
00338         if (rt_register(name, mem_ptr, IS_HPCK, 0)) {
00339                         return mem_ptr;
00340                 }
00341                 rt_hfree(mem_ptr);
00342     }
00343     return NULL;
00344 }
00345 
00346 /**
00347  * Free a named chunk of the global real time heap. 
00348  *
00349  * @internal
00350  * 
00351  * rt_named_free is used to free a previously allocated chunk of the global
00352  * real time heap.
00353  *
00354  * @param adr is the addr of the memory to be freed.
00355  *
00356  * Analogously to what done by all the named allocation functions the freeing 
00357  * calls of named memory chunks have just the effect of decrementing its usage
00358  * count, any shared piece of the global heap being freed only when the last 
00359  * is done, as that is the one the really frees any allocated memory.
00360  * So one must be carefull not to use rt_free on a named global heap chunk, 
00361  * since it will force its unconditional immediate freeing.
00362  *
00363  */
00364 
00365 void rt_named_free(void *adr)
00366 {
00367     unsigned long name;
00368 
00369     name = rt_get_name(adr);
00370     if (!rt_drg_on_name_cnt(name)) {
00371         _rt_hfree(adr, &rt_smp_linux_task->heap[GLOBAL]);
00372     }
00373 }
00374 
00375 /* 
00376  * we must care of this because LXRT callable functions are set as non 
00377  * blocking, so they are called directly.
00378  */
00379 #define RTAI_TASK(return_instr) \
00380 do { \
00381     if (!(task = _rt_whoami())->is_hard) { \
00382         if (!(task = current->rtai_tskext(TSKEXT0))) { \
00383             return_instr; \
00384         } \
00385     } \
00386 } while (0)
00387 
00388 static inline void *rt_halloc_typed(int size, int htype)
00389 {
00390     RT_TASK *task;
00391 
00392     RTAI_TASK(return NULL);
00393     return _rt_halloc(size, &task->heap[htype]);
00394 }
00395 
00396 static inline void rt_hfree_typed(void *addr, int htype)
00397 {
00398     RT_TASK *task;
00399 
00400     RTAI_TASK(return);
00401     _rt_hfree(addr, &task->heap[htype]);
00402 }
00403 
00404 static inline void *rt_named_halloc_typed(unsigned long name, int size, int htype)
00405 {
00406     RT_TASK *task;
00407     void *mem_ptr;
00408 
00409     RTAI_TASK(return NULL);
00410     if ((mem_ptr = rt_get_adr_cnt(name))) {
00411         return task->heap[htype].uadr + (mem_ptr - task->heap[htype].kadr);
00412     }
00413     if ((mem_ptr = _rt_halloc(size, &task->heap[htype]))) {
00414         if (rt_register(name, task->heap[htype].kadr + (mem_ptr - task->heap[htype].uadr), IS_HPCK, 0)) {
00415                         return mem_ptr;
00416                 }
00417         _rt_hfree(mem_ptr, &task->heap[htype]);
00418     }
00419     return NULL;
00420 }
00421 
00422 static inline void rt_named_hfree_typed(void *adr, int htype)
00423 {
00424     RT_TASK *task;
00425     unsigned long name;
00426 
00427     RTAI_TASK(return);
00428     name = rt_get_name(task->heap[htype].kadr + (adr - task->heap[htype].uadr));
00429     if (!rt_drg_on_name_cnt(name)) {
00430         _rt_hfree(adr, &task->heap[htype]);
00431     }
00432 }
00433 
00434 /**
00435  * Allocate a chunk of a group real time heap in kernel/user space. Since 
00436  * it is not named there is no chance to retrieve and share it elsewhere.
00437  *
00438  * @internal
00439  * 
00440  * rt_halloc is used to allocate a non sharable piece of a group real time 
00441  * heap.
00442  *
00443  * @param size is the size of the requested memory in bytes;
00444  *
00445  * A process/task must have opened the real time group heap to use and can use
00446  * just one real time group heap. Be careful and avoid opening more than one 
00447  * group real time heap per process/task. If more than one is opened then just 
00448  * the last will used.
00449  *
00450  * @returns the pointer to the allocated memory, 0 on failure.
00451  *
00452  */
00453 
00454 RTAI_SYSCALL_MODE void *rt_halloc(int size)
00455 {
00456     return rt_halloc_typed(size, SPECIFIC);
00457 }
00458 
00459 /**
00460  * Free a chunk of a group real time heap.
00461  *
00462  * @internal
00463  * 
00464  * rt_hfree is used to free a previously allocated chunck of a group real 
00465  * time heap.
00466  *
00467  * @param adr is the addr of the memory to be freed.
00468  *
00469  */
00470 
00471 RTAI_SYSCALL_MODE void rt_hfree(void *adr)
00472 {
00473     rt_hfree_typed(adr, SPECIFIC);
00474 }
00475 
00476 /**
00477  * Allocate a chunk of a group real time heap in kernel/user space. Since 
00478  * it is named it can be retrieved and shared everywhere among the group 
00479  * peers, i.e all processes/tasks that have opened the same group heap.
00480  *
00481  * @internal
00482  * 
00483  * rt_named_halloc is used to allocate a sharable piece of a group real 
00484  * time heap.
00485  *
00486  * @param name is an unsigned long identifier;
00487  * 
00488  * @param size is the amount of required shared memory;
00489  * 
00490  * Since @a name can be a clumsy identifier, services are provided to
00491  * convert 6 characters identifiers to unsigned long, and vice versa.
00492  * 
00493  * @see nam2num() and num2nam().
00494  * 
00495  * A process/task must have opened the real time group heap to use and can use
00496  * just one real time group heap. Be careful and avoid opening more than one
00497  * group real time heap per process/task. If more than one is opened then just
00498  * the last will used. It must be remarked that only the very first call does 
00499  * a real allocation, any subsequent call with the same name will just 
00500  * increase the usage count and receive the appropriate pointer to the already
00501  * allocated memory having the same name.
00502  *
00503  * @returns a valid address on succes, 0 on failure.
00504  *
00505  */
00506 
00507 RTAI_SYSCALL_MODE void *rt_named_halloc(unsigned long name, int size)
00508 {
00509     return rt_named_halloc_typed(name, size, SPECIFIC);
00510 }
00511 
00512 /**
00513  * Free a chunk of a group real time heap. 
00514  *
00515  * @internal
00516  * 
00517  * rt_named_hfree is used to free a previously allocated chunk of the global
00518  * real time heap.
00519  *
00520  * @param adr is the address of the memory to be freed.
00521  *
00522  * Analogously to what done by all the named allocation functions the freeing 
00523  * calls of named memory chunks have just the effect of decrementing a usage
00524  * count, any shared piece of the global heap being freed only when the last 
00525  * is done, as that is the one the really frees any allocated memory.
00526  * So one must be carefull not to use rt_hfree on a named global heap chunk, 
00527  * since it will force its unconditional immediate freeing.
00528  *
00529  */
00530 
00531 RTAI_SYSCALL_MODE void rt_named_hfree(void *adr)
00532 {
00533     rt_named_hfree_typed(adr, SPECIFIC);
00534 }
00535 
00536 extern rtheap_t  rtai_global_heap;
00537 extern void     *rtai_global_heap_adr;
00538 extern int       rtai_global_heap_size;
00539 
00540 static RTAI_SYSCALL_MODE void *rt_malloc_usp(int size)
00541 {
00542     return rtai_global_heap_adr ? rt_halloc_typed(size, GLOBAL) : NULL;
00543 }
00544 
00545 static RTAI_SYSCALL_MODE void rt_free_usp(void *adr)
00546 {
00547     if (rtai_global_heap_adr) {
00548         rt_hfree_typed(adr, GLOBAL);
00549     }
00550 }
00551 
00552 static RTAI_SYSCALL_MODE void *rt_named_malloc_usp(unsigned long name, int size)
00553 {
00554     return rtai_global_heap_adr ? rt_named_halloc_typed(name, size, GLOBAL) : NULL;
00555 }
00556 
00557 static RTAI_SYSCALL_MODE void rt_named_free_usp(void *adr)
00558 {
00559     if (rtai_global_heap_adr) {
00560         rt_named_hfree_typed(adr, GLOBAL);
00561     }
00562 }
00563 
00564 static RTAI_SYSCALL_MODE void rt_set_heap(unsigned long name, void *adr)
00565 {
00566     void *heap, *hptr;
00567     int size;
00568     RT_TASK *task;
00569 
00570     heap = rt_get_adr(name);
00571     hptr = ALIGN2PAGE(heap);
00572     size = ((abs(rt_get_type(name)) - sizeof(rtheap_t) - (hptr - heap)) & PAGE_MASK);
00573     heap = hptr + size;
00574     if (!atomic_cmpxchg((atomic_t *)hptr, 0, name)) {
00575         rtheap_init(heap, hptr, size, PAGE_SIZE, 0);
00576     }
00577     RTAI_TASK(return);
00578     if (name == GLOBAL_HEAP_ID) {
00579         task->heap[GLOBAL].heap = &rtai_global_heap;
00580         task->heap[GLOBAL].kadr = rtai_global_heap_adr;
00581         task->heap[GLOBAL].uadr = adr;
00582     } else {
00583         task->heap[SPECIFIC].heap = heap;
00584         task->heap[SPECIFIC].kadr = hptr;
00585         task->heap[SPECIFIC].uadr = adr;
00586     }
00587 }
00588 
00589 /**
00590  * Open/create a named group real time heap to be shared inter-intra kernel 
00591  * modules and Linux processes.
00592  *
00593  * @internal
00594  * 
00595  * rt_heap_open is used to allocate open/create a shared real time heap.
00596  * 
00597  * @param name is an unsigned long identifier;
00598  * 
00599  * @param size is the amount of required shared memory;
00600  * 
00601  * @param suprt is the kernel allocation method to be used, it can be:
00602  * - USE_VMALLOC, use vmalloc;
00603  * - USE_GFP_KERNEL, use kmalloc with GFP_KERNEL;
00604  * - USE_GFP_ATOMIC, use kmalloc with GFP_ATOMIC;
00605  * - USE_GFP_DMA, use kmalloc with GFP_DMA.
00606  *
00607  * Since @a name can be a clumsy identifier, services are provided to
00608  * convert 6 characters identifiers to unsigned long, and vice versa.
00609  * 
00610  * @see nam2num() and num2nam().
00611  * 
00612  * It must be remarked that only the very first open does a real allocation, 
00613  * any subsequent one with the same name from anywhere will just map the area 
00614  * to the user space, or return the related pointer to the already allocated 
00615  * memory in kernel space. In any case the functions return a pointer to the 
00616  * allocated memory, appropriately mapped to the memory space in use.
00617  * Be careful and avoid opening more than one group heap per process/task, if 
00618  * more than one is opened then just the last will used.
00619  *
00620  * @returns a valid address on succes, 0 on failure.
00621  *
00622  */
00623 
00624 void *rt_heap_open(unsigned long name, int size, int suprt)
00625 {
00626     void *adr;
00627     if ((adr = rt_shm_alloc(name, ((size - 1) & PAGE_MASK) + PAGE_SIZE + sizeof(rtheap_t), suprt))) {
00628         rt_set_heap(name, adr);
00629         return adr;
00630     }
00631     return 0;
00632 }
00633 
00634 #endif
00635 
00636 struct rt_native_fun_entry rt_shm_entries[] = {
00637         { { 0, rt_shm_alloc_usp },      SHM_ALLOC },
00638         { { 0, rt_shm_free },           SHM_FREE },
00639         { { 0, rt_shm_size },           SHM_SIZE },
00640 #ifdef CONFIG_RTAI_MALLOC
00641         { { 0, rt_set_heap },           HEAP_SET},
00642         { { 0, rt_halloc },         HEAP_ALLOC },
00643         { { 0, rt_hfree },          HEAP_FREE },
00644         { { 0, rt_named_halloc },       HEAP_NAMED_ALLOC },
00645         { { 0, rt_named_hfree },        HEAP_NAMED_FREE },
00646         { { 0, rt_malloc_usp },         MALLOC },
00647         { { 0, rt_free_usp },           FREE },
00648         { { 0, rt_named_malloc_usp },       NAMED_MALLOC },
00649         { { 0, rt_named_free_usp },     NAMED_FREE },
00650 #endif
00651         { { 0, 0 },             000 }
00652 };
00653 
00654 extern int set_rt_fun_entries(struct rt_native_fun_entry *entry);
00655 extern void reset_rt_fun_entries(struct rt_native_fun_entry *entry);
00656 
00657 #define USE_UDEV_CLASS 0
00658 
00659 #if USE_UDEV_CLASS
00660 static class_t *shm_class = NULL;
00661 #endif
00662 
00663 int __rtai_shm_init (void)
00664 {
00665 #if USE_UDEV_CLASS
00666     if ((shm_class = class_create(THIS_MODULE, "rtai_shm")) == NULL) {
00667         printk("RTAI-SHM: cannot create class.\n");
00668         return -EBUSY;
00669     }
00670     if (CLASS_DEVICE_CREATE(shm_class, MKDEV(MISC_MAJOR, RTAI_SHM_MISC_MINOR), NULL, "rtai_shm") == NULL) {
00671         printk("RTAI-SHM: cannot attach class.\n");
00672         class_destroy(shm_class);
00673         return -EBUSY;
00674     }
00675 #endif
00676 
00677     if (misc_register(&rtai_shm_dev) < 0) {
00678         printk("***** UNABLE TO REGISTER THE SHARED MEMORY DEVICE (miscdev minor: %d) *****\n", RTAI_SHM_MISC_MINOR);
00679         return -EBUSY;
00680     }
00681 #ifdef CONFIG_RTAI_MALLOC
00682 #ifdef CONFIG_RTAI_MALLOC_VMALLOC
00683     rt_register(GLOBAL_HEAP_ID, rtai_global_heap_adr, rtai_global_heap_size, 0);
00684     rt_smp_linux_task->heap[GLOBAL].heap = &rtai_global_heap;
00685     rt_smp_linux_task->heap[GLOBAL].kadr =
00686     rt_smp_linux_task->heap[GLOBAL].uadr = rtai_global_heap_adr;
00687 #else
00688     printk("***** WARNING: GLOBAL HEAP NEITHER SHARABLE NOR USABLE FROM USER SPACE (use the vmalloc option for RTAI malloc) *****\n");
00689 #endif
00690 #endif
00691     return set_rt_fun_entries(rt_shm_entries);
00692 }
00693 
00694 void __rtai_shm_exit (void)
00695 {
00696     extern int max_slots;
00697         int slot;
00698         struct rt_registry_entry entry;
00699 
00700 #ifdef CONFIG_RTAI_MALLOC_VMALLOC
00701     rt_drg_on_name_cnt(GLOBAL_HEAP_ID);
00702 #endif
00703     for (slot = 1; slot <= max_slots; slot++) {
00704         if (rt_get_registry_slot(slot, &entry)) {
00705             if (abs(entry.type) >= PAGE_SIZE) {
00706                     char name[8];
00707                 while (_rt_shm_free(entry.name, entry.type));
00708                             num2nam(entry.name, name);
00709                             rt_printk("\nSHM_CLEANUP_MODULE releases: '%s':0x%lx:%lu (%d).\n", name, entry.name, entry.name, entry.type);
00710                         }
00711         }
00712     }
00713     reset_rt_fun_entries(rt_shm_entries);
00714     misc_deregister(&rtai_shm_dev);
00715 #if USE_UDEV_CLASS
00716     class_device_destroy(shm_class, MKDEV(MISC_MAJOR, RTAI_SHM_MISC_MINOR));
00717     class_destroy(shm_class);
00718 #endif
00719     return;
00720 }
00721 
00722 /*@}*/
00723 
00724 #ifndef CONFIG_RTAI_SHM_BUILTIN
00725 module_init(__rtai_shm_init);
00726 module_exit(__rtai_shm_exit);
00727 #endif /* !CONFIG_RTAI_SHL_BUILTIN */
00728 
00729 #ifdef CONFIG_KBUILD
00730 EXPORT_SYMBOL(rt_shm_alloc);
00731 EXPORT_SYMBOL(rt_shm_free);
00732 #ifdef CONFIG_RTAI_MALLOC
00733 EXPORT_SYMBOL(rt_named_malloc);
00734 EXPORT_SYMBOL(rt_named_free);
00735 EXPORT_SYMBOL(rt_halloc);
00736 EXPORT_SYMBOL(rt_hfree);
00737 EXPORT_SYMBOL(rt_named_halloc);
00738 EXPORT_SYMBOL(rt_named_hfree);
00739 EXPORT_SYMBOL(rt_heap_open);
00740 #endif
00741 #endif /* CONFIG_KBUILD */

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