module_win32.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2013-02-26 prife first version for win32
  9. */
  10. #include <rthw.h>
  11. #include <rtthread.h>
  12. #include <rtm.h>
  13. #ifdef RT_USING_MODULE
  14. void rt_module_init_object_container(struct rt_module *module)
  15. {
  16. RT_ASSERT(module != RT_NULL);
  17. /* initialize object container - thread */
  18. rt_list_init(&(module->module_object[RT_Object_Class_Thread].object_list));
  19. module->module_object[RT_Object_Class_Thread].object_size = sizeof(struct rt_thread);
  20. module->module_object[RT_Object_Class_Thread].type = RT_Object_Class_Thread;
  21. #ifdef RT_USING_SEMAPHORE
  22. /* initialize object container - semaphore */
  23. rt_list_init(&(module->module_object[RT_Object_Class_Semaphore].object_list));
  24. module->module_object[RT_Object_Class_Semaphore].object_size = sizeof(struct rt_semaphore);
  25. module->module_object[RT_Object_Class_Semaphore].type = RT_Object_Class_Semaphore;
  26. #endif
  27. #ifdef RT_USING_MUTEX
  28. /* initialize object container - mutex */
  29. rt_list_init(&(module->module_object[RT_Object_Class_Mutex].object_list));
  30. module->module_object[RT_Object_Class_Mutex].object_size = sizeof(struct rt_mutex);
  31. module->module_object[RT_Object_Class_Mutex].type = RT_Object_Class_Mutex;
  32. #endif
  33. #ifdef RT_USING_EVENT
  34. /* initialize object container - event */
  35. rt_list_init(&(module->module_object[RT_Object_Class_Event].object_list));
  36. module->module_object[RT_Object_Class_Event].object_size = sizeof(struct rt_event);
  37. module->module_object[RT_Object_Class_Event].type = RT_Object_Class_Event;
  38. #endif
  39. #ifdef RT_USING_MAILBOX
  40. /* initialize object container - mailbox */
  41. rt_list_init(&(module->module_object[RT_Object_Class_MailBox].object_list));
  42. module->module_object[RT_Object_Class_MailBox].object_size = sizeof(struct rt_mailbox);
  43. module->module_object[RT_Object_Class_MailBox].type = RT_Object_Class_MailBox;
  44. #endif
  45. #ifdef RT_USING_MESSAGEQUEUE
  46. /* initialize object container - message queue */
  47. rt_list_init(&(module->module_object[RT_Object_Class_MessageQueue].object_list));
  48. module->module_object[RT_Object_Class_MessageQueue].object_size = sizeof(struct rt_messagequeue);
  49. module->module_object[RT_Object_Class_MessageQueue].type = RT_Object_Class_MessageQueue;
  50. #endif
  51. #ifdef RT_USING_MEMHEAP
  52. /* initialize object container - memory heap */
  53. rt_list_init(&(module->module_object[RT_Object_Class_MemHeap].object_list));
  54. module->module_object[RT_Object_Class_MemHeap].object_size = sizeof(struct rt_memheap);
  55. module->module_object[RT_Object_Class_MemHeap].type = RT_Object_Class_MemHeap;
  56. #endif
  57. #ifdef RT_USING_MEMPOOL
  58. /* initialize object container - memory pool */
  59. rt_list_init(&(module->module_object[RT_Object_Class_MemPool].object_list));
  60. module->module_object[RT_Object_Class_MemPool].object_size = sizeof(struct rt_mempool);
  61. module->module_object[RT_Object_Class_MemPool].type = RT_Object_Class_MemPool;
  62. #endif
  63. #ifdef RT_USING_DEVICE
  64. /* initialize object container - device */
  65. rt_list_init(&(module->module_object[RT_Object_Class_Device].object_list));
  66. module->module_object[RT_Object_Class_Device].object_size = sizeof(struct rt_device);
  67. module->module_object[RT_Object_Class_Device].type = RT_Object_Class_Device;
  68. #endif
  69. /* initialize object container - timer */
  70. rt_list_init(&(module->module_object[RT_Object_Class_Timer].object_list));
  71. module->module_object[RT_Object_Class_Timer].object_size = sizeof(struct rt_timer);
  72. module->module_object[RT_Object_Class_Timer].type = RT_Object_Class_Timer;
  73. }
  74. #ifdef RT_USING_HOOK
  75. static void (*rt_module_load_hook)(rt_module_t module);
  76. static void (*rt_module_unload_hook)(rt_module_t module);
  77. /**
  78. * @addtogroup Hook
  79. */
  80. /*@{*/
  81. /**
  82. * This function will set a hook function, which will be invoked when module
  83. * be loaded to system.
  84. *
  85. * @param hook the hook function
  86. */
  87. void rt_module_load_sethook(void (*hook)(rt_module_t module))
  88. {
  89. rt_module_load_hook = hook;
  90. }
  91. /**
  92. * This function will set a hook function, which will be invoked when module
  93. * be unloaded from system.
  94. *
  95. * @param hook the hook function
  96. */
  97. void rt_module_unload_sethook(void (*hook)(rt_module_t module))
  98. {
  99. rt_module_unload_hook = hook;
  100. }
  101. /*@}*/
  102. #endif
  103. /**
  104. * @ingroup SystemInit
  105. *
  106. * This function will initialize system module
  107. */
  108. int rt_system_module_init(void)
  109. {
  110. return 0;
  111. }
  112. /**
  113. * This function will return self module object
  114. *
  115. * @return the self module object
  116. */
  117. rt_module_t rt_module_self(void)
  118. {
  119. rt_thread_t tid;
  120. tid = rt_thread_self();
  121. if (tid == RT_NULL)
  122. return RT_NULL;
  123. /* return current module */
  124. return (rt_module_t)tid->module_id;
  125. }
  126. RTM_EXPORT(rt_module_self);
  127. /**
  128. * This function will find the specified module.
  129. *
  130. * @param name the name of module finding
  131. *
  132. * @return the module
  133. */
  134. rt_module_t rt_module_find(const char *name)
  135. {
  136. struct rt_object_information *information;
  137. struct rt_object *object;
  138. struct rt_list_node *node;
  139. RT_DEBUG_NOT_IN_INTERRUPT;
  140. /* enter critical */
  141. rt_enter_critical();
  142. /* try to find device object */
  143. information = rt_object_get_information(RT_Object_Class_Module);
  144. RT_ASSERT(information != RT_NULL);
  145. for (node = information->object_list.next;
  146. node != &(information->object_list);
  147. node = node->next)
  148. {
  149. object = rt_list_entry(node, struct rt_object, list);
  150. if (rt_strncmp(object->name, name, RT_NAME_MAX) == 0)
  151. {
  152. /* leave critical */
  153. rt_exit_critical();
  154. return (rt_module_t)object;
  155. }
  156. }
  157. /* leave critical */
  158. rt_exit_critical();
  159. /* not found */
  160. return RT_NULL;
  161. }
  162. RTM_EXPORT(rt_module_find);
  163. #ifdef RT_USING_DFS
  164. #include <windows.h>
  165. #include <dfs_posix.h>
  166. extern char * dfs_win32_dirdup(char * path);
  167. static char* _module_name(const char *path)
  168. {
  169. const char *first, *end, *ptr;
  170. char *name;
  171. int size;
  172. ptr = (char *)path;
  173. first = ptr;
  174. end = path + rt_strlen(path);
  175. while (*ptr != '\0')
  176. {
  177. if (*ptr == '/')
  178. first = ptr + 1;
  179. if (*ptr == '.')
  180. end = ptr - 1;
  181. ptr ++;
  182. }
  183. size = end - first + 1;
  184. name = rt_malloc(size);
  185. rt_strncpy(name, first, size);
  186. name[size] = '\0';
  187. return name;
  188. }
  189. typedef int (*appentry_t)(void);
  190. /**
  191. * This function will load a module from a file
  192. *
  193. * @param path the full path of application module
  194. *
  195. * @return the module object
  196. */
  197. rt_module_t rt_module_open(const char *path)
  198. {
  199. struct dfs_filesystem *fs;
  200. appentry_t fptr;
  201. HINSTANCE hinstlib;
  202. rt_module_t module;
  203. char * winpath = RT_NULL;
  204. char * name = RT_NULL;
  205. RT_DEBUG_NOT_IN_INTERRUPT;
  206. /* check parameters */
  207. RT_ASSERT(path != RT_NULL);
  208. /* app module should only in DFS_WIN32 */
  209. fs = dfs_filesystem_lookup(path);
  210. if ((fs == RT_NULL) || (strcmp(fs->ops->name,"wdir") != 0))
  211. {
  212. rt_kprintf("invalid path: %s\n", path);
  213. return RT_NULL;
  214. }
  215. /* change path */
  216. // len = strlen(path+1);
  217. if ((winpath = dfs_win32_dirdup((char *)path)) == RT_NULL)
  218. {
  219. rt_kprintf("out of memory, exit");
  220. return RT_NULL;
  221. }
  222. hinstlib = LoadLibrary(winpath);
  223. if (hinstlib == NULL)
  224. {
  225. rt_kprintf("error: unable to open %s\n", winpath);
  226. return RT_NULL;
  227. }
  228. fptr = (appentry_t)GetProcAddress(hinstlib, "main");
  229. if (fptr == NULL)
  230. {
  231. rt_kprintf("error: unable to find function in %s\n", winpath);
  232. FreeLibrary(hinstlib);
  233. return RT_NULL;
  234. }
  235. /* get the name of the module */
  236. name = _module_name(path);
  237. /* allocate module */
  238. module = (struct rt_module *)rt_object_allocate(RT_Object_Class_Module, name);
  239. if (!module) return RT_NULL;
  240. module->nref = 0;
  241. module->module_entry = fptr;
  242. /* init module object container */
  243. rt_module_init_object_container(module);
  244. /* increase module reference count */
  245. module->nref ++;
  246. if (module->module_entry != 0)
  247. {
  248. #ifdef RT_USING_SLAB
  249. /* init module memory allocator */
  250. module->mem_list = RT_NULL;
  251. /* create page array */
  252. module->page_array =
  253. (void *)rt_malloc(PAGE_COUNT_MAX * sizeof(struct rt_page_info));
  254. module->page_cnt = 0;
  255. #endif
  256. /* create module thread */
  257. module->module_thread =
  258. rt_thread_create(name,
  259. (void(*)(void *))module->module_entry, RT_NULL,
  260. 2048, RT_THREAD_PRIORITY_MAX - 2, 10);
  261. RT_DEBUG_LOG(RT_DEBUG_MODULE, ("thread entry 0x%x\n",
  262. module->module_entry));
  263. /* set module id */
  264. module->module_thread->module_id = (void *)module;
  265. module->parent.flag = RT_MODULE_FLAG_WITHENTRY;
  266. /* startup module thread */
  267. rt_thread_startup(module->module_thread);
  268. }
  269. else
  270. {
  271. /* without entry point */
  272. module->parent.flag |= RT_MODULE_FLAG_WITHOUTENTRY;
  273. }
  274. #ifdef RT_USING_HOOK
  275. if (rt_module_load_hook != RT_NULL)
  276. {
  277. rt_module_load_hook(module);
  278. }
  279. #endif
  280. rt_free(name);
  281. return module;
  282. /* FreeLibrary(hinstlib); */
  283. }
  284. #if defined(RT_USING_FINSH)
  285. #include <finsh.h>
  286. FINSH_FUNCTION_EXPORT_ALIAS(rt_module_open, exec, exec module from a file);
  287. #endif
  288. #endif
  289. #define RT_MODULE_ARG_MAX 8
  290. static int _rt_module_split_arg(char* cmd, rt_size_t length, char* argv[])
  291. {
  292. int argc = 0;
  293. char *ptr = cmd;
  294. while ((ptr - cmd) < length)
  295. {
  296. /* strip bank and tab */
  297. while ((*ptr == ' ' || *ptr == '\t') && (ptr -cmd)< length)
  298. *ptr++ = '\0';
  299. /* check whether it's the end of line */
  300. if ((ptr - cmd)>= length) break;
  301. /* handle string with quote */
  302. if (*ptr == '"')
  303. {
  304. argv[argc++] = ++ptr;
  305. /* skip this string */
  306. while (*ptr != '"' && (ptr-cmd) < length)
  307. if (*ptr ++ == '\\') ptr ++;
  308. if ((ptr - cmd) >= length) break;
  309. /* skip '"' */
  310. *ptr ++ = '\0';
  311. }
  312. else
  313. {
  314. argv[argc++] = ptr;
  315. while ((*ptr != ' ' && *ptr != '\t') && (ptr - cmd) < length)
  316. ptr ++;
  317. }
  318. if (argc >= RT_MODULE_ARG_MAX) break;
  319. }
  320. return argc;
  321. }
  322. /* module main thread entry */
  323. static void module_main_entry(void* parameter)
  324. {
  325. int argc;
  326. char *argv[RT_MODULE_ARG_MAX];
  327. typedef int (*main_func_t)(int argc, char** argv);
  328. rt_module_t module = (rt_module_t) parameter;
  329. if (module == RT_NULL || module->module_cmd_line == RT_NULL) return;
  330. rt_memset(argv, 0x00, sizeof(argv));
  331. argc = _rt_module_split_arg((char*)module->module_cmd_line, module->module_cmd_size, argv);
  332. if (argc == 0) return ;
  333. /* do the main function */
  334. ((main_func_t)module->module_entry)(argc, argv);
  335. return;
  336. }
  337. /**
  338. * This function will do a executable program with main function and parameters.
  339. *
  340. * @param path the full path of application module
  341. * @param cmd_line the command line of program
  342. * @param size the size of command line of program
  343. *
  344. * @return the module object
  345. */
  346. rt_module_t rt_module_exec_cmd(const char *path, const char* cmd_line, int line_size)
  347. {
  348. struct dfs_filesystem *fs;
  349. appentry_t fptr;
  350. HINSTANCE hinstlib;
  351. rt_module_t module;
  352. char * winpath = RT_NULL;
  353. char * name = RT_NULL;
  354. char *full_path = RT_NULL;
  355. RT_DEBUG_NOT_IN_INTERRUPT;
  356. /* check parameters */
  357. RT_ASSERT(path != RT_NULL);
  358. if (*path != '/')
  359. {
  360. full_path = dfs_normalize_path(RT_NULL, path);
  361. }
  362. else
  363. {
  364. full_path = (const char*)path;
  365. }
  366. /* app module should only in DFS_WIN32 */
  367. fs = dfs_filesystem_lookup(full_path);
  368. if ((fs == RT_NULL) || (strcmp(fs->ops->name,"wdir") != 0))
  369. {
  370. rt_kprintf("invalid path: %s\n", path);
  371. goto __exit;
  372. }
  373. /* change path */
  374. // len = strlen(full_path + 1);
  375. if ((winpath = dfs_win32_dirdup((char *)full_path)) == RT_NULL)
  376. {
  377. rt_kprintf("out of memory, exit", path);
  378. goto __exit;
  379. }
  380. hinstlib = LoadLibrary(winpath);
  381. if (hinstlib == NULL)
  382. {
  383. rt_kprintf("error: unable to open %s\n", winpath);
  384. goto __exit;
  385. }
  386. fptr = (appentry_t)GetProcAddress(hinstlib, "main");
  387. if (fptr == NULL)
  388. {
  389. rt_kprintf("error: unable to find function in %s\n", winpath);
  390. FreeLibrary(hinstlib);
  391. goto __exit;
  392. }
  393. /* release winpath */
  394. rt_free(winpath);
  395. /* get the name of the module */
  396. name = _module_name(path);
  397. /* allocate module */
  398. module = (struct rt_module *)rt_object_allocate(RT_Object_Class_Module, name);
  399. if (!module)
  400. {
  401. goto __exit;
  402. }
  403. module->nref = 0;
  404. module->module_entry = fptr;
  405. /* init module object container */
  406. rt_module_init_object_container(module);
  407. /* increase module reference count */
  408. module->nref ++;
  409. if (module->module_entry != 0)
  410. {
  411. /* set module argument */
  412. module->module_cmd_line = (rt_uint8_t*)rt_malloc(line_size + 1);
  413. rt_memcpy(module->module_cmd_line, cmd_line, line_size);
  414. module->module_cmd_line[line_size] = '\0';
  415. module->module_cmd_size = line_size;
  416. #ifdef RT_USING_SLAB
  417. /* init module memory allocator */
  418. module->mem_list = RT_NULL;
  419. /* create page array */
  420. module->page_array =
  421. (void *)rt_malloc(PAGE_COUNT_MAX * sizeof(struct rt_page_info));
  422. module->page_cnt = 0;
  423. #endif
  424. /* create module thread */
  425. module->module_thread = rt_thread_create(name,
  426. module_main_entry, module,
  427. 2048, RT_THREAD_PRIORITY_MAX - 2, 10);
  428. /* set module id */
  429. module->module_thread->module_id = (void *)module;
  430. module->parent.flag = RT_MODULE_FLAG_WITHENTRY;
  431. /* startup module thread */
  432. rt_thread_startup(module->module_thread);
  433. }
  434. else
  435. {
  436. /* without entry point */
  437. module->parent.flag |= RT_MODULE_FLAG_WITHOUTENTRY;
  438. }
  439. #ifdef RT_USING_HOOK
  440. if (rt_module_load_hook != RT_NULL)
  441. {
  442. rt_module_load_hook(module);
  443. }
  444. #endif
  445. rt_free(name);
  446. return module;
  447. __exit:
  448. if (full_path != path) rt_free(full_path);
  449. if (name != RT_NULL) rt_free(full_path);
  450. if (winpath != RT_NULL)rt_free(winpath);
  451. return RT_NULL;
  452. /* FreeLibrary(hinstlib); */
  453. }
  454. rt_err_t rt_module_destroy(rt_module_t module)
  455. {
  456. return 0;
  457. }
  458. rt_err_t rt_module_unload(rt_module_t module)
  459. {
  460. return 0;
  461. }
  462. #endif