module.c 55.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 - 2012, RT-Thread Development Team
qiuyiuestc's avatar
qiuyiuestc 已提交
5
 *
B
Bernard Xiong 已提交
6 7 8 9 10 11 12 13 14 15 16 17 18
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
qiuyiuestc's avatar
qiuyiuestc 已提交
19 20
 *
 * Change Logs:
D
dzzxzz 已提交
21 22 23 24 25 26
 * 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
27
 * 2012-11-23     Bernard      using RT_DEBUG_LOG instead of rt_kprintf.
B
Bernard Xiong 已提交
28
 * 2012-11-28     Bernard      remove rt_current_module and user
29
 *                             can use rt_module_unload to remove a module.
qiuyiuestc's avatar
qiuyiuestc 已提交
30
 */
qiuyiuestc's avatar
qiuyiuestc 已提交
31

32
#include <rthw.h>
qiuyiuestc's avatar
qiuyiuestc 已提交
33
#include <rtthread.h>
qiuyiuestc's avatar
qiuyiuestc 已提交
34
#include <rtm.h>
qiuyiuestc's avatar
qiuyiuestc 已提交
35

qiuyiuestc's avatar
qiuyiuestc 已提交
36
#ifdef RT_USING_MODULE
37
#include "module.h"
qiuyiuestc's avatar
qiuyiuestc 已提交
38

39 40 41 42 43 44 45 46 47 48 49
#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))

#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 已提交
50

51
#ifdef RT_USING_SLAB
52
#define PAGE_COUNT_MAX    256
qiuyiuestc's avatar
qiuyiuestc 已提交
53

qiuyiuestc's avatar
qiuyiuestc 已提交
54 55 56
/* module memory allocator */
struct rt_mem_head
{
57 58
    rt_size_t size;                /* size of memory block */
    struct rt_mem_head *next;      /* next valid memory block */
qiuyiuestc's avatar
qiuyiuestc 已提交
59 60
};

qiuyiuestc's avatar
qiuyiuestc 已提交
61 62
struct rt_page_info
{
63 64
    rt_uint32_t *page_ptr;
    rt_uint32_t npage;
qiuyiuestc's avatar
qiuyiuestc 已提交
65 66 67
};

static void *rt_module_malloc_page(rt_size_t npages);
68 69 70
static void rt_module_free_page(rt_module_t module,
                                void       *page_ptr,
                                rt_size_t   npages);
qiuyiuestc's avatar
qiuyiuestc 已提交
71

qiuyiuestc's avatar
qiuyiuestc 已提交
72
static struct rt_semaphore mod_sem;
73 74
#endif

75
static struct rt_module_symtab *_rt_module_symtab_begin = RT_NULL;
76
static struct rt_module_symtab *_rt_module_symtab_end   = RT_NULL;
qiuyiuestc's avatar
qiuyiuestc 已提交
77

78 79 80
/**
 * @ingroup SystemInit
 *
B
bernard.xiong@gmail.com 已提交
81
 * This function will initialize system module
82
 */
B
bernard 已提交
83
int rt_system_module_init(void)
84
{
qiuyiuestc's avatar
qiuyiuestc 已提交
85
#ifdef __GNUC__
86 87
    extern int __rtmsymtab_start;
    extern int __rtmsymtab_end;
88

89 90
    _rt_module_symtab_begin = (struct rt_module_symtab *)&__rtmsymtab_start;
    _rt_module_symtab_end   = (struct rt_module_symtab *)&__rtmsymtab_end;
D
dzzxzz 已提交
91
#elif defined (__CC_ARM)
92 93
    extern int RTMSymTab$$Base;
    extern int RTMSymTab$$Limit;
D
dzzxzz 已提交
94

95
    _rt_module_symtab_begin = (struct rt_module_symtab *)&RTMSymTab$$Base;
96
    _rt_module_symtab_end   = (struct rt_module_symtab *)&RTMSymTab$$Limit;
qiuyiuestc's avatar
qiuyiuestc 已提交
97
#endif
98

99
#ifdef RT_USING_SLAB
100 101
    /* initialize heap semaphore */
    rt_sem_init(&mod_sem, "module", 1, RT_IPC_FLAG_FIFO);
102
#endif
B
bernard 已提交
103
	return 0;
104
}
B
Bernard Xiong 已提交
105
INIT_COMPONENT_EXPORT(rt_system_module_init);
106

D
dzzxzz 已提交
107
static rt_uint32_t rt_module_symbol_find(const char *sym_str)
108
{
109 110
    /* find in kernel symbol table */
    struct rt_module_symtab *index;
111 112 113 114

    for (index = _rt_module_symtab_begin;
         index != _rt_module_symtab_end;
         index ++)
115 116 117 118 119 120
    {
        if (rt_strcmp(index->name, sym_str) == 0)
            return (rt_uint32_t)index->addr;
    }

    return 0;
121
}
qiuyiuestc's avatar
qiuyiuestc 已提交
122

qiuyiuestc's avatar
qiuyiuestc 已提交
123 124 125
/**
 * This function will return self module object
 *
qiuyiuestc's avatar
qiuyiuestc 已提交
126
 * @return the self module object
qiuyiuestc's avatar
qiuyiuestc 已提交
127
 */
D
dzzxzz 已提交
128
rt_module_t rt_module_self(void)
qiuyiuestc's avatar
qiuyiuestc 已提交
129
{
130
    rt_thread_t tid;
qiuyiuestc's avatar
qiuyiuestc 已提交
131

132 133 134
    tid = rt_thread_self();
    if (tid == RT_NULL)
        return RT_NULL;
qiuyiuestc's avatar
qiuyiuestc 已提交
135

136 137
    /* return current module */
    return (rt_module_t)tid->module_id;
qiuyiuestc's avatar
qiuyiuestc 已提交
138 139
}

140 141 142
static int rt_module_arm_relocate(struct rt_module *module,
                                  Elf32_Rel        *rel,
                                  Elf32_Addr        sym_val)
qiuyiuestc's avatar
qiuyiuestc 已提交
143
{
144 145 146 147 148 149 150 151 152 153 154
    Elf32_Addr *where, tmp;
    Elf32_Sword addend, offset;
    rt_uint32_t upper, lower, sign, j1, j2;

    where = (Elf32_Addr *)((rt_uint8_t *)module->module_space + rel->r_offset);
    switch (ELF32_R_TYPE(rel->r_info))
    {
    case R_ARM_NONE:
        break;
    case R_ARM_ABS32:
        *where += (Elf32_Addr)sym_val;
155 156
        RT_DEBUG_LOG(RT_DEBUG_MODULE, ("R_ARM_ABS32: %x -> %x\n",
                                       where, *where));
157 158 159 160 161 162 163 164 165 166 167
        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);
168 169
        RT_DEBUG_LOG(RT_DEBUG_MODULE, ("R_ARM_PC24: %x -> %x\n",
                                       where, *where));
170 171 172
        break;
    case R_ARM_REL32:
        *where += sym_val - (Elf32_Addr)where;
173 174 175
        RT_DEBUG_LOG(RT_DEBUG_MODULE,
                     ("R_ARM_REL32: %x -> %x, sym %x, offset %x\n",
                      where, *where, sym_val, rel->r_offset));
176 177 178 179 180 181 182 183
        break;
    case R_ARM_V4BX:
        *where &= 0xf000000f;
        *where |= 0x01a0f000;
        break;
    case R_ARM_GLOB_DAT:
    case R_ARM_JUMP_SLOT:
        *where = (Elf32_Addr)sym_val;
184 185
        RT_DEBUG_LOG(RT_DEBUG_MODULE, ("R_ARM_JUMP_SLOT: 0x%x -> 0x%x 0x%x\n",
                                       where, *where, sym_val));
186 187 188
        break;
#if 0        /* To do */
    case R_ARM_GOT_BREL:
189
        temp   = (Elf32_Addr)sym_val;
190
        *where = (Elf32_Addr)&temp;
191 192
        RT_DEBUG_LOG(RT_DEBUG_MODULE, ("R_ARM_GOT_BREL: 0x%x -> 0x%x 0x%x\n",
                                       where, *where, sym_val));
193
        break;
B
bernard.xiong@gmail.com 已提交
194
#endif
195 196
    case R_ARM_RELATIVE:
        *where = (Elf32_Addr)sym_val + *where;
197 198
        RT_DEBUG_LOG(RT_DEBUG_MODULE, ("R_ARM_RELATIVE: 0x%x -> 0x%x 0x%x\n",
                                       where, *where, sym_val));
199 200 201
        break;
    case R_ARM_THM_CALL:
    case R_ARM_THM_JUMP24:
202 203 204 205 206 207 208 209 210 211 212
        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);
213
        if (offset & 0x01000000)
214
            offset -= 0x02000000;
215 216
        offset += sym_val - (Elf32_Addr)where;

217 218 219
        if (!(offset & 1) ||
            offset <= (rt_int32_t)0xff000000 ||
            offset >= (rt_int32_t)0x01000000)
220
        {
221
            rt_kprintf("Module: Only Thumb addresses allowed\n");
222

223 224 225 226
            return -1;
        }

        sign = (offset >> 24) & 1;
227 228 229 230 231
        j1   = sign ^ (~(offset >> 23) & 1);
        j2   = sign ^ (~(offset >> 22) & 1);
        *(rt_uint16_t *)where = (rt_uint16_t)((upper & 0xf800) |
                                (sign << 10) |
                                ((offset >> 12) & 0x03ff));
232
        *(rt_uint16_t *)(where + 2) = (rt_uint16_t)((lower & 0xd000) |
233 234
                                      (j1 << 13) | (j2 << 11) |
                                      ((offset >> 1) & 0x07ff));
235 236 237 238 239 240 241 242
        upper = *(rt_uint16_t *)where;
        lower = *(rt_uint16_t *)((Elf32_Addr)where + 2);
        break;
    default:
        return -1;
    }

    return 0;
qiuyiuestc's avatar
qiuyiuestc 已提交
243 244
}

B
bernard 已提交
245
void rt_module_init_object_container(struct rt_module *module)
qiuyiuestc's avatar
qiuyiuestc 已提交
246
{
247
    RT_ASSERT(module != RT_NULL);
qiuyiuestc's avatar
qiuyiuestc 已提交
248

249 250 251 252
    /* initialize object container - thread */
    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;
qiuyiuestc's avatar
qiuyiuestc 已提交
253 254

#ifdef RT_USING_SEMAPHORE
255 256 257 258
    /* initialize object container - semaphore */
    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;
qiuyiuestc's avatar
qiuyiuestc 已提交
259 260 261
#endif

#ifdef RT_USING_MUTEX
262 263 264 265
    /* initialize object container - mutex */
    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;
qiuyiuestc's avatar
qiuyiuestc 已提交
266 267 268
#endif

#ifdef RT_USING_EVENT
269 270 271 272
    /* initialize object container - event */
    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;
qiuyiuestc's avatar
qiuyiuestc 已提交
273 274 275
#endif

#ifdef RT_USING_MAILBOX
276 277 278 279
    /* initialize object container - mailbox */
    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;
qiuyiuestc's avatar
qiuyiuestc 已提交
280 281 282
#endif

#ifdef RT_USING_MESSAGEQUEUE
283 284 285 286
    /* initialize object container - message queue */
    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;
qiuyiuestc's avatar
qiuyiuestc 已提交
287 288
#endif

289
#ifdef RT_USING_MEMHEAP
290 291 292 293
    /* initialize object container - memory heap */
    rt_list_init(&(module->module_object[RT_Object_Class_MemHeap].object_list));
    module->module_object[RT_Object_Class_MemHeap].object_size = sizeof(struct rt_memheap);
    module->module_object[RT_Object_Class_MemHeap].type = RT_Object_Class_MemHeap;
294 295
#endif

qiuyiuestc's avatar
qiuyiuestc 已提交
296
#ifdef RT_USING_MEMPOOL
297 298 299 300
    /* initialize object container - memory pool */
    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;
qiuyiuestc's avatar
qiuyiuestc 已提交
301 302 303
#endif

#ifdef RT_USING_DEVICE
304 305 306 307
    /* initialize object container - device */
    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;
qiuyiuestc's avatar
qiuyiuestc 已提交
308 309
#endif

310 311 312 313
    /* initialize object container - timer */
    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 已提交
314 315
}

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

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

qiuyiuestc's avatar
qiuyiuestc 已提交
324 325 326 327 328 329 330 331 332 333
/*@{*/

/**
 * 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))
{
334
    rt_module_load_hook = hook;
qiuyiuestc's avatar
qiuyiuestc 已提交
335 336 337 338 339 340 341 342 343 344
}

/**
 * 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))
{
345
    rt_module_unload_hook = hook;
qiuyiuestc's avatar
qiuyiuestc 已提交
346 347 348 349 350
}

/*@}*/
#endif

351 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
    rt_module_t module = RT_NULL;
356
    rt_bool_t linked   = RT_FALSE;
357 358 359 360
    rt_uint32_t index, module_size = 0;

    RT_ASSERT(module_ptr != RT_NULL);

361
    if (rt_memcmp(elf_module->e_ident, RTMMAG, SELFMAG) == 0)
362 363 364 365
    {
        /* rtmlinker finished */
        linked = RT_TRUE;
    }
366

367 368 369
    /* get the ELF image size */
    for (index = 0; index < elf_module->e_phnum; index++)
    {
370
        if (phdr[index].p_type == PT_LOAD)
371
            module_size += phdr[index].p_memsz;
372 373
    }

374 375
    if (module_size == 0)
    {
376
        rt_kprintf("Module: size error\n");
377

378
        return RT_NULL;
379
    }
380 381

    /* allocate module */
382 383 384 385
    module = (struct rt_module *)rt_object_allocate(RT_Object_Class_Module,
                                                    name);
    if (!module)
        return RT_NULL;
386 387

    module->nref = 0;
388

389 390 391 392
    /* allocate module space */
    module->module_space = rt_malloc(module_size);
    if (module->module_space == RT_NULL)
    {
393
        rt_kprintf("Module: allocate space failed.\n");
394 395 396 397 398 399 400 401 402 403 404 405 406
        rt_object_delete(&(module->parent));

        return RT_NULL;
    }

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

    for (index = 0; index < elf_module->e_phnum; index++)
    {
        if (phdr[index].p_type == PT_LOAD)
        {
407
            rt_memcpy(ptr + phdr[index].p_paddr,
408 409
                      (rt_uint8_t *)elf_module + phdr[index].p_offset,
                      phdr[index].p_filesz);
410 411
        }
    }
412 413 414

    /* set module entry */
    module->module_entry = module->module_space + elf_module->e_entry;
415

416 417 418 419 420 421 422 423
    /* handle relocation section */
    for (index = 0; index < elf_module->e_shnum; index ++)
    {
        rt_uint32_t i, nr_reloc;
        Elf32_Sym *symtab;
        Elf32_Rel *rel;
        rt_uint8_t *strtab;
        static rt_bool_t unsolved = RT_FALSE;
424

425 426
        if (!IS_REL(shdr[index]))
            continue;
427 428 429 430 431

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

        /* locate .rel.plt and .rel.dyn section */
432 433 434 435 436
        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));
437 438 439 440 441 442

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

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

447
            if ((sym->st_shndx != SHT_NULL) ||
448 449
                (ELF_ST_BIND(sym->st_info) == STB_LOCAL))
            {
450
                rt_module_arm_relocate(module, rel,
451
                           (Elf32_Addr)(module->module_space + sym->st_value));
452
            }
453
            else if (!linked)
454 455 456
            {
                Elf32_Addr addr;

457 458
                RT_DEBUG_LOG(RT_DEBUG_MODULE, ("relocate symbol: %s\n",
                                               strtab + sym->st_name));
459 460 461 462 463

                /* need to resolve symbol in kernel symbol table */
                addr = rt_module_symbol_find((const char *)(strtab + sym->st_name));
                if (addr == 0)
                {
464
                    rt_kprintf("Module: can't find %s in kernel symbol table\n",
465
                               strtab + sym->st_name);
466
                    unsolved = RT_TRUE;
467
                }
468 469 470 471 472 473 474 475 476 477 478
                else
                    rt_module_arm_relocate(module, rel, addr);
            }
            rel ++;
        }

        if (unsolved)
        {
            rt_object_delete(&(module->parent));

            return RT_NULL;
479
        }
480 481 482 483
    }

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

    /* found .dynsym section */
    if (index != elf_module->e_shnum)
    {
        int i, count = 0;
497
        Elf32_Sym  *symtab = RT_NULL;
498 499 500 501 502 503 504
        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++)
        {
505
            if ((ELF_ST_BIND(symtab[i].st_info) == STB_GLOBAL) &&
506 507 508 509 510
                (ELF_ST_TYPE(symtab[i].st_info) == STT_FUNC))
                count ++;
        }

        module->symtab = (struct rt_module_symtab *)rt_malloc
511
                         (count * sizeof(struct rt_module_symtab));
512 513 514 515
        module->nsym = count;
        for (i=0, count=0; i<shdr[index].sh_size/sizeof(Elf32_Sym); i++)
        {
            rt_size_t length;
516 517

            if ((ELF_ST_BIND(symtab[i].st_info) != STB_GLOBAL) ||
518 519
                (ELF_ST_TYPE(symtab[i].st_info) != STT_FUNC))
                continue;
520 521 522

            length = rt_strlen((const char *)(strtab + symtab[i].st_name)) + 1;

523
            module->symtab[count].addr =
524 525 526
                (void *)(module->module_space + symtab[i].st_value);
            module->symtab[count].name = rt_malloc(length);
            rt_memset((void *)module->symtab[count].name, 0, length);
527
            rt_memcpy((void *)module->symtab[count].name,
528 529
                      strtab + symtab[i].st_name,
                      length);
530
            count ++;
531
        }
532 533 534
    }

    return module;
535 536
}

537 538
static struct rt_module* _load_relocated_object(const char *name,
                                                void       *module_ptr)
539
{
540 541 542 543 544 545
    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;

    /* get the ELF image size */
546
    for (index = 0; index < elf_module->e_shnum; index ++)
547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575
    {
        /* 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;
        }
        /* 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;
        }
    }

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

    /* allocate module */
576 577
    module = (struct rt_module *)
             rt_object_allocate(RT_Object_Class_Module, (const char *)name);
578 579 580 581 582 583 584
    if (module == RT_NULL)
        return RT_NULL;

    /* allocate module space */
    module->module_space = rt_malloc(module_size);
    if (module->module_space == RT_NULL)
    {
585
        rt_kprintf("Module: allocate space failed.\n");
586 587 588 589 590 591 592 593 594 595
        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 */
596
    for (index = 0; index < elf_module->e_shnum; index ++)
597 598 599 600
    {
        /* load text section */
        if (IS_PROG(shdr[index]) && IS_AX(shdr[index]))
        {
601 602 603
            rt_memcpy(ptr,
                      (rt_uint8_t *)elf_module + shdr[index].sh_offset,
                      shdr[index].sh_size);
604 605
            RT_DEBUG_LOG(RT_DEBUG_MODULE, ("load text 0x%x, size %d\n",
                                           ptr, shdr[index].sh_size));
606 607 608 609 610 611
            ptr += shdr[index].sh_size;
        }

        /* load rodata section */
        if (IS_PROG(shdr[index]) && IS_ALLOC(shdr[index]))
        {
612 613 614
            rt_memcpy(ptr,
                      (rt_uint8_t *)elf_module + shdr[index].sh_offset,
                      shdr[index].sh_size);
615
            rodata_addr = (rt_uint32_t)ptr;
616 617 618
            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));
619 620 621 622 623 624
            ptr += shdr[index].sh_size;
        }

        /* load data section */
        if (IS_PROG(shdr[index]) && IS_AW(shdr[index]))
        {
625 626 627
            rt_memcpy(ptr,
                      (rt_uint8_t *)elf_module + shdr[index].sh_offset,
                      shdr[index].sh_size);
628
            data_addr = (rt_uint32_t)ptr;
629 630 631
            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));
632 633 634 635 636 637 638 639
            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;
640 641
            RT_DEBUG_LOG(RT_DEBUG_MODULE, ("load bss 0x%x, size %d,\n",
                                           ptr, shdr[index].sh_size));
642 643 644 645
        }
    }

    /* set module entry */
646 647
    module->module_entry =
        (rt_uint8_t *)module->module_space + elf_module->e_entry - module_addr;
648 649 650 651 652 653 654

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

656 657
        if (!IS_REL(shdr[index]))
            continue;
658

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

        /* locate .dynsym and .dynstr */
663 664 665 666 667 668 669
        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));
670 671 672 673 674

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

676 677
            RT_DEBUG_LOG(RT_DEBUG_MODULE, ("relocate symbol: %s\n",
                                           strtab + sym->st_name));
678 679 680

            if (sym->st_shndx != STN_UNDEF)
            {
681 682
                if ((ELF_ST_TYPE(sym->st_info) == STT_SECTION) ||
                    (ELF_ST_TYPE(sym->st_info) == STT_OBJECT))
683
                {
684
                    if (rt_strncmp((const char *)(shstrab +
685 686 687
                        shdr[sym->st_shndx].sh_name), ELF_RODATA, 8) == 0)
                    {
                        /* relocate rodata section */
688
                        RT_DEBUG_LOG(RT_DEBUG_MODULE, ("rodata\n"));
689
                        rt_module_arm_relocate(module, rel,
690
                                               (Elf32_Addr)(rodata_addr + sym->st_value));
691
                    }
692 693
                    else if (rt_strncmp((const char*)
                             (shstrab + shdr[sym->st_shndx].sh_name), ELF_BSS, 5) == 0)
694 695
                    {
                        /* relocate bss section */
696
                        RT_DEBUG_LOG(RT_DEBUG_MODULE, ("bss\n"));
697
                        rt_module_arm_relocate(module, rel,
698
                                               (Elf32_Addr)bss_addr + sym->st_value);
699
                    }
700 701
                    else if (rt_strncmp((const char *)(shstrab + shdr[sym->st_shndx].sh_name),
                             ELF_DATA, 6) == 0)
702 703
                    {
                        /* relocate data section */
704
                        RT_DEBUG_LOG(RT_DEBUG_MODULE, ("data\n"));
705
                        rt_module_arm_relocate(module, rel,
706
                                               (Elf32_Addr)data_addr + sym->st_value);
707 708 709
                    }
                }
            }
710
            else if (ELF_ST_TYPE(sym->st_info) == STT_FUNC)
711 712
            {
                /* relocate function */
713
                rt_module_arm_relocate(module, rel, (Elf32_Addr)((rt_uint8_t *)
714 715 716 717 718 719
                    module->module_space - module_addr + sym->st_value));
            }
            else
            {
                Elf32_Addr addr;

720
                if (ELF32_R_TYPE(rel->r_info) != R_ARM_V4BX)
721
                {
722 723
                    RT_DEBUG_LOG(RT_DEBUG_MODULE, ("relocate symbol: %s\n",
                                                   strtab + sym->st_name));
724

725
                    /* need to resolve symbol in kernel symbol table */
726
                    addr = rt_module_symbol_find((const char *)(strtab + sym->st_name));
727 728 729
                    if (addr != (Elf32_Addr)RT_NULL)
                    {
                        rt_module_arm_relocate(module, rel, addr);
730 731
                        RT_DEBUG_LOG(RT_DEBUG_MODULE, ("symbol addr 0x%x\n",
                                                       addr));
732 733
                    }
                    else
734
                        rt_kprintf("Module: can't find %s in kernel symbol table\n",
735
                                   strtab + sym->st_name);
736 737 738 739 740 741 742 743 744 745 746 747
                }
                else
                {
                    rt_module_arm_relocate(module, rel, (Elf32_Addr)((rt_uint8_t*)
                        module->module_space - module_addr + sym->st_value));
                }
            }
            rel ++;
        }
    }

    return module;
748 749 750 751 752 753 754 755 756 757
}

/**
 * This function will load a module from memory and create a thread for it
 *
 * @param name the name of module, which shall be unique
 * @param module_ptr the memory address of module image
 *
 * @return the module object
 */
D
dzzxzz 已提交
758
rt_module_t rt_module_load(const char *name, void *module_ptr)
759
{
760 761 762 763
    rt_module_t module;

    RT_DEBUG_NOT_IN_INTERRUPT;

764
    RT_DEBUG_LOG(RT_DEBUG_MODULE, ("rt_module_load: %s ,", name));
765 766

    /* check ELF header */
767 768
    if (rt_memcmp(elf_module->e_ident, RTMMAG, SELFMAG) != 0 &&
        rt_memcmp(elf_module->e_ident, ELFMAG, SELFMAG) != 0)
769
    {
770
        rt_kprintf("Module: magic error\n");
771 772 773 774 775

        return RT_NULL;
    }

    /* check ELF class */
776
    if (elf_module->e_ident[EI_CLASS] != ELFCLASS32)
777
    {
778
        rt_kprintf("Module: ELF class error\n");
779 780 781 782

        return RT_NULL;
    }

783
    if (elf_module->e_type == ET_REL)
784 785 786
    {
        module = _load_relocated_object(name, module_ptr);
    }
787
    else if (elf_module->e_type == ET_DYN)
788 789 790 791 792
    {
        module = _load_shared_object(name, module_ptr);
    }
    else
    {
793
        rt_kprintf("Module: unsupported elf type\n");
794 795 796 797

        return RT_NULL;
    }

798
    if (module == RT_NULL)
799 800 801 802
        return RT_NULL;

    /* init module object container */
    rt_module_init_object_container(module);
803

804 805 806 807
	/* initialize an empty command */
	module->module_cmd_line = RT_NULL;
	module->module_cmd_size = 0;
	
808 809 810 811
    /* increase module reference count */
    module->nref ++;

    if (elf_module->e_entry != 0)
812
    {
qiuyiuestc's avatar
qiuyiuestc 已提交
813
#ifdef RT_USING_SLAB
814 815
        /* init module memory allocator */
        module->mem_list = RT_NULL;
qiuyiuestc's avatar
qiuyiuestc 已提交
816

817
        /* create page array */
B
Bernard Xiong 已提交
818
        module->page_array =
819
            (void *)rt_malloc(PAGE_COUNT_MAX * sizeof(struct rt_page_info));
820
        module->page_cnt = 0;
821 822
#endif

823
        /* create module thread */
824 825 826
        module->module_thread = rt_thread_create(name,
                             (void(*)(void *))module->module_entry, RT_NULL,
                             2048, RT_THREAD_PRIORITY_MAX - 2, 10);
827

828 829
        RT_DEBUG_LOG(RT_DEBUG_MODULE, ("thread entry 0x%x\n",
                                       module->module_entry));
830 831 832

        /* set module id */
        module->module_thread->module_id = (void *)module;
833 834 835 836
        module->parent.flag = RT_MODULE_FLAG_WITHENTRY;

        /* startup module thread */
        rt_thread_startup(module->module_thread);
837
    }
838 839 840 841
    else
    {
        /* without entry point */
        module->parent.flag |= RT_MODULE_FLAG_WITHOUTENTRY;
842
    }
qiuyiuestc's avatar
qiuyiuestc 已提交
843

qiuyiuestc's avatar
qiuyiuestc 已提交
844
#ifdef RT_USING_HOOK
845 846 847 848
    if (rt_module_load_hook != RT_NULL)
    {
        rt_module_load_hook(module);
    }
qiuyiuestc's avatar
qiuyiuestc 已提交
849 850
#endif

851
    return module;
852 853
}

854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922
#define RT_MODULE_ARG_MAX    8
static int _rt_module_split_arg(char* cmd, rt_size_t length, char* argv[])
{
	int argc = 0;
	char *ptr = cmd;

	while ((ptr - cmd) < length)
	{
		/* strip bank and tab */
		while ((*ptr == ' ' || *ptr == '\t') && (ptr -cmd)< length)
			*ptr++ = '\0';
		/* check whether it's the end of line */
		if ((ptr - cmd)>= length) break;

		/* handle string with quote */
		if (*ptr == '"')
		{
			argv[argc++] = ++ptr;

			/* skip this string */
			while (*ptr != '"' && (ptr-cmd) < length)
				if (*ptr ++ == '\\')  ptr ++;
			if ((ptr - cmd) >= length) break;

			/* skip '"' */
			*ptr ++ = '\0';
		}
		else
		{
			argv[argc++] = ptr;
			while ((*ptr != ' ' && *ptr != '\t') && (ptr - cmd) < length)
				ptr ++;
		}

		if (argc >= RT_MODULE_ARG_MAX) break;
	}

	return argc;
}
/* module main thread entry */
static void module_main_entry(void* parameter)
{
    int argc;
    char *argv[RT_MODULE_ARG_MAX];
	typedef int (*main_func_t)(int argc, char** argv);

	rt_module_t module = (rt_module_t) parameter;
	if (module == RT_NULL || module->module_cmd_line == RT_NULL) return;

    rt_memset(argv, 0x00, sizeof(argv));
    argc = _rt_module_split_arg((char*)module->module_cmd_line, module->module_cmd_size, argv);
    if (argc == 0) return ;

	/* do the main function */
	((main_func_t)module->module_entry)(argc, argv);
	return;
}

/**
 * This function will load a module with a main function from memory and create a 
 * main thread for it
 *
 * @param name the name of module, which shall be unique
 * @param module_ptr the memory address of module image
 * @argc the count of argument
 * @argd the argument data, which should be a 
 *
 * @return the module object
 */
923
rt_module_t rt_module_do_main(const char *name, void *module_ptr, const char* cmd_line, int line_size)
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 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015
{
	rt_module_t module;

	RT_DEBUG_NOT_IN_INTERRUPT;

	RT_DEBUG_LOG(RT_DEBUG_MODULE, ("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: ELF class error\n");
		return RT_NULL;
	}

	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("Module: unsupported excutable program\n");
		return RT_NULL;
	}

	if (module == RT_NULL)
		return RT_NULL;

	/* init module object container */
	rt_module_init_object_container(module);

	/* increase module reference count */
	module->nref ++;

	if (elf_module->e_entry != 0)
	{
#ifdef RT_USING_SLAB
		/* init module memory allocator */
		module->mem_list = RT_NULL;

		/* create page array */
		module->page_array =
			(void *)rt_malloc(PAGE_COUNT_MAX * sizeof(struct rt_page_info));
		module->page_cnt = 0;
#endif

		/* set module argument */
		module->module_cmd_line = (rt_uint8_t*)rt_malloc(line_size + 1);
		rt_memcpy(module->module_cmd_line, cmd_line, line_size);
		module->module_cmd_line[line_size] = '\0';
		module->module_cmd_size = line_size;

		/* create module thread */
		module->module_thread =	rt_thread_create(name,
							 module_main_entry, module,
							 2048, RT_THREAD_PRIORITY_MAX - 2, 10);

		/* set module id */
		module->module_thread->module_id = (void *)module;
		module->parent.flag = RT_MODULE_FLAG_WITHENTRY;

		/* startup main thread */
		rt_thread_startup(module->module_thread);
	}
	else
	{
		/* without entry point */
		module->parent.flag |= RT_MODULE_FLAG_WITHOUTENTRY;
	}

#ifdef RT_USING_HOOK
	if (rt_module_load_hook != RT_NULL)
	{
		rt_module_load_hook(module);
	}
#endif

	return module;
}

1016 1017
#ifdef RT_USING_DFS
#include <dfs_posix.h>
qiuyiuestc's avatar
qiuyiuestc 已提交
1018

1019
static char* _module_name(const char *path)
qiuyiuestc's avatar
qiuyiuestc 已提交
1020
{
1021
    const char *first, *end, *ptr;
1022
    char *name;
qiuyiuestc's avatar
qiuyiuestc 已提交
1023
    int size;
1024

1025 1026 1027 1028 1029
    ptr   = (char *)path;
    first = ptr;
    end   = path + rt_strlen(path);

    while (*ptr != '\0')
qiuyiuestc's avatar
qiuyiuestc 已提交
1030
    {
1031 1032 1033 1034
        if (*ptr == '/')
            first = ptr + 1;
        if (*ptr == '.')
            end = ptr - 1;
1035

1036
        ptr ++;
qiuyiuestc's avatar
qiuyiuestc 已提交
1037 1038 1039 1040 1041 1042 1043 1044 1045 1046
    }

    size = end - first + 1;
    name = rt_malloc(size);
    rt_strncpy(name, first, size);
    name[size] = '\0';

    return name;
}

qiuyiuestc's avatar
qiuyiuestc 已提交
1047
/**
B
bernard.xiong@gmail.com 已提交
1048
 * This function will load a module from a file
qiuyiuestc's avatar
qiuyiuestc 已提交
1049
 *
B
bernard.xiong@gmail.com 已提交
1050
 * @param path the full path of application module
qiuyiuestc's avatar
qiuyiuestc 已提交
1051 1052 1053
 *
 * @return the module object
 */
D
dzzxzz 已提交
1054
rt_module_t rt_module_open(const char *path)
qiuyiuestc's avatar
qiuyiuestc 已提交
1055
{
1056 1057 1058 1059
    int fd, length;
    struct rt_module *module;
    struct stat s;
    char *buffer, *offset_ptr;
1060
    char *name;
1061 1062 1063 1064 1065 1066 1067 1068

    RT_DEBUG_NOT_IN_INTERRUPT;

    /* check parameters */
    RT_ASSERT(path != RT_NULL);

    if (stat(path, &s) !=0)
    {
1069
        rt_kprintf("Module: access %s failed\n", path);
1070 1071 1072 1073 1074 1075

        return RT_NULL;
    }
    buffer = (char *)rt_malloc(s.st_size);
    if (buffer == RT_NULL)
    {
1076
        rt_kprintf("Module: out of memory\n");
1077 1078 1079 1080 1081 1082 1083 1084

        return RT_NULL;
    }

    offset_ptr = buffer;
    fd = open(path, O_RDONLY, 0);
    if (fd < 0)
    {
1085
        rt_kprintf("Module: open %s failed\n", path);
1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104
        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)
    {
1105
        rt_kprintf("Module: read file failed\n");
1106 1107 1108 1109 1110
        rt_free(buffer);

        return RT_NULL;
    }

1111 1112
    name   = _module_name(path);
    module = rt_module_load(name, (void *)buffer);
1113
    rt_free(buffer);
qiuyiuestc's avatar
qiuyiuestc 已提交
1114
    rt_free(name);
1115 1116

    return module;
qiuyiuestc's avatar
qiuyiuestc 已提交
1117
}
qiuyiuestc's avatar
qiuyiuestc 已提交
1118

1119 1120 1121 1122
/**
 * This function will do a excutable program with main function and parameters.
 *
 * @param path the full path of application module
1123 1124
 * @param cmd_line the command line of program
 * @param size the size of command line of program
1125 1126 1127
 *
 * @return the module object
 */
1128
rt_module_t rt_module_exec_cmd(const char *path, const char* cmd_line, int size)
1129 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 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192
{
    struct stat s;
    int fd, length;
    char *name, *buffer, *offset_ptr;
    struct rt_module *module = RT_NULL;

	name = buffer = RT_NULL;

    RT_DEBUG_NOT_IN_INTERRUPT;

    /* check parameters */
    RT_ASSERT(path != RT_NULL);

	/* get file size */
    if (stat(path, &s) !=0)
    {
        rt_kprintf("Module: access %s failed\n", path);
        goto __exit;
    }

	/* allocate buffer to save program */
    offset_ptr = buffer = (char *)rt_malloc(s.st_size);
    if (buffer == RT_NULL)
    {
        rt_kprintf("Module: out of memory\n");
		goto __exit;
    }

    fd = open(path, O_RDONLY, 0);
    if (fd < 0)
    {
        rt_kprintf("Module: open %s failed\n", path);
		goto __exit;
    }

    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)
    {
        rt_kprintf("Module: read file failed\n");
		goto __exit;
    }

	/* get module */
    name   = _module_name(path);
	/* execute module */
    module = rt_module_do_main(name, (void *)buffer, cmd_line, size);

__exit:
    rt_free(buffer);
    rt_free(name);

    return module;
}

qiuyiuestc's avatar
qiuyiuestc 已提交
1193 1194
#if defined(RT_USING_FINSH)
#include <finsh.h>
1195
FINSH_FUNCTION_EXPORT_ALIAS(rt_module_open, exec, exec module from a file);
qiuyiuestc's avatar
qiuyiuestc 已提交
1196
#endif
1197

qiuyiuestc's avatar
qiuyiuestc 已提交
1198 1199
#endif

qiuyiuestc's avatar
qiuyiuestc 已提交
1200
/**
1201
 * This function will destroy a module and release its resource.
qiuyiuestc's avatar
qiuyiuestc 已提交
1202
 *
1203
 * @param module the module to be destroyed.
qiuyiuestc's avatar
qiuyiuestc 已提交
1204 1205 1206
 *
 * @return the operation status, RT_EOK on OK; -RT_ERROR on error
 */
1207
rt_err_t rt_module_destroy(rt_module_t module)
qiuyiuestc's avatar
qiuyiuestc 已提交
1208
{
1209 1210 1211 1212 1213 1214 1215 1216
    int i;
    struct rt_object *object;
    struct rt_list_node *list;

    RT_DEBUG_NOT_IN_INTERRUPT;

    /* check parameter */
    RT_ASSERT(module != RT_NULL);
1217
    RT_ASSERT(module->nref == 0);
1218

1219 1220
    RT_DEBUG_LOG(RT_DEBUG_MODULE, ("rt_module_destroy: %8.*s\n",
                                   RT_NAME_MAX, module->parent.name));
1221 1222 1223 1224

    /* module has entry point */
    if (!(module->parent.flag & RT_MODULE_FLAG_WITHOUTENTRY))
    {
qiuyiuestc's avatar
qiuyiuestc 已提交
1225
#ifdef RT_USING_SEMAPHORE
1226
        /* delete semaphores */
1227
        list = &module->module_object[RT_Object_Class_Thread].object_list;
1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241
        while (list->next != list)
        {
            object = rt_list_entry(list->next, struct rt_object, list);
            if (rt_object_is_systemobject(object) == RT_TRUE)
            {
                /* detach static object */
                rt_sem_detach((rt_sem_t)object);
            }
            else
            {
                /* delete dynamic object */
                rt_sem_delete((rt_sem_t)object);
            }
        }
qiuyiuestc's avatar
qiuyiuestc 已提交
1242 1243 1244
#endif

#ifdef RT_USING_MUTEX
1245
        /* delete mutexs*/
1246
        list = &module->module_object[RT_Object_Class_Mutex].object_list;
1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260
        while (list->next != list)
        {
            object = rt_list_entry(list->next, struct rt_object, list);
            if (rt_object_is_systemobject(object) == RT_TRUE)
            {
                /* detach static object */
                rt_mutex_detach((rt_mutex_t)object);
            }
            else
            {
                /* delete dynamic object */
                rt_mutex_delete((rt_mutex_t)object);
            }
        }
qiuyiuestc's avatar
qiuyiuestc 已提交
1261 1262 1263
#endif

#ifdef RT_USING_EVENT
1264
        /* delete mailboxs */
1265
        list = &module->module_object[RT_Object_Class_Event].object_list;
1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279
        while (list->next != list)
        {
            object = rt_list_entry(list->next, struct rt_object, list);
            if (rt_object_is_systemobject(object) == RT_TRUE)
            {
                /* detach static object */
                rt_event_detach((rt_event_t)object);
            }
            else
            {
                /* delete dynamic object */
                rt_event_delete((rt_event_t)object);
            }
        }
qiuyiuestc's avatar
qiuyiuestc 已提交
1280 1281 1282
#endif

#ifdef RT_USING_MAILBOX
1283
        /* delete mailboxs */
1284
        list = &module->module_object[RT_Object_Class_MailBox].object_list;
1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298
        while (list->next != list)
        {
            object = rt_list_entry(list->next, struct rt_object, list);
            if (rt_object_is_systemobject(object) == RT_TRUE)
            {
                /* detach static object */
                rt_mb_detach((rt_mailbox_t)object);
            }
            else
            {
                /* delete dynamic object */
                rt_mb_delete((rt_mailbox_t)object);
            }
        }
qiuyiuestc's avatar
qiuyiuestc 已提交
1299 1300 1301
#endif

#ifdef RT_USING_MESSAGEQUEUE
1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317
        /* delete msgqueues */
        list = &module->module_object[RT_Object_Class_MessageQueue].object_list;
        while (list->next != list)
        {
            object = rt_list_entry(list->next, struct rt_object, list);
            if (rt_object_is_systemobject(object) == RT_TRUE)
            {
                /* detach static object */
                rt_mq_detach((rt_mq_t)object);
            }
            else
            {
                /* delete dynamic object */
                rt_mq_delete((rt_mq_t)object);
            }
        }
qiuyiuestc's avatar
qiuyiuestc 已提交
1318 1319 1320
#endif

#ifdef RT_USING_MEMPOOL
1321
        /* delete mempools */
1322
        list = &module->module_object[RT_Object_Class_MemPool].object_list;
1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336
        while (list->next != list)
        {
            object = rt_list_entry(list->next, struct rt_object, list);
            if (rt_object_is_systemobject(object) == RT_TRUE)
            {
                /* detach static object */
                rt_mp_detach((rt_mp_t)object);
            }
            else
            {
                /* delete dynamic object */
                rt_mp_delete((rt_mp_t)object);
            }
        }
qiuyiuestc's avatar
qiuyiuestc 已提交
1337 1338 1339
#endif

#ifdef RT_USING_DEVICE
1340
        /* delete devices */
1341
        list = &module->module_object[RT_Object_Class_Device].object_list;
1342 1343 1344 1345 1346
        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 已提交
1347 1348
#endif

1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364
        /* delete timers */
        list = &module->module_object[RT_Object_Class_Timer].object_list;
        while (list->next != list)
        {
            object = rt_list_entry(list->next, struct rt_object, list);
            if (rt_object_is_systemobject(object) == RT_TRUE)
            {
                /* detach static object */
                rt_timer_detach((rt_timer_t)object);
            }
            else
            {
                /* delete dynamic object */
                rt_timer_delete((rt_timer_t)object);
            }
        }
1365 1366 1367 1368 1369 1370
		
		/* delete command line */
		if (module->module_cmd_line != RT_NULL)
		{
			rt_free(module->module_cmd_line);
		}
1371
    }
qiuyiuestc's avatar
qiuyiuestc 已提交
1372

1373
#ifdef RT_USING_SLAB
1374 1375 1376
    if (module->page_cnt > 0)
    {
        struct rt_page_info *page = (struct rt_page_info *)module->page_array;
B
bernard.xiong@gmail.com 已提交
1377

1378
        rt_kprintf("Module: warning - memory still hasn't been free finished\n");
qiuyiuestc's avatar
qiuyiuestc 已提交
1379

1380
        while (module->page_cnt != 0)
1381 1382 1383 1384
        {
            rt_module_free_page(module, page[0].page_ptr, page[0].npage);
        }
    }
1385
#endif
D
dzzxzz 已提交
1386

1387 1388
    /* release module space memory */
    rt_free(module->module_space);
qiuyiuestc's avatar
qiuyiuestc 已提交
1389

1390
    /* release module symbol table */
1391
    for (i = 0; i < module->nsym; i ++)
1392
    {
1393
        rt_free((void *)module->symtab[i].name);
1394
    }
1395 1396
    if (module->symtab != RT_NULL)
        rt_free(module->symtab);
qiuyiuestc's avatar
qiuyiuestc 已提交
1397

qiuyiuestc's avatar
qiuyiuestc 已提交
1398
#ifdef RT_USING_SLAB
1399
    if (module->page_array != RT_NULL)
1400
        rt_free(module->page_array);
qiuyiuestc's avatar
qiuyiuestc 已提交
1401
#endif
qiuyiuestc's avatar
qiuyiuestc 已提交
1402

1403 1404
    /* delete module object */
    rt_object_delete((rt_object_t)module);
qiuyiuestc's avatar
qiuyiuestc 已提交
1405

1406
    return RT_EOK;
qiuyiuestc's avatar
qiuyiuestc 已提交
1407 1408
}

1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423
/**
 * 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)
{
    struct rt_object *object;
    struct rt_list_node *list;

    RT_DEBUG_NOT_IN_INTERRUPT;

    /* check parameter */
1424 1425
    if (module == RT_NULL)
        return -RT_ERROR;
1426

1427
    rt_enter_critical();
1428 1429
    if (!(module->parent.flag & RT_MODULE_FLAG_WITHOUTENTRY))
    {
1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451
        /* delete all sub-threads */
        list = &module->module_object[RT_Object_Class_Thread].object_list;
        while (list->next != list)
        {
            object = rt_list_entry(list->next, struct rt_object, list);
            if (rt_object_is_systemobject(object) == RT_TRUE)
            {
                /* detach static object */
                rt_thread_detach((rt_thread_t)object);
            }
            else
            {
                /* delete dynamic object */
                rt_thread_delete((rt_thread_t)object);
            }
        }

        /* delete the main thread of module */
        if (module->module_thread != RT_NULL)
        {
            rt_thread_delete(module->module_thread);
        }
1452
    }
1453
    rt_exit_critical();
1454 1455

#ifdef RT_USING_HOOK
1456 1457 1458 1459
    if (rt_module_unload_hook != RT_NULL)
    {
        rt_module_unload_hook(module);
    }
1460 1461
#endif

1462
    return RT_EOK;
1463 1464
}

qiuyiuestc's avatar
qiuyiuestc 已提交
1465 1466 1467 1468 1469 1470 1471
/**
 * This function will find the specified module.
 *
 * @param name the name of module finding
 *
 * @return the module
 */
D
dzzxzz 已提交
1472
rt_module_t rt_module_find(const char *name)
qiuyiuestc's avatar
qiuyiuestc 已提交
1473
{
1474 1475 1476
    struct rt_object_information *information;
    struct rt_object *object;
    struct rt_list_node *node;
qiuyiuestc's avatar
qiuyiuestc 已提交
1477

1478
    extern struct rt_object_information rt_object_container[];
B
bernard.xiong 已提交
1479

1480
    RT_DEBUG_NOT_IN_INTERRUPT;
1481

1482 1483
    /* enter critical */
    rt_enter_critical();
B
bernard.xiong 已提交
1484

1485 1486
    /* try to find device object */
    information = &rt_object_container[RT_Object_Class_Module];
1487
    for (node = information->object_list.next;
1488 1489
         node != &(information->object_list);
         node = node->next)
1490 1491 1492 1493 1494 1495
    {
        object = rt_list_entry(node, struct rt_object, list);
        if (rt_strncmp(object->name, name, RT_NAME_MAX) == 0)
        {
            /* leave critical */
            rt_exit_critical();
B
bernard.xiong 已提交
1496

1497 1498 1499
            return (rt_module_t)object;
        }
    }
B
bernard.xiong 已提交
1500

1501 1502
    /* leave critical */
    rt_exit_critical();
B
bernard.xiong 已提交
1503

1504 1505
    /* not found */
    return RT_NULL;
qiuyiuestc's avatar
qiuyiuestc 已提交
1506 1507
}

qiuyiuestc's avatar
qiuyiuestc 已提交
1508 1509 1510 1511 1512 1513 1514 1515 1516
#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 已提交
1517
{
1518 1519
    void *chunk;
    struct rt_page_info *page;
1520
    rt_module_t self_module;
1521

1522 1523
    self_module = rt_module_self();
    RT_ASSERT(self_module != RT_NULL);
qiuyiuestc's avatar
qiuyiuestc 已提交
1524

1525 1526 1527
    chunk = rt_page_alloc(npages);
    if (chunk == RT_NULL)
        return RT_NULL;
1528

1529 1530
    page = (struct rt_page_info *)self_module->page_array;
    page[self_module->page_cnt].page_ptr = chunk;
1531
    page[self_module->page_cnt].npage    = npages;
1532
    self_module->page_cnt ++;
qiuyiuestc's avatar
qiuyiuestc 已提交
1533

1534
    RT_ASSERT(self_module->page_cnt <= PAGE_COUNT_MAX);
1535 1536
    RT_DEBUG_LOG(RT_DEBUG_MODULE, ("rt_module_malloc_page 0x%x %d\n",
                                   chunk, npages));
D
dzzxzz 已提交
1537

1538
    return chunk;
qiuyiuestc's avatar
qiuyiuestc 已提交
1539
}
qiuyiuestc's avatar
qiuyiuestc 已提交
1540

qiuyiuestc's avatar
qiuyiuestc 已提交
1541
/*
D
dzzxzz 已提交
1542
 * This function will release the previously allocated memory page
qiuyiuestc's avatar
qiuyiuestc 已提交
1543 1544 1545 1546
 * 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 已提交
1547
 *
qiuyiuestc's avatar
qiuyiuestc 已提交
1548 1549
 * @note this function is used for RT-Thread Application Module
 */
1550 1551 1552
static void rt_module_free_page(rt_module_t module,
                                void       *page_ptr,
                                rt_size_t   npages)
qiuyiuestc's avatar
qiuyiuestc 已提交
1553
{
1554 1555
    int i, index;
    struct rt_page_info *page;
1556
    rt_module_t self_module;
1557

1558 1559
    self_module = rt_module_self();
    RT_ASSERT(self_module != RT_NULL);
1560

1561 1562
    RT_DEBUG_LOG(RT_DEBUG_MODULE, ("rt_module_free_page 0x%x %d\n",
                                   page_ptr, npages));
1563 1564
    rt_page_free(page_ptr, npages);

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

1567
    for (i = 0; i < module->page_cnt; i ++)
1568 1569 1570 1571 1572
    {
        if (page[i].page_ptr == page_ptr)
        {
            if (page[i].npage == npages + 1)
            {
1573 1574 1575
                page[i].page_ptr +=
                    npages * RT_MM_PAGE_SIZE / sizeof(rt_uint32_t);
                page[i].npage    -= npages;
1576
            }
1577
            else if (page[i].npage == npages)
1578
            {
1579
                for (index = i; index < module->page_cnt-1; index ++)
1580 1581
                {
                    page[index].page_ptr = page[index + 1].page_ptr;
1582
                    page[index].npage    = page[index + 1].npage;
1583 1584
                }
                page[module->page_cnt - 1].page_ptr = RT_NULL;
1585
                page[module->page_cnt - 1].npage    = 0;
1586

1587
                module->page_cnt --;
1588 1589 1590
            }
            else
                RT_ASSERT(RT_FALSE);
1591
            self_module->page_cnt --;
1592 1593 1594 1595 1596

            return;
        }
    }

1597
    /* should not get here */
1598
    RT_ASSERT(RT_FALSE);
qiuyiuestc's avatar
qiuyiuestc 已提交
1599
}
qiuyiuestc's avatar
qiuyiuestc 已提交
1600

1601 1602 1603
/**
 * rt_module_malloc - allocate memory block in free list
 */
qiuyiuestc's avatar
qiuyiuestc 已提交
1604 1605
void *rt_module_malloc(rt_size_t size)
{
1606 1607 1608 1609
    struct rt_mem_head *b, *n, *up;
    struct rt_mem_head **prev;
    rt_uint32_t npage;
    rt_size_t nunits;
1610
    rt_module_t self_module;
1611

1612 1613
    self_module = rt_module_self();
    RT_ASSERT(self_module != RT_NULL);
1614

1615
    RT_DEBUG_NOT_IN_INTERRUPT;
1616

1617 1618 1619
    nunits = (size + sizeof(struct rt_mem_head) - 1) /
             sizeof(struct rt_mem_head)
             + 1;
qiuyiuestc's avatar
qiuyiuestc 已提交
1620

1621 1622
    RT_ASSERT(size != 0);
    RT_ASSERT(nunits != 0);
qiuyiuestc's avatar
qiuyiuestc 已提交
1623

1624
    rt_sem_take(&mod_sem, RT_WAITING_FOREVER);
qiuyiuestc's avatar
qiuyiuestc 已提交
1625

1626
    for (prev = (struct rt_mem_head **)&self_module->mem_list;
1627 1628
         (b = *prev) != RT_NULL;
         prev = &(b->next))
1629 1630 1631 1632
    {
        if (b->size > nunits)
        {
            /* split memory */
1633
            n       = b + nunits;
1634 1635 1636
            n->next = b->next;
            n->size = b->size - nunits;
            b->size = nunits;
1637
            *prev   = n;
qiuyiuestc's avatar
qiuyiuestc 已提交
1638

1639 1640
            RT_DEBUG_LOG(RT_DEBUG_MODULE, ("rt_module_malloc 0x%x, %d\n",
                                           b + 1, size));
1641
            rt_sem_release(&mod_sem);
D
dzzxzz 已提交
1642

1643 1644
            return (void *)(b + 1);
        }
qiuyiuestc's avatar
qiuyiuestc 已提交
1645

1646 1647 1648 1649
        if (b->size == nunits)
        {
            /* this node fit, remove this node */
            *prev = b->next;
qiuyiuestc's avatar
qiuyiuestc 已提交
1650

1651 1652
            RT_DEBUG_LOG(RT_DEBUG_MODULE, ("rt_module_malloc 0x%x, %d\n",
                                           b + 1, size));
B
bernard.xiong@gmail.com 已提交
1653

1654
            rt_sem_release(&mod_sem);
D
dzzxzz 已提交
1655

1656 1657 1658
            return (void *)(b + 1);
        }
    }
qiuyiuestc's avatar
qiuyiuestc 已提交
1659

1660
    /* allocate pages from system heap */
1661 1662
    npage = (size + sizeof(struct rt_mem_head) + RT_MM_PAGE_SIZE - 1) /
            RT_MM_PAGE_SIZE;
1663 1664
    if ((up = (struct rt_mem_head *)rt_module_malloc_page(npage)) == RT_NULL)
        return RT_NULL;
qiuyiuestc's avatar
qiuyiuestc 已提交
1665

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

1668
    for (prev = (struct rt_mem_head **)&self_module->mem_list;
1669 1670
         (b = *prev) != RT_NULL;
         prev = &(b->next))
1671 1672 1673 1674
    {
        if (b > up + up->size)
            break;
    }
qiuyiuestc's avatar
qiuyiuestc 已提交
1675

1676
    up->next = b;
1677
    *prev    = up;
qiuyiuestc's avatar
qiuyiuestc 已提交
1678

1679
    rt_sem_release(&mod_sem);
D
dzzxzz 已提交
1680

1681
    return rt_module_malloc(size);
qiuyiuestc's avatar
qiuyiuestc 已提交
1682 1683
}

1684 1685 1686
/**
 * rt_module_free - free memory block in free list
 */
qiuyiuestc's avatar
qiuyiuestc 已提交
1687 1688
void rt_module_free(rt_module_t module, void *addr)
{
1689 1690 1691 1692 1693 1694 1695 1696
    struct rt_mem_head *b, *n, *r;
    struct rt_mem_head **prev;

    RT_DEBUG_NOT_IN_INTERRUPT;

    RT_ASSERT(addr);
    RT_ASSERT((((rt_uint32_t)addr) & (sizeof(struct rt_mem_head) -1)) == 0);

1697
    RT_DEBUG_LOG(RT_DEBUG_MODULE, ("rt_module_free 0x%x\n", addr));
1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720

    rt_sem_take(&mod_sem, RT_WAITING_FOREVER);

    n = (struct rt_mem_head *)addr - 1;
    prev = (struct rt_mem_head **)&module->mem_list;

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

        if (b + b->size == n && ((rt_uint32_t)n % RT_MM_PAGE_SIZE != 0))
        {
            if (b + (b->size + n->size) == b->next)
            {
                b->size += b->next->size + n->size;
                b->next = b->next->next;
            }
            else
                b->size += n->size;

            if ((rt_uint32_t)b % RT_MM_PAGE_SIZE == 0)
            {
1721 1722
                int npage =
                    b->size * sizeof(struct rt_page_info) / RT_MM_PAGE_SIZE;
1723 1724 1725 1726
                if (npage > 0)
                {
                    if ((b->size * sizeof(struct rt_page_info) % RT_MM_PAGE_SIZE) != 0)
                    {
1727 1728 1729
                        rt_size_t nunits = npage *
                                           RT_MM_PAGE_SIZE /
                                           sizeof(struct rt_mem_head);
1730
                        /* split memory */
1731
                        r       = b + nunits;
1732 1733
                        r->next = b->next;
                        r->size = b->size - nunits;
1734
                        *prev   = r;
1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757
                    }
                    else
                    {
                        *prev = b->next;
                    }

                    rt_module_free_page(module, b, npage);
                }
            }

            /* unlock */
            rt_sem_release(&mod_sem);

            return;
        }

        if (b == n + n->size)
        {
            n->size = b->size + n->size;
            n->next = b->next;

            if ((rt_uint32_t)n % RT_MM_PAGE_SIZE == 0)
            {
1758 1759
                int npage =
                    n->size * sizeof(struct rt_page_info) / RT_MM_PAGE_SIZE;
1760 1761 1762 1763
                if (npage > 0)
                {
                    if ((n->size * sizeof(struct rt_page_info) % RT_MM_PAGE_SIZE) != 0)
                    {
1764 1765 1766
                        rt_size_t nunits = npage *
                                           RT_MM_PAGE_SIZE /
                                           sizeof(struct rt_mem_head);
1767
                        /* split memory */
1768
                        r       = n + nunits;
1769 1770
                        r->next = n->next;
                        r->size = n->size - nunits;
1771
                        *prev   = r;
1772
                    }
1773 1774
                    else
                        *prev = n->next;
1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802

                    rt_module_free_page(module, n, npage);
                }
            }
            else
            {
                *prev = n;
            }

            /* unlock */
            rt_sem_release(&mod_sem);

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

        prev = &(b->next);
    }

    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(module, n, npage);
            if (n->size % RT_MM_PAGE_SIZE != 0)
            {
1803 1804
                rt_size_t nunits =
                    npage * RT_MM_PAGE_SIZE / sizeof(struct rt_mem_head);
1805
                /* split memory */
1806
                r       = n + nunits;
1807 1808
                r->next = b;
                r->size = n->size - nunits;
1809
                *prev   = r;
1810 1811 1812 1813 1814 1815 1816 1817 1818 1819
            }
            else
            {
                *prev = b;
            }
        }
    }
    else
    {
        n->next = b;
1820
        *prev   = n;
1821 1822 1823 1824
    }

    /* unlock */
    rt_sem_release(&mod_sem);
qiuyiuestc's avatar
qiuyiuestc 已提交
1825 1826
}

1827 1828 1829
/**
 * rt_module_realloc - realloc memory block in free list
 */
qiuyiuestc's avatar
qiuyiuestc 已提交
1830 1831
void *rt_module_realloc(void *ptr, rt_size_t size)
{
1832 1833
    struct rt_mem_head *b, *p, *prev, *tmpp;
    rt_size_t nunits;
1834
    rt_module_t self_module;
1835

1836 1837
    self_module = rt_module_self();
    RT_ASSERT(self_module != RT_NULL);
1838 1839 1840 1841 1842 1843 1844

    RT_DEBUG_NOT_IN_INTERRUPT;

    if (!ptr)
        return rt_module_malloc(size);
    if (size == 0)
    {
1845
        rt_module_free(self_module, ptr);
1846 1847 1848 1849

        return RT_NULL;
    }

1850 1851 1852
    nunits = (size + sizeof(struct rt_mem_head) - 1) /
             sizeof(struct rt_mem_head)
             +1;
1853 1854 1855 1856 1857 1858 1859 1860 1861
    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
        {
1862
            p       = b + nunits;
1863 1864
            p->size = b->size - nunits;
            b->size = nunits;
1865
            rt_module_free(self_module, (void *)(p + 1));
1866 1867 1868 1869 1870 1871 1872

            return (void *)(b + 1);
        }
    }
    else
    {
        /* more space then required */
1873
        prev = (struct rt_mem_head *)self_module->mem_list;
1874 1875 1876 1877
        for (p = prev->next;
             p != (b->size + b) && p != RT_NULL;
             prev = p, p = p->next)
        {
1878
            break;
1879
        }
1880

1881
        /* available block after ap in freelist */
1882 1883 1884
        if (p != RT_NULL &&
            (p->size >= (nunits - (b->size))) &&
            p == (b + b->size))
1885 1886
        {
            /* perfect match */
1887
            if (p->size == (nunits - (b->size)))
1888
            {
1889
                b->size    = nunits;
1890 1891
                prev->next = p->next;
            }
1892
            else  /* more space then required, split block */
1893 1894 1895
            {
                /* pointer to old header */
                tmpp = p;
1896
                p    = b + nunits;
1897 1898 1899

                /* restoring old pointer */
                p->next = tmpp->next;
1900

1901
                /* new size for p */
1902 1903
                p->size    = tmpp->size + b->size - nunits;
                b->size    = nunits;
1904 1905
                prev->next = p;
            }
1906
            self_module->mem_list = (void *)prev;
1907 1908 1909 1910 1911

            return (void *)(b + 1);
        }
        else /* allocate new memory and copy old data */
        {
1912 1913
            if ((p = rt_module_malloc(size)) == RT_NULL)
                return RT_NULL;
1914
            rt_memmove(p, (b+1), ((b->size) * sizeof(struct rt_mem_head)));
1915
            rt_module_free(self_module, (void *)(b + 1));
1916 1917 1918 1919

            return (void *)(p);
        }
    }
qiuyiuestc's avatar
qiuyiuestc 已提交
1920
}
qiuyiuestc's avatar
qiuyiuestc 已提交
1921 1922 1923

#ifdef RT_USING_FINSH
#include <finsh.h>
1924

D
dzzxzz 已提交
1925
void list_memlist(const char *name)
qiuyiuestc's avatar
qiuyiuestc 已提交
1926
{
1927 1928 1929 1930 1931 1932 1933 1934
    rt_module_t module;
    struct rt_mem_head **prev;
    struct rt_mem_head *b;

    module = rt_module_find(name);
    if (module == RT_NULL)
        return;

1935
    for (prev = (struct rt_mem_head **)&module->mem_list;
1936 1937
         (b = *prev) != RT_NULL;
         prev = &(b->next))
1938 1939 1940
    {
        rt_kprintf("0x%x--%d\n", b, b->size * sizeof(struct rt_mem_head));
    }
qiuyiuestc's avatar
qiuyiuestc 已提交
1941 1942 1943
}
FINSH_FUNCTION_EXPORT(list_memlist, list module free memory information)

D
dzzxzz 已提交
1944
void list_mempage(const char *name)
qiuyiuestc's avatar
qiuyiuestc 已提交
1945
{
1946 1947 1948
    rt_module_t module;
    struct rt_page_info *page;
    int i;
qiuyiuestc's avatar
qiuyiuestc 已提交
1949

1950 1951 1952
    module = rt_module_find(name);
    if (module == RT_NULL)
        return;
qiuyiuestc's avatar
qiuyiuestc 已提交
1953

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

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

qiuyiuestc's avatar
qiuyiuestc 已提交
1964
#endif
qiuyiuestc's avatar
qiuyiuestc 已提交
1965 1966

#endif