565 lines
14 KiB
C
565 lines
14 KiB
C
/*
|
|
* Copyright (c) 2006-2021, RT-Thread Development Team
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* Change Logs:
|
|
* Date Author Notes
|
|
* 2013-02-26 prife first version for win32
|
|
*/
|
|
|
|
#include <rthw.h>
|
|
#include <rtthread.h>
|
|
#include <rtm.h>
|
|
|
|
#ifdef RT_USING_MODULE
|
|
void rt_module_init_object_container(struct rt_module *module)
|
|
{
|
|
RT_ASSERT(module != RT_NULL);
|
|
|
|
/* 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;
|
|
|
|
#ifdef RT_USING_SEMAPHORE
|
|
/* 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;
|
|
#endif
|
|
|
|
#ifdef RT_USING_MUTEX
|
|
/* 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;
|
|
#endif
|
|
|
|
#ifdef RT_USING_EVENT
|
|
/* 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;
|
|
#endif
|
|
|
|
#ifdef RT_USING_MAILBOX
|
|
/* 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;
|
|
#endif
|
|
|
|
#ifdef RT_USING_MESSAGEQUEUE
|
|
/* 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;
|
|
#endif
|
|
|
|
#ifdef RT_USING_MEMHEAP
|
|
/* 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;
|
|
#endif
|
|
|
|
#ifdef RT_USING_MEMPOOL
|
|
/* 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;
|
|
#endif
|
|
|
|
#ifdef RT_USING_DEVICE
|
|
/* 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;
|
|
#endif
|
|
|
|
/* 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;
|
|
}
|
|
|
|
#ifdef RT_USING_HOOK
|
|
static void (*rt_module_load_hook)(rt_module_t module);
|
|
static void (*rt_module_unload_hook)(rt_module_t module);
|
|
|
|
/**
|
|
* @addtogroup Hook
|
|
*/
|
|
|
|
/*@{*/
|
|
|
|
/**
|
|
* This function will set a hook function, which will be invoked when module
|
|
* be loaded to system.
|
|
*
|
|
* @param hook the hook function
|
|
*/
|
|
void rt_module_load_sethook(void (*hook)(rt_module_t module))
|
|
{
|
|
rt_module_load_hook = hook;
|
|
}
|
|
|
|
/**
|
|
* This function will set a hook function, which will be invoked when module
|
|
* be unloaded from system.
|
|
*
|
|
* @param hook the hook function
|
|
*/
|
|
void rt_module_unload_sethook(void (*hook)(rt_module_t module))
|
|
{
|
|
rt_module_unload_hook = hook;
|
|
}
|
|
|
|
/*@}*/
|
|
#endif
|
|
|
|
/**
|
|
* @ingroup SystemInit
|
|
*
|
|
* This function will initialize system module
|
|
*/
|
|
int rt_system_module_init(void)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* This function will return self module object
|
|
*
|
|
* @return the self module object
|
|
*/
|
|
rt_module_t rt_module_self(void)
|
|
{
|
|
rt_thread_t tid;
|
|
|
|
tid = rt_thread_self();
|
|
if (tid == RT_NULL)
|
|
return RT_NULL;
|
|
|
|
/* return current module */
|
|
return (rt_module_t)tid->module_id;
|
|
}
|
|
RTM_EXPORT(rt_module_self);
|
|
|
|
/**
|
|
* This function will find the specified module.
|
|
*
|
|
* @param name the name of module finding
|
|
*
|
|
* @return the module
|
|
*/
|
|
rt_module_t rt_module_find(const char *name)
|
|
{
|
|
struct rt_object_information *information;
|
|
struct rt_object *object;
|
|
struct rt_list_node *node;
|
|
|
|
RT_DEBUG_NOT_IN_INTERRUPT;
|
|
|
|
/* enter critical */
|
|
rt_enter_critical();
|
|
|
|
/* try to find device object */
|
|
information = rt_object_get_information(RT_Object_Class_Module);
|
|
RT_ASSERT(information != RT_NULL);
|
|
|
|
for (node = information->object_list.next;
|
|
node != &(information->object_list);
|
|
node = node->next)
|
|
{
|
|
object = rt_list_entry(node, struct rt_object, list);
|
|
if (rt_strncmp(object->name, name, RT_NAME_MAX) == 0)
|
|
{
|
|
/* leave critical */
|
|
rt_exit_critical();
|
|
|
|
return (rt_module_t)object;
|
|
}
|
|
}
|
|
|
|
/* leave critical */
|
|
rt_exit_critical();
|
|
|
|
/* not found */
|
|
return RT_NULL;
|
|
}
|
|
RTM_EXPORT(rt_module_find);
|
|
|
|
#ifdef RT_USING_DFS
|
|
#include <windows.h>
|
|
#include <dfs_file.h>
|
|
#include <unistd.h>
|
|
#include <stdio.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/statfs.h>
|
|
extern char * dfs_win32_dirdup(char * path);
|
|
static char* _module_name(const char *path)
|
|
{
|
|
const char *first, *end, *ptr;
|
|
char *name;
|
|
int size;
|
|
|
|
ptr = (char *)path;
|
|
first = ptr;
|
|
end = path + rt_strlen(path);
|
|
|
|
while (*ptr != '\0')
|
|
{
|
|
if (*ptr == '/')
|
|
first = ptr + 1;
|
|
if (*ptr == '.')
|
|
end = ptr - 1;
|
|
|
|
ptr ++;
|
|
}
|
|
|
|
size = end - first + 1;
|
|
name = rt_malloc(size);
|
|
rt_strncpy(name, first, size);
|
|
name[size] = '\0';
|
|
|
|
return name;
|
|
}
|
|
|
|
typedef int (*appentry_t)(void);
|
|
/**
|
|
* This function will load a module from a file
|
|
*
|
|
* @param path the full path of application module
|
|
*
|
|
* @return the module object
|
|
*/
|
|
rt_module_t rt_module_open(const char *path)
|
|
{
|
|
struct dfs_filesystem *fs;
|
|
appentry_t fptr;
|
|
HINSTANCE hinstlib;
|
|
rt_module_t module;
|
|
|
|
char * winpath = RT_NULL;
|
|
char * name = RT_NULL;
|
|
|
|
RT_DEBUG_NOT_IN_INTERRUPT;
|
|
|
|
/* check parameters */
|
|
RT_ASSERT(path != RT_NULL);
|
|
|
|
/* app module should only in DFS_WIN32 */
|
|
fs = dfs_filesystem_lookup(path);
|
|
if ((fs == RT_NULL) || (strcmp(fs->ops->name,"wdir") != 0))
|
|
{
|
|
rt_kprintf("invalid path: %s\n", path);
|
|
return RT_NULL;
|
|
}
|
|
|
|
/* change path */
|
|
// len = strlen(path+1);
|
|
if ((winpath = dfs_win32_dirdup((char *)path)) == RT_NULL)
|
|
{
|
|
rt_kprintf("out of memory, exit");
|
|
return RT_NULL;
|
|
}
|
|
|
|
hinstlib = LoadLibrary(winpath);
|
|
if (hinstlib == NULL)
|
|
{
|
|
rt_kprintf("error: unable to open %s\n", winpath);
|
|
return RT_NULL;
|
|
}
|
|
|
|
fptr = (appentry_t)GetProcAddress(hinstlib, "main");
|
|
if (fptr == NULL)
|
|
{
|
|
rt_kprintf("error: unable to find function in %s\n", winpath);
|
|
FreeLibrary(hinstlib);
|
|
return RT_NULL;
|
|
}
|
|
|
|
/* get the name of the module */
|
|
name = _module_name(path);
|
|
|
|
/* allocate module */
|
|
module = (struct rt_module *)rt_object_allocate(RT_Object_Class_Module, name);
|
|
if (!module) return RT_NULL;
|
|
|
|
module->nref = 0;
|
|
module->module_entry = fptr;
|
|
|
|
/* init module object container */
|
|
rt_module_init_object_container(module);
|
|
|
|
/* increase module reference count */
|
|
module->nref ++;
|
|
|
|
if (module->module_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
|
|
|
|
/* create module thread */
|
|
module->module_thread =
|
|
rt_thread_create(name,
|
|
(void(*)(void *))module->module_entry, RT_NULL,
|
|
2048, RT_THREAD_PRIORITY_MAX - 2, 10);
|
|
|
|
RT_DEBUG_LOG(RT_DEBUG_MODULE, ("thread entry 0x%x\n",
|
|
module->module_entry));
|
|
|
|
/* set module id */
|
|
module->module_thread->module_id = (void *)module;
|
|
module->parent.flag = RT_MODULE_FLAG_WITHENTRY;
|
|
|
|
/* startup module 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
|
|
|
|
rt_free(name);
|
|
return module;
|
|
/* FreeLibrary(hinstlib); */
|
|
}
|
|
|
|
#if defined(RT_USING_FINSH)
|
|
#include <finsh.h>
|
|
FINSH_FUNCTION_EXPORT_ALIAS(rt_module_open, exec, exec module from a file);
|
|
#endif
|
|
|
|
#endif
|
|
|
|
#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 do a executable program with main function and parameters.
|
|
*
|
|
* @param path the full path of application module
|
|
* @param cmd_line the command line of program
|
|
* @param size the size of command line of program
|
|
*
|
|
* @return the module object
|
|
*/
|
|
rt_module_t rt_module_exec_cmd(const char *path, const char* cmd_line, int line_size)
|
|
{
|
|
struct dfs_filesystem *fs;
|
|
appentry_t fptr;
|
|
HINSTANCE hinstlib;
|
|
rt_module_t module;
|
|
|
|
char * winpath = RT_NULL;
|
|
char * name = RT_NULL;
|
|
char *full_path = RT_NULL;
|
|
|
|
RT_DEBUG_NOT_IN_INTERRUPT;
|
|
|
|
/* check parameters */
|
|
RT_ASSERT(path != RT_NULL);
|
|
|
|
if (*path != '/')
|
|
{
|
|
full_path = dfs_normalize_path(RT_NULL, path);
|
|
}
|
|
else
|
|
{
|
|
full_path = (const char*)path;
|
|
}
|
|
|
|
/* app module should only in DFS_WIN32 */
|
|
fs = dfs_filesystem_lookup(full_path);
|
|
if ((fs == RT_NULL) || (strcmp(fs->ops->name,"wdir") != 0))
|
|
{
|
|
rt_kprintf("invalid path: %s\n", path);
|
|
goto __exit;
|
|
}
|
|
|
|
/* change path */
|
|
// len = strlen(full_path + 1);
|
|
if ((winpath = dfs_win32_dirdup((char *)full_path)) == RT_NULL)
|
|
{
|
|
rt_kprintf("out of memory, exit", path);
|
|
goto __exit;
|
|
}
|
|
|
|
hinstlib = LoadLibrary(winpath);
|
|
if (hinstlib == NULL)
|
|
{
|
|
rt_kprintf("error: unable to open %s\n", winpath);
|
|
goto __exit;
|
|
}
|
|
|
|
fptr = (appentry_t)GetProcAddress(hinstlib, "main");
|
|
if (fptr == NULL)
|
|
{
|
|
rt_kprintf("error: unable to find function in %s\n", winpath);
|
|
FreeLibrary(hinstlib);
|
|
goto __exit;
|
|
}
|
|
|
|
/* release winpath */
|
|
rt_free(winpath);
|
|
|
|
/* get the name of the module */
|
|
name = _module_name(path);
|
|
|
|
/* allocate module */
|
|
module = (struct rt_module *)rt_object_allocate(RT_Object_Class_Module, name);
|
|
if (!module)
|
|
{
|
|
goto __exit;
|
|
}
|
|
|
|
module->nref = 0;
|
|
module->module_entry = fptr;
|
|
|
|
/* init module object container */
|
|
rt_module_init_object_container(module);
|
|
|
|
/* increase module reference count */
|
|
module->nref ++;
|
|
|
|
if (module->module_entry != 0)
|
|
{
|
|
/* 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;
|
|
|
|
#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
|
|
|
|
/* 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 module 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
|
|
|
|
rt_free(name);
|
|
return module;
|
|
|
|
__exit:
|
|
if (full_path != path) rt_free(full_path);
|
|
if (name != RT_NULL) rt_free(full_path);
|
|
if (winpath != RT_NULL)rt_free(winpath);
|
|
|
|
return RT_NULL;
|
|
/* FreeLibrary(hinstlib); */
|
|
}
|
|
|
|
rt_err_t rt_module_destroy(rt_module_t module)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
rt_err_t rt_module_unload(rt_module_t module)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
#endif
|