381 lines
		
	
	
		
			9.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			381 lines
		
	
	
		
			9.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 * Copyright (c) 2006-2018, RT-Thread Development Team
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * SPDX-License-Identifier: Apache-2.0
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Change Logs:
							 | 
						||
| 
								 | 
							
								 * Date           Author       Notes
							 | 
						||
| 
								 | 
							
								 * 2006-03-12     Bernard      first version
							 | 
						||
| 
								 | 
							
								 * 2018-11-02     heyuanjie    fix complie error in iar
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <rtthread.h>
							 | 
						||
| 
								 | 
							
								#include <rthw.h>
							 | 
						||
| 
								 | 
							
								#include <dfs_posix.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifndef RT_USING_DFS
							 | 
						||
| 
								 | 
							
								    #error  "lwp need file system(RT_USING_DFS)"
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "lwp.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define DBG_ENABLE
							 | 
						||
| 
								 | 
							
								#define DBG_SECTION_NAME    "LWP"
							 | 
						||
| 
								 | 
							
								#define DBG_COLOR
							 | 
						||
| 
								 | 
							
								#define DBG_LEVEL           DBG_WARNING
							 | 
						||
| 
								 | 
							
								#include <rtdbg.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								extern void lwp_user_entry(void *args, const void *text, void *data);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * RT-Thread light-weight process
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								void lwp_set_kernel_sp(uint32_t *sp)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    struct rt_lwp *user_data;
							 | 
						||
| 
								 | 
							
								    user_data = (struct rt_lwp *)rt_thread_self()->lwp;
							 | 
						||
| 
								 | 
							
								    user_data->kernel_sp = sp;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								uint32_t *lwp_get_kernel_sp(void)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    struct rt_lwp *user_data;
							 | 
						||
| 
								 | 
							
								    user_data = (struct rt_lwp *)rt_thread_self()->lwp;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return user_data->kernel_sp;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static int lwp_argscopy(struct rt_lwp *lwp, int argc, char **argv)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    int size = sizeof(int)*3; /* store argc, argv, NULL */
							 | 
						||
| 
								 | 
							
								    int *args;
							 | 
						||
| 
								 | 
							
								    char *str;
							 | 
						||
| 
								 | 
							
								    char **new_argv;
							 | 
						||
| 
								 | 
							
								    int i;
							 | 
						||
| 
								 | 
							
								    int len;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    for (i = 0; i < argc; i ++)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        size += (rt_strlen(argv[i]) + 1);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    size  += (sizeof(int) * argc);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    args = (int*)rt_malloc(size);
							 | 
						||
| 
								 | 
							
								    if (args == RT_NULL)
							 | 
						||
| 
								 | 
							
								        return -1;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    str = (char*)((int)args + (argc + 3) * sizeof(int));
							 | 
						||
| 
								 | 
							
								    new_argv = (char**)&args[2];
							 | 
						||
| 
								 | 
							
								    args[0] = argc;
							 | 
						||
| 
								 | 
							
								    args[1] = (int)new_argv;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    for (i = 0; i < argc; i ++)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        len = rt_strlen(argv[i]) + 1;
							 | 
						||
| 
								 | 
							
								        new_argv[i] = str;
							 | 
						||
| 
								 | 
							
								        rt_memcpy(str, argv[i], len);
							 | 
						||
| 
								 | 
							
								        str += len;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    new_argv[i] = 0;
							 | 
						||
| 
								 | 
							
								    lwp->args = args;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static int lwp_load(const char *filename, struct rt_lwp *lwp, uint8_t *load_addr, size_t addr_size)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    int fd;
							 | 
						||
| 
								 | 
							
								    uint8_t *ptr;
							 | 
						||
| 
								 | 
							
								    int result = RT_EOK;
							 | 
						||
| 
								 | 
							
								    int nbytes;
							 | 
						||
| 
								 | 
							
								    struct lwp_header header;
							 | 
						||
| 
								 | 
							
								    struct lwp_chunk  chunk;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* check file name */
							 | 
						||
| 
								 | 
							
								    RT_ASSERT(filename != RT_NULL);
							 | 
						||
| 
								 | 
							
								    /* check lwp control block */
							 | 
						||
| 
								 | 
							
								    RT_ASSERT(lwp != RT_NULL);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (load_addr != RT_NULL)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        lwp->lwp_type = LWP_TYPE_FIX_ADDR;
							 | 
						||
| 
								 | 
							
								        ptr = load_addr;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    else
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        lwp->lwp_type = LWP_TYPE_DYN_ADDR;
							 | 
						||
| 
								 | 
							
								        ptr = RT_NULL;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* open lwp */
							 | 
						||
| 
								 | 
							
								    fd = open(filename, 0, O_RDONLY);
							 | 
						||
| 
								 | 
							
								    if (fd < 0)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        dbg_log(DBG_ERROR, "open file:%s failed!\n", filename);
							 | 
						||
| 
								 | 
							
								        result = -RT_ENOSYS;
							 | 
						||
| 
								 | 
							
								        goto _exit;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* read lwp header */
							 | 
						||
| 
								 | 
							
								    nbytes = read(fd, &header, sizeof(struct lwp_header));
							 | 
						||
| 
								 | 
							
								    if (nbytes != sizeof(struct lwp_header))
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        dbg_log(DBG_ERROR, "read lwp header return error size: %d!\n", nbytes);
							 | 
						||
| 
								 | 
							
								        result = -RT_EIO;
							 | 
						||
| 
								 | 
							
								        goto _exit;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* check file header */
							 | 
						||
| 
								 | 
							
								    if (header.magic != LWP_MAGIC)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        dbg_log(DBG_ERROR, "erro header magic number: 0x%02X\n", header.magic);
							 | 
						||
| 
								 | 
							
								        result = -RT_EINVAL;
							 | 
						||
| 
								 | 
							
								        goto _exit;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* read text chunk info */
							 | 
						||
| 
								 | 
							
								    nbytes = read(fd, &chunk, sizeof(struct lwp_chunk));
							 | 
						||
| 
								 | 
							
								    if (nbytes != sizeof(struct lwp_chunk))
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        dbg_log(DBG_ERROR, "read text chunk info failed!\n");
							 | 
						||
| 
								 | 
							
								        result = -RT_EIO;
							 | 
						||
| 
								 | 
							
								        goto _exit;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    dbg_log(DBG_LOG, "chunk name: %s, total len %d, data %d, need space %d!\n",
							 | 
						||
| 
								 | 
							
								            "text", /*chunk.name*/ chunk.total_len, chunk.data_len, chunk.data_len_space);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* load text */
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        lwp->text_size = RT_ALIGN(chunk.data_len_space, 4);
							 | 
						||
| 
								 | 
							
								        if (load_addr)
							 | 
						||
| 
								 | 
							
								            lwp->text_entry = ptr;
							 | 
						||
| 
								 | 
							
								        else
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								#ifdef RT_USING_CACHE
							 | 
						||
| 
								 | 
							
								            lwp->text_entry = (rt_uint8_t *)rt_malloc_align(lwp->text_size, RT_CPU_CACHE_LINE_SZ);
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								            lwp->text_entry = (rt_uint8_t *)rt_malloc(lwp->text_size);
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            if (lwp->text_entry == RT_NULL)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								                dbg_log(DBG_ERROR, "alloc text memory faild!\n");
							 | 
						||
| 
								 | 
							
								                result = -RT_ENOMEM;
							 | 
						||
| 
								 | 
							
								                goto _exit;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            else
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								                dbg_log(DBG_LOG, "lwp text malloc : %p, size: %d!\n", lwp->text_entry, lwp->text_size);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        dbg_log(DBG_INFO, "load text %d  => (0x%08x, 0x%08x)\n", lwp->text_size, (uint32_t)lwp->text_entry, (uint32_t)lwp->text_entry + lwp->text_size);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        nbytes = read(fd, lwp->text_entry, chunk.data_len);
							 | 
						||
| 
								 | 
							
								        if (nbytes != chunk.data_len)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            dbg_log(DBG_ERROR, "read text region from file failed!\n");
							 | 
						||
| 
								 | 
							
								            result = -RT_EIO;
							 | 
						||
| 
								 | 
							
								            goto _exit;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								#ifdef RT_USING_CACHE
							 | 
						||
| 
								 | 
							
								        else
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, lwp->text_entry, lwp->text_size);
							 | 
						||
| 
								 | 
							
								            rt_hw_cpu_icache_ops(RT_HW_CACHE_INVALIDATE, lwp->text_entry, lwp->text_size);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (ptr != RT_NULL) ptr += nbytes;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        /* skip text hole */
							 | 
						||
| 
								 | 
							
								        if ((chunk.total_len - sizeof(struct lwp_chunk) - chunk.data_len))
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            dbg_log(DBG_LOG, "skip text hole %d!\n", (chunk.total_len - sizeof(struct lwp_chunk) - chunk.data_len));
							 | 
						||
| 
								 | 
							
								            lseek(fd, (chunk.total_len - sizeof(struct lwp_chunk) - chunk.data_len), SEEK_CUR);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* load data */
							 | 
						||
| 
								 | 
							
								    nbytes = read(fd, &chunk, sizeof(struct lwp_chunk));
							 | 
						||
| 
								 | 
							
								    if (nbytes != sizeof(struct lwp_chunk))
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        dbg_log(DBG_ERROR, "read data chunk info failed!\n");
							 | 
						||
| 
								 | 
							
								        result = -RT_EIO;
							 | 
						||
| 
								 | 
							
								        goto _exit;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    dbg_log(DBG_LOG, "chunk name: %s, total len %d, data %d, need space %d!\n",
							 | 
						||
| 
								 | 
							
								            chunk.name, chunk.total_len, chunk.data_len, chunk.data_len_space);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        lwp->data_size = RT_ALIGN(chunk.data_len_space, 4);
							 | 
						||
| 
								 | 
							
								        if (load_addr)
							 | 
						||
| 
								 | 
							
								            lwp->data = ptr;
							 | 
						||
| 
								 | 
							
								        else
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            lwp->data = rt_malloc(lwp->data_size);
							 | 
						||
| 
								 | 
							
								            if (lwp->data == RT_NULL)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								                dbg_log(DBG_ERROR, "alloc data memory faild!\n");
							 | 
						||
| 
								 | 
							
								                result = -RT_ENOMEM;
							 | 
						||
| 
								 | 
							
								                goto _exit;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            else
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								                dbg_log(DBG_LOG, "lwp data malloc : %p, size: %d!\n", lwp->data, lwp->data_size);
							 | 
						||
| 
								 | 
							
								                rt_memset(lwp->data, 0, lwp->data_size);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        dbg_log(DBG_INFO, "load data %d => (0x%08x, 0x%08x)\n", lwp->data_size, (uint32_t)lwp->data, (uint32_t)lwp->data + lwp->data_size);
							 | 
						||
| 
								 | 
							
								        nbytes = read(fd, lwp->data, chunk.data_len);
							 | 
						||
| 
								 | 
							
								        if (nbytes != chunk.data_len)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            dbg_log(DBG_ERROR, "read data region from file failed!\n");
							 | 
						||
| 
								 | 
							
								            result = -RT_ERROR;
							 | 
						||
| 
								 | 
							
								            goto _exit;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								_exit:
							 | 
						||
| 
								 | 
							
								    if (fd >= 0)
							 | 
						||
| 
								 | 
							
								        close(fd);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (result != RT_EOK)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        if (lwp->lwp_type == LWP_TYPE_DYN_ADDR)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            dbg_log(DBG_ERROR, "lwp dynamic load faild, %d\n", result);
							 | 
						||
| 
								 | 
							
								            if (lwp->text_entry)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								                dbg_log(DBG_LOG, "lwp text free: %p\n", lwp->text_entry);
							 | 
						||
| 
								 | 
							
								#ifdef RT_USING_CACHE
							 | 
						||
| 
								 | 
							
								                rt_free_align(lwp->text_entry);
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								                rt_free(lwp->text_entry);
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            if (lwp->data)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								                dbg_log(DBG_LOG, "lwp data free: %p\n", lwp->data);
							 | 
						||
| 
								 | 
							
								                rt_free(lwp->data);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return result;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void lwp_cleanup(struct rt_thread *tid)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    struct rt_lwp *lwp;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    dbg_log(DBG_INFO, "thread: %s, stack_addr: %08X\n", tid->name, tid->stack_addr);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    lwp = (struct rt_lwp *)tid->lwp;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (lwp->lwp_type == LWP_TYPE_DYN_ADDR)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        dbg_log(DBG_INFO, "dynamic lwp\n");
							 | 
						||
| 
								 | 
							
								        if (lwp->text_entry)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            dbg_log(DBG_LOG, "lwp text free: %p\n", lwp->text_entry);
							 | 
						||
| 
								 | 
							
								#ifdef RT_USING_CACHE
							 | 
						||
| 
								 | 
							
								            rt_free_align(lwp->text_entry);
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								            rt_free(lwp->text_entry);
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        if (lwp->data)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            dbg_log(DBG_LOG, "lwp data free: %p\n", lwp->data);
							 | 
						||
| 
								 | 
							
								            rt_free(lwp->data);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    dbg_log(DBG_LOG, "lwp free memory pages\n");
							 | 
						||
| 
								 | 
							
								    rt_lwp_mem_deinit(lwp);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* cleanup fd table */
							 | 
						||
| 
								 | 
							
								    rt_free(lwp->fdt.fds);
							 | 
						||
| 
								 | 
							
								    rt_free(lwp->args);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    dbg_log(DBG_LOG, "lwp free: %p\n", lwp);
							 | 
						||
| 
								 | 
							
								    rt_free(lwp);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* TODO: cleanup fd table */
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void lwp_thread(void *parameter)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    rt_thread_t tid;
							 | 
						||
| 
								 | 
							
								    struct rt_lwp *lwp;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    lwp = (struct rt_lwp *)parameter;
							 | 
						||
| 
								 | 
							
								    rt_lwp_mem_init(lwp);
							 | 
						||
| 
								 | 
							
								    tid = rt_thread_self();
							 | 
						||
| 
								 | 
							
								    tid->lwp = lwp;
							 | 
						||
| 
								 | 
							
								    tid->cleanup = lwp_cleanup;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    lwp_user_entry(lwp->args, lwp->text_entry, lwp->data);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								struct rt_lwp *rt_lwp_self(void)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return (struct rt_lwp *)rt_thread_self()->lwp;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int exec(char *filename, int argc, char **argv)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    struct rt_lwp *lwp;
							 | 
						||
| 
								 | 
							
								    int result;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (filename == RT_NULL)
							 | 
						||
| 
								 | 
							
								        return -RT_ERROR;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    lwp = (struct rt_lwp *)rt_malloc(sizeof(struct rt_lwp));
							 | 
						||
| 
								 | 
							
								    if (lwp == RT_NULL)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        dbg_log(DBG_ERROR, "lwp struct out of memory!\n");
							 | 
						||
| 
								 | 
							
								        return -RT_ENOMEM;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    dbg_log(DBG_INFO, "lwp malloc : %p, size: %d!\n", lwp, sizeof(struct rt_lwp));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    rt_memset(lwp, 0, sizeof(*lwp));
							 | 
						||
| 
								 | 
							
								    if (lwp_argscopy(lwp, argc, argv) != 0)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        rt_free(lwp);
							 | 
						||
| 
								 | 
							
								        return -ENOMEM;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    result = lwp_load(filename, lwp, RT_NULL, 0);
							 | 
						||
| 
								 | 
							
								    if (result == RT_EOK)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        rt_thread_t tid;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        tid = rt_thread_create("user", lwp_thread, (void *)lwp,
							 | 
						||
| 
								 | 
							
								                               1024 * 4, 2, 200);
							 | 
						||
| 
								 | 
							
								        if (tid != RT_NULL)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            dbg_log(DBG_LOG, "lwp kernel => (0x%08x, 0x%08x)\n", (rt_uint32_t)tid->stack_addr, (rt_uint32_t)tid->stack_addr + tid->stack_size);
							 | 
						||
| 
								 | 
							
								            rt_thread_startup(tid);
							 | 
						||
| 
								 | 
							
								            return RT_EOK;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        else
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								#ifdef RT_USING_CACHE
							 | 
						||
| 
								 | 
							
								            rt_free_align(lwp->text_entry);
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								            rt_free(lwp->text_entry);
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								            rt_free(lwp->data);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    rt_free(lwp->args);
							 | 
						||
| 
								 | 
							
								    rt_free(lwp);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return -RT_ERROR;
							 | 
						||
| 
								 | 
							
								}
							 |