📄 shm.c
字号:
* */void *rt_named_malloc(unsigned long name, int size){ void *mem_ptr; if ((mem_ptr = rt_get_adr_cnt(name))) { return mem_ptr; } if ((mem_ptr = _rt_halloc(size, &rt_smp_linux_task->heap[GLOBAL]))) { if (rt_register(name, mem_ptr, IS_HPCK, 0)) { return mem_ptr; } rt_hfree(mem_ptr); } return NULL;}/** * Free a named chunk of the global real time heap. * * @internal * * rt_named_free is used to free a previously allocated chunk of the global * real time heap. * * @param addr is the addr of the memory to be freed. * * Analogously to what done by all the named allocation functions the freeing * calls of named memory chunks have just the effect of decrementing its usage * count, any shared piece of the global heap being freed only when the last * is done, as that is the one the really frees any allocated memory. * So one must be carefull not to use rt_free on a named global heap chunk, * since it will force its unconditional immediate freeing. * */void rt_named_free(void *adr){ unsigned long name; name = rt_get_name(adr); if (!rt_drg_on_name_cnt(name)) { _rt_hfree(adr, &rt_smp_linux_task->heap[GLOBAL]); }}/* * we must care of this because LXRT callable functions are set as non * blocking, so they are called directly. */#define RTAI_TASK(return_instr) \do { \ if (!(task = _rt_whoami())->is_hard) { \ if (!(task = current->this_rt_task[0])) { \ return_instr; \ } \ } \} while (0)static inline void *rt_halloc_typed(int size, int htype){ RT_TASK *task; RTAI_TASK(return NULL); return _rt_halloc(size, &task->heap[htype]);}static inline void rt_hfree_typed(void *addr, int htype){ RT_TASK *task; RTAI_TASK(return); _rt_hfree(addr, &task->heap[htype]);}static inline void *rt_named_halloc_typed(unsigned long name, int size, int htype){ RT_TASK *task; void *mem_ptr; RTAI_TASK(return NULL); if ((mem_ptr = rt_get_adr_cnt(name))) { return task->heap[htype].huadr + (mem_ptr - task->heap[htype].hkadr); } if ((mem_ptr = _rt_halloc(size, &task->heap[htype]))) { if (rt_register(name, task->heap[htype].hkadr + (mem_ptr - task->heap[htype].huadr), IS_HPCK, 0)) { return mem_ptr; } _rt_hfree(mem_ptr, &task->heap[htype]); } return NULL;}static inline void rt_named_hfree_typed(void *adr, int htype){ RT_TASK *task; unsigned long name; RTAI_TASK(return); name = rt_get_name(task->heap[htype].hkadr + (adr - task->heap[htype].huadr)); if (!rt_drg_on_name_cnt(name)) { _rt_hfree(adr, &task->heap[htype]); }}/** * Allocate a chunk of a group real time heap in kernel/user space. Since * it is not named there is no chance to retrieve and share it elsewhere. * * @internal * * rt_halloc is used to allocate a non sharable piece of a group real time * heap. * * @param size is the size of the requested memory in bytes; * * A process/task must have opened the real time group heap to use and can use * just one real time group heap. Be careful and avoid opening more than one * group real time heap per process/task. If more than one is opened then just * the last will used. * * @returns the pointer to the allocated memory, 0 on failure. * */void *rt_halloc(int size){ return rt_halloc_typed(size, SPECIFIC);}/** * Free a chunk of a group real time heap. * * @internal * * rt_hfree is used to free a previously allocated chunck of a group real * time heap. * * @param addr is the addr of the memory to be freed. * */void rt_hfree(void *adr){ rt_hfree_typed(adr, SPECIFIC);}/** * Allocate a chunk of a group real time heap in kernel/user space. Since * it is named it can be retrieved and shared everywhere among the group * peers, i.e all processes/tasks that have opened the same group heap. * * @internal * * rt_named_halloc is used to allocate a sharable piece of a group real * time heap. * * @param name is an unsigned long identifier; * * @param size is the amount of required shared memory; * * Since @a name can be a clumsy identifier, services are provided to * convert 6 characters identifiers to unsigned long, and vice versa. * * @see nam2num() and num2nam(). * * A process/task must have opened the real time group heap to use and can use * just one real time group heap. Be careful and avoid opening more than one * group real time heap per process/task. If more than one is opened then just * the last will used. It must be remarked that only the very first call does * a real allocation, any subsequent call with the same name will just * increase the usage count and receive the appropriate pointer to the already * allocated memory having the same name. * * @returns a valid address on succes, 0 on failure. * */void *rt_named_halloc(unsigned long name, int size){ return rt_named_halloc_typed(name, size, SPECIFIC);}/** * Free a chunk of a group real time heap. * * @internal * * rt_named_hfree is used to free a previously allocated chunk of the global * real time heap. * * @param addr is the addr of the memory to be freed. * * Analogously to what done by all the named allocation functions the freeing * calls of named memory chunks have just the effect of decrementing a usage * count, any shared piece of the global heap being freed only when the last * is done, as that is the one the really frees any allocated memory. * So one must be carefull not to use rt_hfree on a named global heap chunk, * since it will force its unconditional immediate freeing. * */void rt_named_hfree(void *adr){ rt_named_hfree_typed(adr, SPECIFIC);}static void *rt_malloc_new_usp(int size){ return rt_halloc_typed(size, GLOBAL);}static void rt_free_new_usp(void *adr){ rt_hfree_typed(adr, GLOBAL);}static void *rt_named_malloc_usp(unsigned long name, int size){ return rt_named_halloc_typed(name, size, GLOBAL);}static void rt_named_free_usp(void *adr){ rt_named_hfree_typed(adr, GLOBAL);}static void rt_set_heap(unsigned long name, void *adr){ int size, htype; void *hptr; RT_TASK *task; hptr = ALIGN2PAGE(rt_get_adr(name)); size = ((abs(rt_get_type(name)) - sizeof(rtheap_t) - 1) & PAGE_MASK); if (!atomic_cmpxchg((int *)hptr, 0, name)) { rtheap_init(hptr + size, hptr, size, PAGE_SIZE); if (name == GLOBAL_HEAP_ID) { rt_smp_linux_task->heap[GLOBAL].hkadr = (void *)hptr; rt_smp_linux_task->heap[GLOBAL].huadr = adr; rt_smp_linux_task->heap[GLOBAL].hsize = size; } } RTAI_TASK(return); htype = name == GLOBAL_HEAP_ID ? GLOBAL : SPECIFIC; task->heap[htype].hkadr = (void *)hptr; task->heap[htype].huadr = adr; task->heap[htype].hsize = size;}/** * Open/create a named group real time heap to be shared inter-intra kernel * modules and Linux processes. * * @internal * * rt_heap_open is used to allocate open/create a shared real time heap. * * @param name is an unsigned long identifier; * * @param size is the amount of required shared memory; * * @param suprt is the kernel allocation method to be used, it can be: * - USE_VMALLOC, use vmalloc; * - USE_GFP_KERNEL, use kmalloc with GFP_KERNEL; * - USE_GFP_ATOMIC, use kmalloc with GFP_ATOMIC; * - USE_GFP_DMA, use kmalloc with GFP_DMA. * * Since @a name can be a clumsy identifier, services are provided to * convert 6 characters identifiers to unsigned long, and vice versa. * * @see nam2num() and num2nam(). * * It must be remarked that only the very first open does a real allocation, * any subsequent one with the same name from anywhere will just map the area * to the user space, or return the related pointer to the already allocated * memory in kernel space. In any case the functions return a pointer to the * allocated memory, appropriately mapped to the memory space in use. * Be careful and avoid opening more than one group heap per process/task, if * more than one is opened then just the last will used. * * @returns a valid address on succes, 0 on failure. * */void *rt_heap_open(unsigned long name, int size, int suprt){ void *adr; if ((adr = rt_shm_alloc(name, ((size - 1) & PAGE_MASK) + PAGE_SIZE + sizeof(rtheap_t), suprt))) { rt_set_heap(name, adr); return adr; } return 0;}struct rt_native_fun_entry rt_shm_entries[] = { { { 0, rt_shm_alloc_usp }, SHM_ALLOC }, { { 0, rt_shm_free }, SHM_FREE }, { { 0, rt_shm_size }, SHM_SIZE }, { { 0, rt_set_heap }, HEAP_SET}, { { 0, rt_halloc }, HEAP_ALLOC }, { { 0, rt_hfree }, HEAP_FREE }, { { 0, rt_named_halloc }, HEAP_NAMED_ALLOC }, { { 0, rt_named_hfree }, HEAP_NAMED_FREE }, { { 0, rt_malloc_new_usp }, MALLOC }, { { 0, rt_free_new_usp }, FREE }, { { 0, rt_named_malloc_usp }, NAMED_MALLOC }, { { 0, rt_named_free_usp }, NAMED_FREE }, { { 0, 0 }, 000 }};extern int set_rt_fun_entries(struct rt_native_fun_entry *entry);extern void reset_rt_fun_entries(struct rt_native_fun_entry *entry);#define GLOBAL_HEAP_SIZE PAGE_SIZE*31; // just to have something at the momentstatic int GlobalHeapSize = GLOBAL_HEAP_SIZE;MODULE_PARM(GlobalHeapSize, "i");static void *global_heap;int __rtai_shm_init (void){ if (misc_register(&rtai_shm_dev) < 0) { printk("***** UNABLE TO REGISTER THE SHARED MEMORY DEVICE (miscdev minor: %d) *****\n", RTAI_SHM_MISC_MINOR); return -EBUSY; } if (!(global_heap = rt_heap_open(GLOBAL_HEAP_ID, GlobalHeapSize, #ifdef CONFIG_RTAI_MALLOC_VMALLOCUSE_VMALLOC#else USE_GFP_KERNEL#endif))) { misc_deregister(&rtai_shm_dev); printk("***** UNABLE TO CREATE THE GLOBAL REAL TIME HEAP (size: %d) *****\n", GlobalHeapSize); return -ENOMEM; } return set_rt_fun_entries(rt_shm_entries);}void __rtai_shm_exit (void){ int slot; struct rt_registry_entry_struct entry; rt_heap_close(GLOBAL_HEAP_ID, global_heap); for (slot = 1; slot <= MAX_SLOTS; slot++) { if (rt_get_registry_slot(slot, &entry) && entry.adr) { if (abs(entry.type) >= PAGE_SIZE) { char name[8]; while (_rt_shm_free(entry.name, entry.type)); num2nam(entry.name, name); rt_printk("\nSHM_CLEANUP_MODULE releases: '%s':0x%lx:%lu (%d).\n", name, entry.name, entry.name, entry.type); } } } reset_rt_fun_entries(rt_shm_entries); misc_deregister(&rtai_shm_dev); return;}/*@}*/#ifndef CONFIG_RTAI_SHM_BUILTINmodule_init(__rtai_shm_init);module_exit(__rtai_shm_exit);#endif /* !CONFIG_RTAI_SHL_BUILTIN */#ifdef CONFIG_KBUILDEXPORT_SYMBOL(rt_shm_alloc);EXPORT_SYMBOL(rt_shm_free);EXPORT_SYMBOL(rt_malloc_new);EXPORT_SYMBOL(rt_free_new);EXPORT_SYMBOL(rt_named_malloc);EXPORT_SYMBOL(rt_named_free);EXPORT_SYMBOL(rt_halloc);EXPORT_SYMBOL(rt_hfree);EXPORT_SYMBOL(rt_named_halloc);EXPORT_SYMBOL(rt_named_hfree);EXPORT_SYMBOL(rt_heap_open);#endif /* CONFIG_KBUILD */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -