module.c 30.8 KB
Newer Older
qiuyiuestc's avatar
qiuyiuestc 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13
/*
 * File      : module.c
 * This file is part of RT-Thread RTOS
 * COPYRIGHT (C) 2006 - 2010, RT-Thread Development Team
 *
 * 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:
 * Date           Author		Notes
 * 2010-01-09      Bernard	first version
 * 2010-04-09      yi.qiu	implement based on first version
qiuyiuestc's avatar
qiuyiuestc 已提交
14 15 16
 * 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

qiuyiuestc's avatar
qiuyiuestc 已提交
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 33

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

qiuyiuestc's avatar
qiuyiuestc 已提交
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 56 57
struct rt_page_info
{
	rt_uint32_t *page_ptr;
	rt_uint32_t npage;
};

static void *rt_module_malloc_page(rt_size_t npages);
static void rt_module_free_page(void *page_ptr, rt_size_t npages);
qiuyiuestc's avatar
qiuyiuestc 已提交
58

qiuyiuestc's avatar
qiuyiuestc 已提交
59
static rt_module_t rt_current_module = RT_NULL;
qiuyiuestc's avatar
qiuyiuestc 已提交
60 61
static struct rt_semaphore mod_sem;
static struct rt_module_symtab *_rt_module_symtab_begin = RT_NULL, *_rt_module_symtab_end = RT_NULL;
62
rt_list_t rt_module_symbol_list;
qiuyiuestc's avatar
qiuyiuestc 已提交
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86

static char* _strip_name(const char* string)
{
	int i = 0, p = 0, q = 0;
	const char* str = string;
	char* dest = RT_NULL;
	
	while(*str != '\n' && *str != '\0')
	{
		if(*str =='/' ) p = i + 1;
		if(*str == '.') q = i;	
		str++; i++;
	}

	if(p < q)
	{
		int len = q - p;
		dest = (char*)rt_malloc(len + 1);
		rt_strncpy(dest, &string[p], len);
		dest[len] = '\0';
	}

	return dest;
}
87 88 89 90

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

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

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

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

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

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

qiuyiuestc's avatar
qiuyiuestc 已提交
132 133 134
/**
 * This function will return self module object
 *
qiuyiuestc's avatar
qiuyiuestc 已提交
135
 * @return the self module object
qiuyiuestc's avatar
qiuyiuestc 已提交
136 137 138 139
 *
 */
rt_module_t rt_module_self (void)
{
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 149 150 151 152 153 154 155 156
/**
 * This function will set current module object
 *
 * @return RT_EOK
 */
rt_err_t rt_module_set (rt_module_t module)
{
	/* set current module */
	rt_current_module = module;

	return RT_EOK;
}

qiuyiuestc's avatar
qiuyiuestc 已提交
157
static int rt_module_arm_relocate(struct rt_module* module, Elf32_Rel *rel, Elf32_Addr sym_val)
qiuyiuestc's avatar
qiuyiuestc 已提交
158 159 160 161
{
	Elf32_Addr *where, tmp;
	Elf32_Sword addend;

qiuyiuestc's avatar
qiuyiuestc 已提交
162
	where = (Elf32_Addr *)((rt_uint8_t*)module->module_space + rel->r_offset);
qiuyiuestc's avatar
qiuyiuestc 已提交
163 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;
170 171 172 173

		RT_DEBUG_LOG(RT_DEBUG_MODULE,
			("R_ARM_ABS32: %x -> %x\n", where, *where));

qiuyiuestc's avatar
qiuyiuestc 已提交
174 175 176 177 178 179 180 181 182 183 184 185
		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);
186 187 188

		RT_DEBUG_LOG(RT_DEBUG_MODULE,("R_ARM_PC24: %x -> %x\n", where, *where));

qiuyiuestc's avatar
qiuyiuestc 已提交
189 190
		break;

qiuyiuestc's avatar
qiuyiuestc 已提交
191 192 193 194
	case R_ARM_V4BX:
		*where &= 0xf000000f;
		*where |= 0x01a0f000;
		break;
qiuyiuestc's avatar
qiuyiuestc 已提交
195 196
	case R_ARM_GLOB_DAT:
	case R_ARM_JUMP_SLOT:
qiuyiuestc's avatar
qiuyiuestc 已提交
197
		*where = (Elf32_Addr)sym_val;
198 199 200 201

		RT_DEBUG_LOG(RT_DEBUG_MODULE,
			("R_ARM_JUMP_SLOT: 0x%x -> 0x%x 0x%x\n", where, *where, sym_val));

qiuyiuestc's avatar
qiuyiuestc 已提交
202
	break;
qiuyiuestc's avatar
qiuyiuestc 已提交
203 204
	case R_ARM_RELATIVE:
		*where += (Elf32_Addr)sym_val;
205 206 207 208

		RT_DEBUG_LOG(RT_DEBUG_MODULE,
			("R_ARM_RELATIVE: 0x%x -> 0x%x 0x%x\n", where, *where, sym_val));

209
		 break;
qiuyiuestc's avatar
qiuyiuestc 已提交
210 211 212 213 214 215 216 217 218 219 220
	default:
		return -1;
	}

	return 0;
}

static void rt_module_init_object_container(struct rt_module* module)
{
	RT_ASSERT(module != RT_NULL);

B
bernard.xiong@gmail.com 已提交
221
	/* initialize object container - thread */
qiuyiuestc's avatar
qiuyiuestc 已提交
222 223 224 225 226
	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 已提交
227
	/* initialize object container - semaphore */
qiuyiuestc's avatar
qiuyiuestc 已提交
228 229 230 231 232 233
	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 已提交
234
	/* initialize object container - mutex */
qiuyiuestc's avatar
qiuyiuestc 已提交
235 236 237 238 239 240
	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 已提交
241
	/* initialize object container - event */
qiuyiuestc's avatar
qiuyiuestc 已提交
242 243 244 245 246 247
	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 已提交
248
	/* initialize object container - mailbox */
qiuyiuestc's avatar
qiuyiuestc 已提交
249 250 251 252 253 254
	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 已提交
255
	/* initialize object container - message queue */
qiuyiuestc's avatar
qiuyiuestc 已提交
256 257 258 259 260 261
	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 已提交
262
	/* initialize object container - memory pool */
qiuyiuestc's avatar
qiuyiuestc 已提交
263 264 265 266 267 268
	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 已提交
269
	/* initialize object container - device */
qiuyiuestc's avatar
qiuyiuestc 已提交
270 271 272 273 274
	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 已提交
275
	/* initialize object container - timer */
qiuyiuestc's avatar
qiuyiuestc 已提交
276 277 278 279 280
	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 已提交
281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314
#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
 */
/*@{*/

/**
 * 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

qiuyiuestc's avatar
qiuyiuestc 已提交
315 316 317 318 319 320 321 322 323
/**
 * 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
 *
 */
qiuyiuestc's avatar
qiuyiuestc 已提交
324
rt_module_t rt_module_load(const char* name, void* module_ptr)
qiuyiuestc's avatar
qiuyiuestc 已提交
325
{
326
	rt_uint8_t *ptr = RT_NULL;
327 328
	rt_module_t module = RT_NULL;
	rt_bool_t linked = RT_FALSE;
329
	rt_uint32_t index, module_size = 0;
qiuyiuestc's avatar
qiuyiuestc 已提交
330

331
	RT_DEBUG_NOT_IN_INTERRUPT;
332

qiuyiuestc's avatar
qiuyiuestc 已提交
333
	rt_kprintf("rt_module_load: %s ,", name);
qiuyiuestc's avatar
qiuyiuestc 已提交
334

qiuyiuestc's avatar
qiuyiuestc 已提交
335
	/* check ELF header */
336 337 338 339 340
	if (rt_memcmp(elf_module->e_ident, RTMMAG, SELFMAG) == 0)
	{
		/* rtmlinke finished */
		linked = RT_TRUE;
	}
qiuyiuestc's avatar
qiuyiuestc 已提交
341
	else if (rt_memcmp(elf_module->e_ident, ELFMAG, SELFMAG) != 0)
qiuyiuestc's avatar
qiuyiuestc 已提交
342
	{
qiuyiuestc's avatar
qiuyiuestc 已提交
343
		rt_kprintf(" module magic error\n");
qiuyiuestc's avatar
qiuyiuestc 已提交
344
		return RT_NULL;
qiuyiuestc's avatar
qiuyiuestc 已提交
345
	}
346 347 348 349 350 351 352

	/* check ELF class */
	if(elf_module->e_ident[EI_CLASS] != ELFCLASS32)
	{
		rt_kprintf(" module class error\n");
		return RT_NULL;
	}
qiuyiuestc's avatar
qiuyiuestc 已提交
353
	
qiuyiuestc's avatar
qiuyiuestc 已提交
354
	/* get the ELF image size */
qiuyiuestc's avatar
qiuyiuestc 已提交
355
	for (index = 0; index < elf_module->e_phnum; index++)
qiuyiuestc's avatar
qiuyiuestc 已提交
356
	{
qiuyiuestc's avatar
qiuyiuestc 已提交
357 358 359 360
		if(phdr[index].p_type == PT_LOAD)
			module_size += phdr[index].p_memsz;
	}	
	
qiuyiuestc's avatar
qiuyiuestc 已提交
361 362 363 364 365
	if (module_size == 0) 
	{
		rt_kprintf(" module size error\n");
		return module;
	}	
qiuyiuestc's avatar
qiuyiuestc 已提交
366 367

	/* allocate module */
qiuyiuestc's avatar
qiuyiuestc 已提交
368
	module = (struct rt_module *)rt_object_allocate(RT_Object_Class_Module, name);
qiuyiuestc's avatar
qiuyiuestc 已提交
369
	if (!module) return RT_NULL;
qiuyiuestc's avatar
qiuyiuestc 已提交
370 371 372 373 374 375 376 377 378 379 380 381 382

	/* allocate module space */
	module->module_space = rt_malloc(module_size);
	if (module->module_space == RT_NULL)
	{
		rt_object_delete(&(module->parent));
		return RT_NULL;
	}

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

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

qiuyiuestc's avatar
qiuyiuestc 已提交
385
	for (index = 0; index < elf_module->e_phnum; index++)
qiuyiuestc's avatar
qiuyiuestc 已提交
386
	{
qiuyiuestc's avatar
qiuyiuestc 已提交
387
		if(phdr[index].p_type == PT_LOAD)
qiuyiuestc's avatar
qiuyiuestc 已提交
388
		{
qiuyiuestc's avatar
qiuyiuestc 已提交
389 390 391 392
			rt_memcpy(ptr, (rt_uint8_t*)elf_module + phdr[index].p_offset, phdr[index].p_filesz);
			ptr += phdr[index].p_memsz;
		}		
	}	
qiuyiuestc's avatar
qiuyiuestc 已提交
393 394

	/* set module entry */
qiuyiuestc's avatar
qiuyiuestc 已提交
395
	module->module_entry = module->module_space + elf_module->e_entry;
qiuyiuestc's avatar
qiuyiuestc 已提交
396
	
qiuyiuestc's avatar
qiuyiuestc 已提交
397 398 399 400 401 402 403 404
	/* 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;
405 406
			rt_uint8_t *strtab;
			static rt_bool_t unsolved = RT_FALSE;
qiuyiuestc's avatar
qiuyiuestc 已提交
407 408 409 410

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

411
			/* locate .rel.plt and .rel.dyn section */
qiuyiuestc's avatar
qiuyiuestc 已提交
412 413
			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;
qiuyiuestc's avatar
qiuyiuestc 已提交
414
 			nr_reloc = (rt_uint32_t) (shdr[index].sh_size / sizeof(Elf32_Rel));
qiuyiuestc's avatar
qiuyiuestc 已提交
415 416 417 418 419

			/* relocate every items */
			for (i = 0; i < nr_reloc; i ++)
			{
				Elf32_Sym *sym = &symtab[ELF32_R_SYM(rel->r_info)];
420 421 422 423

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

qiuyiuestc's avatar
qiuyiuestc 已提交
424
				if((sym->st_shndx != SHT_NULL) || (ELF_ST_BIND(sym->st_info) == STB_LOCAL))	
425
					rt_module_arm_relocate(module, rel,  (Elf32_Addr)(module->module_space + sym->st_value));
426
				else if(!linked)
427 428
				{
					Elf32_Addr addr;
429 430 431 432

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

433
					/* need to resolve symbol in kernel symbol table */
qiuyiuestc's avatar
qiuyiuestc 已提交
434
					addr = rt_module_symbol_find((const char*)(strtab + sym->st_name));
435 436 437
					if (addr == 0)
					{
						rt_kprintf("can't find %s in kernel symbol table\n", strtab + sym->st_name);
438
						unsolved = RT_TRUE;
439
					}	
440
					else rt_module_arm_relocate(module, rel, addr);
441
				}
qiuyiuestc's avatar
qiuyiuestc 已提交
442 443
				rel ++;
			}
444 445 446 447 448 449 450

			if(unsolved) 
			{
				rt_object_delete(&(module->parent));
				rt_free(module);
				return RT_NULL;
			}	
qiuyiuestc's avatar
qiuyiuestc 已提交
451 452 453
		}
	}

454 455 456 457 458
	/* construct module symbol table */
	for (index = 0; index < elf_module->e_shnum; index ++)
	{	
		/* find .dynsym section */
		rt_uint8_t* shstrab = (rt_uint8_t*) module_ptr + shdr[elf_module->e_shstrndx].sh_offset;
qiuyiuestc's avatar
qiuyiuestc 已提交
459
		if (rt_strcmp((const char *)(shstrab + shdr[index].sh_name), ELF_DYNSYM) == 0) break;
460 461
	}

qiuyiuestc's avatar
qiuyiuestc 已提交
462
	/* found .dynsym section */
463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483
	if(index != elf_module->e_shnum)
	{
		int i, count = 0;
		Elf32_Sym *symtab = RT_NULL;
		rt_uint8_t *strtab  = RT_NULL;

		symtab =(Elf32_Sym *) ((rt_uint8_t*)module_ptr + shdr[index].sh_offset);
		strtab = (rt_uint8_t*) module_ptr + shdr[shdr[index].sh_link].sh_offset;			

		for(i=0; i<shdr[index].sh_size/sizeof(Elf32_Sym); i++)
		{
			if((ELF_ST_BIND(symtab[i].st_info) == STB_GLOBAL) && (ELF_ST_TYPE(symtab[i].st_info) == STT_FUNC))
				count++;
		}

		module->symtab = (struct rt_module_symtab*)rt_malloc(count * sizeof(struct rt_module_symtab));
		module->nsym = count;
		for(i=0, count=0; i<shdr[index].sh_size/sizeof(Elf32_Sym); i++)
		{
			if((ELF_ST_BIND(symtab[i].st_info) == STB_GLOBAL) && (ELF_ST_TYPE(symtab[i].st_info) == STT_FUNC))
			{
qiuyiuestc's avatar
qiuyiuestc 已提交
484
				rt_size_t length = rt_strlen((const char*)(strtab + symtab[i].st_name)) + 1;
485

qiuyiuestc's avatar
qiuyiuestc 已提交
486
				module->symtab[count].addr = (void*)(module->module_space + symtab[i].st_value); 
487
				module->symtab[count].name = rt_malloc(length);
qiuyiuestc's avatar
qiuyiuestc 已提交
488 489
				rt_memset((void*)module->symtab[count].name, 0, length);
				rt_memcpy((void*)module->symtab[count].name, strtab + symtab[i].st_name, length);
490 491 492 493
				count++;
			}	
		}	
	}	
qiuyiuestc's avatar
qiuyiuestc 已提交
494

qiuyiuestc's avatar
qiuyiuestc 已提交
495 496
	/* init module object container */
	rt_module_init_object_container(module);
qiuyiuestc's avatar
qiuyiuestc 已提交
497
		
qiuyiuestc's avatar
qiuyiuestc 已提交
498 499
	/* increase module reference count  */
	module->nref++;
qiuyiuestc's avatar
qiuyiuestc 已提交
500 501 502 503

	if(elf_module->e_entry != 0)
	{	
		/* init module memory allocator */
qiuyiuestc's avatar
qiuyiuestc 已提交
504
		module->mem_list = RT_NULL;
qiuyiuestc's avatar
qiuyiuestc 已提交
505 506 507 508

		/* create page array */
		module->page_array = (void *)rt_malloc(PAGE_COUNT_MAX * sizeof(struct rt_page_info));
		module->page_cnt = 0;
qiuyiuestc's avatar
qiuyiuestc 已提交
509 510
		
		/* create module thread */
qiuyiuestc's avatar
qiuyiuestc 已提交
511
		module->stack_size = 2048;
qiuyiuestc's avatar
qiuyiuestc 已提交
512
		module->thread_priority = 25;
qiuyiuestc's avatar
qiuyiuestc 已提交
513 514 515 516 517 518
		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 已提交
519 520
		module->parent.flag = RT_MODULE_FLAG_WITHENTRY;
			
qiuyiuestc's avatar
qiuyiuestc 已提交
521 522 523 524 525 526 527 528 529
		/* startup module thread */
		rt_thread_startup(module->module_thread);
	}	
	else
	{
		/* without entry point */
		module->parent.flag |= RT_MODULE_FLAG_WITHOUTENTRY;
	}	

qiuyiuestc's avatar
qiuyiuestc 已提交
530 531 532 533 534 535 536
#ifdef RT_USING_HOOK
	if(rt_module_load_hook != RT_NULL)
	{
		rt_module_load_hook(module);
	}
#endif

qiuyiuestc's avatar
qiuyiuestc 已提交
537
	return module;
qiuyiuestc's avatar
qiuyiuestc 已提交
538 539
}	

qiuyiuestc's avatar
qiuyiuestc 已提交
540 541 542
#ifdef RT_USING_DFS
#include <dfs_posix.h>
/**
B
bernard.xiong@gmail.com 已提交
543
 * This function will load a module from a file
qiuyiuestc's avatar
qiuyiuestc 已提交
544
 *
B
bernard.xiong@gmail.com 已提交
545
 * @param filename the file name of application module
qiuyiuestc's avatar
qiuyiuestc 已提交
546 547 548 549
 *
 * @return the module object
 *
 */
qiuyiuestc's avatar
qiuyiuestc 已提交
550
rt_module_t rt_module_open(const char* path)
qiuyiuestc's avatar
qiuyiuestc 已提交
551 552 553
{
	int fd, length;
	struct rt_module* module;
B
bernard.xiong@gmail.com 已提交
554
	struct stat s;
qiuyiuestc's avatar
qiuyiuestc 已提交
555
	char *buffer, *offset_ptr, *name;
qiuyiuestc's avatar
qiuyiuestc 已提交
556

557
	RT_DEBUG_NOT_IN_INTERRUPT;
558

qiuyiuestc's avatar
qiuyiuestc 已提交
559
	/* check parameters */
qiuyiuestc's avatar
qiuyiuestc 已提交
560
	RT_ASSERT(path != RT_NULL);
qiuyiuestc's avatar
qiuyiuestc 已提交
561

qiuyiuestc's avatar
qiuyiuestc 已提交
562
	if (stat(path, &s) !=0)
563
	{
qiuyiuestc's avatar
qiuyiuestc 已提交
564
		rt_kprintf("access %s failed\n", path);
565 566
		return RT_NULL;
	}
qiuyiuestc's avatar
qiuyiuestc 已提交
567
	buffer = (char *)rt_malloc(s.st_size);
568 569 570 571 572 573 574
	if (buffer == RT_NULL)
	{
		rt_kprintf("out of memory\n");
		return RT_NULL;
	}

	offset_ptr = buffer;
qiuyiuestc's avatar
qiuyiuestc 已提交
575
	fd = open(path, O_RDONLY, 0);
576 577
	if (fd < 0)
	{
qiuyiuestc's avatar
qiuyiuestc 已提交
578
		rt_kprintf("open %s failed\n", path);
579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595
		rt_free(buffer);
		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 已提交
596 597 598 599 600
	{
		rt_kprintf("check: read file failed\n");
		rt_free(buffer);
		return RT_NULL;
	}
qiuyiuestc's avatar
qiuyiuestc 已提交
601 602 603

	name = _strip_name(path);
	module = rt_module_load(name, (void *)buffer);
qiuyiuestc's avatar
qiuyiuestc 已提交
604
	rt_free(buffer);
qiuyiuestc's avatar
qiuyiuestc 已提交
605
	rt_free(name);
qiuyiuestc's avatar
qiuyiuestc 已提交
606 607 608

	return module;
}
qiuyiuestc's avatar
qiuyiuestc 已提交
609 610 611

#if defined(RT_USING_FINSH)
#include <finsh.h>
612
FINSH_FUNCTION_EXPORT_ALIAS(rt_module_open, exec, exec module from file);
qiuyiuestc's avatar
qiuyiuestc 已提交
613
#endif
qiuyiuestc's avatar
qiuyiuestc 已提交
614 615
#endif

qiuyiuestc's avatar
qiuyiuestc 已提交
616 617 618 619 620 621 622 623 624
/**
 * This function will unload a module from memory and release resources 
 *
 * @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 已提交
625
{
626
	int i;
qiuyiuestc's avatar
qiuyiuestc 已提交
627
	struct rt_object* object;
qiuyiuestc's avatar
qiuyiuestc 已提交
628
	struct rt_list_node *list;
qiuyiuestc's avatar
qiuyiuestc 已提交
629

630
	RT_DEBUG_NOT_IN_INTERRUPT;
631

qiuyiuestc's avatar
qiuyiuestc 已提交
632 633 634
	/* check parameter */
	RT_ASSERT(module != RT_NULL);

qiuyiuestc's avatar
qiuyiuestc 已提交
635 636
	rt_kprintf("rt_module_unload: %s\n", module->parent.name);
	
qiuyiuestc's avatar
qiuyiuestc 已提交
637
	/* module has entry point */
qiuyiuestc's avatar
qiuyiuestc 已提交
638
	if((module->parent.flag & RT_MODULE_FLAG_WITHOUTENTRY) != RT_MODULE_FLAG_WITHOUTENTRY)
qiuyiuestc's avatar
qiuyiuestc 已提交
639 640 641 642 643 644 645 646 647 648 649
	{	
		/* suspend module main thread */
		if(module->module_thread != RT_NULL)
		{	
			if (module->module_thread->stat == RT_THREAD_READY)
				rt_thread_suspend(module->module_thread);
		}
		
		/* delete threads */
		list = &module->module_object[RT_Object_Class_Thread].object_list;	
		while(list->next != list)
qiuyiuestc's avatar
qiuyiuestc 已提交
650
		{
qiuyiuestc's avatar
qiuyiuestc 已提交
651 652 653
			object = rt_list_entry(list->next, struct rt_object, list);
			if (rt_object_is_systemobject(object) == RT_EOK)
			{
qiuyiuestc's avatar
qiuyiuestc 已提交
654
				/* detach static object */
qiuyiuestc's avatar
qiuyiuestc 已提交
655 656 657 658 659 660 661
				rt_thread_detach((rt_thread_t)object);
			}
			else
			{	
				/* delete dynamic object */
				rt_thread_delete((rt_thread_t)object);
			}	
qiuyiuestc's avatar
qiuyiuestc 已提交
662
		}
qiuyiuestc's avatar
qiuyiuestc 已提交
663
		
qiuyiuestc's avatar
qiuyiuestc 已提交
664
#ifdef RT_USING_SEMAPHORE
qiuyiuestc's avatar
qiuyiuestc 已提交
665 666 667
		/* delete semaphores */
		list = &module->module_object[RT_Object_Class_Thread].object_list;	
		while(list->next != list)
qiuyiuestc's avatar
qiuyiuestc 已提交
668
		{
qiuyiuestc's avatar
qiuyiuestc 已提交
669 670 671
			object = rt_list_entry(list->next, struct rt_object, list);
			if (rt_object_is_systemobject(object) == RT_EOK)
			{
qiuyiuestc's avatar
qiuyiuestc 已提交
672
				/* detach static object */
qiuyiuestc's avatar
qiuyiuestc 已提交
673 674 675 676 677 678 679
				rt_sem_detach((rt_sem_t)object);
			}
			else
			{	
				/* delete dynamic object */
				rt_sem_delete((rt_sem_t)object);
			}	
qiuyiuestc's avatar
qiuyiuestc 已提交
680 681 682 683
		}
#endif

#ifdef RT_USING_MUTEX
qiuyiuestc's avatar
qiuyiuestc 已提交
684 685 686
		/* delete mutexs*/
		list = &module->module_object[RT_Object_Class_Mutex].object_list;	
		while(list->next != list)
qiuyiuestc's avatar
qiuyiuestc 已提交
687
		{
qiuyiuestc's avatar
qiuyiuestc 已提交
688 689 690
			object = rt_list_entry(list->next, struct rt_object, list);
			if (rt_object_is_systemobject(object) == RT_EOK)
			{
qiuyiuestc's avatar
qiuyiuestc 已提交
691
				/* detach static object */
qiuyiuestc's avatar
qiuyiuestc 已提交
692 693 694 695 696 697 698
				rt_mutex_detach((rt_mutex_t)object);
			}
			else
			{	
				/* delete dynamic object */
				rt_mutex_delete((rt_mutex_t)object);
			}	
qiuyiuestc's avatar
qiuyiuestc 已提交
699 700 701 702
		}
#endif

#ifdef RT_USING_EVENT
qiuyiuestc's avatar
qiuyiuestc 已提交
703 704 705
		/* delete mailboxs */
		list = &module->module_object[RT_Object_Class_Event].object_list;	
		while(list->next != list)
qiuyiuestc's avatar
qiuyiuestc 已提交
706
		{
qiuyiuestc's avatar
qiuyiuestc 已提交
707 708 709
			object = rt_list_entry(list->next, struct rt_object, list);
			if (rt_object_is_systemobject(object) == RT_EOK)
			{
qiuyiuestc's avatar
qiuyiuestc 已提交
710
				/* detach static object */
qiuyiuestc's avatar
qiuyiuestc 已提交
711 712 713 714 715 716 717
				rt_event_detach((rt_event_t)object);
			}
			else
			{	
				/* delete dynamic object */
				rt_event_delete((rt_event_t)object);
			}	
qiuyiuestc's avatar
qiuyiuestc 已提交
718
		}
qiuyiuestc's avatar
qiuyiuestc 已提交
719 720 721
#endif

#ifdef RT_USING_MAILBOX
qiuyiuestc's avatar
qiuyiuestc 已提交
722 723 724
		/* delete mailboxs */
		list = &module->module_object[RT_Object_Class_MailBox].object_list;	
		while(list->next != list)
qiuyiuestc's avatar
qiuyiuestc 已提交
725
		{
qiuyiuestc's avatar
qiuyiuestc 已提交
726 727 728
			object = rt_list_entry(list->next, struct rt_object, list);
			if (rt_object_is_systemobject(object) == RT_EOK)
			{
qiuyiuestc's avatar
qiuyiuestc 已提交
729
				/* detach static object */
qiuyiuestc's avatar
qiuyiuestc 已提交
730 731 732 733 734 735 736
				rt_mb_detach((rt_mailbox_t)object);
			}
			else
			{	
				/* delete dynamic object */
				rt_mb_delete((rt_mailbox_t)object);
			}	
qiuyiuestc's avatar
qiuyiuestc 已提交
737 738 739 740
		}
#endif

#ifdef RT_USING_MESSAGEQUEUE
qiuyiuestc's avatar
qiuyiuestc 已提交
741 742 743
		/* delete msgqueues */
		list = &module->module_object[RT_Object_Class_MessageQueue].object_list;	
		while(list->next != list)
qiuyiuestc's avatar
qiuyiuestc 已提交
744
		{
qiuyiuestc's avatar
qiuyiuestc 已提交
745 746 747
			object = rt_list_entry(list->next, struct rt_object, list);
			if (rt_object_is_systemobject(object) == RT_EOK)
			{
qiuyiuestc's avatar
qiuyiuestc 已提交
748
				/* detach static object */
qiuyiuestc's avatar
qiuyiuestc 已提交
749 750 751 752 753 754 755
				rt_mq_detach((rt_mq_t)object);
			}
			else
			{	
				/* delete dynamic object */
				rt_mq_delete((rt_mq_t)object);
			}	
qiuyiuestc's avatar
qiuyiuestc 已提交
756 757 758 759
		}
#endif

#ifdef RT_USING_MEMPOOL
qiuyiuestc's avatar
qiuyiuestc 已提交
760 761 762
		/* delete mempools */
		list = &module->module_object[RT_Object_Class_MemPool].object_list;	
		while(list->next != list)
qiuyiuestc's avatar
qiuyiuestc 已提交
763
		{
qiuyiuestc's avatar
qiuyiuestc 已提交
764 765 766
			object = rt_list_entry(list->next, struct rt_object, list);
			if (rt_object_is_systemobject(object) == RT_EOK)
			{
qiuyiuestc's avatar
qiuyiuestc 已提交
767
				/* detach static object */
qiuyiuestc's avatar
qiuyiuestc 已提交
768 769 770 771 772 773 774
				rt_mp_detach((rt_mp_t)object);
			}
			else
			{	
				/* delete dynamic object */
				rt_mp_delete((rt_mp_t)object);
			}	
qiuyiuestc's avatar
qiuyiuestc 已提交
775 776 777 778
		}
#endif

#ifdef RT_USING_DEVICE
qiuyiuestc's avatar
qiuyiuestc 已提交
779 780 781 782 783 784 785
		/* delete devices */
		list = &module->module_object[RT_Object_Class_Device].object_list;	
		while(list->next != list)
		{
			object = rt_list_entry(list->next, struct rt_object, list);
			rt_device_unregister((rt_device_t)object);
		}	
qiuyiuestc's avatar
qiuyiuestc 已提交
786 787
#endif

qiuyiuestc's avatar
qiuyiuestc 已提交
788 789 790
		/* delete timers */
		list = &module->module_object[RT_Object_Class_Timer].object_list;
		while(list->next != list)
qiuyiuestc's avatar
qiuyiuestc 已提交
791
		{
qiuyiuestc's avatar
qiuyiuestc 已提交
792 793 794
			object = rt_list_entry(list->next, struct rt_object, list);
			if (rt_object_is_systemobject(object) == RT_EOK)
			{
qiuyiuestc's avatar
qiuyiuestc 已提交
795
				/* detach static object */
qiuyiuestc's avatar
qiuyiuestc 已提交
796 797 798 799 800 801 802
				rt_timer_detach((rt_timer_t)object);
			}
			else
			{	
				/* delete dynamic object */
				rt_timer_delete((rt_timer_t)object);
			}	
qiuyiuestc's avatar
qiuyiuestc 已提交
803 804
		}		
	}
qiuyiuestc's avatar
qiuyiuestc 已提交
805

qiuyiuestc's avatar
qiuyiuestc 已提交
806 807 808 809 810 811
	if(module->page_cnt > 0)
	{
		int i;
		struct rt_page_info* page = (struct rt_page_info*)module->page_array;
		
		rt_kprintf("warning: some module memory still hasn't be freed\n");		
qiuyiuestc's avatar
qiuyiuestc 已提交
812

qiuyiuestc's avatar
qiuyiuestc 已提交
813
		//list_memlist("tetris");
qiuyiuestc's avatar
qiuyiuestc 已提交
814

qiuyiuestc's avatar
qiuyiuestc 已提交
815 816 817 818
		for(i=0; i<module->page_cnt; i++)
		{
			rt_module_free_page(page[i].page_ptr, page[i].npage);
		}
qiuyiuestc's avatar
qiuyiuestc 已提交
819
	}
qiuyiuestc's avatar
qiuyiuestc 已提交
820
	
qiuyiuestc's avatar
qiuyiuestc 已提交
821
	/* release module space memory */
qiuyiuestc's avatar
qiuyiuestc 已提交
822
	rt_free(module->module_space);
qiuyiuestc's avatar
qiuyiuestc 已提交
823

824
	/* release module symbol table */
qiuyiuestc's avatar
qiuyiuestc 已提交
825
	for(i=0; i<module->nsym; i++) rt_free((void *)module->symtab[i].name);
826
	if(module->symtab != RT_NULL) rt_free(module->symtab);
qiuyiuestc's avatar
qiuyiuestc 已提交
827

qiuyiuestc's avatar
qiuyiuestc 已提交
828 829 830 831 832 833 834 835 836
#ifdef RT_USING_HOOK
		if(rt_module_unload_hook != RT_NULL)
		{
			rt_module_unload_hook(module);
		}
#endif

	rt_free(module->page_array);

qiuyiuestc's avatar
qiuyiuestc 已提交
837
	/* delete module object */
qiuyiuestc's avatar
qiuyiuestc 已提交
838
	rt_object_delete((rt_object_t)module);
qiuyiuestc's avatar
qiuyiuestc 已提交
839 840

	return RT_EOK;
qiuyiuestc's avatar
qiuyiuestc 已提交
841 842
}

qiuyiuestc's avatar
qiuyiuestc 已提交
843 844 845 846 847 848 849
/**
 * This function will find the specified module.
 *
 * @param name the name of module finding
 *
 * @return the module
 */
qiuyiuestc's avatar
qiuyiuestc 已提交
850
rt_module_t rt_module_find(const char* name)
qiuyiuestc's avatar
qiuyiuestc 已提交
851
{
B
bernard.xiong 已提交
852 853 854
	struct rt_object_information *information;
	struct rt_object* object;
	struct rt_list_node* node;
qiuyiuestc's avatar
qiuyiuestc 已提交
855

B
bernard.xiong 已提交
856 857
	extern struct rt_object_information rt_object_container[];

858
	RT_DEBUG_NOT_IN_INTERRUPT;
859

B
bernard.xiong 已提交
860 861 862 863
	/* enter critical */
	rt_enter_critical();

	/* try to find device object */
qiuyiuestc's avatar
qiuyiuestc 已提交
864
	information = &rt_object_container[RT_Object_Class_Module];
B
bernard.xiong 已提交
865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881
	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 已提交
882 883
}

qiuyiuestc's avatar
qiuyiuestc 已提交
884 885 886 887 888 889 890 891 892
#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 已提交
893
{
qiuyiuestc's avatar
qiuyiuestc 已提交
894 895
	void* chunk;
	struct rt_page_info *page;
qiuyiuestc's avatar
qiuyiuestc 已提交
896

qiuyiuestc's avatar
qiuyiuestc 已提交
897 898
	chunk = rt_page_alloc(npages);
	if (chunk == RT_NULL) return RT_NULL;
899

qiuyiuestc's avatar
qiuyiuestc 已提交
900 901 902 903
	page = (struct rt_page_info*)rt_current_module->page_array;
	page[rt_current_module->page_cnt].page_ptr = chunk;
	page[rt_current_module->page_cnt].npage = npages;	
	rt_current_module->page_cnt++;	
qiuyiuestc's avatar
qiuyiuestc 已提交
904

qiuyiuestc's avatar
qiuyiuestc 已提交
905
	RT_ASSERT(rt_current_module->page_cnt <= PAGE_COUNT_MAX);
qiuyiuestc's avatar
qiuyiuestc 已提交
906
	
qiuyiuestc's avatar
qiuyiuestc 已提交
907 908
	return chunk;
}
qiuyiuestc's avatar
qiuyiuestc 已提交
909

qiuyiuestc's avatar
qiuyiuestc 已提交
910 911 912 913 914 915 916 917 918 919 920 921 922
/*
 * This function will release the previously allocated memory page 
 * by rt_malloc_page.
 *
 * @param page_ptr the page address to be released.
 * @param npages the number of page shall be released.
 * 
 * @note this function is used for RT-Thread Application Module
 */
static void rt_module_free_page(void *page_ptr, rt_size_t npages)
{
	int i, index;
	struct rt_page_info *page;
qiuyiuestc's avatar
qiuyiuestc 已提交
923

qiuyiuestc's avatar
qiuyiuestc 已提交
924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949
	//rt_kprintf("rt_module_free_page 0x%x %d\n", page_ptr, npages);
	rt_page_free(page_ptr, npages);

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

	for(i=0; i<rt_current_module->page_cnt; i++)
	{
		if(page[i].page_ptr == page_ptr)
		{
			if(page[i].npage == npages + 1)
			{
				page[i].page_ptr += npages * RT_MM_PAGE_SIZE / sizeof(rt_uint32_t);
			}
			else if(page[i].npage == npages)
			{				
				for(index=i; index<rt_current_module->page_cnt-1; index++)
				{
					page[index].page_ptr = page[index + 1].page_ptr;
					page[index].npage = page[index + 1].npage;
				}
				page[rt_current_module->page_cnt - 1].page_ptr = RT_NULL;
				page[rt_current_module->page_cnt - 1].npage = 0;
			}
			else RT_ASSERT(RT_FALSE);		
			
			rt_current_module->page_cnt--;	
qiuyiuestc's avatar
qiuyiuestc 已提交
950

qiuyiuestc's avatar
qiuyiuestc 已提交
951 952 953 954 955 956
			return;
		}
	}

	/* should not be get here */
	RT_ASSERT(RT_FALSE);
qiuyiuestc's avatar
qiuyiuestc 已提交
957
}
qiuyiuestc's avatar
qiuyiuestc 已提交
958 959

/*
B
bernard.xiong@gmail.com 已提交
960
  rt_module_malloc - allocate memory block in free list
qiuyiuestc's avatar
qiuyiuestc 已提交
961 962 963
*/
void *rt_module_malloc(rt_size_t size)
{
qiuyiuestc's avatar
qiuyiuestc 已提交
964
	struct rt_mem_head *b, *n, *up;
qiuyiuestc's avatar
qiuyiuestc 已提交
965
	struct rt_mem_head **prev;
qiuyiuestc's avatar
qiuyiuestc 已提交
966
	rt_uint32_t npage;	
qiuyiuestc's avatar
qiuyiuestc 已提交
967
	rt_size_t nunits;
968

969
	RT_DEBUG_NOT_IN_INTERRUPT;
970

qiuyiuestc's avatar
qiuyiuestc 已提交
971 972 973 974 975
	nunits = (size + sizeof(struct rt_mem_head) -1)/sizeof(struct rt_mem_head) + 1; 

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

qiuyiuestc's avatar
qiuyiuestc 已提交
976
	rt_sem_take(&mod_sem, RT_WAITING_FOREVER);
qiuyiuestc's avatar
qiuyiuestc 已提交
977

qiuyiuestc's avatar
qiuyiuestc 已提交
978
	for (prev = (struct rt_mem_head **)&rt_current_module->mem_list; (b = *prev) != RT_NULL; prev = &(b->next))	
qiuyiuestc's avatar
qiuyiuestc 已提交
979
	{
qiuyiuestc's avatar
qiuyiuestc 已提交
980 981
		if (b->size > nunits)
		{
B
bernard.xiong@gmail.com 已提交
982
			/* split memory */
qiuyiuestc's avatar
qiuyiuestc 已提交
983 984 985 986 987
			n = b + nunits;
			n->next = b->next;
			n->size = b->size - nunits;
			b->size = nunits;
			*prev = n;
qiuyiuestc's avatar
qiuyiuestc 已提交
988 989 990 991 992

			//rt_kprintf("rt_module_malloc 0x%x, %d\n",b + 1, size);
			rt_sem_release(&mod_sem);
			//list_memlist("tetris");
			return (void *)(b + 1);
qiuyiuestc's avatar
qiuyiuestc 已提交
993 994 995 996 997 998
		}

		if (b->size == nunits)
		{
			/* this node fit, remove this node */
			*prev = b->next;
qiuyiuestc's avatar
qiuyiuestc 已提交
999 1000 1001 1002 1003

			rt_kprintf("rt_module_malloc 0x%x, %d\n",b + 1, size);
			//list_memlist("tetris");			
			rt_sem_release(&mod_sem);
			return (void *)(b + 1);
qiuyiuestc's avatar
qiuyiuestc 已提交
1004
		}
qiuyiuestc's avatar
qiuyiuestc 已提交
1005
	}
qiuyiuestc's avatar
qiuyiuestc 已提交
1006

qiuyiuestc's avatar
qiuyiuestc 已提交
1007 1008 1009 1010 1011 1012
	/* allocate pages from system heap */
	npage = (size + sizeof(struct rt_mem_head) + RT_MM_PAGE_SIZE - 1)/RT_MM_PAGE_SIZE;
	if((up = (struct rt_mem_head*)rt_module_malloc_page(npage)) == RT_NULL) return RT_NULL;

	up->size = npage * RT_MM_PAGE_SIZE / sizeof(struct rt_mem_head);
	
qiuyiuestc's avatar
qiuyiuestc 已提交
1013
	for (prev = (struct rt_mem_head **)&rt_current_module->mem_list; (b = *prev) != RT_NULL; prev = &(b->next))	 
qiuyiuestc's avatar
qiuyiuestc 已提交
1014 1015
	{
		if (b > up + up->size) break;
qiuyiuestc's avatar
qiuyiuestc 已提交
1016 1017
	}

qiuyiuestc's avatar
qiuyiuestc 已提交
1018 1019 1020 1021 1022 1023
	up->next = b;
	*prev = up;

	rt_sem_release(&mod_sem);
		
	return rt_module_malloc(size);
qiuyiuestc's avatar
qiuyiuestc 已提交
1024 1025 1026
}

/*
qiuyiuestc's avatar
qiuyiuestc 已提交
1027
  rt_module_free - free memory block in free list
qiuyiuestc's avatar
qiuyiuestc 已提交
1028 1029 1030
*/
void rt_module_free(rt_module_t module, void *addr)
{
qiuyiuestc's avatar
qiuyiuestc 已提交
1031
	struct rt_mem_head *b, *n, *r;
qiuyiuestc's avatar
qiuyiuestc 已提交
1032
	struct rt_mem_head **prev;
1033

1034
	RT_DEBUG_NOT_IN_INTERRUPT;
1035

qiuyiuestc's avatar
qiuyiuestc 已提交
1036
	RT_ASSERT(addr);
qiuyiuestc's avatar
qiuyiuestc 已提交
1037 1038
	RT_ASSERT((((rt_uint32_t)addr) & (sizeof(struct rt_mem_head) -1)) == 0);

qiuyiuestc's avatar
qiuyiuestc 已提交
1039 1040 1041 1042
	//rt_kprintf("rt_module_free 0x%x\n", addr);
	
	rt_sem_take(&mod_sem, RT_WAITING_FOREVER);
	
qiuyiuestc's avatar
qiuyiuestc 已提交
1043
	n = (struct rt_mem_head *)addr - 1;
qiuyiuestc's avatar
qiuyiuestc 已提交
1044
	prev = (struct rt_mem_head **)&module->mem_list;
qiuyiuestc's avatar
qiuyiuestc 已提交
1045 1046 1047 1048 1049 1050

	while ((b = *prev) != RT_NULL)
	{		
		RT_ASSERT(b->size > 0);
		RT_ASSERT(b > n || b + b->size <= n);

qiuyiuestc's avatar
qiuyiuestc 已提交
1051
		if (b + b->size == n  && ((rt_uint32_t)n % RT_MM_PAGE_SIZE != 0))
qiuyiuestc's avatar
qiuyiuestc 已提交
1052
		{
qiuyiuestc's avatar
qiuyiuestc 已提交
1053
			if (b + (b->size + n->size) == b->next)
qiuyiuestc's avatar
qiuyiuestc 已提交
1054
			{
qiuyiuestc's avatar
qiuyiuestc 已提交
1055 1056
				b->size += b->next->size + n->size;
				b->next = b->next->next;
qiuyiuestc's avatar
qiuyiuestc 已提交
1057
			}
qiuyiuestc's avatar
qiuyiuestc 已提交
1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081
			else b->size += n->size;

			if((rt_uint32_t)b % RT_MM_PAGE_SIZE == 0)
			{
				int npage = b->size * sizeof(struct rt_page_info) / RT_MM_PAGE_SIZE;
				if(npage > 0)
				{
					if((b->size * sizeof(struct rt_page_info) % RT_MM_PAGE_SIZE) != 0)
					{
						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
					{
						*prev = b->next;	
					}
					
					rt_module_free_page(b, npage);
				}
			}	
qiuyiuestc's avatar
qiuyiuestc 已提交
1082

qiuyiuestc's avatar
qiuyiuestc 已提交
1083 1084 1085 1086
			/* unlock */
			rt_sem_release(&mod_sem);
			////list_memlist("tetris");
			
qiuyiuestc's avatar
qiuyiuestc 已提交
1087 1088 1089 1090 1091 1092 1093
			return;
		}

		if (b == n + n->size)
		{
			n->size = b->size + n->size;
			n->next = b->next;
qiuyiuestc's avatar
qiuyiuestc 已提交
1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121
			
			if((rt_uint32_t)n % RT_MM_PAGE_SIZE == 0)
			{
				int npage = n->size * sizeof(struct rt_page_info) / RT_MM_PAGE_SIZE;
				if(npage > 0)
				{
					if((n->size * sizeof(struct rt_page_info) % RT_MM_PAGE_SIZE) != 0)
					{
						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;
					}
					else *prev = n->next;	
					
					rt_module_free_page(n, npage);
				}
			}	
			else
			{
				*prev = n;
			}

			/* unlock */
			rt_sem_release(&mod_sem);
			//list_memlist("tetris");
qiuyiuestc's avatar
qiuyiuestc 已提交
1122 1123 1124 1125 1126 1127 1128 1129

			return;
		}
		if (b > n + n->size) break;

		prev = &(b->next);
	}

qiuyiuestc's avatar
qiuyiuestc 已提交
1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155
	if((rt_uint32_t)n % RT_MM_PAGE_SIZE == 0)
	{
		int npage = n->size * sizeof(struct rt_page_info) / RT_MM_PAGE_SIZE;
		if(npage > 0)
		{
			rt_module_free_page(n, npage);
			if(n->size % RT_MM_PAGE_SIZE != 0)
			{
				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
			{
				*prev = b;	
			}	
		}	
	}
	else 
	{	
		n->next = b;
		*prev = n;
	}
qiuyiuestc's avatar
qiuyiuestc 已提交
1156

qiuyiuestc's avatar
qiuyiuestc 已提交
1157 1158 1159
	/* unlock */
	rt_sem_release(&mod_sem);	
	//list_memlist("tetris");
qiuyiuestc's avatar
qiuyiuestc 已提交
1160 1161 1162 1163 1164 1165 1166
}

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

1170
	RT_DEBUG_NOT_IN_INTERRUPT;
1171

qiuyiuestc's avatar
qiuyiuestc 已提交
1172
	if (!ptr) return rt_module_malloc(size);
qiuyiuestc's avatar
qiuyiuestc 已提交
1173 1174 1175 1176 1177
	if (size == 0)
	{
		rt_module_free(rt_current_module, ptr);
		return RT_NULL;
	}
qiuyiuestc's avatar
qiuyiuestc 已提交
1178

qiuyiuestc's avatar
qiuyiuestc 已提交
1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197
	nunits = (size + sizeof(struct rt_mem_head) - 1) / sizeof(struct rt_mem_head) + 1;
	b = (struct rt_mem_head *)ptr - 1;

	if (nunits <= b->size) 
	{   
		/* new size is smaller or equal then before */    
		if (nunits == b->size) return ptr;
		else 
		{
			p = b + nunits;
			p->size = b->size - nunits;
			b->size = nunits;
			rt_module_free(rt_current_module, (void *)(p + 1));
			return (void *)(b + 1);
		}
	}
	else 
	{      
		/* more space then required */
qiuyiuestc's avatar
qiuyiuestc 已提交
1198
		prev = (struct rt_mem_head *)rt_current_module->mem_list;
qiuyiuestc's avatar
qiuyiuestc 已提交
1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223
		for (p = prev->next; p != (b->size + b) && p != RT_NULL; prev = p, p = p->next) break;

		/* 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 */
				tmpp = p;  
				p = b + nunits;

				/* restoring old pointer */
				p->next = tmpp->next;
				
				/* new size for p */
				p->size = tmpp->size + b->size - nunits; 
				b->size = nunits;
				prev->next = p;
			}
qiuyiuestc's avatar
qiuyiuestc 已提交
1224
			rt_current_module->mem_list = (void *)prev;
qiuyiuestc's avatar
qiuyiuestc 已提交
1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235
			return (void *) (b + 1);
		}
		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));
			return (void *) (p);
		}
	}
}
qiuyiuestc's avatar
qiuyiuestc 已提交
1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246
#endif

#ifdef RT_USING_FINSH
#include <finsh.h>
void list_memlist(const char* name)
{
	rt_module_t module;
	struct rt_mem_head **prev;
	struct rt_mem_head *b;
		
	module = rt_module_find(name);
qiuyiuestc's avatar
qiuyiuestc 已提交
1247
	if(module == RT_NULL) return;
qiuyiuestc's avatar
qiuyiuestc 已提交
1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262

	for (prev = (struct rt_mem_head **)&module->mem_list; (b = *prev) != RT_NULL; prev = &(b->next))	
	{
		rt_kprintf("0x%x--%d\n", b, b->size * sizeof(struct rt_mem_head));
	}
}
FINSH_FUNCTION_EXPORT(list_memlist, list module free memory information)

void list_mempage(const char* name)
{
	rt_module_t module;
	struct rt_page_info *page;
	int i;

	module = rt_module_find(name);
qiuyiuestc's avatar
qiuyiuestc 已提交
1263
	if(module == RT_NULL) return;
qiuyiuestc's avatar
qiuyiuestc 已提交
1264 1265 1266 1267 1268 1269 1270 1271 1272 1273

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

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

qiuyiuestc's avatar
qiuyiuestc 已提交
1275
#endif