base/include/rtai_shm.h

Go to the documentation of this file.
00001 /**
00002  * @ingroup shm
00003  * @file
00004  *
00005  * Interface 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 ACKNOWLEDGMENTS:
00028 - The suggestion and the code for mmapping at a user specified address is due to  Trevor Woolven (trevw@zentropix.com).
00029 */
00030 
00031 
00032 #ifndef _RTAI_SHM_H
00033 #define _RTAI_SHM_H
00034 
00035 /** @addtogroup shm
00036  *@{*/
00037 
00038 #define GLOBAL_HEAP_ID  0x9ac6d9e7  // nam2num("RTGLBH");
00039 
00040 #define USE_VMALLOC     0
00041 #define USE_GFP_KERNEL  1
00042 #define USE_GFP_ATOMIC  2
00043 #define USE_GFP_DMA     3
00044 
00045 /**
00046  * Allocate a chunk of memory to be shared inter-intra kernel modules and 
00047  * Linux processes.
00048  *
00049  * @internal
00050  * 
00051  * rtai_kalloc is used to allocate shared memory from kernel space.
00052  * 
00053  * @param name is an unsigned long identifier;
00054  * 
00055  * @param size is the amount of required shared memory;
00056  * 
00057  * rtai_kmalloc is a legacy helper macro, the real job is carried out by a
00058  * call to rt_shm_alloc() with the same name, size and with vmalloc support.
00059  * This function should not be used in newly developed applications. See 
00060  * rt_shm_alloc for more details.
00061  *
00062  * @returns a valid address on succes, 0 on failure.
00063  *
00064  */
00065 
00066 #define rtai_kmalloc(name, size) \
00067     rt_shm_alloc(name, size, USE_VMALLOC)  // legacy
00068 
00069 /**
00070  * Free a chunk of shared memory being shared inter-intra kernel modules and 
00071  * Linux processes.
00072  *
00073  * rtai_kfree is used to free a shared memory chunk from kernel space.
00074  *
00075  * @param name is the unsigned long identifier used when the memory was
00076  * allocated;
00077  *
00078  * rtai_kfree is a legacy helper macro, the real job is carried out by a
00079  * call to rt_shm_free with the same name. This function should not be used 
00080  * in newly developed applications. See rt_shm_free for more details.
00081  *
00082  * @returns the size of the succesfully freed memory, 0 on failure.
00083  *
00084  */
00085 
00086 #define rtai_kfree(name) \
00087     rt_shm_free(name)  // legacy
00088 
00089 #if defined(__KERNEL__)
00090 
00091 #include <linux/module.h>
00092 #include <linux/version.h>
00093 #include <linux/vmalloc.h>
00094 #include <linux/mm.h>
00095 
00096 #if 0
00097 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
00098 #include <linux/wrapper.h>
00099 #else /* >= 2.6.0 */
00100 #include <linux/mm.h>
00101 #define mem_map_reserve(p)   SetPageReserved(p)
00102 #define mem_map_unreserve(p) ClearPageReserved(p)
00103 #endif /* < 2.6.0 */
00104 #endif
00105 
00106 #define UVIRT_TO_KVA(adr)  uvirt_to_kva(pgd_offset_k(adr), (adr))
00107 
00108 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,10)
00109 static inline int remap_page_range(struct vm_area_struct *vma, unsigned long uvaddr, unsigned long paddr, unsigned long size, pgprot_t prot)
00110 {
00111     return remap_pfn_range(vma, uvaddr, paddr >> PAGE_SHIFT, size, prot);
00112 }
00113 #endif
00114 
00115 #include <rtai.h>
00116 //#include <asm/rtai_shm.h>
00117 
00118 #include <rtai_malloc.h>
00119 
00120 #ifndef CONFIG_MMU
00121 
00122 static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr)
00123 {
00124     return adr;
00125 }
00126 
00127 #else
00128 
00129 static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr)
00130 {
00131     if (!pgd_none(*pgd) && !pgd_bad(*pgd)) {
00132         pmd_t *pmd;
00133 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11)
00134         pmd = pmd_offset(pgd, adr);
00135 #else /* >= 2.6.11 */
00136         pmd = pmd_offset(pud_offset(pgd, adr), adr);
00137 #endif /* < 2.6.11 */
00138         if (!pmd_none(*pmd)) {
00139             pte_t *ptep, pte;
00140 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
00141             ptep = pte_offset(pmd, adr);
00142 #else /* >= 2.6.0 */
00143             ptep = pte_offset_kernel(pmd, adr);
00144 #endif /* < 2.6.0 */
00145             pte = *ptep;
00146             if (pte_present(pte)) {
00147                 return (((unsigned long)page_address(pte_page(pte))) | (adr & (PAGE_SIZE - 1)));
00148             }
00149         }
00150     }
00151     return 0UL;
00152 }
00153 
00154 static inline unsigned long kvirt_to_pa(unsigned long adr)
00155 {
00156     return virt_to_phys((void *)uvirt_to_kva(pgd_offset_k(adr), adr));
00157 }
00158 
00159 #endif
00160 
00161 #ifdef __cplusplus
00162 extern "C" {
00163 #endif /* __cplusplus */
00164 
00165 int __rtai_shm_init(void);
00166 
00167 void __rtai_shm_exit(void);
00168 
00169 void *rt_shm_alloc(unsigned long name,
00170            int size,
00171            int suprt);
00172 
00173 #define rt_shm_alloc_adr(adr, name, size) \
00174     rt_shm_alloc(name, size, suprt)
00175 
00176 RTAI_SYSCALL_MODE int rt_shm_free(unsigned long name);
00177 
00178 void *rt_heap_open(unsigned long name,
00179            int size,
00180            int suprt);
00181 
00182 #define rt_heap_open_adr(adr, name, size, suprt) \
00183     rt_heap_open(name, size, suprt)
00184 
00185 RTAI_SYSCALL_MODE void *rt_halloc(int size);
00186 
00187 RTAI_SYSCALL_MODE void rt_hfree(void *addr);
00188 
00189 RTAI_SYSCALL_MODE void *rt_named_halloc(unsigned long name, int size);
00190 
00191 RTAI_SYSCALL_MODE void rt_named_hfree(void *addr);
00192 
00193 void *rt_named_malloc(unsigned long name,
00194               int size);
00195 
00196 void rt_named_free(void *addr);
00197 
00198 void *rvmalloc(unsigned long size);
00199 
00200 void rvfree(void *mem,
00201         unsigned long size);
00202 
00203 int rvmmap(void *mem,
00204        unsigned long memsize,
00205        struct vm_area_struct *vma);
00206 
00207 void *rkmalloc(int *size,
00208            int suprt);
00209 
00210 void rkfree(void *mem,
00211         unsigned long size);
00212 
00213 int rkmmap(void *mem,
00214        unsigned long memsize,
00215        struct vm_area_struct *vma);
00216 
00217 #ifdef __cplusplus
00218 }
00219 #endif /* __cplusplus */
00220 
00221 #else /* !__KERNEL__ */
00222 
00223 #include <fcntl.h>
00224 #include <unistd.h>
00225 #include <sys/mman.h>
00226 #include <sys/ioctl.h>
00227 #include <rtai_lxrt.h>
00228 
00229 //#define SHM_USE_LXRT
00230 
00231 #define RTAI_SHM_DEV  "/dev/rtai_shm"
00232 
00233 RTAI_PROTO (void *, _rt_shm_alloc, (void *start, unsigned long name, int size, int suprt, int isheap))
00234 {
00235     int hook;
00236     void *adr = NULL;
00237 
00238     if ((hook = open(RTAI_SHM_DEV, O_RDWR)) <= 0) {
00239         return NULL;
00240     } else {
00241         struct { unsigned long name, arg, suprt; } arg = { name, size, suprt };
00242 #ifdef SHM_USE_LXRT
00243         if ((size = rtai_lxrt(BIDX, SIZARG, SHM_ALLOC, &arg).i[LOW])) {
00244 #else
00245         if ((size = ioctl(hook, SHM_ALLOC, (unsigned long)(&arg)))) {
00246 #endif
00247             if ((adr = mmap(start, size, PROT_WRITE | PROT_READ, MAP_SHARED | MAP_LOCKED, hook, 0)) == MAP_FAILED) {;
00248 #ifdef SHM_USE_LXRT
00249                 rtai_lxrt(BIDX, sizeof(name), SHM_FREE, &name);
00250 #else
00251                 ioctl(hook, SHM_FREE, &name);
00252 #endif
00253             } else if (isheap) {
00254                 arg.arg = (unsigned long)adr;
00255 #ifdef SHM_USE_LXRT
00256                 rtai_lxrt(BIDX, SIZARG, HEAP_SET, &arg);
00257 #else
00258                 ioctl(hook, HEAP_SET, &arg);
00259 #endif
00260             }
00261         }
00262     }
00263     close(hook);
00264     return adr;
00265 }
00266 
00267 #define rt_shm_alloc(name, size, suprt)  \
00268     _rt_shm_alloc(0, name, size, suprt, 0)
00269 
00270 #define rt_heap_open(name, size, suprt)  \
00271     _rt_shm_alloc(0, name, size, suprt, 1)
00272 
00273 /**
00274  * Allocate a chunk of memory to be shared inter-intra kernel modules and 
00275  * Linux processes.
00276  *
00277  * @internal
00278  * 
00279  * rtai_malloc is used to allocate shared memory from user space.
00280  * 
00281  * @param name is an unsigned long identifier;
00282  * 
00283  * @param size is the amount of required shared memory;
00284  * 
00285  * rtai_malloc is a legacy helper macro, the real job is carried out by a
00286  * call to rt_shm_alloc() with the same name, size and with vmalloc support.
00287  * This function should not be used in newly developed applications. See
00288  * rt_shm_alloc fro more details.
00289  *
00290  * @returns a valid address on succes, on failure: 0 if it was unable to 
00291  * allocate any memory, MAP_FAILED if it was possible to allocate the
00292  * required memory but failed to mmap it to user space, in which case the
00293  * allocated memory is freed anyhow.
00294  *
00295  */
00296 
00297 #define rtai_malloc(name, size)  \
00298     _rt_shm_alloc(0, name, size, USE_VMALLOC, 0)  // legacy
00299 
00300 /**
00301  * Allocate a chunk of memory to be shared inter-intra kernel modules and Linux
00302  * processes.
00303  *
00304  * rt_shm_alloc_adr is used to allocate in user space.
00305  *
00306  * @param start_address is a user desired address where the allocated memory
00307  * should be mapped in user space;
00308  *
00309  * @param name is an unsigned long identifier;
00310  * 
00311  * @param size is the amount of required shared memory.
00312  *
00313  * @param suprt is the kernel allocation method to be used, it can be:
00314  * - USE_VMALLOC, use vmalloc;
00315  * - USE_GFP_KERNEL, use kmalloc with GFP_KERNEL;
00316  * - USE_GFP_ATOMIC, use kmalloc with GFP_ATOMIC;
00317  * - USE_GFP_DMA, use kmalloc with GFP_DMA.
00318  *
00319  * Since @c name can be a clumsy identifier, services are provided to
00320  * convert 6 characters identifiers to unsigned long, and vice versa.
00321  *
00322  * @see the functions nam2num() and num2nam().
00323  *
00324  * It must be remarked that only the very first call does a real allocation, 
00325  * any subsequent call to allocate with the same name from anywhere will just
00326  * increase the usage count and map the area to user space, or return the
00327  * related pointer to the already allocated space in kernel space. The function 
00328  * returns a pointer to the allocated memory, appropriately mapped to the memory
00329  * space in use. So if one is really sure that the named shared memory has been 
00330  * allocated already parameters size and suprt are not used and can be 
00331  * assigned any value.
00332  *
00333  * @note If the same process calls rtai_malloc_adr and rtai_malloc() twice in
00334  * the same process it get a zero return value on the second call.
00335  *
00336  * @returns a valid address on succes, on failure: 0 if it was unable to
00337  * allocate any memory, MAP_FAILED if it was possible to allocate the
00338  * required memory but failed to mmap it to user space, in which case the
00339  * allocated memory is freed anyhow.
00340  *
00341  */
00342 
00343 #define rt_shm_alloc_adr(start_address, name, size, suprt)  \
00344     _rt_shm_alloc(start_address, name, size, suprt, 0)
00345 
00346 #define rt_heap_open_adr(start, name, size, suprt)  \
00347     _rt_shm_alloc(start, name, size, suprt, 1)
00348 
00349 /**
00350  * Allocate a chunk of memory to be shared inter-intra kernel modules and 
00351  * Linux processes.
00352  *
00353  * @internal
00354  * 
00355  * rtai_malloc_adr is used to allocate shared memory from user space.
00356  *
00357  * @param start_address is the adr were the shared memory should be mapped.
00358  * 
00359  * @param name is an unsigned long identifier;
00360  * 
00361  * @param size is the amount of required shared memory;
00362  * 
00363  * rtai_malloc_adr is a legacy helper macro, the real job is carried out by a
00364  * call to rt_shm_alloc_adr() with the same name, size and with vmalloc support.
00365  * This function should not be used in newly developed applications. See
00366  * rt_shm_alloc_adr for more details.
00367  *
00368  * @returns a valid address on succes, 0 on failure.
00369  *
00370  */
00371 
00372 #define rtai_malloc_adr(start_address, name, size)  \
00373     _rt_shm_alloc(start_address, name, size, USE_VMALLOC, 0)  // legacy
00374 
00375 RTAI_PROTO(int, rt_shm_free, (unsigned long name))
00376 {
00377     int hook, size;
00378     struct { void *nameadr; } arg = { &name };
00379     if ((hook = open(RTAI_SHM_DEV, O_RDWR)) <= 0) {
00380         return 0;
00381     }
00382 // no SHM_FREE needed, we release it all and munmap will do it through 
00383 // the vma close operation provided by shm.c
00384 #ifdef SHM_USE_LXRT
00385     if ((size = rtai_lxrt(BIDX, SIZARG, SHM_SIZE, &arg).i[LOW])) {
00386 #else
00387     if ((size = ioctl(hook, SHM_SIZE, (unsigned long)&arg))) {
00388 #endif
00389         if (munmap((void *)name, size)) {
00390             size = 0;
00391         }
00392     }
00393     close(hook);
00394     return size;
00395 }
00396 
00397 /**
00398  * Free a chunk of shared memory being shared inter-intra 
00399  * kernel modules and Linux processes.
00400  *
00401  * rtai_free is used to free a shared memory chunk from user space.
00402  *
00403  * @param name is the unsigned long identifier used when the memory was
00404  * allocated;
00405  *
00406  * @param adr is not used.
00407  *
00408  * rtai_free is a legacy helper macro, the real job is carried out by a
00409  * call to rt_shm_free with the same name. This function should not be used 
00410  * in newly developed applications. See rt_shm_alloc_adr for more details.
00411  *
00412  * @returns the size of the succesfully freed memory, 0 on failure.
00413  *
00414  */
00415 
00416 #define rtai_free(name, adr)  \
00417     rt_shm_free(name)  // legacy
00418 
00419 RTAI_PROTO(void *, rt_halloc, (int size))
00420 {
00421     struct { long size; } arg = { size };
00422     return rtai_lxrt(BIDX, SIZARG, HEAP_ALLOC, &arg).v[LOW];
00423 }
00424 
00425 RTAI_PROTO(void, rt_hfree, (void *addr))
00426 {
00427     struct { void *addr; } arg = { addr };
00428     rtai_lxrt(BIDX, SIZARG, HEAP_FREE, &arg);
00429 }
00430 
00431 RTAI_PROTO(void *, rt_named_halloc, (unsigned long name, int size))
00432 {
00433     struct { unsigned long name; long size; } arg = { name, size };
00434     return rtai_lxrt(BIDX, SIZARG, HEAP_NAMED_ALLOC, &arg).v[LOW];
00435 }
00436 
00437 RTAI_PROTO(void, rt_named_hfree, (void *addr))
00438 {
00439     struct { void *addr; } arg = { addr };
00440     rtai_lxrt(BIDX, SIZARG, HEAP_NAMED_FREE, &arg);
00441 }
00442 
00443 RTAI_PROTO(void *, rt_malloc, (int size))
00444 {
00445     struct { long size; } arg = { size };
00446     return rtai_lxrt(BIDX, SIZARG, MALLOC, &arg).v[LOW];
00447 }
00448 
00449 RTAI_PROTO(void, rt_free, (void *addr))
00450 {
00451     struct { void *addr; } arg = { addr };
00452     rtai_lxrt(BIDX, SIZARG, FREE, &arg);
00453 }
00454 
00455 RTAI_PROTO(void *, rt_named_malloc, (unsigned long name, int size))
00456 {
00457     struct { unsigned long name; long size; } arg = { name, size };
00458     return rtai_lxrt(BIDX, SIZARG, NAMED_MALLOC, &arg).v[LOW];
00459 }
00460 
00461 RTAI_PROTO(void, rt_named_free, (void *addr))
00462 {
00463     struct { void *addr; } arg = { addr };
00464     rtai_lxrt(BIDX, SIZARG, NAMED_FREE, &arg);
00465 }
00466 
00467 #endif /* __KERNEL__ */
00468 
00469 /**
00470  * Close a real time group heap being shared inter-intra kernel modules and
00471  * Linux processes.
00472  *
00473  * @internal
00474  * 
00475  * rt_heap_close is used to close a previously opened real time group heap.
00476  *
00477  * @param name is the unsigned long identifier used to identify the heap.
00478  *
00479  * @param adr is not used.
00480  *
00481  * Analogously to what done by any allocation function this group real time
00482  * heap closing call have just the effect of decrementing a usage count, 
00483  * unmapping any user space heap being closed, till the last is done, as that 
00484  * is the one the really closes the group heap, freeing any allocated memory.
00485  *
00486  * @returns the size of the succesfully freed heap, 0 on failure.
00487  *
00488  */
00489 
00490 #define rt_heap_close(name, adr)  rt_shm_free(name)
00491 
00492 // aliases in use already, different heads different choices
00493 #define rt_heap_init         rt_heap_open
00494 #define rt_heap_create       rt_heap_open
00495 #define rt_heap_acquire      rt_heap_open
00496 #define rt_heap_init_adr     rt_heap_open_adr
00497 #define rt_heap_create_adr   rt_heap_open_adr
00498 #define rt_heap_acquire_adr  rt_heap_open_adr
00499 
00500 #define rt_heap_delete       rt_heap_close
00501 #define rt_heap_destroy      rt_heap_close
00502 #define rt_heap_release      rt_heap_close
00503 
00504 // these have no aliases, and never will
00505 
00506 /**
00507  * Open the global real time heap to be shared inter-intra kernel modules and 
00508  * Linux processes.
00509  *
00510  * @internal
00511  * 
00512  * rt_global_heap_open is used to open the global real time heap.
00513  * 
00514  * The global heap is created by the shared memory module and its opening is
00515  * needed in user space to map it to the process address space. In kernel
00516  * space opening the global heap in a task is not required but should be done
00517  * anyhow, both for symmetry and to register its usage.
00518  *
00519  */
00520 
00521 #define rt_global_heap_open()  rt_heap_open(GLOBAL_HEAP_ID, 0, 0)
00522 
00523 /**
00524  * Close the global real time heap being shared inter-intra kernel modules and 
00525  * Linux processes.
00526  *
00527  * @internal
00528  * 
00529  * rt_global_heap_close is used to close the global real time heap.
00530  * 
00531  * Closing a global heap in user space has just the effect of deregistering
00532  * its use and unmapping the related memory from a process address space.
00533  * In kernel tasks just the deregistration is performed.
00534  * The global real time heap is destroyed just a the rmmoding of the shared
00535  * memory module.
00536  *
00537  */
00538 
00539 #define rt_global_heap_close()  rt_heap_close(GLOBAL_HEAP_ID, 0)
00540 
00541 /*@}*/
00542 
00543 #endif /* !_RTAI_SHM_H */

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