module.c 38.8 KB
Newer Older
qiuyiuestc's avatar
qiuyiuestc 已提交
1 2 3
/*
 * File      : module.c
 * This file is part of RT-Thread RTOS
D
dzzxzz 已提交
4
 * COPYRIGHT (C) 2006 - 2012, RT-Thread Development Team
qiuyiuestc's avatar
qiuyiuestc 已提交
5 6 7 8 9 10
 *
 * The license and distribution terms for this file may be
 * found in the file LICENSE in this distribution or at
 * http://www.rt-thread.org/license/LICENSE
 *
 * Change Logs:
D
dzzxzz 已提交
11 12 13 14 15 16
 * 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
 * 2011-05-25     yi.qiu       implement module hook function
 * 2011-06-23     yi.qiu       rewrite module memory allocator
qiuyiuestc's avatar
qiuyiuestc 已提交
17
 */
qiuyiuestc's avatar
qiuyiuestc 已提交
18

19
#include <rthw.h>
qiuyiuestc's avatar
qiuyiuestc 已提交
20
#include <rtthread.h>
qiuyiuestc's avatar
qiuyiuestc 已提交
21
#include <rtm.h>
qiuyiuestc's avatar
qiuyiuestc 已提交
22

qiuyiuestc's avatar
qiuyiuestc 已提交
23
#include "string.h"
qiuyiuestc's avatar
qiuyiuestc 已提交
24 25
#include "kservice.h"

qiuyiuestc's avatar
qiuyiuestc 已提交
26
#ifdef RT_USING_MODULE
27
#include "module.h"
qiuyiuestc's avatar
qiuyiuestc 已提交
28

D
dzzxzz 已提交
29 30 31
#define elf_module          ((Elf32_Ehdr *)module_ptr)
#define shdr                ((Elf32_Shdr *)((rt_uint8_t *)module_ptr + elf_module->e_shoff))
#define phdr                ((Elf32_Phdr *)((rt_uint8_t *)module_ptr + elf_module->e_phoff))
qiuyiuestc's avatar
qiuyiuestc 已提交
32

D
dzzxzz 已提交
33 34 35 36 37 38 39
#define IS_PROG(s)          (s.sh_type == SHT_PROGBITS)
#define IS_NOPROG(s)        (s.sh_type == SHT_NOBITS)
#define IS_REL(s)           (s.sh_type == SHT_REL)
#define IS_RELA(s)          (s.sh_type == SHT_RELA)
#define IS_ALLOC(s)         (s.sh_flags == SHF_ALLOC)
#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))
qiuyiuestc's avatar
qiuyiuestc 已提交
40

B
bernard.xiong@gmail.com 已提交
41
#define PAGE_COUNT_MAX	256
qiuyiuestc's avatar
qiuyiuestc 已提交
42

qiuyiuestc's avatar
qiuyiuestc 已提交
43 44 45 46 47 48 49
/* module memory allocator */
struct rt_mem_head
{
	rt_size_t size;				/* size of memory block  */
	struct rt_mem_head *next;		/* next valid memory block */
};

qiuyiuestc's avatar
qiuyiuestc 已提交
50 51 52 53 54 55
struct rt_page_info
{
	rt_uint32_t *page_ptr;
	rt_uint32_t npage;
};

56
#ifdef RT_USING_SLAB
qiuyiuestc's avatar
qiuyiuestc 已提交
57
static void *rt_module_malloc_page(rt_size_t npages);
58 59
static void rt_module_free_page(rt_module_t module, void *page_ptr, rt_size_t npages);
#endif
qiuyiuestc's avatar
qiuyiuestc 已提交
60

qiuyiuestc's avatar
qiuyiuestc 已提交
61
static rt_module_t rt_current_module = RT_NULL;
qiuyiuestc's avatar
qiuyiuestc 已提交
62 63
static struct rt_semaphore mod_sem;
static struct rt_module_symtab *_rt_module_symtab_begin = RT_NULL, *_rt_module_symtab_end = RT_NULL;
64
rt_list_t rt_module_symbol_list;
qiuyiuestc's avatar
qiuyiuestc 已提交
65

D
dzzxzz 已提交
66
static char *_strip_name(const char *string)
qiuyiuestc's avatar
qiuyiuestc 已提交
67 68
{
	int i = 0, p = 0, q = 0;
D
dzzxzz 已提交
69 70
	const char *str = string;
	char *dest = RT_NULL;
B
bernard.xiong@gmail.com 已提交
71

D
dzzxzz 已提交
72
	while (*str != '\n' && *str != '\0')
qiuyiuestc's avatar
qiuyiuestc 已提交
73
	{
D
dzzxzz 已提交
74
		if (*str =='/' ) p = i + 1;
B
bernard.xiong@gmail.com 已提交
75
		if (*str == '.') q = i;
qiuyiuestc's avatar
qiuyiuestc 已提交
76 77 78
		str++; i++;
	}

D
dzzxzz 已提交
79
	if (p < q)
qiuyiuestc's avatar
qiuyiuestc 已提交
80 81
	{
		int len = q - p;
D
dzzxzz 已提交
82
		dest = (char *)rt_malloc(len + 1);
qiuyiuestc's avatar
qiuyiuestc 已提交
83 84 85 86 87 88
		rt_strncpy(dest, &string[p], len);
		dest[len] = '\0';
	}

	return dest;
}
89 90 91 92

/**
 * @ingroup SystemInit
 *
B
bernard.xiong@gmail.com 已提交
93
 * This function will initialize system module
94 95 96
 */
void rt_system_module_init(void)
{
qiuyiuestc's avatar
qiuyiuestc 已提交
97
#ifdef __GNUC__
98 99
	extern int __rtmsymtab_start;
	extern int __rtmsymtab_end;
qiuyiuestc's avatar
qiuyiuestc 已提交
100
	
101 102
	_rt_module_symtab_begin = (struct rt_module_symtab *)&__rtmsymtab_start;
	_rt_module_symtab_end   = (struct rt_module_symtab *)&__rtmsymtab_end;
D
dzzxzz 已提交
103
#elif defined (__CC_ARM)
qiuyiuestc's avatar
qiuyiuestc 已提交
104 105
	extern int RTMSymTab$$Base;
	extern int RTMSymTab$$Limit;
D
dzzxzz 已提交
106

qiuyiuestc's avatar
qiuyiuestc 已提交
107 108
	_rt_module_symtab_begin = (struct rt_module_symtab *)&RTMSymTab$$Base;
	_rt_module_symtab_end   = (struct rt_module_symtab *)&RTMSymTab$$Limit;	
qiuyiuestc's avatar
qiuyiuestc 已提交
109
#endif
110 111

	rt_list_init(&rt_module_symbol_list);
qiuyiuestc's avatar
qiuyiuestc 已提交
112

qiuyiuestc's avatar
qiuyiuestc 已提交
113 114 115
	/* initialize heap semaphore */
	rt_sem_init(&mod_sem, "module", 1, RT_IPC_FLAG_FIFO);

qiuyiuestc's avatar
qiuyiuestc 已提交
116 117
	/* init current module */
	rt_current_module = RT_NULL;
118 119
}

D
dzzxzz 已提交
120
static rt_uint32_t rt_module_symbol_find(const char *sym_str)
121 122
{
	/* find in kernel symbol table */
D
dzzxzz 已提交
123
	struct rt_module_symtab *index;
124 125
	for (index = _rt_module_symtab_begin; index != _rt_module_symtab_end; index ++)
	{
qiuyiuestc's avatar
qiuyiuestc 已提交
126 127
		if (rt_strcmp(index->name, sym_str) == 0)
			return (rt_uint32_t)index->addr;
128 129 130 131
	}

	return 0;
}
qiuyiuestc's avatar
qiuyiuestc 已提交
132

qiuyiuestc's avatar
qiuyiuestc 已提交
133 134 135
/**
 * This function will return self module object
 *
qiuyiuestc's avatar
qiuyiuestc 已提交
136
 * @return the self module object
qiuyiuestc's avatar
qiuyiuestc 已提交
137
 */
D
dzzxzz 已提交
138
rt_module_t rt_module_self(void)
qiuyiuestc's avatar
qiuyiuestc 已提交
139
{
qiuyiuestc's avatar
qiuyiuestc 已提交
140
	/* return current module */
qiuyiuestc's avatar
qiuyiuestc 已提交
141 142 143
	return rt_current_module;
}

qiuyiuestc's avatar
qiuyiuestc 已提交
144 145 146 147 148
/**
 * This function will set current module object
 *
 * @return RT_EOK
 */
D
dzzxzz 已提交
149
rt_err_t rt_module_set(rt_module_t module)
qiuyiuestc's avatar
qiuyiuestc 已提交
150 151 152 153 154 155 156
{
	/* set current module */
	rt_current_module = module;

	return RT_EOK;
}

D
dzzxzz 已提交
157
static int rt_module_arm_relocate(struct rt_module *module, Elf32_Rel *rel, Elf32_Addr sym_val)
qiuyiuestc's avatar
qiuyiuestc 已提交
158 159
{
	Elf32_Addr *where, tmp;
160 161
	Elf32_Sword addend, offset;
	rt_uint32_t upper, lower, sign, j1, j2;
qiuyiuestc's avatar
qiuyiuestc 已提交
162

D
dzzxzz 已提交
163
	where = (Elf32_Addr *)((rt_uint8_t *)module->module_space + rel->r_offset);
qiuyiuestc's avatar
qiuyiuestc 已提交
164 165 166 167 168 169
	switch (ELF32_R_TYPE(rel->r_info))
	{
	case R_ARM_NONE:
		break;
	case R_ARM_ABS32:
		*where += (Elf32_Addr)sym_val;
D
dzzxzz 已提交
170
		RT_DEBUG_LOG(RT_DEBUG_MODULE, ("R_ARM_ABS32: %x -> %x\n", where, *where));
qiuyiuestc's avatar
qiuyiuestc 已提交
171 172 173 174 175 176 177 178 179 180 181
		break;
	case R_ARM_PC24:
	case R_ARM_PLT32:
	case R_ARM_CALL:
	case R_ARM_JUMP24:
		addend = *where & 0x00ffffff;
		if (addend & 0x00800000)
			addend |= 0xff000000;
		tmp = sym_val - (Elf32_Addr)where + (addend << 2);
		tmp >>= 2;
		*where = (*where & 0xff000000) | (tmp & 0x00ffffff);
D
dzzxzz 已提交
182
		RT_DEBUG_LOG(RT_DEBUG_MODULE, ("R_ARM_PC24: %x -> %x\n", where, *where));
qiuyiuestc's avatar
qiuyiuestc 已提交
183
		break;
184 185 186 187
	case R_ARM_REL32:
		*where += sym_val - (Elf32_Addr)where;
		RT_DEBUG_LOG(RT_DEBUG_MODULE,("R_ARM_REL32: %x -> %x, sym %x, offset %x\n", where, *where, sym_val, rel->r_offset));
		break;
qiuyiuestc's avatar
qiuyiuestc 已提交
188 189 190 191
	case R_ARM_V4BX:
		*where &= 0xf000000f;
		*where |= 0x01a0f000;
		break;
qiuyiuestc's avatar
qiuyiuestc 已提交
192 193
	case R_ARM_GLOB_DAT:
	case R_ARM_JUMP_SLOT:
qiuyiuestc's avatar
qiuyiuestc 已提交
194
		*where = (Elf32_Addr)sym_val;
195 196
		RT_DEBUG_LOG(RT_DEBUG_MODULE,
			("R_ARM_JUMP_SLOT: 0x%x -> 0x%x 0x%x\n", where, *where, sym_val));
197 198 199 200 201 202 203 204
		break;
#if 0		/* To do */
	case R_ARM_GOT_BREL:
		temp = (Elf32_Addr)sym_val;
		*where = (Elf32_Addr)&temp;
		RT_DEBUG_LOG(RT_DEBUG_MODULE,
			("R_ARM_GOT_BREL: 0x%x -> 0x%x 0x%x\n", where, *where, sym_val));
		break;
B
bernard.xiong@gmail.com 已提交
205
#endif
qiuyiuestc's avatar
qiuyiuestc 已提交
206 207
	case R_ARM_RELATIVE:
		*where += (Elf32_Addr)sym_val;
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225
		//RT_DEBUG_LOG(RT_DEBUG_MODULE,
			//("R_ARM_RELATIVE: 0x%x -> 0x%x 0x%x\n", where, *where, sym_val));
		break;
	case R_ARM_THM_CALL:
	case R_ARM_THM_JUMP24:
		upper = *(rt_uint16_t *)where;
		lower = *(rt_uint16_t *)((Elf32_Addr)where + 2);

		sign = (upper >> 10) & 1;
		j1 = (lower >> 13) & 1;
		j2 = (lower >> 11) & 1;
		offset = (sign << 24) | ((~(j1 ^ sign) & 1) << 23) |
			 				 ((~(j2 ^ sign) & 1) << 22) |
			 				 ((upper & 0x03ff) << 12) |
			 				 ((lower & 0x07ff) << 1);
		if (offset & 0x01000000)
			 				 offset -= 0x02000000;
		offset += sym_val - (Elf32_Addr)where;
B
bernard.xiong@gmail.com 已提交
226

227
		if (!(offset & 1) || offset <= (rt_int32_t)0xff000000 ||
B
bernard.xiong@gmail.com 已提交
228
			 	offset >= (rt_int32_t)0x01000000)
229 230
		{
			rt_kprintf("only Thumb addresses allowed\n");
D
dzzxzz 已提交
231
			
232 233
			return -1;
		}
B
bernard.xiong@gmail.com 已提交
234

235 236 237 238 239 240 241 242 243 244
		sign = (offset >> 24) & 1;
		j1 = sign ^ (~(offset >> 23) & 1);
		j2 = sign ^ (~(offset >> 22) & 1);
		*(rt_uint16_t *)where = (rt_uint16_t)((upper & 0xf800) | (sign << 10) |
			 						 ((offset >> 12) & 0x03ff));
		*(rt_uint16_t *)(where + 2) = (rt_uint16_t)((lower & 0xd000) |
			 						   (j1 << 13) | (j2 << 11) |
			 						   ((offset >> 1) & 0x07ff));
		upper = *(rt_uint16_t *)where;
		lower = *(rt_uint16_t *)((Elf32_Addr)where + 2);
B
bernard.xiong@gmail.com 已提交
245
		break;
qiuyiuestc's avatar
qiuyiuestc 已提交
246 247 248 249 250 251 252
	default:
		return -1;
	}

	return 0;
}

D
dzzxzz 已提交
253
static void rt_module_init_object_container(struct rt_module *module)
qiuyiuestc's avatar
qiuyiuestc 已提交
254 255 256
{
	RT_ASSERT(module != RT_NULL);

B
bernard.xiong@gmail.com 已提交
257
	/* initialize object container - thread */
qiuyiuestc's avatar
qiuyiuestc 已提交
258 259 260 261 262
	rt_list_init(&(module->module_object[RT_Object_Class_Thread].object_list));
	module->module_object[RT_Object_Class_Thread].object_size = sizeof(struct rt_thread);
	module->module_object[RT_Object_Class_Thread].type = RT_Object_Class_Thread;

#ifdef RT_USING_SEMAPHORE
B
bernard.xiong@gmail.com 已提交
263
	/* initialize object container - semaphore */
qiuyiuestc's avatar
qiuyiuestc 已提交
264 265 266 267 268 269
	rt_list_init(&(module->module_object[RT_Object_Class_Semaphore].object_list));
	module->module_object[RT_Object_Class_Semaphore].object_size = sizeof(struct rt_semaphore);
	module->module_object[RT_Object_Class_Semaphore].type = RT_Object_Class_Semaphore;
#endif

#ifdef RT_USING_MUTEX
B
bernard.xiong@gmail.com 已提交
270
	/* initialize object container - mutex */
qiuyiuestc's avatar
qiuyiuestc 已提交
271 272 273 274 275 276
	rt_list_init(&(module->module_object[RT_Object_Class_Mutex].object_list));
	module->module_object[RT_Object_Class_Mutex].object_size = sizeof(struct rt_mutex);
	module->module_object[RT_Object_Class_Mutex].type = RT_Object_Class_Mutex;
#endif

#ifdef RT_USING_EVENT
B
bernard.xiong@gmail.com 已提交
277
	/* initialize object container - event */
qiuyiuestc's avatar
qiuyiuestc 已提交
278 279 280 281 282 283
	rt_list_init(&(module->module_object[RT_Object_Class_Event].object_list));
	module->module_object[RT_Object_Class_Event].object_size = sizeof(struct rt_event);
	module->module_object[RT_Object_Class_Event].type = RT_Object_Class_Event;
#endif

#ifdef RT_USING_MAILBOX
B
bernard.xiong@gmail.com 已提交
284
	/* initialize object container - mailbox */
qiuyiuestc's avatar
qiuyiuestc 已提交
285 286 287 288 289 290
	rt_list_init(&(module->module_object[RT_Object_Class_MailBox].object_list));
	module->module_object[RT_Object_Class_MailBox].object_size = sizeof(struct rt_mailbox);
	module->module_object[RT_Object_Class_MailBox].type = RT_Object_Class_MailBox;
#endif

#ifdef RT_USING_MESSAGEQUEUE
B
bernard.xiong@gmail.com 已提交
291
	/* initialize object container - message queue */
qiuyiuestc's avatar
qiuyiuestc 已提交
292 293 294 295 296 297
	rt_list_init(&(module->module_object[RT_Object_Class_MessageQueue].object_list));
	module->module_object[RT_Object_Class_MessageQueue].object_size = sizeof(struct rt_messagequeue);
	module->module_object[RT_Object_Class_MessageQueue].type = RT_Object_Class_MessageQueue;
#endif

#ifdef RT_USING_MEMPOOL
B
bernard.xiong@gmail.com 已提交
298
	/* initialize object container - memory pool */
qiuyiuestc's avatar
qiuyiuestc 已提交
299 300 301 302 303 304
	rt_list_init(&(module->module_object[RT_Object_Class_MemPool].object_list));
	module->module_object[RT_Object_Class_MemPool].object_size = sizeof(struct rt_mempool);
	module->module_object[RT_Object_Class_MemPool].type = RT_Object_Class_MemPool;
#endif

#ifdef RT_USING_DEVICE
B
bernard.xiong@gmail.com 已提交
305
	/* initialize object container - device */
qiuyiuestc's avatar
qiuyiuestc 已提交
306 307 308 309 310
	rt_list_init(&(module->module_object[RT_Object_Class_Device].object_list));
	module->module_object[RT_Object_Class_Device].object_size = sizeof(struct rt_device);
	module->module_object[RT_Object_Class_Device].type = RT_Object_Class_Device;
#endif

B
bernard.xiong@gmail.com 已提交
311
	/* initialize object container - timer */
qiuyiuestc's avatar
qiuyiuestc 已提交
312 313 314 315 316
	rt_list_init(&(module->module_object[RT_Object_Class_Timer].object_list));
	module->module_object[RT_Object_Class_Timer].object_size = sizeof(struct rt_timer);
	module->module_object[RT_Object_Class_Timer].type = RT_Object_Class_Timer;
}

qiuyiuestc's avatar
qiuyiuestc 已提交
317 318 319 320 321 322 323
#ifdef RT_USING_HOOK
static void (*rt_module_load_hook)(rt_module_t module);
static void (*rt_module_unload_hook)(rt_module_t module);

/**
 * @addtogroup Hook
 */
D
dzzxzz 已提交
324

qiuyiuestc's avatar
qiuyiuestc 已提交
325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351
/*@{*/

/**
 * This function will set a hook function, which will be invoked when module
 * be loaded to system.
 *
 * @param hook the hook function
 */
void rt_module_load_sethook(void (*hook)(rt_module_t module))
{
	rt_module_load_hook = hook;
}

/**
 * This function will set a hook function, which will be invoked when module
 * be unloaded from system.
 *
 * @param hook the hook function
 */
void rt_module_unload_sethook(void (*hook)(rt_module_t module))
{
	rt_module_unload_hook = hook;
}

/*@}*/
#endif

D
dzzxzz 已提交
352
static struct rt_module* _load_shared_object(const char *name, void *module_ptr)
qiuyiuestc's avatar
qiuyiuestc 已提交
353
{
354
	rt_uint8_t *ptr = RT_NULL;
355 356
	rt_module_t module = RT_NULL;
	rt_bool_t linked = RT_FALSE;
357
	rt_uint32_t index, module_size = 0;
qiuyiuestc's avatar
qiuyiuestc 已提交
358

359
	RT_ASSERT(module_ptr != RT_NULL);
B
bernard.xiong@gmail.com 已提交
360

361
	if(rt_memcmp(elf_module->e_ident, RTMMAG, SELFMAG) == 0)
362
	{
363
		/* rtmlinker finished */
364 365
		linked = RT_TRUE;
	}
qiuyiuestc's avatar
qiuyiuestc 已提交
366
	
qiuyiuestc's avatar
qiuyiuestc 已提交
367
	/* get the ELF image size */
qiuyiuestc's avatar
qiuyiuestc 已提交
368
	for (index = 0; index < elf_module->e_phnum; index++)
qiuyiuestc's avatar
qiuyiuestc 已提交
369
	{
qiuyiuestc's avatar
qiuyiuestc 已提交
370 371 372 373
		if(phdr[index].p_type == PT_LOAD)
			module_size += phdr[index].p_memsz;
	}	
	
D
dzzxzz 已提交
374
	if (module_size == 0)
qiuyiuestc's avatar
qiuyiuestc 已提交
375 376
	{
		rt_kprintf(" module size error\n");
D
dzzxzz 已提交
377

qiuyiuestc's avatar
qiuyiuestc 已提交
378 379
		return module;
	}	
qiuyiuestc's avatar
qiuyiuestc 已提交
380 381

	/* allocate module */
qiuyiuestc's avatar
qiuyiuestc 已提交
382
	module = (struct rt_module *)rt_object_allocate(RT_Object_Class_Module, name);
D
dzzxzz 已提交
383 384
	if (!module)
		return RT_NULL;
qiuyiuestc's avatar
qiuyiuestc 已提交
385 386 387 388 389 390

	/* allocate module space */
	module->module_space = rt_malloc(module_size);
	if (module->module_space == RT_NULL)
	{
		rt_object_delete(&(module->parent));
D
dzzxzz 已提交
391

qiuyiuestc's avatar
qiuyiuestc 已提交
392 393 394 395 396 397 398
		return RT_NULL;
	}

	/* zero all space */
	ptr = module->module_space;
	rt_memset(ptr, 0, module_size);

qiuyiuestc's avatar
qiuyiuestc 已提交
399 400
	rt_kprintf(" load address at 0x%x\n", ptr);

qiuyiuestc's avatar
qiuyiuestc 已提交
401
	for (index = 0; index < elf_module->e_phnum; index++)
qiuyiuestc's avatar
qiuyiuestc 已提交
402
	{
D
dzzxzz 已提交
403
		if (phdr[index].p_type == PT_LOAD)
qiuyiuestc's avatar
qiuyiuestc 已提交
404
		{
D
dzzxzz 已提交
405
			rt_memcpy(ptr, (rt_uint8_t *)elf_module + phdr[index].p_offset, phdr[index].p_filesz);
qiuyiuestc's avatar
qiuyiuestc 已提交
406 407 408
			ptr += phdr[index].p_memsz;
		}		
	}	
qiuyiuestc's avatar
qiuyiuestc 已提交
409 410

	/* set module entry */
qiuyiuestc's avatar
qiuyiuestc 已提交
411
	module->module_entry = module->module_space + elf_module->e_entry;
qiuyiuestc's avatar
qiuyiuestc 已提交
412
	
qiuyiuestc's avatar
qiuyiuestc 已提交
413 414 415 416 417 418 419 420
	/* handle relocation section */
	for (index = 0; index < elf_module->e_shnum; index ++)
	{
		if (IS_REL(shdr[index]))
		{
			rt_uint32_t i, nr_reloc;
			Elf32_Sym *symtab;
			Elf32_Rel *rel;
421 422
			rt_uint8_t *strtab;
			static rt_bool_t unsolved = RT_FALSE;
qiuyiuestc's avatar
qiuyiuestc 已提交
423 424

			/* get relocate item */
D
dzzxzz 已提交
425
			rel = (Elf32_Rel *)((rt_uint8_t *)module_ptr + shdr[index].sh_offset);
qiuyiuestc's avatar
qiuyiuestc 已提交
426

427
			/* locate .rel.plt and .rel.dyn section */
428 429 430
			symtab =(Elf32_Sym *) ((rt_uint8_t*)module_ptr + shdr[shdr[index].sh_link].sh_offset);
			strtab = (rt_uint8_t*) module_ptr + shdr[shdr[shdr[index].sh_link].sh_link].sh_offset;
			nr_reloc = (rt_uint32_t) (shdr[index].sh_size / sizeof(Elf32_Rel));
qiuyiuestc's avatar
qiuyiuestc 已提交
431 432 433 434 435

			/* relocate every items */
			for (i = 0; i < nr_reloc; i ++)
			{
				Elf32_Sym *sym = &symtab[ELF32_R_SYM(rel->r_info)];
436 437 438 439

				RT_DEBUG_LOG(RT_DEBUG_MODULE,
					("relocate symbol %s shndx %d\n", strtab + sym->st_name, sym->st_shndx));

B
bernard.xiong@gmail.com 已提交
440
				if((sym->st_shndx != SHT_NULL) || (ELF_ST_BIND(sym->st_info) == STB_LOCAL))
441 442
					rt_module_arm_relocate(module, rel,  (Elf32_Addr)(module->module_space + sym->st_value));
				else if(!linked)
443 444
				{
					Elf32_Addr addr;
445 446

					RT_DEBUG_LOG(RT_DEBUG_MODULE,
447
						("relocate symbol: %s\n", strtab + sym->st_name));
448

449
					/* need to resolve symbol in kernel symbol table */
D
dzzxzz 已提交
450
					addr = rt_module_symbol_find((const char *)(strtab + sym->st_name));
451 452 453
					if (addr == 0)
					{
						rt_kprintf("can't find %s in kernel symbol table\n", strtab + sym->st_name);
454
						unsolved = RT_TRUE;
455
					}	
D
dzzxzz 已提交
456 457
					else
						rt_module_arm_relocate(module, rel, addr);
458
				}
qiuyiuestc's avatar
qiuyiuestc 已提交
459 460
				rel ++;
			}
461

D
dzzxzz 已提交
462
			if (unsolved)
463 464 465
			{
				rt_object_delete(&(module->parent));
				rt_free(module);
D
dzzxzz 已提交
466

467 468
				return RT_NULL;
			}	
qiuyiuestc's avatar
qiuyiuestc 已提交
469 470 471
		}
	}

472 473
#if 0
	for (index = 0; index < elf_module->e_shnum; index ++)
B
bernard.xiong@gmail.com 已提交
474
	{
475 476
		/* find .dynsym section */
		rt_uint8_t* shstrab = (rt_uint8_t*) module_ptr + shdr[elf_module->e_shstrndx].sh_offset;
B
bernard.xiong@gmail.com 已提交
477 478
		if (rt_strcmp((const char *)(shstrab + shdr[index].sh_name), ELF_GOT) == 0)
		{
479 480
			rt_hw_set_got_base(module->module_space + shdr[index].sh_offset);
			break;
B
bernard.xiong@gmail.com 已提交
481
		}
482 483 484
	}
#endif

485 486 487 488
	/* construct module symbol table */
	for (index = 0; index < elf_module->e_shnum; index ++)
	{	
		/* find .dynsym section */
D
dzzxzz 已提交
489
		rt_uint8_t *shstrab = (rt_uint8_t *)module_ptr + shdr[elf_module->e_shstrndx].sh_offset;
D
dzzxzz 已提交
490 491
		if (rt_strcmp((const char *)(shstrab + shdr[index].sh_name), ELF_DYNSYM) == 0)
			break;
492 493
	}

qiuyiuestc's avatar
qiuyiuestc 已提交
494
	/* found .dynsym section */
D
dzzxzz 已提交
495
	if (index != elf_module->e_shnum)
496 497 498
	{
		int i, count = 0;
		Elf32_Sym *symtab = RT_NULL;
D
dzzxzz 已提交
499
		rt_uint8_t *strtab = RT_NULL;
500

D
dzzxzz 已提交
501
		symtab =(Elf32_Sym *)((rt_uint8_t *)module_ptr + shdr[index].sh_offset);
B
bernard.xiong@gmail.com 已提交
502
		strtab = (rt_uint8_t *)module_ptr + shdr[shdr[index].sh_link].sh_offset;
503

D
dzzxzz 已提交
504
		for (i=0; i<shdr[index].sh_size/sizeof(Elf32_Sym); i++)
505
		{
D
dzzxzz 已提交
506 507
			if ((ELF_ST_BIND(symtab[i].st_info) == STB_GLOBAL) && (ELF_ST_TYPE(symtab[i].st_info) == STT_FUNC))
				count ++;
508 509
		}

D
dzzxzz 已提交
510
		module->symtab = (struct rt_module_symtab *)rt_malloc(count * sizeof(struct rt_module_symtab));
511
		module->nsym = count;
D
dzzxzz 已提交
512
		for (i=0, count=0; i<shdr[index].sh_size/sizeof(Elf32_Sym); i++)
513
		{
D
dzzxzz 已提交
514
			if ((ELF_ST_BIND(symtab[i].st_info) == STB_GLOBAL) && (ELF_ST_TYPE(symtab[i].st_info) == STT_FUNC))
515
			{
D
dzzxzz 已提交
516
				rt_size_t length = rt_strlen((const char *)(strtab + symtab[i].st_name)) + 1;
517

D
dzzxzz 已提交
518
				module->symtab[count].addr = (void *)(module->module_space + symtab[i].st_value);
519
				module->symtab[count].name = rt_malloc(length);
D
dzzxzz 已提交
520 521 522
				rt_memset((void *)module->symtab[count].name, 0, length);
				rt_memcpy((void *)module->symtab[count].name, strtab + symtab[i].st_name, length);
				count ++;
523 524
			}	
		}	
525
	}
B
bernard.xiong@gmail.com 已提交
526

527 528 529
	return module;
}

D
dzzxzz 已提交
530
static struct rt_module* _load_relocated_object(const char *name, void *module_ptr)
531 532 533
{
	rt_uint32_t index, rodata_addr = 0, bss_addr = 0, data_addr = 0;
	rt_uint32_t module_addr = 0, module_size = 0;
D
dzzxzz 已提交
534
	struct rt_module *module = RT_NULL;
535 536
	rt_uint8_t *ptr, *strtab, *shstrab;
	rt_bool_t linked = RT_FALSE;
B
bernard.xiong@gmail.com 已提交
537

538 539 540 541 542
	if(rt_memcmp(elf_module->e_ident, RTMMAG, SELFMAG) == 0)
	{
		/* rtmlinker finished */
		linked = RT_TRUE;
	}
B
bernard.xiong@gmail.com 已提交
543

544 545 546 547 548 549 550 551 552 553 554 555 556
	/* get the ELF image size */
	for (index = 0; index < elf_module->e_shnum; index++)
	{
		/* text */
		if (IS_PROG(shdr[index]) && IS_AX(shdr[index]))
		{
			module_size += shdr[index].sh_size;
			module_addr = shdr[index].sh_addr;
		}
		/* rodata */
		if (IS_PROG(shdr[index]) && IS_ALLOC(shdr[index]))
		{
			module_size += shdr[index].sh_size;
B
bernard.xiong@gmail.com 已提交
557
		}
558 559 560 561 562 563 564 565 566
		/* data */
		if (IS_PROG(shdr[index]) && IS_AW(shdr[index]))
		{
			module_size += shdr[index].sh_size;
		}
		/* bss */
		if (IS_NOPROG(shdr[index]) && IS_AW(shdr[index]))
		{
			module_size += shdr[index].sh_size;
B
bernard.xiong@gmail.com 已提交
567
		}
568 569 570
	}

	/* no text, data and bss on image */
D
dzzxzz 已提交
571 572
	if (module_size == 0)
		return RT_NULL;
573 574

	/* allocate module */
D
dzzxzz 已提交
575 576 577
	module = (struct rt_module *)rt_object_allocate(RT_Object_Class_Module, (const char *)name);
	if (module == RT_NULL)
		return RT_NULL;
578 579 580 581 582 583

	/* allocate module space */
	module->module_space = rt_malloc(module_size);
	if (module->module_space == RT_NULL)
	{
		rt_object_delete(&(module->parent));
D
dzzxzz 已提交
584

585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601
		return RT_NULL;
	}

	/* zero all space */
	ptr = module->module_space;
	rt_memset(ptr, 0, module_size);

	/* load text and data section */
	for (index = 0; index < elf_module->e_shnum; index++)
	{
		/* load text section */
		if (IS_PROG(shdr[index]) && IS_AX(shdr[index]))
		{
			rt_memcpy(ptr, (rt_uint8_t*)elf_module + shdr[index].sh_offset, shdr[index].sh_size);
			RT_DEBUG_LOG(RT_DEBUG_MODULE,("load text 0x%x, size %d\n", ptr, shdr[index].sh_size));
			ptr += shdr[index].sh_size;
		}
qiuyiuestc's avatar
qiuyiuestc 已提交
602

603 604 605 606 607 608 609 610
		/* load rodata section */
		if (IS_PROG(shdr[index]) && IS_ALLOC(shdr[index]))
		{
			rt_memcpy(ptr, (rt_uint8_t*)elf_module + shdr[index].sh_offset, shdr[index].sh_size);
			rodata_addr = (rt_uint32_t)ptr;
			RT_DEBUG_LOG(RT_DEBUG_MODULE,("load rodata 0x%x, size %d, rodata 0x%x\n", ptr, shdr[index].sh_size, *(rt_uint32_t*)data_addr));
			ptr += shdr[index].sh_size;
		}
B
bernard.xiong@gmail.com 已提交
611

612 613 614
		/* load data section */
		if (IS_PROG(shdr[index]) && IS_AW(shdr[index]))
		{
B
bernard.xiong@gmail.com 已提交
615
			rt_memcpy(ptr, (rt_uint8_t*)elf_module + shdr[index].sh_offset, shdr[index].sh_size);
616 617 618 619 620 621 622 623 624 625
			data_addr = (rt_uint32_t)ptr;
			RT_DEBUG_LOG(RT_DEBUG_MODULE,("load data 0x%x, size %d, data 0x%x\n", ptr, shdr[index].sh_size, *(rt_uint32_t*)data_addr));
			ptr += shdr[index].sh_size;
		}

		/* load bss section */
		if (IS_NOPROG(shdr[index]) && IS_AW(shdr[index]))
		{
			rt_memset(ptr, 0, shdr[index].sh_size);
			bss_addr = (rt_uint32_t)ptr;
B
bernard.xiong@gmail.com 已提交
626
			RT_DEBUG_LOG(RT_DEBUG_MODULE,("load bss 0x%x, size %d,\n", ptr, shdr[index].sh_size));
627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655
		}
	}

	/* set module entry */
	module->module_entry = (rt_uint8_t*)module->module_space + elf_module->e_entry - module_addr;

	/* handle relocation section */
	for (index = 0; index < elf_module->e_shnum; index ++)
	{
		if (IS_REL(shdr[index]))
		{
			rt_uint32_t i, nr_reloc;
			Elf32_Sym *symtab;
			Elf32_Rel *rel;

			/* get relocate item */
			rel = (Elf32_Rel *) ((rt_uint8_t*)module_ptr + shdr[index].sh_offset);

			/* locate .dynsym and .dynstr */
			symtab =(Elf32_Sym *) ((rt_uint8_t*)module_ptr + shdr[shdr[index].sh_link].sh_offset);
			strtab = (rt_uint8_t*) module_ptr + shdr[shdr[shdr[index].sh_link].sh_link].sh_offset;
			shstrab = (rt_uint8_t*) module_ptr + shdr[elf_module->e_shstrndx].sh_offset;
			nr_reloc = (rt_uint32_t) (shdr[index].sh_size / sizeof(Elf32_Rel));

			/* relocate every items */
			for (i = 0; i < nr_reloc; i ++)
			{
				Elf32_Sym *sym = &symtab[ELF32_R_SYM(rel->r_info)];
				RT_DEBUG_LOG(RT_DEBUG_MODULE,("relocate symbol: %s\n", strtab + sym->st_name));
B
bernard.xiong@gmail.com 已提交
656

657
				if (sym->st_shndx != STN_UNDEF)
B
bernard.xiong@gmail.com 已提交
658 659
				{
					if((ELF_ST_TYPE(sym->st_info) == STT_SECTION)
660
						|| (ELF_ST_TYPE(sym->st_info) == STT_OBJECT))
B
bernard.xiong@gmail.com 已提交
661
					{
662 663 664 665 666 667 668 669
						if (rt_strncmp(shstrab + shdr[sym->st_shndx].sh_name, ELF_RODATA, 8) == 0)
						{
							/* relocate rodata section */
							RT_DEBUG_LOG(RT_DEBUG_MODULE,("rodata\n"));
							rt_module_arm_relocate(module, rel,(Elf32_Addr)(rodata_addr + sym->st_value));
						}
						else if(strncmp(shstrab + shdr[sym->st_shndx].sh_name, ELF_BSS, 5) == 0)
						{
B
bernard.xiong@gmail.com 已提交
670
							/* relocate bss section */
671 672 673 674 675
							RT_DEBUG_LOG(RT_DEBUG_MODULE,("bss\n"));
							rt_module_arm_relocate(module, rel, (Elf32_Addr)bss_addr + sym->st_value);
						}
						else if(strncmp(shstrab + shdr[sym->st_shndx].sh_name, ELF_DATA, 6) == 0)
						{
B
bernard.xiong@gmail.com 已提交
676
							/* relocate data section */
677 678
							RT_DEBUG_LOG(RT_DEBUG_MODULE,("data\n"));
							rt_module_arm_relocate(module, rel, (Elf32_Addr)data_addr + sym->st_value);
B
bernard.xiong@gmail.com 已提交
679 680 681
						}
					}
				}
682
				else if(ELF_ST_TYPE(sym->st_info) == STT_FUNC )
B
bernard.xiong@gmail.com 已提交
683
				{
684 685
					/* relocate function */
					rt_module_arm_relocate(module, rel,
B
bernard.xiong@gmail.com 已提交
686
						(Elf32_Addr)((rt_uint8_t*)module->module_space - module_addr + sym->st_value));
687 688 689 690 691 692
				}
				else
				{
					Elf32_Addr addr;

					if(ELF32_R_TYPE(rel->r_info) != R_ARM_V4BX)
B
bernard.xiong@gmail.com 已提交
693
					{
694 695 696 697 698 699 700
						RT_DEBUG_LOG(RT_DEBUG_MODULE,("relocate symbol: %s\n", strtab + sym->st_name));
						/* need to resolve symbol in kernel symbol table */
						addr = rt_module_symbol_find(strtab + sym->st_name);
						if (addr != (Elf32_Addr)RT_NULL)
						{
							rt_module_arm_relocate(module, rel, addr);
							RT_DEBUG_LOG(RT_DEBUG_MODULE,("symbol addr 0x%x\n", addr));
B
bernard.xiong@gmail.com 已提交
701
						}
D
dzzxzz 已提交
702 703
						else
							rt_kprintf("can't find %s in kernel symbol table\n", strtab + sym->st_name);
704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725
					}
					else
					{
						rt_module_arm_relocate(module, rel, addr);
					}
				}
				rel ++;
			}
		}
	}

	return module;
}

/**
 * This function will load a module from memory and create a thread for it
 *
 * @param name the name of module, which shall be unique
 * @param module_ptr the memory address of module image
 *
 * @return the module object
 */
D
dzzxzz 已提交
726
rt_module_t rt_module_load(const char *name, void *module_ptr)
727 728
{
	rt_module_t module;
B
bernard.xiong@gmail.com 已提交
729

730 731 732 733 734 735 736 737 738
	RT_DEBUG_NOT_IN_INTERRUPT;

	rt_kprintf("rt_module_load: %s ,", name);

	/* check ELF header */
	if(rt_memcmp(elf_module->e_ident, RTMMAG, SELFMAG) != 0
		&& rt_memcmp(elf_module->e_ident, ELFMAG, SELFMAG) != 0)
	{
		rt_kprintf(" module magic error\n");
D
dzzxzz 已提交
739

740 741 742 743 744 745 746
		return RT_NULL;
	}

	/* check ELF class */
	if(elf_module->e_ident[EI_CLASS] != ELFCLASS32)
	{
		rt_kprintf(" module class error\n");
D
dzzxzz 已提交
747

748 749
		return RT_NULL;
	}
B
bernard.xiong@gmail.com 已提交
750

751 752 753 754 755 756 757 758 759 760 761
	if(elf_module->e_type == ET_REL)
	{
		module = _load_relocated_object(name, module_ptr);
	}
	else if(elf_module->e_type == ET_DYN)
	{
		module = _load_shared_object(name, module_ptr);
	}
	else
	{
		rt_kprintf("unsupported elf type\n");
D
dzzxzz 已提交
762

763 764 765
		return RT_NULL;
	}

D
dzzxzz 已提交
766 767
	if(module == RT_NULL)
		return RT_NULL;
B
bernard.xiong@gmail.com 已提交
768

qiuyiuestc's avatar
qiuyiuestc 已提交
769 770
	/* init module object container */
	rt_module_init_object_container(module);
qiuyiuestc's avatar
qiuyiuestc 已提交
771
		
D
dzzxzz 已提交
772 773
	/* increase module reference count */
	module->nref ++;
qiuyiuestc's avatar
qiuyiuestc 已提交
774

D
dzzxzz 已提交
775
	if (elf_module->e_entry != 0)
qiuyiuestc's avatar
qiuyiuestc 已提交
776 777
	{	
		/* init module memory allocator */
qiuyiuestc's avatar
qiuyiuestc 已提交
778
		module->mem_list = RT_NULL;
qiuyiuestc's avatar
qiuyiuestc 已提交
779

780
#ifdef RT_USING_SLAB
qiuyiuestc's avatar
qiuyiuestc 已提交
781 782 783
		/* create page array */
		module->page_array = (void *)rt_malloc(PAGE_COUNT_MAX * sizeof(struct rt_page_info));
		module->page_cnt = 0;
784 785
#endif

qiuyiuestc's avatar
qiuyiuestc 已提交
786
		/* create module thread */
qiuyiuestc's avatar
qiuyiuestc 已提交
787
		module->stack_size = 2048;
qiuyiuestc's avatar
qiuyiuestc 已提交
788
		module->thread_priority = 25;
qiuyiuestc's avatar
qiuyiuestc 已提交
789 790 791 792 793 794
		module->module_thread = rt_thread_create(name,
			module->module_entry, RT_NULL,
			module->stack_size,
			module->thread_priority, 10);
		
		module->module_thread->module_id = (void*)module;
qiuyiuestc's avatar
qiuyiuestc 已提交
795
		module->parent.flag = RT_MODULE_FLAG_WITHENTRY;
B
bernard.xiong@gmail.com 已提交
796

qiuyiuestc's avatar
qiuyiuestc 已提交
797 798 799 800 801 802 803 804 805
		/* startup module thread */
		rt_thread_startup(module->module_thread);
	}	
	else
	{
		/* without entry point */
		module->parent.flag |= RT_MODULE_FLAG_WITHOUTENTRY;
	}	

qiuyiuestc's avatar
qiuyiuestc 已提交
806
#ifdef RT_USING_HOOK
D
dzzxzz 已提交
807
	if (rt_module_load_hook != RT_NULL)
qiuyiuestc's avatar
qiuyiuestc 已提交
808 809 810 811 812
	{
		rt_module_load_hook(module);
	}
#endif

qiuyiuestc's avatar
qiuyiuestc 已提交
813
	return module;
qiuyiuestc's avatar
qiuyiuestc 已提交
814 815
}	

qiuyiuestc's avatar
qiuyiuestc 已提交
816 817 818
#ifdef RT_USING_DFS
#include <dfs_posix.h>
/**
B
bernard.xiong@gmail.com 已提交
819
 * This function will load a module from a file
qiuyiuestc's avatar
qiuyiuestc 已提交
820
 *
B
bernard.xiong@gmail.com 已提交
821
 * @param path the full path of application module
qiuyiuestc's avatar
qiuyiuestc 已提交
822 823 824
 *
 * @return the module object
 */
D
dzzxzz 已提交
825
rt_module_t rt_module_open(const char *path)
qiuyiuestc's avatar
qiuyiuestc 已提交
826 827
{
	int fd, length;
D
dzzxzz 已提交
828
	struct rt_module *module;
B
bernard.xiong@gmail.com 已提交
829
	struct stat s;
qiuyiuestc's avatar
qiuyiuestc 已提交
830
	char *buffer, *offset_ptr;
qiuyiuestc's avatar
qiuyiuestc 已提交
831

832
	RT_DEBUG_NOT_IN_INTERRUPT;
833

qiuyiuestc's avatar
qiuyiuestc 已提交
834
	/* check parameters */
qiuyiuestc's avatar
qiuyiuestc 已提交
835
	RT_ASSERT(path != RT_NULL);
qiuyiuestc's avatar
qiuyiuestc 已提交
836

qiuyiuestc's avatar
qiuyiuestc 已提交
837
	if (stat(path, &s) !=0)
838
	{
qiuyiuestc's avatar
qiuyiuestc 已提交
839
		rt_kprintf("access %s failed\n", path);
D
dzzxzz 已提交
840

841 842
		return RT_NULL;
	}
qiuyiuestc's avatar
qiuyiuestc 已提交
843
	buffer = (char *)rt_malloc(s.st_size);
844 845 846
	if (buffer == RT_NULL)
	{
		rt_kprintf("out of memory\n");
D
dzzxzz 已提交
847

848 849 850 851
		return RT_NULL;
	}

	offset_ptr = buffer;
qiuyiuestc's avatar
qiuyiuestc 已提交
852
	fd = open(path, O_RDONLY, 0);
853 854
	if (fd < 0)
	{
qiuyiuestc's avatar
qiuyiuestc 已提交
855
		rt_kprintf("open %s failed\n", path);
856
		rt_free(buffer);
D
dzzxzz 已提交
857

858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873
		return RT_NULL;
	}

	do
	{
		length = read(fd, offset_ptr, 4096);
		if (length > 0)
		{
			offset_ptr += length;
		}
	}while (length > 0);

	/* close fd */
	close(fd);

	if ((rt_uint32_t)offset_ptr - (rt_uint32_t)buffer != s.st_size)
qiuyiuestc's avatar
qiuyiuestc 已提交
874 875 876
	{
		rt_kprintf("check: read file failed\n");
		rt_free(buffer);
D
dzzxzz 已提交
877

qiuyiuestc's avatar
qiuyiuestc 已提交
878 879
		return RT_NULL;
	}
qiuyiuestc's avatar
qiuyiuestc 已提交
880

qiuyiuestc's avatar
qiuyiuestc 已提交
881
	module = rt_module_load(path, (void *)buffer);
qiuyiuestc's avatar
qiuyiuestc 已提交
882 883 884 885
	rt_free(buffer);

	return module;
}
qiuyiuestc's avatar
qiuyiuestc 已提交
886 887 888

#if defined(RT_USING_FINSH)
#include <finsh.h>
889
FINSH_FUNCTION_EXPORT_ALIAS(rt_module_open, exec, exec module from file);
qiuyiuestc's avatar
qiuyiuestc 已提交
890
#endif
qiuyiuestc's avatar
qiuyiuestc 已提交
891 892
#endif

qiuyiuestc's avatar
qiuyiuestc 已提交
893
/**
D
dzzxzz 已提交
894
 * This function will unload a module from memory and release resources
qiuyiuestc's avatar
qiuyiuestc 已提交
895 896 897 898 899 900
 *
 * @param module the module to be unloaded
 *
 * @return the operation status, RT_EOK on OK; -RT_ERROR on error
 */
rt_err_t rt_module_unload(rt_module_t module)
qiuyiuestc's avatar
qiuyiuestc 已提交
901
{
902
	int i;
D
dzzxzz 已提交
903
	struct rt_object *object;
qiuyiuestc's avatar
qiuyiuestc 已提交
904
	struct rt_list_node *list;
qiuyiuestc's avatar
qiuyiuestc 已提交
905

906
	RT_DEBUG_NOT_IN_INTERRUPT;
907

qiuyiuestc's avatar
qiuyiuestc 已提交
908 909 910
	/* check parameter */
	RT_ASSERT(module != RT_NULL);

qiuyiuestc's avatar
qiuyiuestc 已提交
911
	rt_kprintf("rt_module_unload: %s\n", module->parent.name);
B
bernard.xiong@gmail.com 已提交
912

qiuyiuestc's avatar
qiuyiuestc 已提交
913
	/* module has entry point */
qiuyiuestc's avatar
qiuyiuestc 已提交
914
	if (!(module->parent.flag & RT_MODULE_FLAG_WITHOUTENTRY))
D
dzzxzz 已提交
915
	{
qiuyiuestc's avatar
qiuyiuestc 已提交
916
		/* suspend module main thread */
D
dzzxzz 已提交
917 918
		if (module->module_thread != RT_NULL)
		{
qiuyiuestc's avatar
qiuyiuestc 已提交
919 920 921 922 923
			if (module->module_thread->stat == RT_THREAD_READY)
				rt_thread_suspend(module->module_thread);
		}
		
		/* delete threads */
D
dzzxzz 已提交
924 925
		list = &module->module_object[RT_Object_Class_Thread].object_list;
		while (list->next != list)
qiuyiuestc's avatar
qiuyiuestc 已提交
926
		{
qiuyiuestc's avatar
qiuyiuestc 已提交
927 928 929
			object = rt_list_entry(list->next, struct rt_object, list);
			if (rt_object_is_systemobject(object) == RT_EOK)
			{
qiuyiuestc's avatar
qiuyiuestc 已提交
930
				/* detach static object */
qiuyiuestc's avatar
qiuyiuestc 已提交
931 932 933
				rt_thread_detach((rt_thread_t)object);
			}
			else
D
dzzxzz 已提交
934
			{
qiuyiuestc's avatar
qiuyiuestc 已提交
935 936
				/* delete dynamic object */
				rt_thread_delete((rt_thread_t)object);
D
dzzxzz 已提交
937
			}
qiuyiuestc's avatar
qiuyiuestc 已提交
938
		}
qiuyiuestc's avatar
qiuyiuestc 已提交
939
		
qiuyiuestc's avatar
qiuyiuestc 已提交
940
#ifdef RT_USING_SEMAPHORE
qiuyiuestc's avatar
qiuyiuestc 已提交
941 942
		/* delete semaphores */
		list = &module->module_object[RT_Object_Class_Thread].object_list;	
D
dzzxzz 已提交
943
		while (list->next != list)
qiuyiuestc's avatar
qiuyiuestc 已提交
944
		{
qiuyiuestc's avatar
qiuyiuestc 已提交
945 946 947
			object = rt_list_entry(list->next, struct rt_object, list);
			if (rt_object_is_systemobject(object) == RT_EOK)
			{
qiuyiuestc's avatar
qiuyiuestc 已提交
948
				/* detach static object */
qiuyiuestc's avatar
qiuyiuestc 已提交
949 950 951
				rt_sem_detach((rt_sem_t)object);
			}
			else
D
dzzxzz 已提交
952
			{
qiuyiuestc's avatar
qiuyiuestc 已提交
953 954
				/* delete dynamic object */
				rt_sem_delete((rt_sem_t)object);
D
dzzxzz 已提交
955
			}
qiuyiuestc's avatar
qiuyiuestc 已提交
956 957 958 959
		}
#endif

#ifdef RT_USING_MUTEX
qiuyiuestc's avatar
qiuyiuestc 已提交
960 961
		/* delete mutexs*/
		list = &module->module_object[RT_Object_Class_Mutex].object_list;	
D
dzzxzz 已提交
962
		while (list->next != list)
qiuyiuestc's avatar
qiuyiuestc 已提交
963
		{
qiuyiuestc's avatar
qiuyiuestc 已提交
964 965 966
			object = rt_list_entry(list->next, struct rt_object, list);
			if (rt_object_is_systemobject(object) == RT_EOK)
			{
qiuyiuestc's avatar
qiuyiuestc 已提交
967
				/* detach static object */
qiuyiuestc's avatar
qiuyiuestc 已提交
968 969 970
				rt_mutex_detach((rt_mutex_t)object);
			}
			else
D
dzzxzz 已提交
971
			{
qiuyiuestc's avatar
qiuyiuestc 已提交
972 973
				/* delete dynamic object */
				rt_mutex_delete((rt_mutex_t)object);
D
dzzxzz 已提交
974
			}
qiuyiuestc's avatar
qiuyiuestc 已提交
975 976 977 978
		}
#endif

#ifdef RT_USING_EVENT
qiuyiuestc's avatar
qiuyiuestc 已提交
979 980
		/* delete mailboxs */
		list = &module->module_object[RT_Object_Class_Event].object_list;	
D
dzzxzz 已提交
981
		while (list->next != list)
qiuyiuestc's avatar
qiuyiuestc 已提交
982
		{
qiuyiuestc's avatar
qiuyiuestc 已提交
983 984 985
			object = rt_list_entry(list->next, struct rt_object, list);
			if (rt_object_is_systemobject(object) == RT_EOK)
			{
qiuyiuestc's avatar
qiuyiuestc 已提交
986
				/* detach static object */
qiuyiuestc's avatar
qiuyiuestc 已提交
987 988 989
				rt_event_detach((rt_event_t)object);
			}
			else
D
dzzxzz 已提交
990
			{
qiuyiuestc's avatar
qiuyiuestc 已提交
991 992
				/* delete dynamic object */
				rt_event_delete((rt_event_t)object);
D
dzzxzz 已提交
993
			}
qiuyiuestc's avatar
qiuyiuestc 已提交
994
		}
qiuyiuestc's avatar
qiuyiuestc 已提交
995 996 997
#endif

#ifdef RT_USING_MAILBOX
qiuyiuestc's avatar
qiuyiuestc 已提交
998 999
		/* delete mailboxs */
		list = &module->module_object[RT_Object_Class_MailBox].object_list;	
D
dzzxzz 已提交
1000
		while (list->next != list)
qiuyiuestc's avatar
qiuyiuestc 已提交
1001
		{
qiuyiuestc's avatar
qiuyiuestc 已提交
1002 1003 1004
			object = rt_list_entry(list->next, struct rt_object, list);
			if (rt_object_is_systemobject(object) == RT_EOK)
			{
qiuyiuestc's avatar
qiuyiuestc 已提交
1005
				/* detach static object */
qiuyiuestc's avatar
qiuyiuestc 已提交
1006 1007 1008
				rt_mb_detach((rt_mailbox_t)object);
			}
			else
D
dzzxzz 已提交
1009
			{
qiuyiuestc's avatar
qiuyiuestc 已提交
1010 1011
				/* delete dynamic object */
				rt_mb_delete((rt_mailbox_t)object);
D
dzzxzz 已提交
1012
			}
qiuyiuestc's avatar
qiuyiuestc 已提交
1013 1014 1015 1016
		}
#endif

#ifdef RT_USING_MESSAGEQUEUE
qiuyiuestc's avatar
qiuyiuestc 已提交
1017
		/* delete msgqueues */
D
dzzxzz 已提交
1018 1019
		list = &module->module_object[RT_Object_Class_MessageQueue].object_list;
		while (list->next != list)
qiuyiuestc's avatar
qiuyiuestc 已提交
1020
		{
qiuyiuestc's avatar
qiuyiuestc 已提交
1021 1022 1023
			object = rt_list_entry(list->next, struct rt_object, list);
			if (rt_object_is_systemobject(object) == RT_EOK)
			{
qiuyiuestc's avatar
qiuyiuestc 已提交
1024
				/* detach static object */
qiuyiuestc's avatar
qiuyiuestc 已提交
1025 1026 1027
				rt_mq_detach((rt_mq_t)object);
			}
			else
D
dzzxzz 已提交
1028
			{
qiuyiuestc's avatar
qiuyiuestc 已提交
1029 1030
				/* delete dynamic object */
				rt_mq_delete((rt_mq_t)object);
D
dzzxzz 已提交
1031
			}
qiuyiuestc's avatar
qiuyiuestc 已提交
1032 1033 1034 1035
		}
#endif

#ifdef RT_USING_MEMPOOL
qiuyiuestc's avatar
qiuyiuestc 已提交
1036 1037
		/* delete mempools */
		list = &module->module_object[RT_Object_Class_MemPool].object_list;	
D
dzzxzz 已提交
1038
		while (list->next != list)
qiuyiuestc's avatar
qiuyiuestc 已提交
1039
		{
qiuyiuestc's avatar
qiuyiuestc 已提交
1040 1041 1042
			object = rt_list_entry(list->next, struct rt_object, list);
			if (rt_object_is_systemobject(object) == RT_EOK)
			{
qiuyiuestc's avatar
qiuyiuestc 已提交
1043
				/* detach static object */
qiuyiuestc's avatar
qiuyiuestc 已提交
1044 1045 1046
				rt_mp_detach((rt_mp_t)object);
			}
			else
D
dzzxzz 已提交
1047
			{
qiuyiuestc's avatar
qiuyiuestc 已提交
1048 1049
				/* delete dynamic object */
				rt_mp_delete((rt_mp_t)object);
D
dzzxzz 已提交
1050
			}
qiuyiuestc's avatar
qiuyiuestc 已提交
1051 1052 1053 1054
		}
#endif

#ifdef RT_USING_DEVICE
qiuyiuestc's avatar
qiuyiuestc 已提交
1055 1056
		/* delete devices */
		list = &module->module_object[RT_Object_Class_Device].object_list;	
D
dzzxzz 已提交
1057
		while (list->next != list)
qiuyiuestc's avatar
qiuyiuestc 已提交
1058 1059 1060
		{
			object = rt_list_entry(list->next, struct rt_object, list);
			rt_device_unregister((rt_device_t)object);
D
dzzxzz 已提交
1061
		}
qiuyiuestc's avatar
qiuyiuestc 已提交
1062 1063
#endif

qiuyiuestc's avatar
qiuyiuestc 已提交
1064 1065
		/* delete timers */
		list = &module->module_object[RT_Object_Class_Timer].object_list;
D
dzzxzz 已提交
1066
		while (list->next != list)
qiuyiuestc's avatar
qiuyiuestc 已提交
1067
		{
qiuyiuestc's avatar
qiuyiuestc 已提交
1068 1069 1070
			object = rt_list_entry(list->next, struct rt_object, list);
			if (rt_object_is_systemobject(object) == RT_EOK)
			{
qiuyiuestc's avatar
qiuyiuestc 已提交
1071
				/* detach static object */
qiuyiuestc's avatar
qiuyiuestc 已提交
1072 1073 1074
				rt_timer_detach((rt_timer_t)object);
			}
			else
D
dzzxzz 已提交
1075
			{
qiuyiuestc's avatar
qiuyiuestc 已提交
1076 1077
				/* delete dynamic object */
				rt_timer_delete((rt_timer_t)object);
D
dzzxzz 已提交
1078 1079
			}
		}
qiuyiuestc's avatar
qiuyiuestc 已提交
1080
	}
qiuyiuestc's avatar
qiuyiuestc 已提交
1081

1082
#ifdef RT_USING_SLAB
D
dzzxzz 已提交
1083
	if (module->page_cnt > 0)
qiuyiuestc's avatar
qiuyiuestc 已提交
1084
	{
D
dzzxzz 已提交
1085
		struct rt_page_info *page = (struct rt_page_info *)module->page_array;
B
bernard.xiong@gmail.com 已提交
1086 1087

		rt_kprintf("warning: module memory still hasn't been free finished\n");
qiuyiuestc's avatar
qiuyiuestc 已提交
1088

1089
		while(module->page_cnt != 0)
qiuyiuestc's avatar
qiuyiuestc 已提交
1090
		{
1091
			rt_module_free_page(module, page[0].page_ptr, page[0].npage);
B
bernard.xiong@gmail.com 已提交
1092
		}
qiuyiuestc's avatar
qiuyiuestc 已提交
1093
	}
1094
#endif
D
dzzxzz 已提交
1095

qiuyiuestc's avatar
qiuyiuestc 已提交
1096
	/* release module space memory */
qiuyiuestc's avatar
qiuyiuestc 已提交
1097
	rt_free(module->module_space);
qiuyiuestc's avatar
qiuyiuestc 已提交
1098

1099
	/* release module symbol table */
D
dzzxzz 已提交
1100 1101 1102 1103
	for (i=0; i<module->nsym; i++)
		rt_free((void *)module->symtab[i].name);
	if (module->symtab != RT_NULL)
		rt_free(module->symtab);
qiuyiuestc's avatar
qiuyiuestc 已提交
1104

qiuyiuestc's avatar
qiuyiuestc 已提交
1105
#ifdef RT_USING_HOOK
D
dzzxzz 已提交
1106 1107 1108 1109
	if (rt_module_unload_hook != RT_NULL)
	{
		rt_module_unload_hook(module);
	}
qiuyiuestc's avatar
qiuyiuestc 已提交
1110 1111
#endif

qiuyiuestc's avatar
qiuyiuestc 已提交
1112 1113 1114 1115
#ifdef RT_USING_SLAB
	if(module->page_array != RT_NULL) 
		rt_free(module->page_array);
#endif
qiuyiuestc's avatar
qiuyiuestc 已提交
1116

qiuyiuestc's avatar
qiuyiuestc 已提交
1117
	/* delete module object */
qiuyiuestc's avatar
qiuyiuestc 已提交
1118
	rt_object_delete((rt_object_t)module);
qiuyiuestc's avatar
qiuyiuestc 已提交
1119 1120

	return RT_EOK;
qiuyiuestc's avatar
qiuyiuestc 已提交
1121 1122
}

qiuyiuestc's avatar
qiuyiuestc 已提交
1123 1124 1125 1126 1127 1128 1129
/**
 * This function will find the specified module.
 *
 * @param name the name of module finding
 *
 * @return the module
 */
D
dzzxzz 已提交
1130
rt_module_t rt_module_find(const char *name)
qiuyiuestc's avatar
qiuyiuestc 已提交
1131
{
B
bernard.xiong 已提交
1132
	struct rt_object_information *information;
D
dzzxzz 已提交
1133 1134
	struct rt_object *object;
	struct rt_list_node *node;
qiuyiuestc's avatar
qiuyiuestc 已提交
1135

B
bernard.xiong 已提交
1136 1137
	extern struct rt_object_information rt_object_container[];

1138
	RT_DEBUG_NOT_IN_INTERRUPT;
1139

B
bernard.xiong 已提交
1140 1141 1142 1143
	/* enter critical */
	rt_enter_critical();

	/* try to find device object */
qiuyiuestc's avatar
qiuyiuestc 已提交
1144
	information = &rt_object_container[RT_Object_Class_Module];
B
bernard.xiong 已提交
1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161
	for (node = information->object_list.next; node != &(information->object_list); node = node->next)
	{
		object = rt_list_entry(node, struct rt_object, list);
		if (rt_strncmp(object->name, name, RT_NAME_MAX) == 0)
		{
			/* leave critical */
			rt_exit_critical();

			return (rt_module_t)object;
		}
	}

	/* leave critical */
	rt_exit_critical();

	/* not found */
	return RT_NULL;
qiuyiuestc's avatar
qiuyiuestc 已提交
1162 1163
}

qiuyiuestc's avatar
qiuyiuestc 已提交
1164 1165 1166 1167 1168 1169 1170 1171 1172
#ifdef RT_USING_SLAB
/*
 * This function will allocate the numbers page with specified size
 * in page memory.
 *
 * @param size the size of memory to be allocated.
 * @note this function is used for RT-Thread Application Module
 */
static void *rt_module_malloc_page(rt_size_t npages)
qiuyiuestc's avatar
qiuyiuestc 已提交
1173
{
D
dzzxzz 已提交
1174
	void *chunk;
qiuyiuestc's avatar
qiuyiuestc 已提交
1175
	struct rt_page_info *page;
qiuyiuestc's avatar
qiuyiuestc 已提交
1176

qiuyiuestc's avatar
qiuyiuestc 已提交
1177
	chunk = rt_page_alloc(npages);
D
dzzxzz 已提交
1178 1179
	if (chunk == RT_NULL)
		return RT_NULL;
1180

D
dzzxzz 已提交
1181
	page = (struct rt_page_info *)rt_current_module->page_array;
qiuyiuestc's avatar
qiuyiuestc 已提交
1182
	page[rt_current_module->page_cnt].page_ptr = chunk;
D
dzzxzz 已提交
1183 1184
	page[rt_current_module->page_cnt].npage = npages;
	rt_current_module->page_cnt ++;
qiuyiuestc's avatar
qiuyiuestc 已提交
1185

qiuyiuestc's avatar
qiuyiuestc 已提交
1186
	RT_ASSERT(rt_current_module->page_cnt <= PAGE_COUNT_MAX);
1187
	rt_kprintf("rt_module_malloc_page 0x%x %d\n", chunk, npages);
D
dzzxzz 已提交
1188

qiuyiuestc's avatar
qiuyiuestc 已提交
1189 1190
	return chunk;
}
qiuyiuestc's avatar
qiuyiuestc 已提交
1191

qiuyiuestc's avatar
qiuyiuestc 已提交
1192
/*
D
dzzxzz 已提交
1193
 * This function will release the previously allocated memory page
qiuyiuestc's avatar
qiuyiuestc 已提交
1194 1195 1196 1197
 * by rt_malloc_page.
 *
 * @param page_ptr the page address to be released.
 * @param npages the number of page shall be released.
B
bernard.xiong@gmail.com 已提交
1198
 *
qiuyiuestc's avatar
qiuyiuestc 已提交
1199 1200
 * @note this function is used for RT-Thread Application Module
 */
1201
static void rt_module_free_page(rt_module_t module, void *page_ptr, rt_size_t npages)
qiuyiuestc's avatar
qiuyiuestc 已提交
1202 1203 1204
{
	int i, index;
	struct rt_page_info *page;
qiuyiuestc's avatar
qiuyiuestc 已提交
1205

1206
	rt_kprintf("rt_module_free_page 0x%x %d\n", page_ptr, npages);
qiuyiuestc's avatar
qiuyiuestc 已提交
1207 1208
	rt_page_free(page_ptr, npages);

1209
	page = (struct rt_page_info*)module->page_array;
qiuyiuestc's avatar
qiuyiuestc 已提交
1210

1211
	for(i=0; i<module->page_cnt; i++)
qiuyiuestc's avatar
qiuyiuestc 已提交
1212
	{
D
dzzxzz 已提交
1213
		if (page[i].page_ptr == page_ptr)
qiuyiuestc's avatar
qiuyiuestc 已提交
1214
		{
D
dzzxzz 已提交
1215
			if (page[i].npage == npages + 1)
qiuyiuestc's avatar
qiuyiuestc 已提交
1216 1217
			{
				page[i].page_ptr += npages * RT_MM_PAGE_SIZE / sizeof(rt_uint32_t);
1218
				page[i].npage -= npages;
qiuyiuestc's avatar
qiuyiuestc 已提交
1219
			}
1220
			else if(page[i].npage == npages)
B
bernard.xiong@gmail.com 已提交
1221
			{
1222
				for(index=i; index<module->page_cnt-1; index++)
qiuyiuestc's avatar
qiuyiuestc 已提交
1223 1224 1225 1226
				{
					page[index].page_ptr = page[index + 1].page_ptr;
					page[index].npage = page[index + 1].npage;
				}
1227 1228
				page[module->page_cnt - 1].page_ptr = RT_NULL;
				page[module->page_cnt - 1].npage = 0;
B
bernard.xiong@gmail.com 已提交
1229 1230

				module->page_cnt--;
qiuyiuestc's avatar
qiuyiuestc 已提交
1231
			}
D
dzzxzz 已提交
1232 1233
			else
				RT_ASSERT(RT_FALSE);
1234
			rt_current_module->page_cnt--;
qiuyiuestc's avatar
qiuyiuestc 已提交
1235

qiuyiuestc's avatar
qiuyiuestc 已提交
1236 1237 1238 1239 1240 1241
			return;
		}
	}

	/* should not be get here */
	RT_ASSERT(RT_FALSE);
qiuyiuestc's avatar
qiuyiuestc 已提交
1242
}
qiuyiuestc's avatar
qiuyiuestc 已提交
1243 1244

/*
B
bernard.xiong@gmail.com 已提交
1245
  rt_module_malloc - allocate memory block in free list
qiuyiuestc's avatar
qiuyiuestc 已提交
1246 1247 1248
*/
void *rt_module_malloc(rt_size_t size)
{
qiuyiuestc's avatar
qiuyiuestc 已提交
1249
	struct rt_mem_head *b, *n, *up;
qiuyiuestc's avatar
qiuyiuestc 已提交
1250
	struct rt_mem_head **prev;
D
dzzxzz 已提交
1251
	rt_uint32_t npage;
qiuyiuestc's avatar
qiuyiuestc 已提交
1252
	rt_size_t nunits;
1253

1254
	RT_DEBUG_NOT_IN_INTERRUPT;
1255

D
dzzxzz 已提交
1256
	nunits = (size + sizeof(struct rt_mem_head) -1)/sizeof(struct rt_mem_head) + 1;
qiuyiuestc's avatar
qiuyiuestc 已提交
1257 1258 1259 1260

	RT_ASSERT(size != 0);
	RT_ASSERT(nunits != 0);

qiuyiuestc's avatar
qiuyiuestc 已提交
1261
	rt_sem_take(&mod_sem, RT_WAITING_FOREVER);
qiuyiuestc's avatar
qiuyiuestc 已提交
1262

D
dzzxzz 已提交
1263
	for (prev = (struct rt_mem_head **)&rt_current_module->mem_list; (b = *prev) != RT_NULL; prev = &(b->next))
qiuyiuestc's avatar
qiuyiuestc 已提交
1264
	{
qiuyiuestc's avatar
qiuyiuestc 已提交
1265 1266
		if (b->size > nunits)
		{
B
bernard.xiong@gmail.com 已提交
1267
			/* split memory */
qiuyiuestc's avatar
qiuyiuestc 已提交
1268 1269 1270 1271 1272
			n = b + nunits;
			n->next = b->next;
			n->size = b->size - nunits;
			b->size = nunits;
			*prev = n;
qiuyiuestc's avatar
qiuyiuestc 已提交
1273

1274
			rt_kprintf("rt_module_malloc 0x%x, %d\n",b + 1, size);
qiuyiuestc's avatar
qiuyiuestc 已提交
1275
			rt_sem_release(&mod_sem);
D
dzzxzz 已提交
1276

qiuyiuestc's avatar
qiuyiuestc 已提交
1277
			return (void *)(b + 1);
qiuyiuestc's avatar
qiuyiuestc 已提交
1278 1279 1280 1281 1282 1283
		}

		if (b->size == nunits)
		{
			/* this node fit, remove this node */
			*prev = b->next;
qiuyiuestc's avatar
qiuyiuestc 已提交
1284 1285

			rt_kprintf("rt_module_malloc 0x%x, %d\n",b + 1, size);
B
bernard.xiong@gmail.com 已提交
1286

qiuyiuestc's avatar
qiuyiuestc 已提交
1287
			rt_sem_release(&mod_sem);
D
dzzxzz 已提交
1288

qiuyiuestc's avatar
qiuyiuestc 已提交
1289
			return (void *)(b + 1);
qiuyiuestc's avatar
qiuyiuestc 已提交
1290
		}
qiuyiuestc's avatar
qiuyiuestc 已提交
1291
	}
qiuyiuestc's avatar
qiuyiuestc 已提交
1292

qiuyiuestc's avatar
qiuyiuestc 已提交
1293 1294
	/* allocate pages from system heap */
	npage = (size + sizeof(struct rt_mem_head) + RT_MM_PAGE_SIZE - 1)/RT_MM_PAGE_SIZE;
D
dzzxzz 已提交
1295 1296
	if ((up = (struct rt_mem_head *)rt_module_malloc_page(npage)) == RT_NULL)
		return RT_NULL;
qiuyiuestc's avatar
qiuyiuestc 已提交
1297 1298

	up->size = npage * RT_MM_PAGE_SIZE / sizeof(struct rt_mem_head);
B
bernard.xiong@gmail.com 已提交
1299 1300

	for (prev = (struct rt_mem_head **)&rt_current_module->mem_list; (b = *prev) != RT_NULL; prev = &(b->next))
qiuyiuestc's avatar
qiuyiuestc 已提交
1301
	{
D
dzzxzz 已提交
1302 1303
		if (b > up + up->size)
			break;
qiuyiuestc's avatar
qiuyiuestc 已提交
1304 1305
	}

qiuyiuestc's avatar
qiuyiuestc 已提交
1306 1307 1308 1309
	up->next = b;
	*prev = up;

	rt_sem_release(&mod_sem);
D
dzzxzz 已提交
1310

qiuyiuestc's avatar
qiuyiuestc 已提交
1311
	return rt_module_malloc(size);
qiuyiuestc's avatar
qiuyiuestc 已提交
1312 1313 1314
}

/*
qiuyiuestc's avatar
qiuyiuestc 已提交
1315
  rt_module_free - free memory block in free list
qiuyiuestc's avatar
qiuyiuestc 已提交
1316 1317 1318
*/
void rt_module_free(rt_module_t module, void *addr)
{
qiuyiuestc's avatar
qiuyiuestc 已提交
1319
	struct rt_mem_head *b, *n, *r;
qiuyiuestc's avatar
qiuyiuestc 已提交
1320
	struct rt_mem_head **prev;
1321

1322
	RT_DEBUG_NOT_IN_INTERRUPT;
1323

qiuyiuestc's avatar
qiuyiuestc 已提交
1324
	RT_ASSERT(addr);
qiuyiuestc's avatar
qiuyiuestc 已提交
1325 1326
	RT_ASSERT((((rt_uint32_t)addr) & (sizeof(struct rt_mem_head) -1)) == 0);

1327
	rt_kprintf("rt_module_free 0x%x\n", addr);
D
dzzxzz 已提交
1328

qiuyiuestc's avatar
qiuyiuestc 已提交
1329
	rt_sem_take(&mod_sem, RT_WAITING_FOREVER);
D
dzzxzz 已提交
1330

qiuyiuestc's avatar
qiuyiuestc 已提交
1331
	n = (struct rt_mem_head *)addr - 1;
qiuyiuestc's avatar
qiuyiuestc 已提交
1332
	prev = (struct rt_mem_head **)&module->mem_list;
qiuyiuestc's avatar
qiuyiuestc 已提交
1333 1334

	while ((b = *prev) != RT_NULL)
D
dzzxzz 已提交
1335
	{
qiuyiuestc's avatar
qiuyiuestc 已提交
1336 1337 1338
		RT_ASSERT(b->size > 0);
		RT_ASSERT(b > n || b + b->size <= n);

D
dzzxzz 已提交
1339
		if (b + b->size == n && ((rt_uint32_t)n % RT_MM_PAGE_SIZE != 0))
qiuyiuestc's avatar
qiuyiuestc 已提交
1340
		{
qiuyiuestc's avatar
qiuyiuestc 已提交
1341
			if (b + (b->size + n->size) == b->next)
qiuyiuestc's avatar
qiuyiuestc 已提交
1342
			{
qiuyiuestc's avatar
qiuyiuestc 已提交
1343 1344
				b->size += b->next->size + n->size;
				b->next = b->next->next;
qiuyiuestc's avatar
qiuyiuestc 已提交
1345
			}
D
dzzxzz 已提交
1346 1347
			else
				b->size += n->size;
qiuyiuestc's avatar
qiuyiuestc 已提交
1348

D
dzzxzz 已提交
1349
			if ((rt_uint32_t)b % RT_MM_PAGE_SIZE == 0)
qiuyiuestc's avatar
qiuyiuestc 已提交
1350 1351
			{
				int npage = b->size * sizeof(struct rt_page_info) / RT_MM_PAGE_SIZE;
D
dzzxzz 已提交
1352
				if (npage > 0)
qiuyiuestc's avatar
qiuyiuestc 已提交
1353
				{
D
dzzxzz 已提交
1354
					if ((b->size * sizeof(struct rt_page_info) % RT_MM_PAGE_SIZE) != 0)
qiuyiuestc's avatar
qiuyiuestc 已提交
1355 1356 1357 1358 1359 1360 1361 1362 1363 1364
					{
						rt_size_t nunits = npage * RT_MM_PAGE_SIZE / sizeof(struct rt_mem_head);
						/* split memory */
						r = b + nunits;
						r->next = b->next;
						r->size = b->size - nunits;
						*prev = r;
					}
					else
					{
D
dzzxzz 已提交
1365
						*prev = b->next;
qiuyiuestc's avatar
qiuyiuestc 已提交
1366
					}
B
bernard.xiong@gmail.com 已提交
1367

1368
					rt_module_free_page(module, b, npage);
qiuyiuestc's avatar
qiuyiuestc 已提交
1369
				}
B
bernard.xiong@gmail.com 已提交
1370
			}
qiuyiuestc's avatar
qiuyiuestc 已提交
1371

qiuyiuestc's avatar
qiuyiuestc 已提交
1372 1373
			/* unlock */
			rt_sem_release(&mod_sem);
D
dzzxzz 已提交
1374

qiuyiuestc's avatar
qiuyiuestc 已提交
1375 1376 1377 1378 1379 1380 1381
			return;
		}

		if (b == n + n->size)
		{
			n->size = b->size + n->size;
			n->next = b->next;
B
bernard.xiong@gmail.com 已提交
1382

D
dzzxzz 已提交
1383
			if ((rt_uint32_t)n % RT_MM_PAGE_SIZE == 0)
qiuyiuestc's avatar
qiuyiuestc 已提交
1384 1385
			{
				int npage = n->size * sizeof(struct rt_page_info) / RT_MM_PAGE_SIZE;
D
dzzxzz 已提交
1386
				if (npage > 0)
qiuyiuestc's avatar
qiuyiuestc 已提交
1387
				{
D
dzzxzz 已提交
1388
					if ((n->size * sizeof(struct rt_page_info) % RT_MM_PAGE_SIZE) != 0)
qiuyiuestc's avatar
qiuyiuestc 已提交
1389 1390 1391 1392 1393 1394 1395 1396
					{
						rt_size_t nunits = npage * RT_MM_PAGE_SIZE / sizeof(struct rt_mem_head);
						/* split memory */
						r = n + nunits;
						r->next = n->next;
						r->size = n->size - nunits;
						*prev = r;
					}
D
dzzxzz 已提交
1397
					else *prev = n->next;
B
bernard.xiong@gmail.com 已提交
1398

1399
					rt_module_free_page(module, n, npage);
qiuyiuestc's avatar
qiuyiuestc 已提交
1400
				}
D
dzzxzz 已提交
1401
			}
qiuyiuestc's avatar
qiuyiuestc 已提交
1402 1403 1404 1405 1406 1407 1408
			else
			{
				*prev = n;
			}

			/* unlock */
			rt_sem_release(&mod_sem);
qiuyiuestc's avatar
qiuyiuestc 已提交
1409 1410 1411

			return;
		}
D
dzzxzz 已提交
1412 1413
		if (b > n + n->size)
			break;
qiuyiuestc's avatar
qiuyiuestc 已提交
1414 1415 1416 1417

		prev = &(b->next);
	}

D
dzzxzz 已提交
1418
	if ((rt_uint32_t)n % RT_MM_PAGE_SIZE == 0)
qiuyiuestc's avatar
qiuyiuestc 已提交
1419 1420
	{
		int npage = n->size * sizeof(struct rt_page_info) / RT_MM_PAGE_SIZE;
D
dzzxzz 已提交
1421
		if (npage > 0)
qiuyiuestc's avatar
qiuyiuestc 已提交
1422
		{
1423
			rt_module_free_page(module, n, npage);
D
dzzxzz 已提交
1424
			if (n->size % RT_MM_PAGE_SIZE != 0)
qiuyiuestc's avatar
qiuyiuestc 已提交
1425 1426 1427 1428 1429 1430 1431 1432 1433 1434
			{
				rt_size_t nunits = npage * RT_MM_PAGE_SIZE / sizeof(struct rt_mem_head);
				/* split memory */
				r = n + nunits;
				r->next = b;
				r->size = n->size - nunits;
				*prev = r;
			}
			else
			{
B
bernard.xiong@gmail.com 已提交
1435 1436 1437
				*prev = b;
			}
		}
qiuyiuestc's avatar
qiuyiuestc 已提交
1438
	}
D
dzzxzz 已提交
1439 1440
	else
	{
qiuyiuestc's avatar
qiuyiuestc 已提交
1441 1442 1443
		n->next = b;
		*prev = n;
	}
qiuyiuestc's avatar
qiuyiuestc 已提交
1444

qiuyiuestc's avatar
qiuyiuestc 已提交
1445
	/* unlock */
D
dzzxzz 已提交
1446
	rt_sem_release(&mod_sem);
qiuyiuestc's avatar
qiuyiuestc 已提交
1447 1448 1449 1450 1451 1452 1453
}

/*
  rt_module_realloc - realloc memory block in free list
*/
void *rt_module_realloc(void *ptr, rt_size_t size)
{
qiuyiuestc's avatar
qiuyiuestc 已提交
1454 1455
	struct rt_mem_head *b, *p, *prev, *tmpp;
	rt_size_t nunits;
qiuyiuestc's avatar
qiuyiuestc 已提交
1456

1457
	RT_DEBUG_NOT_IN_INTERRUPT;
1458

D
dzzxzz 已提交
1459 1460
	if (!ptr)
		return rt_module_malloc(size);
qiuyiuestc's avatar
qiuyiuestc 已提交
1461 1462 1463
	if (size == 0)
	{
		rt_module_free(rt_current_module, ptr);
D
dzzxzz 已提交
1464

qiuyiuestc's avatar
qiuyiuestc 已提交
1465 1466
		return RT_NULL;
	}
qiuyiuestc's avatar
qiuyiuestc 已提交
1467

qiuyiuestc's avatar
qiuyiuestc 已提交
1468 1469 1470
	nunits = (size + sizeof(struct rt_mem_head) - 1) / sizeof(struct rt_mem_head) + 1;
	b = (struct rt_mem_head *)ptr - 1;

D
dzzxzz 已提交
1471 1472 1473
	if (nunits <= b->size)
	{
		/* new size is smaller or equal then before */
D
dzzxzz 已提交
1474 1475
		if (nunits == b->size)
			return ptr;
D
dzzxzz 已提交
1476
		else
qiuyiuestc's avatar
qiuyiuestc 已提交
1477 1478 1479 1480 1481
		{
			p = b + nunits;
			p->size = b->size - nunits;
			b->size = nunits;
			rt_module_free(rt_current_module, (void *)(p + 1));
D
dzzxzz 已提交
1482

qiuyiuestc's avatar
qiuyiuestc 已提交
1483 1484 1485
			return (void *)(b + 1);
		}
	}
D
dzzxzz 已提交
1486 1487
	else
	{
qiuyiuestc's avatar
qiuyiuestc 已提交
1488
		/* more space then required */
qiuyiuestc's avatar
qiuyiuestc 已提交
1489
		prev = (struct rt_mem_head *)rt_current_module->mem_list;
D
dzzxzz 已提交
1490 1491
		for (p = prev->next; p != (b->size + b) && p != RT_NULL; prev = p, p = p->next)
			break;
qiuyiuestc's avatar
qiuyiuestc 已提交
1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504

		/* available block after ap in freelist */ 
		if (p != RT_NULL && (p->size >= (nunits - (b->size))) &&  p == (b + b->size))  
		{
			/* perfect match */
			if (p->size == (nunits - (b->size)))  
			{
				b->size = nunits;
				prev->next = p->next;
			}
			else  /* more space then required, split block*/
			{
				/* pointer to old header */
D
dzzxzz 已提交
1505
				tmpp = p;
qiuyiuestc's avatar
qiuyiuestc 已提交
1506 1507 1508 1509 1510 1511
				p = b + nunits;

				/* restoring old pointer */
				p->next = tmpp->next;
				
				/* new size for p */
D
dzzxzz 已提交
1512
				p->size = tmpp->size + b->size - nunits;
qiuyiuestc's avatar
qiuyiuestc 已提交
1513 1514 1515
				b->size = nunits;
				prev->next = p;
			}
qiuyiuestc's avatar
qiuyiuestc 已提交
1516
			rt_current_module->mem_list = (void *)prev;
D
dzzxzz 已提交
1517

D
dzzxzz 已提交
1518
			return (void *)(b + 1);
qiuyiuestc's avatar
qiuyiuestc 已提交
1519 1520 1521 1522 1523 1524
		}
		else /* allocate new memory and copy old data */
		{
			if ((p = rt_module_malloc(size)) == RT_NULL) return RT_NULL;
			rt_memmove(p, (b+1), ((b->size) * sizeof(struct rt_mem_head)));
			rt_module_free(rt_current_module, (void *)(b + 1));
D
dzzxzz 已提交
1525

D
dzzxzz 已提交
1526
			return (void *)(p);
qiuyiuestc's avatar
qiuyiuestc 已提交
1527 1528 1529
		}
	}
}
qiuyiuestc's avatar
qiuyiuestc 已提交
1530 1531 1532 1533
#endif

#ifdef RT_USING_FINSH
#include <finsh.h>
D
dzzxzz 已提交
1534
void list_memlist(const char *name)
qiuyiuestc's avatar
qiuyiuestc 已提交
1535 1536 1537 1538
{
	rt_module_t module;
	struct rt_mem_head **prev;
	struct rt_mem_head *b;
B
bernard.xiong@gmail.com 已提交
1539

qiuyiuestc's avatar
qiuyiuestc 已提交
1540
	module = rt_module_find(name);
D
dzzxzz 已提交
1541 1542
	if (module == RT_NULL)
		return;
qiuyiuestc's avatar
qiuyiuestc 已提交
1543

D
dzzxzz 已提交
1544
	for (prev = (struct rt_mem_head **)&module->mem_list; (b = *prev) != RT_NULL; prev = &(b->next))
qiuyiuestc's avatar
qiuyiuestc 已提交
1545 1546 1547 1548 1549 1550
	{
		rt_kprintf("0x%x--%d\n", b, b->size * sizeof(struct rt_mem_head));
	}
}
FINSH_FUNCTION_EXPORT(list_memlist, list module free memory information)

D
dzzxzz 已提交
1551
void list_mempage(const char *name)
qiuyiuestc's avatar
qiuyiuestc 已提交
1552 1553 1554 1555 1556 1557
{
	rt_module_t module;
	struct rt_page_info *page;
	int i;

	module = rt_module_find(name);
D
dzzxzz 已提交
1558 1559
	if (module == RT_NULL)
		return;
qiuyiuestc's avatar
qiuyiuestc 已提交
1560 1561 1562

	page = (struct rt_page_info*)module->page_array;

D
dzzxzz 已提交
1563
	for (i=0; i<module->page_cnt; i++)
qiuyiuestc's avatar
qiuyiuestc 已提交
1564 1565
	{
		rt_kprintf("0x%x--%d\n", page[i].page_ptr, page[i].npage);
D
dzzxzz 已提交
1566
	}
qiuyiuestc's avatar
qiuyiuestc 已提交
1567 1568 1569
}
FINSH_FUNCTION_EXPORT(list_mempage, list module using memory page information)
#endif
qiuyiuestc's avatar
qiuyiuestc 已提交
1570

qiuyiuestc's avatar
qiuyiuestc 已提交
1571
#endif