From fb7d4122fc97be364cf2ce76380b0e5465aba7eb Mon Sep 17 00:00:00 2001 From: qiuyiuestc Date: Thu, 28 Oct 2010 01:21:47 +0000 Subject: [PATCH] implement module memory allocator git-svn-id: https://rt-thread.googlecode.com/svn/trunk@1030 bbd45198-f89e-11dd-88c7-29a3b14d5316 --- include/rtdef.h | 49 ++++++++------- include/rtthread.h | 13 +++- src/idle.c | 29 ++++----- src/ipc.c | 19 +++++- src/kservice.c | 2 +- src/mempool.c | 8 +++ src/module.c | 150 ++++++++++++++++++++++++++++++++++++++++++++- src/object.c | 20 +++++- src/scheduler.c | 4 +- src/slab.c | 24 +++++++- src/thread.c | 8 --- 11 files changed, 269 insertions(+), 57 deletions(-) diff --git a/include/rtdef.h b/include/rtdef.h index c5a87510f2..55f87c1a89 100644 --- a/include/rtdef.h +++ b/include/rtdef.h @@ -10,7 +10,8 @@ * Change Logs: * Date Author Notes * 2007-01-10 Bernard the first version - * 2008-07-12 Bernard remove all rt_int8, rt_uint32_t etc typedef + * 2008-07-12 Bernard remove all rt_int8, rt_uint32_t etc typedef + * 2010-10-26 yi.qiu add module support */ #ifndef __RT_DEF_H__ #define __RT_DEF_H__ @@ -163,6 +164,12 @@ typedef struct rt_list_node rt_list_t; /* Type for lists. */ * @addtogroup KernelObject */ /*@{*/ + +/* + * kernel object macros + */ +#define RT_OBJECT_FLAG_MODULE 0x80 /* is module object. */ + /* * Base structure of Kernel object */ @@ -174,6 +181,12 @@ struct rt_object rt_uint8_t type; /* flag of kernel object */ rt_uint8_t flag; + +#ifdef RT_USING_MODULE + /* id of application module */ + void* module_id; +#endif + /* list pointer of kernel object */ rt_list_t list; }; @@ -303,7 +316,6 @@ typedef struct rt_timer* rt_timer_t; #define RT_THREAD_CTRL_INFO 0x03 /* Get thread information. */ typedef struct rt_thread* rt_thread_t; -typedef struct rt_module* rt_module_t; /* * Thread related structure @@ -314,6 +326,10 @@ struct rt_thread char name[RT_NAME_MAX]; /* the name of thread */ rt_uint8_t type; /* type of object */ rt_uint8_t flags; /* thread's flags */ + +#ifdef RT_USING_MODULE + void* module_id; /* id of application module */ +#endif rt_list_t list; /* the object list */ rt_list_t tlist; /* the thread list */ @@ -350,10 +366,6 @@ struct rt_thread struct rt_timer thread_timer; /* thread timer */ -#ifdef RT_USING_MODULE - rt_module_t module_parent; /* module parent */ -#endif - rt_uint32_t user_data; /* user data */ }; /*@}*/ @@ -362,33 +374,26 @@ struct rt_thread /* * module system */ -enum rt_module_class_type -{ - RT_Module_Class_APP = 0, /* application module */ - RT_Module_Class_EXTENSION, - RT_Module_Class_SERVICE, /* service module */ - RT_Module_Class_Unknown /* unknown module */ -}; - struct rt_module { /* inherit from object */ - struct rt_object parent; + struct rt_object parent; - rt_uint8_t* module_space; + rt_uint8_t* module_space; /* module memory space */ - void* module_entry; - rt_uint32_t stack_size; + void* module_entry; /* entry address of module's thread */ + rt_thread_t module_thread; /* stack size of module's thread */ + rt_uint32_t stack_size; /* priority of module's thread */ rt_uint32_t thread_priority; - rt_thread_t module_thread; - /* module memory pool */ - rt_uint32_t mempool_size; - void* module_mempool; + /* module memory allocator */ + void* module_mem_list; + rt_list_t module_page; /* object in this module, module object is the last basic object type */ struct rt_object_information module_object[RT_Object_Class_Module]; }; +typedef struct rt_module* rt_module_t; #endif /** diff --git a/include/rtthread.h b/include/rtthread.h index 9ce56f2049..bcd5ed154e 100644 --- a/include/rtthread.h +++ b/include/rtthread.h @@ -14,7 +14,7 @@ * 2006-08-10 Bernard add version information * 2007-01-28 Bernard rename RT_OBJECT_Class_Static to RT_Object_Class_Static * 2007-03-03 Bernard clean up the definitions to rtdef.h - * 2010-04-11 yi.qiu add module feature + * 2010-04-11 yi.qiu add module feature */ #ifndef __RT_THREAD_H__ @@ -184,6 +184,11 @@ void rt_memory_info(rt_uint32_t *total, void rt_malloc_sethook(void (*hook)(void *ptr, rt_uint32_t size)); void rt_free_sethook(void (*hook)(void *ptr)); #endif + +#ifdef RT_USING_SLAB +void *rt_page_alloc(rt_size_t npages); +void rt_page_free(void *addr, rt_size_t npages); +#endif #endif /*@}*/ @@ -305,8 +310,11 @@ rt_err_t rt_device_control(rt_device_t dev, rt_uint8_t cmd, void* arg); rt_module_t rt_module_load(const rt_uint8_t* name, void* module_ptr); rt_module_t rt_module_load_from_file(const rt_uint8_t* name, const char* filename); rt_err_t rt_module_unload(rt_module_t module); -rt_err_t rt_module_self_set (rt_module_t module); +void *rt_module_malloc(rt_size_t size); +void *rt_module_realloc(void *ptr, rt_size_t size); +void rt_module_free(rt_module_t module, void *addr); rt_module_t rt_module_self (void); +rt_err_t rt_module_set (rt_module_t module); rt_module_t rt_module_find(char* name); #endif @@ -343,6 +351,7 @@ void* rt_memset(void *src, int c, rt_ubase_t n); void* rt_memcpy(void *dest, const void *src, rt_ubase_t n); rt_ubase_t rt_strncmp(const char * cs, const char * ct, rt_ubase_t count); +rt_ubase_t rt_strcmp (const char *cs, const char *ct); rt_ubase_t rt_strlen (const char *src); char *rt_strdup(const char *s); diff --git a/src/idle.c b/src/idle.c index 6d5ce9fca0..a0a87677e2 100644 --- a/src/idle.c +++ b/src/idle.c @@ -64,9 +64,8 @@ void rt_thread_idle_excute(void) rt_base_t lock; rt_thread_t thread; #ifdef RT_USING_MODULE - rt_module_t module; + rt_module_t module = RT_NULL; #endif - /* disable interrupt */ lock = rt_hw_interrupt_disable(); @@ -76,9 +75,16 @@ void rt_thread_idle_excute(void) /* get defunct thread */ thread = rt_list_entry(rt_thread_defunct.next, struct rt_thread, tlist); - /* get thread's parent module */ #ifdef RT_USING_MODULE - module = thread->module_parent; + /* get thread's parent module */ + module = (rt_module_t)thread->module_id; + + /* if the thread is module's main thread */ + if(module->module_thread == thread) + { + /* detach module's main thread */ + module->module_thread = RT_NULL; + } #endif /* remove defunct thread */ rt_list_remove(&(thread->tlist)); @@ -96,15 +102,10 @@ void rt_thread_idle_excute(void) rt_hw_interrupt_enable(lock); #ifdef RT_USING_MODULE - if(module != RT_NULL) - { - /* if the thread is module's main thread */ - if(module->module_thread == thread) - { - /* detach module's main thread */ - module->module_thread = RT_NULL; - } - } + /* the thread belongs to an application module */ + if(thread->flags & RT_OBJECT_FLAG_MODULE) + rt_module_free((rt_module_t)thread->module_id, thread->stack_addr); + else #endif /* release thread's stack */ rt_free(thread->stack_addr); @@ -122,7 +123,7 @@ void rt_thread_idle_excute(void) /* unload module */ rt_module_unload(module); } - } + } #endif //RT_USING_MODULE } diff --git a/src/ipc.c b/src/ipc.c index 986a39f6a0..96b11410c1 100644 --- a/src/ipc.c +++ b/src/ipc.c @@ -32,6 +32,7 @@ * is RT_IPC_FLAG_PRIO * 2010-01-20 mbbill remove rt_ipc_object_decrease function. * 2010-04-20 Bernard move memcpy outside interrupt disable in mq + * 2010-10-26 yi.qiu add module support in rt_mp_delete and rt_mq_delete */ #include @@ -1228,6 +1229,13 @@ rt_err_t rt_mb_delete (rt_mailbox_t mb) /* resume all suspended thread */ rt_ipc_object_resume_all(&(mb->parent)); +#ifdef RT_USING_MODULE + /* the mb object belongs to an application module */ + if(mb->parent.parent.flag & RT_OBJECT_FLAG_MODULE) + rt_module_free(mb->parent.parent.module_id, mb->msg_pool); + else +#endif + /* free mailbox pool */ rt_free(mb->msg_pool); @@ -1580,10 +1588,17 @@ rt_err_t rt_mq_delete (rt_mq_t mq) /* resume all suspended thread */ rt_ipc_object_resume_all(&(mq->parent)); - /* free mailbox pool */ +#ifdef RT_USING_MODULE + /* the mq object belongs to an application module */ + if(mq->parent.parent.flag & RT_OBJECT_FLAG_MODULE) + rt_module_free(mq->parent.parent.module_id, mq->msg_pool); + else +#endif + + /* free message queue pool */ rt_free(mq->msg_pool); - /* delete mailbox object */ + /* delete message queue object */ rt_object_delete(&(mq->parent.parent)); return RT_EOK; diff --git a/src/kservice.c b/src/kservice.c index e5c93f105d..18ccb67525 100644 --- a/src/kservice.c +++ b/src/kservice.c @@ -370,7 +370,7 @@ rt_ubase_t rt_strncmp(const char * cs, const char * ct, rt_ubase_t count) * * @return the result */ -rt_uint32_t rt_strcmp (const char *cs, const char *ct) +rt_ubase_t rt_strcmp (const char *cs, const char *ct) { while (*cs && *cs == *ct) cs++, ct++; diff --git a/src/mempool.c b/src/mempool.c index 53f1162802..5d91118604 100644 --- a/src/mempool.c +++ b/src/mempool.c @@ -15,6 +15,7 @@ * 2006-08-04 Bernard add hook support * 2006-08-10 Bernard fix interrupt bug in rt_mp_alloc * 2010-07-13 Bernard fix RT_ALIGN issue found by kuronca + * 2010-10-26 yi.qiu add module support in rt_mp_delete */ #include @@ -252,6 +253,13 @@ rt_err_t rt_mp_delete(rt_mp_t mp) rt_hw_interrupt_enable(temp); } +#ifdef RT_USING_MODULE + /* the mp object belongs to an application module */ + if(mp->parent.flag & RT_OBJECT_FLAG_MODULE) + rt_module_free(mp->parent.module_id, mp->start_address); + else +#endif + /* release allocated room */ rt_free(mp->start_address); diff --git a/src/module.c b/src/module.c index d101c5b3b0..54e6378fd4 100644 --- a/src/module.c +++ b/src/module.c @@ -11,6 +11,7 @@ * Date Author Notes * 2010-01-09 Bernard first version * 2010-04-09 yi.qiu implement based on first version + * 2010-10-23 yi.qiu implement module memory allocator */ #include @@ -35,7 +36,7 @@ #define IS_AX(s) ((s.sh_flags & SHF_ALLOC) && (s.sh_flags & SHF_EXECINSTR)) #define IS_AW(s) ((s.sh_flags & SHF_ALLOC) && (s.sh_flags & SHF_WRITE)) -static struct rt_module* rt_current_module = RT_NULL; +static rt_module_t rt_current_module = RT_NULL; rt_list_t rt_module_symbol_list; struct rt_module_symtab *_rt_module_symtab_begin = RT_NULL, *_rt_module_symtab_end = RT_NULL; @@ -50,8 +51,10 @@ void rt_system_module_init(void) extern int __rtmsymtab_start; extern int __rtmsymtab_end; +#ifdef __GNUC__ _rt_module_symtab_begin = (struct rt_module_symtab *)&__rtmsymtab_start; _rt_module_symtab_end = (struct rt_module_symtab *)&__rtmsymtab_end; +#endif rt_list_init(&rt_module_symbol_list); } @@ -348,7 +351,9 @@ rt_module_t rt_module_load(const rt_uint8_t* name, void* module_ptr) module->module_entry, RT_NULL, module->stack_size, module->thread_priority, 10); - module->module_thread->module_parent = module; + module->module_thread->module_id = (void*)module; + module->module_mem_list = RT_NULL; + rt_list_init(&module->module_page); rt_thread_startup(module->module_thread); return module; @@ -620,6 +625,147 @@ rt_module_t rt_module_find(char* name) return RT_NULL; } +/* module memory allocator */ +struct rt_mem_head +{ + rt_size_t size; /* size of memory block */ + struct rt_mem_head *next; /* next valid memory block */ +}; +static struct rt_mem_head *morepage(rt_size_t nu); + +/* + rt_module_free - alloc memory block in free list +*/ +void *rt_module_malloc(rt_size_t size) +{ + struct rt_mem_head *b, *n; + struct rt_mem_head **prev; + rt_size_t nunits; + + nunits = (size + sizeof(struct rt_mem_head) -1)/sizeof(struct rt_mem_head) + 1; + + RT_ASSERT(size != 0); + RT_ASSERT(nunits != 0); + + prev = (struct rt_mem_head **)&rt_current_module->module_mem_list; + + while(RT_TRUE) + { + b = *prev; + if(b == RT_NULL) + { + if ((b = morepage(nunits)) == RT_NULL) + return RT_NULL; + } + + if (b->size > nunits) + { + /* splite memory */ + n = b + nunits; + n->next = b->next; + n->size = b->size - nunits; + b->size = nunits; + *prev = n; + break; + } + + if (b->size == nunits) + { + /* this node fit, remove this node */ + *prev = b->next; + break; + } + + prev = &(b->next); + } + + return (void *)(b + 1); +} + +/* + rt_module_free - insert memory block in free list +*/ +void rt_module_free(rt_module_t module, void *addr) +{ + struct rt_mem_head *b, *n; + struct rt_mem_head **prev; + + RT_ASSERT(addr != RT_NULL); + RT_ASSERT((((rt_uint32_t)addr) & (sizeof(struct rt_mem_head) -1)) == 0); + + n = (struct rt_mem_head *)addr - 1; + prev = (struct rt_mem_head **)&module->module_mem_list; + + while ((b = *prev) != RT_NULL) + { + RT_ASSERT(b->size > 0); + RT_ASSERT(b > n || b + b->size <= n); + + if (b + b->size == n) + { + if (b + (b->size += n->size) == b->next) + { + b->size += b->next->size; + b->next = b->next->next; + } + + return; + } + + if (b == n + n->size) + { + n->size = b->size + n->size; + n->next = b->next; + *prev = n; + + return; + } + if (b > n + n->size) break; + + prev = &(b->next); + } + + n->next = b; + *prev = n; +} + +/* + rt_module_realloc - realloc memory block in free list +*/ +void *rt_module_realloc(void *ptr, rt_size_t size) +{ + RT_ASSERT(RT_NULL); + + /* TO DO */ +} + +/* module memory allocator */ +struct rt_module_page +{ + rt_uint8_t *ptr; /* address of memory block */ + rt_size_t npage; /* number of pages */ + rt_list_t list; +}; +static struct rt_module_page *rt_module_page_list; + +static struct rt_mem_head *morepage(rt_size_t nu) +{ + rt_uint8_t *cp; + rt_uint32_t npage; + struct rt_mem_head *up; + + RT_ASSERT (nu != 0); + + npage = (nu * sizeof(struct rt_mem_head) + RT_MM_PAGE_SIZE - 1)/RT_MM_PAGE_SIZE; + cp = rt_page_alloc(npage); + if(cp == RT_NULL) return RT_NULL; + + up = (struct rt_mem_head *) cp; + up->size = npage * RT_MM_PAGE_SIZE / sizeof(struct rt_mem_head); + rt_module_free(rt_current_module, (void *)(up+1)); + return up; +} + #if defined(RT_USING_FINSH) #include diff --git a/src/object.c b/src/object.c index 2b8ccb62d3..c992f0fe04 100644 --- a/src/object.c +++ b/src/object.c @@ -14,6 +14,7 @@ * 2006-05-18 Bernard fix the object init bug * 2006-08-03 Bernard add hook support * 2007-01-28 Bernard rename RT_OBJECT_Class_Static to RT_Object_Class_Static + * 2010-10-26 yi.qiu add module support in rt_object_allocate and rt_object_free */ #include @@ -270,12 +271,23 @@ rt_object_t rt_object_allocate(enum rt_object_class_type type, const char* name) /* no memory can be allocated */ return RT_NULL; } - + /* init object's parameters */ /* set object type */ object->type = type; + /* set object flag */ + object->flag = 0; + +#ifdef RT_USING_MODULE + if(rt_module_self() != RT_NULL) + { + object->module_id = (void*)rt_module_self(); + object->flag |= RT_OBJECT_FLAG_MODULE; + } +#endif + /* copy name */ for (temp = 0; temp < RT_NAME_MAX; temp ++) { @@ -325,6 +337,12 @@ void rt_object_delete(rt_object_t object) /* unlock interrupt */ rt_hw_interrupt_enable(temp); +#ifdef RT_USING_MODULE + if(object->flag & RT_OBJECT_FLAG_MODULE) + rt_module_free((rt_module_t)object->module_id, object); + else +#endif + /* free the memory of object */ rt_free(object); } diff --git a/src/scheduler.c b/src/scheduler.c index d14328feba..340c01bb27 100644 --- a/src/scheduler.c +++ b/src/scheduler.c @@ -264,8 +264,8 @@ void rt_schedule() rt_current_thread = to_thread; #ifdef RT_USING_MODULE - rt_module_set ((rt_current_thread->module_parent != RT_NULL) ? - rt_current_thread->module_parent : RT_NULL); + rt_module_set ((rt_current_thread->module_id != RT_NULL) ? + (rt_module_t)rt_current_thread->module_id : RT_NULL); #endif #ifdef RT_USING_HOOK diff --git a/src/slab.c b/src/slab.c index dc904230f2..2624df1832 100644 --- a/src/slab.c +++ b/src/slab.c @@ -11,6 +11,7 @@ * Date Author Notes * 2008-07-12 Bernard the first version * 2010-07-13 Bernard fix RT_ALIGN issue found by kuronca + * 2010-10-23 yi.qiu add module memory allocator */ /* @@ -52,6 +53,7 @@ #include #include +#include "kservice.h" /* #define RT_SLAB_DEBUG */ @@ -222,11 +224,11 @@ struct rt_page_head rt_size_t page; /* number of page */ /* dummy */ - char dummy[RT_MM_PAGE_SIZE - (sizeof(struct rt_page_head*) + sizeof (rt_size_t))]; + char dummy[RT_MM_PAGE_SIZE - (sizeof(struct rt_page_head*) + sizeof (rt_size_t) + sizeof(rt_list_t))]; }; static struct rt_page_head *rt_page_list; -static void *rt_page_alloc(rt_size_t npages) +void *rt_page_alloc(rt_size_t npages) { struct rt_page_head *b, *n; struct rt_page_head **prev; @@ -256,7 +258,7 @@ static void *rt_page_alloc(rt_size_t npages) return b; } -static void rt_page_free(void *addr, rt_size_t npages) +void rt_page_free(void *addr, rt_size_t npages) { struct rt_page_head *b, *n; struct rt_page_head **prev; @@ -450,6 +452,10 @@ void *rt_malloc(rt_size_t size) /* zero size, return RT_NULL */ if (size == 0) return RT_NULL; +#ifdef RT_USING_MODULE + if(rt_module_self() != RT_NULL) return rt_module_malloc(size); +#endif + /* * Handle large allocations directly. There should not be very many of * these so performance is not a big issue. @@ -630,6 +636,10 @@ void *rt_realloc(void *ptr, rt_size_t size) return RT_NULL; } +#ifdef RT_USING_MODULE + if(rt_module_self() != RT_NULL) return rt_module_realloc(ptr, size); +#endif + /* * Get the original allocation's zone. If the new request winds up * using the same chunk size we do not have to do anything. @@ -715,6 +725,14 @@ void rt_free(void *ptr) if (rt_free_hook != RT_NULL) rt_free_hook(ptr); #endif +#ifdef RT_USING_MODULE + if(rt_module_self() != RT_NULL) + { + rt_module_free(rt_module_self(), ptr); + return; + } +#endif + /* get memory usage */ #ifdef RT_SLAB_DEBUG rt_uint32 addr = ((rt_uint32_t)ptr & ~RT_MM_PAGE_MASK); diff --git a/src/thread.c b/src/thread.c index 536189070e..05eb403b56 100644 --- a/src/thread.c +++ b/src/thread.c @@ -19,7 +19,6 @@ * 2006-09-03 Bernard implement rt_thread_detach * 2008-02-16 Bernard fix the rt_thread_timeout bug * 2010-03-21 Bernard change the errno of rt_thread_delay/sleep to RT_EOK. - * 2010-04-11 Yi.Qiu add module feature */ #include @@ -73,13 +72,6 @@ static rt_err_t _rt_thread_init(struct rt_thread* thread, /* error and flags */ thread->error = RT_EOK; thread->stat = RT_THREAD_INIT; - thread->flags = 0; - -#ifdef RT_USING_MODULE - /* init module parent */ - thread->module_parent = - (rt_module_self() != RT_NULL) ? rt_module_self() : RT_NULL; -#endif /* init user data */ thread->user_data = 0;