module.c 38.7 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 - 2011, 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 97
 *
 */
void rt_system_module_init(void)
{
qiuyiuestc's avatar
qiuyiuestc 已提交
98
#ifdef __GNUC__
99 100
	extern int __rtmsymtab_start;
	extern int __rtmsymtab_end;
qiuyiuestc's avatar
qiuyiuestc 已提交
101
	
102 103
	_rt_module_symtab_begin = (struct rt_module_symtab *)&__rtmsymtab_start;
	_rt_module_symtab_end   = (struct rt_module_symtab *)&__rtmsymtab_end;
D
dzzxzz 已提交
104
#elif defined (__CC_ARM)
qiuyiuestc's avatar
qiuyiuestc 已提交
105 106
	extern int RTMSymTab$$Base;
	extern int RTMSymTab$$Limit;
D
dzzxzz 已提交
107

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

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

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

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

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

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

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

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

	return RT_EOK;
}

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

D
dzzxzz 已提交
165
	where = (Elf32_Addr *)((rt_uint8_t *)module->module_space + rel->r_offset);
qiuyiuestc's avatar
qiuyiuestc 已提交
166 167 168 169 170 171
	switch (ELF32_R_TYPE(rel->r_info))
	{
	case R_ARM_NONE:
		break;
	case R_ARM_ABS32:
		*where += (Elf32_Addr)sym_val;
D
dzzxzz 已提交
172
		RT_DEBUG_LOG(RT_DEBUG_MODULE, ("R_ARM_ABS32: %x -> %x\n", where, *where));
qiuyiuestc's avatar
qiuyiuestc 已提交
173 174 175 176 177 178 179 180 181 182 183
		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 已提交
184
		RT_DEBUG_LOG(RT_DEBUG_MODULE, ("R_ARM_PC24: %x -> %x\n", where, *where));
qiuyiuestc's avatar
qiuyiuestc 已提交
185
		break;
186 187 188 189
	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 已提交
190 191 192 193
	case R_ARM_V4BX:
		*where &= 0xf000000f;
		*where |= 0x01a0f000;
		break;
qiuyiuestc's avatar
qiuyiuestc 已提交
194 195
	case R_ARM_GLOB_DAT:
	case R_ARM_JUMP_SLOT:
qiuyiuestc's avatar
qiuyiuestc 已提交
196
		*where = (Elf32_Addr)sym_val;
197 198
		RT_DEBUG_LOG(RT_DEBUG_MODULE,
			("R_ARM_JUMP_SLOT: 0x%x -> 0x%x 0x%x\n", where, *where, sym_val));
199 200 201 202 203 204 205 206
		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 已提交
207
#endif
qiuyiuestc's avatar
qiuyiuestc 已提交
208 209
	case R_ARM_RELATIVE:
		*where += (Elf32_Addr)sym_val;
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
		//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 已提交
228

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

236 237 238 239 240 241 242 243 244 245
		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 已提交
246
		break;
qiuyiuestc's avatar
qiuyiuestc 已提交
247 248 249 250 251 252 253
	default:
		return -1;
	}

	return 0;
}

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

B
bernard.xiong@gmail.com 已提交
258
	/* initialize object container - thread */
qiuyiuestc's avatar
qiuyiuestc 已提交
259 260 261 262 263
	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 已提交
264
	/* initialize object container - semaphore */
qiuyiuestc's avatar
qiuyiuestc 已提交
265 266 267 268 269 270
	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 已提交
271
	/* initialize object container - mutex */
qiuyiuestc's avatar
qiuyiuestc 已提交
272 273 274 275 276 277
	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 已提交
278
	/* initialize object container - event */
qiuyiuestc's avatar
qiuyiuestc 已提交
279 280 281 282 283 284
	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 已提交
285
	/* initialize object container - mailbox */
qiuyiuestc's avatar
qiuyiuestc 已提交
286 287 288 289 290 291
	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 已提交
292
	/* initialize object container - message queue */
qiuyiuestc's avatar
qiuyiuestc 已提交
293 294 295 296 297 298
	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 已提交
299
	/* initialize object container - memory pool */
qiuyiuestc's avatar
qiuyiuestc 已提交
300 301 302 303 304 305
	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 已提交
306
	/* initialize object container - device */
qiuyiuestc's avatar
qiuyiuestc 已提交
307 308 309 310 311
	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 已提交
312
	/* initialize object container - timer */
qiuyiuestc's avatar
qiuyiuestc 已提交
313 314 315 316 317
	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 已提交
318 319 320 321 322 323 324 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
#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

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 377 378
	{
		rt_kprintf(" module size error\n");
		return module;
	}	
qiuyiuestc's avatar
qiuyiuestc 已提交
379 380

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

	/* 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 已提交
396 397
	rt_kprintf(" load address at 0x%x\n", ptr);

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

	/* set module entry */
qiuyiuestc's avatar
qiuyiuestc 已提交
408
	module->module_entry = module->module_space + elf_module->e_entry;
qiuyiuestc's avatar
qiuyiuestc 已提交
409
	
qiuyiuestc's avatar
qiuyiuestc 已提交
410 411 412 413 414 415 416 417
	/* 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;
418 419
			rt_uint8_t *strtab;
			static rt_bool_t unsolved = RT_FALSE;
qiuyiuestc's avatar
qiuyiuestc 已提交
420 421

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

424
			/* locate .rel.plt and .rel.dyn section */
425 426 427
			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 已提交
428 429 430 431 432

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

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

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

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

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

D
dzzxzz 已提交
458
			if (unsolved)
459 460 461 462 463
			{
				rt_object_delete(&(module->parent));
				rt_free(module);
				return RT_NULL;
			}	
qiuyiuestc's avatar
qiuyiuestc 已提交
464 465 466
		}
	}

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

480 481 482 483
	/* construct module symbol table */
	for (index = 0; index < elf_module->e_shnum; index ++)
	{	
		/* find .dynsym section */
D
dzzxzz 已提交
484
		rt_uint8_t *shstrab = (rt_uint8_t *)module_ptr + shdr[elf_module->e_shstrndx].sh_offset;
qiuyiuestc's avatar
qiuyiuestc 已提交
485
		if (rt_strcmp((const char *)(shstrab + shdr[index].sh_name), ELF_DYNSYM) == 0) break;
486 487
	}

qiuyiuestc's avatar
qiuyiuestc 已提交
488
	/* found .dynsym section */
D
dzzxzz 已提交
489
	if (index != elf_module->e_shnum)
490 491 492
	{
		int i, count = 0;
		Elf32_Sym *symtab = RT_NULL;
D
dzzxzz 已提交
493
		rt_uint8_t *strtab = RT_NULL;
494

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

D
dzzxzz 已提交
498
		for (i=0; i<shdr[index].sh_size/sizeof(Elf32_Sym); i++)
499
		{
D
dzzxzz 已提交
500 501
			if ((ELF_ST_BIND(symtab[i].st_info) == STB_GLOBAL) && (ELF_ST_TYPE(symtab[i].st_info) == STT_FUNC))
				count ++;
502 503
		}

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

D
dzzxzz 已提交
512
				module->symtab[count].addr = (void *)(module->module_space + symtab[i].st_value);
513
				module->symtab[count].name = rt_malloc(length);
D
dzzxzz 已提交
514 515 516
				rt_memset((void *)module->symtab[count].name, 0, length);
				rt_memcpy((void *)module->symtab[count].name, strtab + symtab[i].st_name, length);
				count ++;
517 518
			}	
		}	
519
	}
B
bernard.xiong@gmail.com 已提交
520

521 522 523
	return module;
}

B
bernard.xiong@gmail.com 已提交
524
static struct rt_module* _load_relocated_object(const char* name, void* module_ptr)
525 526 527 528 529 530
{
	rt_uint32_t index, rodata_addr = 0, bss_addr = 0, data_addr = 0;
	rt_uint32_t module_addr = 0, module_size = 0;
	struct rt_module* module = RT_NULL;
	rt_uint8_t *ptr, *strtab, *shstrab;
	rt_bool_t linked = RT_FALSE;
B
bernard.xiong@gmail.com 已提交
531

532 533 534 535 536
	if(rt_memcmp(elf_module->e_ident, RTMMAG, SELFMAG) == 0)
	{
		/* rtmlinker finished */
		linked = RT_TRUE;
	}
B
bernard.xiong@gmail.com 已提交
537

538 539 540 541 542 543 544 545 546 547 548 549 550
	/* 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 已提交
551
		}
552 553 554 555 556 557 558 559 560
		/* 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 已提交
561
		}
562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592
	}

	/* no text, data and bss on image */
	if (module_size == 0) return RT_NULL;

	/* allocate module */
	module = (struct rt_module *)rt_object_allocate(RT_Object_Class_Module, (const char*)name);
	if (module == RT_NULL) return RT_NULL;

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

	/* 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 已提交
593

594 595 596 597 598 599 600 601
		/* 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 已提交
602

603 604 605
		/* load data section */
		if (IS_PROG(shdr[index]) && IS_AW(shdr[index]))
		{
B
bernard.xiong@gmail.com 已提交
606
			rt_memcpy(ptr, (rt_uint8_t*)elf_module + shdr[index].sh_offset, shdr[index].sh_size);
607 608 609 610 611 612 613 614 615 616
			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 已提交
617
			RT_DEBUG_LOG(RT_DEBUG_MODULE,("load bss 0x%x, size %d,\n", ptr, shdr[index].sh_size));
618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646
		}
	}

	/* 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 已提交
647

648
				if (sym->st_shndx != STN_UNDEF)
B
bernard.xiong@gmail.com 已提交
649 650
				{
					if((ELF_ST_TYPE(sym->st_info) == STT_SECTION)
651
						|| (ELF_ST_TYPE(sym->st_info) == STT_OBJECT))
B
bernard.xiong@gmail.com 已提交
652
					{
653 654 655 656 657 658 659 660
						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 已提交
661
							/* relocate bss section */
662 663 664 665 666
							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 已提交
667
							/* relocate data section */
668 669
							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 已提交
670 671 672
						}
					}
				}
673
				else if(ELF_ST_TYPE(sym->st_info) == STT_FUNC )
B
bernard.xiong@gmail.com 已提交
674
				{
675 676
					/* relocate function */
					rt_module_arm_relocate(module, rel,
B
bernard.xiong@gmail.com 已提交
677
						(Elf32_Addr)((rt_uint8_t*)module->module_space - module_addr + sym->st_value));
678 679 680 681 682 683
				}
				else
				{
					Elf32_Addr addr;

					if(ELF32_R_TYPE(rel->r_info) != R_ARM_V4BX)
B
bernard.xiong@gmail.com 已提交
684
					{
685 686 687 688 689 690 691
						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 已提交
692
						}
693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719
						else rt_kprintf("can't find %s in kernel symbol table\n", strtab + sym->st_name);
					}
					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
 *
 */
rt_module_t rt_module_load(const char* name, void* module_ptr)
{
	rt_module_t module;
B
bernard.xiong@gmail.com 已提交
720

721 722 723 724 725 726 727 728 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");
		return RT_NULL;
	}

	/* check ELF class */
	if(elf_module->e_ident[EI_CLASS] != ELFCLASS32)
	{
		rt_kprintf(" module class error\n");
		return RT_NULL;
	}
B
bernard.xiong@gmail.com 已提交
739

740 741 742 743 744 745 746 747 748 749 750 751 752 753
	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");
		return RT_NULL;
	}

B
bernard.xiong@gmail.com 已提交
754 755
	if(module == RT_NULL) return RT_NULL;

qiuyiuestc's avatar
qiuyiuestc 已提交
756 757
	/* init module object container */
	rt_module_init_object_container(module);
qiuyiuestc's avatar
qiuyiuestc 已提交
758
		
D
dzzxzz 已提交
759 760
	/* increase module reference count */
	module->nref ++;
qiuyiuestc's avatar
qiuyiuestc 已提交
761

D
dzzxzz 已提交
762
	if (elf_module->e_entry != 0)
qiuyiuestc's avatar
qiuyiuestc 已提交
763 764
	{	
		/* init module memory allocator */
qiuyiuestc's avatar
qiuyiuestc 已提交
765
		module->mem_list = RT_NULL;
qiuyiuestc's avatar
qiuyiuestc 已提交
766

767
#ifdef RT_USING_SLAB
qiuyiuestc's avatar
qiuyiuestc 已提交
768 769 770
		/* create page array */
		module->page_array = (void *)rt_malloc(PAGE_COUNT_MAX * sizeof(struct rt_page_info));
		module->page_cnt = 0;
771 772
#endif

qiuyiuestc's avatar
qiuyiuestc 已提交
773
		/* create module thread */
qiuyiuestc's avatar
qiuyiuestc 已提交
774
		module->stack_size = 2048;
qiuyiuestc's avatar
qiuyiuestc 已提交
775
		module->thread_priority = 25;
qiuyiuestc's avatar
qiuyiuestc 已提交
776 777 778 779 780 781
		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 已提交
782
		module->parent.flag = RT_MODULE_FLAG_WITHENTRY;
B
bernard.xiong@gmail.com 已提交
783

qiuyiuestc's avatar
qiuyiuestc 已提交
784 785 786 787 788 789 790 791 792
		/* startup module thread */
		rt_thread_startup(module->module_thread);
	}	
	else
	{
		/* without entry point */
		module->parent.flag |= RT_MODULE_FLAG_WITHOUTENTRY;
	}	

qiuyiuestc's avatar
qiuyiuestc 已提交
793
#ifdef RT_USING_HOOK
D
dzzxzz 已提交
794
	if (rt_module_load_hook != RT_NULL)
qiuyiuestc's avatar
qiuyiuestc 已提交
795 796 797 798 799
	{
		rt_module_load_hook(module);
	}
#endif

qiuyiuestc's avatar
qiuyiuestc 已提交
800
	return module;
qiuyiuestc's avatar
qiuyiuestc 已提交
801 802
}	

qiuyiuestc's avatar
qiuyiuestc 已提交
803 804 805
#ifdef RT_USING_DFS
#include <dfs_posix.h>
/**
B
bernard.xiong@gmail.com 已提交
806
 * This function will load a module from a file
qiuyiuestc's avatar
qiuyiuestc 已提交
807
 *
B
bernard.xiong@gmail.com 已提交
808
 * @param path the full path of application module
qiuyiuestc's avatar
qiuyiuestc 已提交
809 810 811 812
 *
 * @return the module object
 *
 */
D
dzzxzz 已提交
813
rt_module_t rt_module_open(const char *path)
qiuyiuestc's avatar
qiuyiuestc 已提交
814 815
{
	int fd, length;
D
dzzxzz 已提交
816
	struct rt_module *module;
B
bernard.xiong@gmail.com 已提交
817
	struct stat s;
qiuyiuestc's avatar
qiuyiuestc 已提交
818
	char *buffer, *offset_ptr;
qiuyiuestc's avatar
qiuyiuestc 已提交
819

820
	RT_DEBUG_NOT_IN_INTERRUPT;
821

qiuyiuestc's avatar
qiuyiuestc 已提交
822
	/* check parameters */
qiuyiuestc's avatar
qiuyiuestc 已提交
823
	RT_ASSERT(path != RT_NULL);
qiuyiuestc's avatar
qiuyiuestc 已提交
824

qiuyiuestc's avatar
qiuyiuestc 已提交
825
	if (stat(path, &s) !=0)
826
	{
qiuyiuestc's avatar
qiuyiuestc 已提交
827
		rt_kprintf("access %s failed\n", path);
828 829
		return RT_NULL;
	}
qiuyiuestc's avatar
qiuyiuestc 已提交
830
	buffer = (char *)rt_malloc(s.st_size);
831 832 833 834 835 836 837
	if (buffer == RT_NULL)
	{
		rt_kprintf("out of memory\n");
		return RT_NULL;
	}

	offset_ptr = buffer;
qiuyiuestc's avatar
qiuyiuestc 已提交
838
	fd = open(path, O_RDONLY, 0);
839 840
	if (fd < 0)
	{
qiuyiuestc's avatar
qiuyiuestc 已提交
841
		rt_kprintf("open %s failed\n", path);
842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858
		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 已提交
859 860 861 862 863
	{
		rt_kprintf("check: read file failed\n");
		rt_free(buffer);
		return RT_NULL;
	}
qiuyiuestc's avatar
qiuyiuestc 已提交
864

qiuyiuestc's avatar
qiuyiuestc 已提交
865
	module = rt_module_load(path, (void *)buffer);
qiuyiuestc's avatar
qiuyiuestc 已提交
866 867 868 869
	rt_free(buffer);

	return module;
}
qiuyiuestc's avatar
qiuyiuestc 已提交
870 871 872

#if defined(RT_USING_FINSH)
#include <finsh.h>
873
FINSH_FUNCTION_EXPORT_ALIAS(rt_module_open, exec, exec module from file);
qiuyiuestc's avatar
qiuyiuestc 已提交
874
#endif
qiuyiuestc's avatar
qiuyiuestc 已提交
875 876
#endif

qiuyiuestc's avatar
qiuyiuestc 已提交
877
/**
D
dzzxzz 已提交
878
 * This function will unload a module from memory and release resources
qiuyiuestc's avatar
qiuyiuestc 已提交
879 880 881 882 883 884 885
 *
 * @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 已提交
886
{
887
	int i;
D
dzzxzz 已提交
888
	struct rt_object *object;
qiuyiuestc's avatar
qiuyiuestc 已提交
889
	struct rt_list_node *list;
qiuyiuestc's avatar
qiuyiuestc 已提交
890

891
	RT_DEBUG_NOT_IN_INTERRUPT;
892

qiuyiuestc's avatar
qiuyiuestc 已提交
893 894 895
	/* check parameter */
	RT_ASSERT(module != RT_NULL);

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

qiuyiuestc's avatar
qiuyiuestc 已提交
898
	/* module has entry point */
D
dzzxzz 已提交
899 900
	if ((module->parent.flag & RT_MODULE_FLAG_WITHOUTENTRY) != RT_MODULE_FLAG_WITHOUTENTRY)
	{
qiuyiuestc's avatar
qiuyiuestc 已提交
901
		/* suspend module main thread */
D
dzzxzz 已提交
902 903
		if (module->module_thread != RT_NULL)
		{
qiuyiuestc's avatar
qiuyiuestc 已提交
904 905 906 907 908
			if (module->module_thread->stat == RT_THREAD_READY)
				rt_thread_suspend(module->module_thread);
		}
		
		/* delete threads */
D
dzzxzz 已提交
909 910
		list = &module->module_object[RT_Object_Class_Thread].object_list;
		while (list->next != list)
qiuyiuestc's avatar
qiuyiuestc 已提交
911
		{
qiuyiuestc's avatar
qiuyiuestc 已提交
912 913 914
			object = rt_list_entry(list->next, struct rt_object, list);
			if (rt_object_is_systemobject(object) == RT_EOK)
			{
qiuyiuestc's avatar
qiuyiuestc 已提交
915
				/* detach static object */
qiuyiuestc's avatar
qiuyiuestc 已提交
916 917 918
				rt_thread_detach((rt_thread_t)object);
			}
			else
D
dzzxzz 已提交
919
			{
qiuyiuestc's avatar
qiuyiuestc 已提交
920 921
				/* delete dynamic object */
				rt_thread_delete((rt_thread_t)object);
D
dzzxzz 已提交
922
			}
qiuyiuestc's avatar
qiuyiuestc 已提交
923
		}
qiuyiuestc's avatar
qiuyiuestc 已提交
924
		
qiuyiuestc's avatar
qiuyiuestc 已提交
925
#ifdef RT_USING_SEMAPHORE
qiuyiuestc's avatar
qiuyiuestc 已提交
926 927
		/* delete semaphores */
		list = &module->module_object[RT_Object_Class_Thread].object_list;	
D
dzzxzz 已提交
928
		while (list->next != list)
qiuyiuestc's avatar
qiuyiuestc 已提交
929
		{
qiuyiuestc's avatar
qiuyiuestc 已提交
930 931 932
			object = rt_list_entry(list->next, struct rt_object, list);
			if (rt_object_is_systemobject(object) == RT_EOK)
			{
qiuyiuestc's avatar
qiuyiuestc 已提交
933
				/* detach static object */
qiuyiuestc's avatar
qiuyiuestc 已提交
934 935 936
				rt_sem_detach((rt_sem_t)object);
			}
			else
D
dzzxzz 已提交
937
			{
qiuyiuestc's avatar
qiuyiuestc 已提交
938 939
				/* delete dynamic object */
				rt_sem_delete((rt_sem_t)object);
D
dzzxzz 已提交
940
			}
qiuyiuestc's avatar
qiuyiuestc 已提交
941 942 943 944
		}
#endif

#ifdef RT_USING_MUTEX
qiuyiuestc's avatar
qiuyiuestc 已提交
945 946
		/* delete mutexs*/
		list = &module->module_object[RT_Object_Class_Mutex].object_list;	
D
dzzxzz 已提交
947
		while (list->next != list)
qiuyiuestc's avatar
qiuyiuestc 已提交
948
		{
qiuyiuestc's avatar
qiuyiuestc 已提交
949 950 951
			object = rt_list_entry(list->next, struct rt_object, list);
			if (rt_object_is_systemobject(object) == RT_EOK)
			{
qiuyiuestc's avatar
qiuyiuestc 已提交
952
				/* detach static object */
qiuyiuestc's avatar
qiuyiuestc 已提交
953 954 955
				rt_mutex_detach((rt_mutex_t)object);
			}
			else
D
dzzxzz 已提交
956
			{
qiuyiuestc's avatar
qiuyiuestc 已提交
957 958
				/* delete dynamic object */
				rt_mutex_delete((rt_mutex_t)object);
D
dzzxzz 已提交
959
			}
qiuyiuestc's avatar
qiuyiuestc 已提交
960 961 962 963
		}
#endif

#ifdef RT_USING_EVENT
qiuyiuestc's avatar
qiuyiuestc 已提交
964 965
		/* delete mailboxs */
		list = &module->module_object[RT_Object_Class_Event].object_list;	
D
dzzxzz 已提交
966
		while (list->next != list)
qiuyiuestc's avatar
qiuyiuestc 已提交
967
		{
qiuyiuestc's avatar
qiuyiuestc 已提交
968 969 970
			object = rt_list_entry(list->next, struct rt_object, list);
			if (rt_object_is_systemobject(object) == RT_EOK)
			{
qiuyiuestc's avatar
qiuyiuestc 已提交
971
				/* detach static object */
qiuyiuestc's avatar
qiuyiuestc 已提交
972 973 974
				rt_event_detach((rt_event_t)object);
			}
			else
D
dzzxzz 已提交
975
			{
qiuyiuestc's avatar
qiuyiuestc 已提交
976 977
				/* delete dynamic object */
				rt_event_delete((rt_event_t)object);
D
dzzxzz 已提交
978
			}
qiuyiuestc's avatar
qiuyiuestc 已提交
979
		}
qiuyiuestc's avatar
qiuyiuestc 已提交
980 981 982
#endif

#ifdef RT_USING_MAILBOX
qiuyiuestc's avatar
qiuyiuestc 已提交
983 984
		/* delete mailboxs */
		list = &module->module_object[RT_Object_Class_MailBox].object_list;	
D
dzzxzz 已提交
985
		while (list->next != list)
qiuyiuestc's avatar
qiuyiuestc 已提交
986
		{
qiuyiuestc's avatar
qiuyiuestc 已提交
987 988 989
			object = rt_list_entry(list->next, struct rt_object, list);
			if (rt_object_is_systemobject(object) == RT_EOK)
			{
qiuyiuestc's avatar
qiuyiuestc 已提交
990
				/* detach static object */
qiuyiuestc's avatar
qiuyiuestc 已提交
991 992 993
				rt_mb_detach((rt_mailbox_t)object);
			}
			else
D
dzzxzz 已提交
994
			{
qiuyiuestc's avatar
qiuyiuestc 已提交
995 996
				/* delete dynamic object */
				rt_mb_delete((rt_mailbox_t)object);
D
dzzxzz 已提交
997
			}
qiuyiuestc's avatar
qiuyiuestc 已提交
998 999 1000 1001
		}
#endif

#ifdef RT_USING_MESSAGEQUEUE
qiuyiuestc's avatar
qiuyiuestc 已提交
1002
		/* delete msgqueues */
D
dzzxzz 已提交
1003 1004
		list = &module->module_object[RT_Object_Class_MessageQueue].object_list;
		while (list->next != list)
qiuyiuestc's avatar
qiuyiuestc 已提交
1005
		{
qiuyiuestc's avatar
qiuyiuestc 已提交
1006 1007 1008
			object = rt_list_entry(list->next, struct rt_object, list);
			if (rt_object_is_systemobject(object) == RT_EOK)
			{
qiuyiuestc's avatar
qiuyiuestc 已提交
1009
				/* detach static object */
qiuyiuestc's avatar
qiuyiuestc 已提交
1010 1011 1012
				rt_mq_detach((rt_mq_t)object);
			}
			else
D
dzzxzz 已提交
1013
			{
qiuyiuestc's avatar
qiuyiuestc 已提交
1014 1015
				/* delete dynamic object */
				rt_mq_delete((rt_mq_t)object);
D
dzzxzz 已提交
1016
			}
qiuyiuestc's avatar
qiuyiuestc 已提交
1017 1018 1019 1020
		}
#endif

#ifdef RT_USING_MEMPOOL
qiuyiuestc's avatar
qiuyiuestc 已提交
1021 1022
		/* delete mempools */
		list = &module->module_object[RT_Object_Class_MemPool].object_list;	
D
dzzxzz 已提交
1023
		while (list->next != list)
qiuyiuestc's avatar
qiuyiuestc 已提交
1024
		{
qiuyiuestc's avatar
qiuyiuestc 已提交
1025 1026 1027
			object = rt_list_entry(list->next, struct rt_object, list);
			if (rt_object_is_systemobject(object) == RT_EOK)
			{
qiuyiuestc's avatar
qiuyiuestc 已提交
1028
				/* detach static object */
qiuyiuestc's avatar
qiuyiuestc 已提交
1029 1030 1031
				rt_mp_detach((rt_mp_t)object);
			}
			else
D
dzzxzz 已提交
1032
			{
qiuyiuestc's avatar
qiuyiuestc 已提交
1033 1034
				/* delete dynamic object */
				rt_mp_delete((rt_mp_t)object);
D
dzzxzz 已提交
1035
			}
qiuyiuestc's avatar
qiuyiuestc 已提交
1036 1037 1038 1039
		}
#endif

#ifdef RT_USING_DEVICE
qiuyiuestc's avatar
qiuyiuestc 已提交
1040 1041
		/* delete devices */
		list = &module->module_object[RT_Object_Class_Device].object_list;	
D
dzzxzz 已提交
1042
		while (list->next != list)
qiuyiuestc's avatar
qiuyiuestc 已提交
1043 1044 1045
		{
			object = rt_list_entry(list->next, struct rt_object, list);
			rt_device_unregister((rt_device_t)object);
D
dzzxzz 已提交
1046
		}
qiuyiuestc's avatar
qiuyiuestc 已提交
1047 1048
#endif

qiuyiuestc's avatar
qiuyiuestc 已提交
1049 1050
		/* delete timers */
		list = &module->module_object[RT_Object_Class_Timer].object_list;
D
dzzxzz 已提交
1051
		while (list->next != list)
qiuyiuestc's avatar
qiuyiuestc 已提交
1052
		{
qiuyiuestc's avatar
qiuyiuestc 已提交
1053 1054 1055
			object = rt_list_entry(list->next, struct rt_object, list);
			if (rt_object_is_systemobject(object) == RT_EOK)
			{
qiuyiuestc's avatar
qiuyiuestc 已提交
1056
				/* detach static object */
qiuyiuestc's avatar
qiuyiuestc 已提交
1057 1058 1059
				rt_timer_detach((rt_timer_t)object);
			}
			else
D
dzzxzz 已提交
1060
			{
qiuyiuestc's avatar
qiuyiuestc 已提交
1061 1062
				/* delete dynamic object */
				rt_timer_delete((rt_timer_t)object);
D
dzzxzz 已提交
1063 1064
			}
		}
qiuyiuestc's avatar
qiuyiuestc 已提交
1065
	}
qiuyiuestc's avatar
qiuyiuestc 已提交
1066

1067 1068
#ifdef RT_USING_SLAB
	if(module->page_cnt > 0)
qiuyiuestc's avatar
qiuyiuestc 已提交
1069
	{
D
dzzxzz 已提交
1070
		struct rt_page_info *page = (struct rt_page_info *)module->page_array;
B
bernard.xiong@gmail.com 已提交
1071 1072

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

1074
		while(module->page_cnt != 0)
qiuyiuestc's avatar
qiuyiuestc 已提交
1075
		{
1076
			rt_module_free_page(module, page[0].page_ptr, page[0].npage);
B
bernard.xiong@gmail.com 已提交
1077
		}
qiuyiuestc's avatar
qiuyiuestc 已提交
1078
	}
1079
#endif
D
dzzxzz 已提交
1080

qiuyiuestc's avatar
qiuyiuestc 已提交
1081
	/* release module space memory */
qiuyiuestc's avatar
qiuyiuestc 已提交
1082
	rt_free(module->module_space);
qiuyiuestc's avatar
qiuyiuestc 已提交
1083

1084
	/* release module symbol table */
D
dzzxzz 已提交
1085 1086
	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 已提交
1087

qiuyiuestc's avatar
qiuyiuestc 已提交
1088
#ifdef RT_USING_HOOK
D
dzzxzz 已提交
1089 1090 1091 1092
	if (rt_module_unload_hook != RT_NULL)
	{
		rt_module_unload_hook(module);
	}
qiuyiuestc's avatar
qiuyiuestc 已提交
1093 1094 1095 1096
#endif

	rt_free(module->page_array);

qiuyiuestc's avatar
qiuyiuestc 已提交
1097
	/* delete module object */
qiuyiuestc's avatar
qiuyiuestc 已提交
1098
	rt_object_delete((rt_object_t)module);
qiuyiuestc's avatar
qiuyiuestc 已提交
1099 1100

	return RT_EOK;
qiuyiuestc's avatar
qiuyiuestc 已提交
1101 1102
}

qiuyiuestc's avatar
qiuyiuestc 已提交
1103 1104 1105 1106 1107 1108 1109
/**
 * This function will find the specified module.
 *
 * @param name the name of module finding
 *
 * @return the module
 */
D
dzzxzz 已提交
1110
rt_module_t rt_module_find(const char *name)
qiuyiuestc's avatar
qiuyiuestc 已提交
1111
{
B
bernard.xiong 已提交
1112
	struct rt_object_information *information;
D
dzzxzz 已提交
1113 1114
	struct rt_object *object;
	struct rt_list_node *node;
qiuyiuestc's avatar
qiuyiuestc 已提交
1115

B
bernard.xiong 已提交
1116 1117
	extern struct rt_object_information rt_object_container[];

1118
	RT_DEBUG_NOT_IN_INTERRUPT;
1119

B
bernard.xiong 已提交
1120 1121 1122 1123
	/* enter critical */
	rt_enter_critical();

	/* try to find device object */
qiuyiuestc's avatar
qiuyiuestc 已提交
1124
	information = &rt_object_container[RT_Object_Class_Module];
B
bernard.xiong 已提交
1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141
	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 已提交
1142 1143
}

qiuyiuestc's avatar
qiuyiuestc 已提交
1144 1145 1146 1147 1148 1149 1150 1151 1152
#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 已提交
1153
{
D
dzzxzz 已提交
1154
	void *chunk;
qiuyiuestc's avatar
qiuyiuestc 已提交
1155
	struct rt_page_info *page;
qiuyiuestc's avatar
qiuyiuestc 已提交
1156

qiuyiuestc's avatar
qiuyiuestc 已提交
1157 1158
	chunk = rt_page_alloc(npages);
	if (chunk == RT_NULL) return RT_NULL;
1159

D
dzzxzz 已提交
1160
	page = (struct rt_page_info *)rt_current_module->page_array;
qiuyiuestc's avatar
qiuyiuestc 已提交
1161
	page[rt_current_module->page_cnt].page_ptr = chunk;
D
dzzxzz 已提交
1162 1163
	page[rt_current_module->page_cnt].npage = npages;
	rt_current_module->page_cnt ++;
qiuyiuestc's avatar
qiuyiuestc 已提交
1164

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

qiuyiuestc's avatar
qiuyiuestc 已提交
1168 1169
	return chunk;
}
qiuyiuestc's avatar
qiuyiuestc 已提交
1170

qiuyiuestc's avatar
qiuyiuestc 已提交
1171
/*
D
dzzxzz 已提交
1172
 * This function will release the previously allocated memory page
qiuyiuestc's avatar
qiuyiuestc 已提交
1173 1174 1175 1176
 * 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 已提交
1177
 *
qiuyiuestc's avatar
qiuyiuestc 已提交
1178 1179
 * @note this function is used for RT-Thread Application Module
 */
1180
static void rt_module_free_page(rt_module_t module, void *page_ptr, rt_size_t npages)
qiuyiuestc's avatar
qiuyiuestc 已提交
1181 1182 1183
{
	int i, index;
	struct rt_page_info *page;
qiuyiuestc's avatar
qiuyiuestc 已提交
1184

1185
	rt_kprintf("rt_module_free_page 0x%x %d\n", page_ptr, npages);
qiuyiuestc's avatar
qiuyiuestc 已提交
1186 1187
	rt_page_free(page_ptr, npages);

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

1190
	for(i=0; i<module->page_cnt; i++)
qiuyiuestc's avatar
qiuyiuestc 已提交
1191
	{
D
dzzxzz 已提交
1192
		if (page[i].page_ptr == page_ptr)
qiuyiuestc's avatar
qiuyiuestc 已提交
1193
		{
D
dzzxzz 已提交
1194
			if (page[i].npage == npages + 1)
qiuyiuestc's avatar
qiuyiuestc 已提交
1195 1196
			{
				page[i].page_ptr += npages * RT_MM_PAGE_SIZE / sizeof(rt_uint32_t);
1197
				page[i].npage -= npages;
qiuyiuestc's avatar
qiuyiuestc 已提交
1198
			}
1199
			else if(page[i].npage == npages)
B
bernard.xiong@gmail.com 已提交
1200
			{
1201
				for(index=i; index<module->page_cnt-1; index++)
qiuyiuestc's avatar
qiuyiuestc 已提交
1202 1203 1204 1205
				{
					page[index].page_ptr = page[index + 1].page_ptr;
					page[index].npage = page[index + 1].npage;
				}
1206 1207
				page[module->page_cnt - 1].page_ptr = RT_NULL;
				page[module->page_cnt - 1].npage = 0;
B
bernard.xiong@gmail.com 已提交
1208 1209

				module->page_cnt--;
qiuyiuestc's avatar
qiuyiuestc 已提交
1210
			}
D
dzzxzz 已提交
1211
			else RT_ASSERT(RT_FALSE);
1212
			rt_current_module->page_cnt--;
qiuyiuestc's avatar
qiuyiuestc 已提交
1213

qiuyiuestc's avatar
qiuyiuestc 已提交
1214 1215 1216 1217 1218 1219
			return;
		}
	}

	/* should not be get here */
	RT_ASSERT(RT_FALSE);
qiuyiuestc's avatar
qiuyiuestc 已提交
1220
}
qiuyiuestc's avatar
qiuyiuestc 已提交
1221 1222

/*
B
bernard.xiong@gmail.com 已提交
1223
  rt_module_malloc - allocate memory block in free list
qiuyiuestc's avatar
qiuyiuestc 已提交
1224 1225 1226
*/
void *rt_module_malloc(rt_size_t size)
{
qiuyiuestc's avatar
qiuyiuestc 已提交
1227
	struct rt_mem_head *b, *n, *up;
qiuyiuestc's avatar
qiuyiuestc 已提交
1228
	struct rt_mem_head **prev;
D
dzzxzz 已提交
1229
	rt_uint32_t npage;
qiuyiuestc's avatar
qiuyiuestc 已提交
1230
	rt_size_t nunits;
1231

1232
	RT_DEBUG_NOT_IN_INTERRUPT;
1233

D
dzzxzz 已提交
1234
	nunits = (size + sizeof(struct rt_mem_head) -1)/sizeof(struct rt_mem_head) + 1;
qiuyiuestc's avatar
qiuyiuestc 已提交
1235 1236 1237 1238

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

qiuyiuestc's avatar
qiuyiuestc 已提交
1239
	rt_sem_take(&mod_sem, RT_WAITING_FOREVER);
qiuyiuestc's avatar
qiuyiuestc 已提交
1240

D
dzzxzz 已提交
1241
	for (prev = (struct rt_mem_head **)&rt_current_module->mem_list; (b = *prev) != RT_NULL; prev = &(b->next))
qiuyiuestc's avatar
qiuyiuestc 已提交
1242
	{
qiuyiuestc's avatar
qiuyiuestc 已提交
1243 1244
		if (b->size > nunits)
		{
B
bernard.xiong@gmail.com 已提交
1245
			/* split memory */
qiuyiuestc's avatar
qiuyiuestc 已提交
1246 1247 1248 1249 1250
			n = b + nunits;
			n->next = b->next;
			n->size = b->size - nunits;
			b->size = nunits;
			*prev = n;
qiuyiuestc's avatar
qiuyiuestc 已提交
1251

1252
			rt_kprintf("rt_module_malloc 0x%x, %d\n",b + 1, size);
qiuyiuestc's avatar
qiuyiuestc 已提交
1253 1254
			rt_sem_release(&mod_sem);
			return (void *)(b + 1);
qiuyiuestc's avatar
qiuyiuestc 已提交
1255 1256 1257 1258 1259 1260
		}

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

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

qiuyiuestc's avatar
qiuyiuestc 已提交
1264 1265
			rt_sem_release(&mod_sem);
			return (void *)(b + 1);
qiuyiuestc's avatar
qiuyiuestc 已提交
1266
		}
qiuyiuestc's avatar
qiuyiuestc 已提交
1267
	}
qiuyiuestc's avatar
qiuyiuestc 已提交
1268

qiuyiuestc's avatar
qiuyiuestc 已提交
1269 1270
	/* allocate pages from system heap */
	npage = (size + sizeof(struct rt_mem_head) + RT_MM_PAGE_SIZE - 1)/RT_MM_PAGE_SIZE;
D
dzzxzz 已提交
1271
	if ((up = (struct rt_mem_head *)rt_module_malloc_page(npage)) == RT_NULL) return RT_NULL;
qiuyiuestc's avatar
qiuyiuestc 已提交
1272 1273

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

	for (prev = (struct rt_mem_head **)&rt_current_module->mem_list; (b = *prev) != RT_NULL; prev = &(b->next))
qiuyiuestc's avatar
qiuyiuestc 已提交
1276 1277
	{
		if (b > up + up->size) break;
qiuyiuestc's avatar
qiuyiuestc 已提交
1278 1279
	}

qiuyiuestc's avatar
qiuyiuestc 已提交
1280 1281 1282 1283
	up->next = b;
	*prev = up;

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

qiuyiuestc's avatar
qiuyiuestc 已提交
1285
	return rt_module_malloc(size);
qiuyiuestc's avatar
qiuyiuestc 已提交
1286 1287 1288
}

/*
qiuyiuestc's avatar
qiuyiuestc 已提交
1289
  rt_module_free - free memory block in free list
qiuyiuestc's avatar
qiuyiuestc 已提交
1290 1291 1292
*/
void rt_module_free(rt_module_t module, void *addr)
{
qiuyiuestc's avatar
qiuyiuestc 已提交
1293
	struct rt_mem_head *b, *n, *r;
qiuyiuestc's avatar
qiuyiuestc 已提交
1294
	struct rt_mem_head **prev;
1295

1296
	RT_DEBUG_NOT_IN_INTERRUPT;
1297

qiuyiuestc's avatar
qiuyiuestc 已提交
1298
	RT_ASSERT(addr);
qiuyiuestc's avatar
qiuyiuestc 已提交
1299 1300
	RT_ASSERT((((rt_uint32_t)addr) & (sizeof(struct rt_mem_head) -1)) == 0);

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

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

qiuyiuestc's avatar
qiuyiuestc 已提交
1305
	n = (struct rt_mem_head *)addr - 1;
qiuyiuestc's avatar
qiuyiuestc 已提交
1306
	prev = (struct rt_mem_head **)&module->mem_list;
qiuyiuestc's avatar
qiuyiuestc 已提交
1307 1308

	while ((b = *prev) != RT_NULL)
D
dzzxzz 已提交
1309
	{
qiuyiuestc's avatar
qiuyiuestc 已提交
1310 1311 1312
		RT_ASSERT(b->size > 0);
		RT_ASSERT(b > n || b + b->size <= n);

D
dzzxzz 已提交
1313
		if (b + b->size == n && ((rt_uint32_t)n % RT_MM_PAGE_SIZE != 0))
qiuyiuestc's avatar
qiuyiuestc 已提交
1314
		{
qiuyiuestc's avatar
qiuyiuestc 已提交
1315
			if (b + (b->size + n->size) == b->next)
qiuyiuestc's avatar
qiuyiuestc 已提交
1316
			{
qiuyiuestc's avatar
qiuyiuestc 已提交
1317 1318
				b->size += b->next->size + n->size;
				b->next = b->next->next;
qiuyiuestc's avatar
qiuyiuestc 已提交
1319
			}
qiuyiuestc's avatar
qiuyiuestc 已提交
1320 1321
			else b->size += n->size;

D
dzzxzz 已提交
1322
			if ((rt_uint32_t)b % RT_MM_PAGE_SIZE == 0)
qiuyiuestc's avatar
qiuyiuestc 已提交
1323 1324
			{
				int npage = b->size * sizeof(struct rt_page_info) / RT_MM_PAGE_SIZE;
D
dzzxzz 已提交
1325
				if (npage > 0)
qiuyiuestc's avatar
qiuyiuestc 已提交
1326
				{
D
dzzxzz 已提交
1327
					if ((b->size * sizeof(struct rt_page_info) % RT_MM_PAGE_SIZE) != 0)
qiuyiuestc's avatar
qiuyiuestc 已提交
1328 1329 1330 1331 1332 1333 1334 1335 1336 1337
					{
						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 已提交
1338
						*prev = b->next;
qiuyiuestc's avatar
qiuyiuestc 已提交
1339
					}
B
bernard.xiong@gmail.com 已提交
1340

1341
					rt_module_free_page(module, b, npage);
qiuyiuestc's avatar
qiuyiuestc 已提交
1342
				}
B
bernard.xiong@gmail.com 已提交
1343
			}
qiuyiuestc's avatar
qiuyiuestc 已提交
1344

qiuyiuestc's avatar
qiuyiuestc 已提交
1345 1346
			/* unlock */
			rt_sem_release(&mod_sem);
D
dzzxzz 已提交
1347

qiuyiuestc's avatar
qiuyiuestc 已提交
1348 1349 1350 1351 1352 1353 1354
			return;
		}

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

D
dzzxzz 已提交
1356
			if ((rt_uint32_t)n % RT_MM_PAGE_SIZE == 0)
qiuyiuestc's avatar
qiuyiuestc 已提交
1357 1358
			{
				int npage = n->size * sizeof(struct rt_page_info) / RT_MM_PAGE_SIZE;
D
dzzxzz 已提交
1359
				if (npage > 0)
qiuyiuestc's avatar
qiuyiuestc 已提交
1360
				{
D
dzzxzz 已提交
1361
					if ((n->size * sizeof(struct rt_page_info) % RT_MM_PAGE_SIZE) != 0)
qiuyiuestc's avatar
qiuyiuestc 已提交
1362 1363 1364 1365 1366 1367 1368 1369
					{
						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 已提交
1370
					else *prev = n->next;
B
bernard.xiong@gmail.com 已提交
1371

1372
					rt_module_free_page(module, n, npage);
qiuyiuestc's avatar
qiuyiuestc 已提交
1373
				}
D
dzzxzz 已提交
1374
			}
qiuyiuestc's avatar
qiuyiuestc 已提交
1375 1376 1377 1378 1379 1380 1381
			else
			{
				*prev = n;
			}

			/* unlock */
			rt_sem_release(&mod_sem);
qiuyiuestc's avatar
qiuyiuestc 已提交
1382 1383 1384 1385 1386 1387 1388 1389

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

		prev = &(b->next);
	}

D
dzzxzz 已提交
1390
	if ((rt_uint32_t)n % RT_MM_PAGE_SIZE == 0)
qiuyiuestc's avatar
qiuyiuestc 已提交
1391 1392
	{
		int npage = n->size * sizeof(struct rt_page_info) / RT_MM_PAGE_SIZE;
D
dzzxzz 已提交
1393
		if (npage > 0)
qiuyiuestc's avatar
qiuyiuestc 已提交
1394
		{
1395
			rt_module_free_page(module, n, npage);
D
dzzxzz 已提交
1396
			if (n->size % RT_MM_PAGE_SIZE != 0)
qiuyiuestc's avatar
qiuyiuestc 已提交
1397 1398 1399 1400 1401 1402 1403 1404 1405 1406
			{
				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 已提交
1407 1408 1409
				*prev = b;
			}
		}
qiuyiuestc's avatar
qiuyiuestc 已提交
1410
	}
D
dzzxzz 已提交
1411 1412
	else
	{
qiuyiuestc's avatar
qiuyiuestc 已提交
1413 1414 1415
		n->next = b;
		*prev = n;
	}
qiuyiuestc's avatar
qiuyiuestc 已提交
1416

qiuyiuestc's avatar
qiuyiuestc 已提交
1417
	/* unlock */
D
dzzxzz 已提交
1418
	rt_sem_release(&mod_sem);
qiuyiuestc's avatar
qiuyiuestc 已提交
1419 1420 1421 1422 1423 1424 1425
}

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

1429
	RT_DEBUG_NOT_IN_INTERRUPT;
1430

qiuyiuestc's avatar
qiuyiuestc 已提交
1431
	if (!ptr) return rt_module_malloc(size);
qiuyiuestc's avatar
qiuyiuestc 已提交
1432 1433 1434 1435 1436
	if (size == 0)
	{
		rt_module_free(rt_current_module, ptr);
		return RT_NULL;
	}
qiuyiuestc's avatar
qiuyiuestc 已提交
1437

qiuyiuestc's avatar
qiuyiuestc 已提交
1438 1439 1440
	nunits = (size + sizeof(struct rt_mem_head) - 1) / sizeof(struct rt_mem_head) + 1;
	b = (struct rt_mem_head *)ptr - 1;

D
dzzxzz 已提交
1441 1442 1443
	if (nunits <= b->size)
	{
		/* new size is smaller or equal then before */
qiuyiuestc's avatar
qiuyiuestc 已提交
1444
		if (nunits == b->size) return ptr;
D
dzzxzz 已提交
1445
		else
qiuyiuestc's avatar
qiuyiuestc 已提交
1446 1447 1448 1449 1450 1451 1452 1453
		{
			p = b + nunits;
			p->size = b->size - nunits;
			b->size = nunits;
			rt_module_free(rt_current_module, (void *)(p + 1));
			return (void *)(b + 1);
		}
	}
D
dzzxzz 已提交
1454 1455
	else
	{
qiuyiuestc's avatar
qiuyiuestc 已提交
1456
		/* more space then required */
qiuyiuestc's avatar
qiuyiuestc 已提交
1457
		prev = (struct rt_mem_head *)rt_current_module->mem_list;
qiuyiuestc's avatar
qiuyiuestc 已提交
1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471
		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 */
D
dzzxzz 已提交
1472
				tmpp = p;
qiuyiuestc's avatar
qiuyiuestc 已提交
1473 1474 1475 1476 1477 1478
				p = b + nunits;

				/* restoring old pointer */
				p->next = tmpp->next;
				
				/* new size for p */
D
dzzxzz 已提交
1479
				p->size = tmpp->size + b->size - nunits;
qiuyiuestc's avatar
qiuyiuestc 已提交
1480 1481 1482
				b->size = nunits;
				prev->next = p;
			}
qiuyiuestc's avatar
qiuyiuestc 已提交
1483
			rt_current_module->mem_list = (void *)prev;
D
dzzxzz 已提交
1484
			return (void *)(b + 1);
qiuyiuestc's avatar
qiuyiuestc 已提交
1485 1486 1487 1488 1489 1490
		}
		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 已提交
1491
			return (void *)(p);
qiuyiuestc's avatar
qiuyiuestc 已提交
1492 1493 1494
		}
	}
}
qiuyiuestc's avatar
qiuyiuestc 已提交
1495 1496 1497 1498 1499 1500 1501 1502 1503
#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;
B
bernard.xiong@gmail.com 已提交
1504

qiuyiuestc's avatar
qiuyiuestc 已提交
1505
	module = rt_module_find(name);
D
dzzxzz 已提交
1506
	if (module == RT_NULL) return;
qiuyiuestc's avatar
qiuyiuestc 已提交
1507

D
dzzxzz 已提交
1508
	for (prev = (struct rt_mem_head **)&module->mem_list; (b = *prev) != RT_NULL; prev = &(b->next))
qiuyiuestc's avatar
qiuyiuestc 已提交
1509 1510 1511 1512 1513 1514
	{
		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 已提交
1515
void list_mempage(const char *name)
qiuyiuestc's avatar
qiuyiuestc 已提交
1516 1517 1518 1519 1520 1521
{
	rt_module_t module;
	struct rt_page_info *page;
	int i;

	module = rt_module_find(name);
D
dzzxzz 已提交
1522
	if (module == RT_NULL) return;
qiuyiuestc's avatar
qiuyiuestc 已提交
1523 1524 1525

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

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

qiuyiuestc's avatar
qiuyiuestc 已提交
1534
#endif