cmd.c 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195
  1. /*
  2. * Copyright (c) 2006-2022, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2006-04-30 Bernard first implementation
  9. * 2006-05-04 Bernard add list_thread,
  10. * list_sem,
  11. * list_timer
  12. * 2006-05-20 Bernard add list_mutex,
  13. * list_mailbox,
  14. * list_msgqueue,
  15. * list_event,
  16. * list_fevent,
  17. * list_mempool
  18. * 2006-06-03 Bernard display stack information in list_thread
  19. * 2006-08-10 Bernard change version to invoke rt_show_version
  20. * 2008-09-10 Bernard update the list function for finsh syscall
  21. * list and sysvar list
  22. * 2009-05-30 Bernard add list_device
  23. * 2010-04-21 yi.qiu add list_module
  24. * 2012-04-29 goprife improve the command line auto-complete feature.
  25. * 2012-06-02 lgnq add list_memheap
  26. * 2012-10-22 Bernard add MS VC++ patch.
  27. * 2016-06-02 armink beautify the list_thread command
  28. * 2018-11-22 Jesven list_thread add smp support
  29. * 2018-12-27 Jesven Fix the problem that disable interrupt too long in list_thread
  30. * Provide protection for the "first layer of objects" when list_*
  31. * 2020-04-07 chenhui add clear
  32. * 2022-07-02 Stanley Lwin add list command
  33. * 2023-09-15 xqyjlj perf rt_hw_interrupt_disable/enable
  34. * 2024-02-09 Bernard fix the version command
  35. * 2023-02-25 GuEe-GUI add console
  36. */
  37. #include <rthw.h>
  38. #include <rtthread.h>
  39. #include <string.h>
  40. #ifdef RT_USING_FINSH
  41. #include <finsh.h>
  42. #define LIST_DFS_OPT_ID 0x100
  43. #define LIST_FIND_OBJ_NR 8
  44. static long clear(void)
  45. {
  46. rt_kprintf("\x1b[2J\x1b[H");
  47. return 0;
  48. }
  49. MSH_CMD_EXPORT(clear, clear the terminal screen);
  50. static long version(void)
  51. {
  52. rt_show_version();
  53. return 0;
  54. }
  55. MSH_CMD_EXPORT(version, show RT-Thread version information);
  56. #if defined(RT_USING_DEVICE) && defined(RT_USING_CONSOLE)
  57. #if !defined(RT_USING_POSIX) && defined(RT_USING_POSIX_STDIO)
  58. #include <posix/stdio.h>
  59. #endif
  60. static int console(int argc, char **argv)
  61. {
  62. if (argc > 1)
  63. {
  64. if (!rt_strcmp(argv[1], "set"))
  65. {
  66. if (argc < 3)
  67. {
  68. goto _help;
  69. }
  70. rt_kprintf("console change to %s\n", argv[2]);
  71. rt_console_set_device(argv[2]);
  72. #ifdef RT_USING_POSIX
  73. {
  74. rt_device_t dev = rt_device_find(argv[2]);
  75. if (dev != RT_NULL)
  76. {
  77. console_set_iodev(dev);
  78. }
  79. }
  80. #elif !defined(RT_USING_POSIX_STDIO)
  81. finsh_set_device(argv[2]);
  82. #else
  83. rt_posix_stdio_init();
  84. #endif /* RT_USING_POSIX */
  85. }
  86. else
  87. {
  88. goto _help;
  89. }
  90. }
  91. else
  92. {
  93. goto _help;
  94. }
  95. return RT_EOK;
  96. _help:
  97. rt_kprintf("Usage: \n");
  98. rt_kprintf("console set <name> - change console by name\n");
  99. return -RT_ERROR;
  100. }
  101. MSH_CMD_EXPORT(console, console setting);
  102. #endif /* RT_USING_DEVICE && RT_USING_CONSOLE */
  103. rt_inline void object_split(int len)
  104. {
  105. while (len--) rt_kprintf("-");
  106. }
  107. typedef struct
  108. {
  109. rt_list_t *list;
  110. rt_list_t **array;
  111. rt_uint8_t type;
  112. int nr; /* input: max nr, can't be 0 */
  113. int nr_out; /* out: got nr */
  114. } list_get_next_t;
  115. static void list_find_init(list_get_next_t *p, rt_uint8_t type, rt_list_t **array, int nr)
  116. {
  117. struct rt_object_information *info;
  118. rt_list_t *list;
  119. info = rt_object_get_information((enum rt_object_class_type)type);
  120. list = &info->object_list;
  121. p->list = list;
  122. p->type = type;
  123. p->array = array;
  124. p->nr = nr;
  125. p->nr_out = 0;
  126. }
  127. static rt_list_t *list_get_next(rt_list_t *current, list_get_next_t *arg)
  128. {
  129. int first_flag = 0;
  130. rt_base_t level;
  131. rt_list_t *node, *list;
  132. rt_list_t **array;
  133. struct rt_object_information *info;
  134. int nr;
  135. arg->nr_out = 0;
  136. if (!arg->nr || !arg->type)
  137. {
  138. return (rt_list_t *)RT_NULL;
  139. }
  140. list = arg->list;
  141. info = rt_list_entry(list, struct rt_object_information, object_list);
  142. if (!current) /* find first */
  143. {
  144. node = list;
  145. first_flag = 1;
  146. }
  147. else
  148. {
  149. node = current;
  150. }
  151. level = rt_spin_lock_irqsave(&info->spinlock);
  152. if (!first_flag)
  153. {
  154. struct rt_object *obj;
  155. /* The node in the list? */
  156. obj = rt_list_entry(node, struct rt_object, list);
  157. if ((obj->type & ~RT_Object_Class_Static) != arg->type)
  158. {
  159. rt_spin_unlock_irqrestore(&info->spinlock, level);
  160. return (rt_list_t *)RT_NULL;
  161. }
  162. }
  163. nr = 0;
  164. array = arg->array;
  165. while (1)
  166. {
  167. node = node->next;
  168. if (node == list)
  169. {
  170. node = (rt_list_t *)RT_NULL;
  171. break;
  172. }
  173. nr++;
  174. *array++ = node;
  175. if (nr == arg->nr)
  176. {
  177. break;
  178. }
  179. }
  180. rt_spin_unlock_irqrestore(&info->spinlock, level);
  181. arg->nr_out = nr;
  182. return node;
  183. }
  184. long list_thread(void)
  185. {
  186. rt_base_t level;
  187. list_get_next_t find_arg;
  188. struct rt_object_information *info;
  189. rt_list_t *obj_list[LIST_FIND_OBJ_NR];
  190. rt_list_t *next = (rt_list_t *)RT_NULL;
  191. const char *item_title = "thread";
  192. const size_t tcb_strlen = sizeof(void *) * 2 + 2;
  193. const size_t usage_strlen = sizeof(void *) + 1;
  194. int maxlen;
  195. list_find_init(&find_arg, RT_Object_Class_Thread, obj_list, sizeof(obj_list) / sizeof(obj_list[0]));
  196. info = rt_list_entry(find_arg.list, struct rt_object_information, object_list);
  197. maxlen = RT_NAME_MAX;
  198. #ifdef RT_USING_SMP
  199. rt_kprintf("%-*.*s cpu bind pri status sp stack size max used left tick error tcb addr usage\n", maxlen, maxlen, item_title);
  200. object_split(maxlen);
  201. rt_kprintf(" --- ---- --- ------- ---------- ---------- ------ ---------- -------");
  202. rt_kprintf(" ");
  203. object_split(tcb_strlen);
  204. rt_kprintf(" ");
  205. object_split(usage_strlen);
  206. rt_kprintf("\n");
  207. #else
  208. rt_kprintf("%-*.*s pri status sp stack size max used left tick error tcb addr usage\n", maxlen, maxlen, item_title);
  209. object_split(maxlen);
  210. rt_kprintf(" --- ------- ---------- ---------- ------ ---------- -------");
  211. rt_kprintf(" ");
  212. object_split(tcb_strlen);
  213. rt_kprintf(" ");
  214. object_split(usage_strlen);
  215. rt_kprintf("\n");
  216. #endif /*RT_USING_SMP*/
  217. do
  218. {
  219. next = list_get_next(next, &find_arg);
  220. {
  221. int i;
  222. for (i = 0; i < find_arg.nr_out; i++)
  223. {
  224. struct rt_object *obj;
  225. struct rt_thread *thread;
  226. obj = rt_list_entry(obj_list[i], struct rt_object, list);
  227. level = rt_spin_lock_irqsave(&info->spinlock);
  228. if ((obj->type & ~RT_Object_Class_Static) != find_arg.type)
  229. {
  230. rt_spin_unlock_irqrestore(&info->spinlock, level);
  231. continue;
  232. }
  233. /* copy info */
  234. rt_spin_unlock_irqrestore(&info->spinlock, level);
  235. thread = (struct rt_thread *)obj;
  236. {
  237. rt_uint8_t stat;
  238. rt_uint8_t *ptr;
  239. #ifdef RT_USING_SMP
  240. /* no synchronization applied since it's only for debug */
  241. if (RT_SCHED_CTX(thread).oncpu != RT_CPU_DETACHED)
  242. rt_kprintf("%-*.*s %3d %3d %4d ", maxlen, RT_NAME_MAX,
  243. thread->parent.name, RT_SCHED_CTX(thread).oncpu,
  244. RT_SCHED_CTX(thread).bind_cpu,
  245. RT_SCHED_PRIV(thread).current_priority);
  246. else
  247. rt_kprintf("%-*.*s N/A %3d %4d ", maxlen, RT_NAME_MAX,
  248. thread->parent.name,
  249. RT_SCHED_CTX(thread).bind_cpu,
  250. RT_SCHED_PRIV(thread).current_priority);
  251. #else
  252. /* no synchronization applied since it's only for debug */
  253. rt_kprintf("%-*.*s %3d ", maxlen, RT_NAME_MAX, thread->parent.name, RT_SCHED_PRIV(thread).current_priority);
  254. #endif /*RT_USING_SMP*/
  255. stat = (RT_SCHED_CTX(thread).stat & RT_THREAD_STAT_MASK);
  256. if (stat == RT_THREAD_READY) rt_kprintf(" ready ");
  257. else if ((stat & RT_THREAD_SUSPEND_MASK) == RT_THREAD_SUSPEND_MASK) rt_kprintf(" suspend");
  258. else if (stat == RT_THREAD_INIT) rt_kprintf(" init ");
  259. else if (stat == RT_THREAD_CLOSE) rt_kprintf(" close ");
  260. else if (stat == RT_THREAD_RUNNING) rt_kprintf(" running");
  261. #if defined(ARCH_CPU_STACK_GROWS_UPWARD)
  262. ptr = (rt_uint8_t *)thread->stack_addr + thread->stack_size - 1;
  263. while (*ptr == '#')ptr --;
  264. rt_kprintf(" 0x%08x 0x%08x %02d%% 0x%08x %s %p",
  265. ((rt_ubase_t)thread->sp - (rt_ubase_t)thread->stack_addr),
  266. thread->stack_size,
  267. ((rt_ubase_t)ptr - (rt_ubase_t)thread->stack_addr) * 100 / thread->stack_size,
  268. thread->remaining_tick,
  269. rt_strerror(thread->error),
  270. thread);
  271. #ifdef RT_USING_CPU_USAGE_TRACER
  272. rt_kprintf(" %3d%%\n", rt_thread_get_usage(thread));
  273. #else
  274. rt_kprintf(" N/A\n");
  275. #endif
  276. #else
  277. ptr = (rt_uint8_t *)thread->stack_addr;
  278. while (*ptr == '#') ptr ++;
  279. rt_kprintf(" 0x%08x 0x%08x %3d%% 0x%08x %s %p",
  280. thread->stack_size + ((rt_ubase_t)thread->stack_addr - (rt_ubase_t)thread->sp),
  281. thread->stack_size,
  282. (thread->stack_size - ((rt_ubase_t) ptr - (rt_ubase_t) thread->stack_addr)) * 100
  283. / thread->stack_size,
  284. RT_SCHED_PRIV(thread).remaining_tick,
  285. rt_strerror(thread->error),
  286. thread);
  287. #ifdef RT_USING_CPU_USAGE_TRACER
  288. rt_kprintf(" %3d%%\n", rt_thread_get_usage(thread));
  289. #else
  290. rt_kprintf(" N/A\n");
  291. #endif
  292. #endif
  293. }
  294. }
  295. }
  296. }
  297. while (next != (rt_list_t *)RT_NULL);
  298. return 0;
  299. }
  300. #ifdef RT_USING_SEMAPHORE
  301. long list_sem(void)
  302. {
  303. rt_base_t level;
  304. list_get_next_t find_arg;
  305. struct rt_object_information *info;
  306. rt_list_t *obj_list[LIST_FIND_OBJ_NR];
  307. rt_list_t *next = (rt_list_t *)RT_NULL;
  308. int maxlen;
  309. const char *item_title = "semaphore";
  310. list_find_init(&find_arg, RT_Object_Class_Semaphore, obj_list, sizeof(obj_list) / sizeof(obj_list[0]));
  311. info = rt_list_entry(find_arg.list, struct rt_object_information, object_list);
  312. maxlen = RT_NAME_MAX;
  313. rt_kprintf("%-*.*s v suspend thread\n", maxlen, maxlen, item_title);
  314. object_split(maxlen);
  315. rt_kprintf(" --- --------------\n");
  316. do
  317. {
  318. next = list_get_next(next, &find_arg);
  319. {
  320. int i;
  321. for (i = 0; i < find_arg.nr_out; i++)
  322. {
  323. struct rt_object *obj;
  324. struct rt_semaphore *sem;
  325. obj = rt_list_entry(obj_list[i], struct rt_object, list);
  326. level = rt_spin_lock_irqsave(&info->spinlock);
  327. if ((obj->type & ~RT_Object_Class_Static) != find_arg.type)
  328. {
  329. rt_spin_unlock_irqrestore(&info->spinlock, level);
  330. continue;
  331. }
  332. rt_spin_unlock_irqrestore(&info->spinlock, level);
  333. sem = (struct rt_semaphore *)obj;
  334. if (!rt_list_isempty(&sem->parent.suspend_thread))
  335. {
  336. rt_kprintf("%-*.*s %03d %d:",
  337. maxlen, RT_NAME_MAX,
  338. sem->parent.parent.name,
  339. sem->value,
  340. rt_list_len(&sem->parent.suspend_thread));
  341. rt_susp_list_print(&(sem->parent.suspend_thread));
  342. rt_kprintf("\n");
  343. }
  344. else
  345. {
  346. rt_kprintf("%-*.*s %03d %d\n",
  347. maxlen, RT_NAME_MAX,
  348. sem->parent.parent.name,
  349. sem->value,
  350. rt_list_len(&sem->parent.suspend_thread));
  351. }
  352. }
  353. }
  354. }
  355. while (next != (rt_list_t *)RT_NULL);
  356. return 0;
  357. }
  358. #endif /* RT_USING_SEMAPHORE */
  359. #ifdef RT_USING_EVENT
  360. long list_event(void)
  361. {
  362. rt_base_t level;
  363. list_get_next_t find_arg;
  364. struct rt_object_information *info;
  365. rt_list_t *obj_list[LIST_FIND_OBJ_NR];
  366. rt_list_t *next = (rt_list_t *)RT_NULL;
  367. int maxlen;
  368. const char *item_title = "event";
  369. list_find_init(&find_arg, RT_Object_Class_Event, obj_list, sizeof(obj_list) / sizeof(obj_list[0]));
  370. info = rt_list_entry(find_arg.list, struct rt_object_information, object_list);
  371. maxlen = RT_NAME_MAX;
  372. rt_kprintf("%-*.*s set suspend thread\n", maxlen, maxlen, item_title);
  373. object_split(maxlen);
  374. rt_kprintf(" ---------- --------------\n");
  375. do
  376. {
  377. next = list_get_next(next, &find_arg);
  378. {
  379. int i;
  380. for (i = 0; i < find_arg.nr_out; i++)
  381. {
  382. struct rt_object *obj;
  383. struct rt_event *e;
  384. obj = rt_list_entry(obj_list[i], struct rt_object, list);
  385. level = rt_spin_lock_irqsave(&info->spinlock);
  386. if ((obj->type & ~RT_Object_Class_Static) != find_arg.type)
  387. {
  388. rt_spin_unlock_irqrestore(&info->spinlock, level);
  389. continue;
  390. }
  391. rt_spin_unlock_irqrestore(&info->spinlock, level);
  392. e = (struct rt_event *)obj;
  393. if (!rt_list_isempty(&e->parent.suspend_thread))
  394. {
  395. rt_kprintf("%-*.*s 0x%08x %03d:",
  396. maxlen, RT_NAME_MAX,
  397. e->parent.parent.name,
  398. e->set,
  399. rt_list_len(&e->parent.suspend_thread));
  400. rt_susp_list_print(&(e->parent.suspend_thread));
  401. rt_kprintf("\n");
  402. }
  403. else
  404. {
  405. rt_kprintf("%-*.*s 0x%08x 0\n",
  406. maxlen, RT_NAME_MAX, e->parent.parent.name, e->set);
  407. }
  408. }
  409. }
  410. }
  411. while (next != (rt_list_t *)RT_NULL);
  412. return 0;
  413. }
  414. #endif /* RT_USING_EVENT */
  415. #ifdef RT_USING_MUTEX
  416. long list_mutex(void)
  417. {
  418. rt_base_t level;
  419. list_get_next_t find_arg;
  420. struct rt_object_information *info;
  421. rt_list_t *obj_list[LIST_FIND_OBJ_NR];
  422. rt_list_t *next = (rt_list_t *)RT_NULL;
  423. int maxlen;
  424. const char *item_title = "mutex";
  425. list_find_init(&find_arg, RT_Object_Class_Mutex, obj_list, sizeof(obj_list) / sizeof(obj_list[0]));
  426. info = rt_list_entry(find_arg.list, struct rt_object_information, object_list);
  427. maxlen = RT_NAME_MAX;
  428. rt_kprintf("%-*.*s owner hold priority suspend thread \n", maxlen, maxlen, item_title);
  429. object_split(maxlen);
  430. rt_kprintf(" -------- ---- -------- --------------\n");
  431. do
  432. {
  433. next = list_get_next(next, &find_arg);
  434. {
  435. int i;
  436. for (i = 0; i < find_arg.nr_out; i++)
  437. {
  438. struct rt_object *obj;
  439. struct rt_mutex *m;
  440. obj = rt_list_entry(obj_list[i], struct rt_object, list);
  441. level = rt_spin_lock_irqsave(&info->spinlock);
  442. if ((obj->type & ~RT_Object_Class_Static) != find_arg.type)
  443. {
  444. rt_spin_unlock_irqrestore(&info->spinlock, level);
  445. continue;
  446. }
  447. rt_spin_unlock_irqrestore(&info->spinlock, level);
  448. m = (struct rt_mutex *)obj;
  449. if (!rt_list_isempty(&m->parent.suspend_thread))
  450. {
  451. rt_kprintf("%-*.*s %-8.*s %04d %8d %04d ",
  452. maxlen, RT_NAME_MAX,
  453. m->parent.parent.name,
  454. RT_NAME_MAX,
  455. (m->owner == RT_NULL) ? "(null)" : m->owner->parent.name,
  456. m->hold,
  457. m->priority,
  458. rt_list_len(&m->parent.suspend_thread));
  459. rt_susp_list_print(&(m->parent.suspend_thread));
  460. rt_kprintf("\n");
  461. }
  462. else
  463. {
  464. rt_kprintf("%-*.*s %-8.*s %04d %8d %04d\n",
  465. maxlen, RT_NAME_MAX,
  466. m->parent.parent.name,
  467. RT_NAME_MAX,
  468. (m->owner == RT_NULL) ? "(null)" : m->owner->parent.name,
  469. m->hold,
  470. m->priority,
  471. rt_list_len(&m->parent.suspend_thread));
  472. }
  473. }
  474. }
  475. }
  476. while (next != (rt_list_t *)RT_NULL);
  477. return 0;
  478. }
  479. #endif /* RT_USING_MUTEX */
  480. #ifdef RT_USING_MAILBOX
  481. long list_mailbox(void)
  482. {
  483. rt_base_t level;
  484. list_get_next_t find_arg;
  485. struct rt_object_information *info;
  486. rt_list_t *obj_list[LIST_FIND_OBJ_NR];
  487. rt_list_t *next = (rt_list_t *)RT_NULL;
  488. int maxlen;
  489. const char *item_title = "mailbox";
  490. list_find_init(&find_arg, RT_Object_Class_MailBox, obj_list, sizeof(obj_list) / sizeof(obj_list[0]));
  491. info = rt_list_entry(find_arg.list, struct rt_object_information, object_list);
  492. maxlen = RT_NAME_MAX;
  493. rt_kprintf("%-*.*s entry size suspend thread\n", maxlen, maxlen, item_title);
  494. object_split(maxlen);
  495. rt_kprintf(" ---- ---- --------------\n");
  496. do
  497. {
  498. next = list_get_next(next, &find_arg);
  499. {
  500. int i;
  501. for (i = 0; i < find_arg.nr_out; i++)
  502. {
  503. struct rt_object *obj;
  504. struct rt_mailbox *m;
  505. obj = rt_list_entry(obj_list[i], struct rt_object, list);
  506. level = rt_spin_lock_irqsave(&info->spinlock);
  507. if ((obj->type & ~RT_Object_Class_Static) != find_arg.type)
  508. {
  509. rt_spin_unlock_irqrestore(&info->spinlock, level);
  510. continue;
  511. }
  512. rt_spin_unlock_irqrestore(&info->spinlock, level);
  513. m = (struct rt_mailbox *)obj;
  514. if (!rt_list_isempty(&m->parent.suspend_thread))
  515. {
  516. rt_kprintf("%-*.*s %04d %04d %d:",
  517. maxlen, RT_NAME_MAX,
  518. m->parent.parent.name,
  519. m->entry,
  520. m->size,
  521. rt_list_len(&m->parent.suspend_thread));
  522. rt_susp_list_print(&(m->parent.suspend_thread));
  523. rt_kprintf("\n");
  524. }
  525. else
  526. {
  527. rt_kprintf("%-*.*s %04d %04d %d\n",
  528. maxlen, RT_NAME_MAX,
  529. m->parent.parent.name,
  530. m->entry,
  531. m->size,
  532. rt_list_len(&m->parent.suspend_thread));
  533. }
  534. }
  535. }
  536. }
  537. while (next != (rt_list_t *)RT_NULL);
  538. return 0;
  539. }
  540. #endif /* RT_USING_MAILBOX */
  541. #ifdef RT_USING_MESSAGEQUEUE
  542. long list_msgqueue(void)
  543. {
  544. rt_base_t level;
  545. list_get_next_t find_arg;
  546. struct rt_object_information *info;
  547. rt_list_t *obj_list[LIST_FIND_OBJ_NR];
  548. rt_list_t *next = (rt_list_t *)RT_NULL;
  549. int maxlen;
  550. const char *item_title = "msgqueue";
  551. list_find_init(&find_arg, RT_Object_Class_MessageQueue, obj_list, sizeof(obj_list) / sizeof(obj_list[0]));
  552. info = rt_list_entry(find_arg.list, struct rt_object_information, object_list);
  553. maxlen = RT_NAME_MAX;
  554. rt_kprintf("%-*.*s entry suspend thread\n", maxlen, maxlen, item_title);
  555. object_split(maxlen);
  556. rt_kprintf(" ---- --------------\n");
  557. do
  558. {
  559. next = list_get_next(next, &find_arg);
  560. {
  561. int i;
  562. for (i = 0; i < find_arg.nr_out; i++)
  563. {
  564. struct rt_object *obj;
  565. struct rt_messagequeue *m;
  566. obj = rt_list_entry(obj_list[i], struct rt_object, list);
  567. level = rt_spin_lock_irqsave(&info->spinlock);
  568. if ((obj->type & ~RT_Object_Class_Static) != find_arg.type)
  569. {
  570. rt_spin_unlock_irqrestore(&info->spinlock, level);
  571. continue;
  572. }
  573. rt_spin_unlock_irqrestore(&info->spinlock, level);
  574. m = (struct rt_messagequeue *)obj;
  575. if (!rt_list_isempty(&m->parent.suspend_thread))
  576. {
  577. rt_kprintf("%-*.*s %04d %d:",
  578. maxlen, RT_NAME_MAX,
  579. m->parent.parent.name,
  580. m->entry,
  581. rt_list_len(&m->parent.suspend_thread));
  582. rt_susp_list_print(&(m->parent.suspend_thread));
  583. rt_kprintf("\n");
  584. }
  585. else
  586. {
  587. rt_kprintf("%-*.*s %04d %d\n",
  588. maxlen, RT_NAME_MAX,
  589. m->parent.parent.name,
  590. m->entry,
  591. rt_list_len(&m->parent.suspend_thread));
  592. }
  593. }
  594. }
  595. }
  596. while (next != (rt_list_t *)RT_NULL);
  597. return 0;
  598. }
  599. #endif /* RT_USING_MESSAGEQUEUE */
  600. #ifdef RT_USING_MEMHEAP
  601. long list_memheap(void)
  602. {
  603. rt_base_t level;
  604. list_get_next_t find_arg;
  605. struct rt_object_information *info;
  606. rt_list_t *obj_list[LIST_FIND_OBJ_NR];
  607. rt_list_t *next = (rt_list_t *)RT_NULL;
  608. int maxlen;
  609. const char *item_title = "memheap";
  610. list_find_init(&find_arg, RT_Object_Class_MemHeap, obj_list, sizeof(obj_list) / sizeof(obj_list[0]));
  611. info = rt_list_entry(find_arg.list, struct rt_object_information, object_list);
  612. maxlen = RT_NAME_MAX;
  613. rt_kprintf("%-*.*s pool size max used size available size\n", maxlen, maxlen, item_title);
  614. object_split(maxlen);
  615. rt_kprintf(" ---------- ------------- --------------\n");
  616. do
  617. {
  618. next = list_get_next(next, &find_arg);
  619. {
  620. int i;
  621. for (i = 0; i < find_arg.nr_out; i++)
  622. {
  623. struct rt_object *obj;
  624. struct rt_memheap *mh;
  625. obj = rt_list_entry(obj_list[i], struct rt_object, list);
  626. level = rt_spin_lock_irqsave(&info->spinlock);
  627. if ((obj->type & ~RT_Object_Class_Static) != find_arg.type)
  628. {
  629. rt_spin_unlock_irqrestore(&info->spinlock, level);
  630. continue;
  631. }
  632. rt_spin_unlock_irqrestore(&info->spinlock, level);
  633. mh = (struct rt_memheap *)obj;
  634. rt_kprintf("%-*.*s %-010d %-013d %-05d\n",
  635. maxlen, RT_NAME_MAX,
  636. mh->parent.name,
  637. mh->pool_size,
  638. mh->max_used_size,
  639. mh->available_size);
  640. }
  641. }
  642. }
  643. while (next != (rt_list_t *)RT_NULL);
  644. return 0;
  645. }
  646. #endif /* RT_USING_MEMHEAP */
  647. #ifdef RT_USING_MEMPOOL
  648. long list_mempool(void)
  649. {
  650. rt_base_t level;
  651. list_get_next_t find_arg;
  652. struct rt_object_information *info;
  653. rt_list_t *obj_list[LIST_FIND_OBJ_NR];
  654. rt_list_t *next = (rt_list_t *)RT_NULL;
  655. int maxlen;
  656. const char *item_title = "mempool";
  657. list_find_init(&find_arg, RT_Object_Class_MemPool, obj_list, sizeof(obj_list) / sizeof(obj_list[0]));
  658. info = rt_list_entry(find_arg.list, struct rt_object_information, object_list);
  659. maxlen = RT_NAME_MAX;
  660. rt_kprintf("%-*.*s block total free suspend thread\n", maxlen, maxlen, item_title);
  661. object_split(maxlen);
  662. rt_kprintf(" ---- ---- ---- --------------\n");
  663. do
  664. {
  665. next = list_get_next(next, &find_arg);
  666. {
  667. int i;
  668. for (i = 0; i < find_arg.nr_out; i++)
  669. {
  670. struct rt_object *obj;
  671. struct rt_mempool *mp;
  672. int suspend_thread_count;
  673. rt_list_t *node;
  674. obj = rt_list_entry(obj_list[i], struct rt_object, list);
  675. level = rt_spin_lock_irqsave(&info->spinlock);
  676. if ((obj->type & ~RT_Object_Class_Static) != find_arg.type)
  677. {
  678. rt_spin_unlock_irqrestore(&info->spinlock, level);
  679. continue;
  680. }
  681. rt_spin_unlock_irqrestore(&info->spinlock, level);
  682. mp = (struct rt_mempool *)obj;
  683. suspend_thread_count = 0;
  684. rt_list_for_each(node, &mp->suspend_thread)
  685. {
  686. suspend_thread_count++;
  687. }
  688. if (suspend_thread_count > 0)
  689. {
  690. rt_kprintf("%-*.*s %04d %04d %04d %d:",
  691. maxlen, RT_NAME_MAX,
  692. mp->parent.name,
  693. mp->block_size,
  694. mp->block_total_count,
  695. mp->block_free_count,
  696. suspend_thread_count);
  697. rt_susp_list_print(&(mp->suspend_thread));
  698. rt_kprintf("\n");
  699. }
  700. else
  701. {
  702. rt_kprintf("%-*.*s %04d %04d %04d %d\n",
  703. maxlen, RT_NAME_MAX,
  704. mp->parent.name,
  705. mp->block_size,
  706. mp->block_total_count,
  707. mp->block_free_count,
  708. suspend_thread_count);
  709. }
  710. }
  711. }
  712. }
  713. while (next != (rt_list_t *)RT_NULL);
  714. return 0;
  715. }
  716. #endif /* RT_USING_MEMPOOL */
  717. long list_timer(void)
  718. {
  719. rt_base_t level;
  720. list_get_next_t find_arg;
  721. struct rt_object_information *info;
  722. rt_list_t *obj_list[LIST_FIND_OBJ_NR];
  723. rt_list_t *next = (rt_list_t *)RT_NULL;
  724. int maxlen;
  725. const char *item_title = "timer";
  726. list_find_init(&find_arg, RT_Object_Class_Timer, obj_list, sizeof(obj_list) / sizeof(obj_list[0]));
  727. info = rt_list_entry(find_arg.list, struct rt_object_information, object_list);
  728. maxlen = RT_NAME_MAX;
  729. rt_kprintf("%-*.*s periodic timeout activated mode\n", maxlen, maxlen, item_title);
  730. object_split(maxlen);
  731. rt_kprintf(" ---------- ---------- ----------- ---------\n");
  732. do
  733. {
  734. next = list_get_next(next, &find_arg);
  735. {
  736. int i;
  737. for (i = 0; i < find_arg.nr_out; i++)
  738. {
  739. struct rt_object *obj;
  740. struct rt_timer *timer;
  741. obj = rt_list_entry(obj_list[i], struct rt_object, list);
  742. level = rt_spin_lock_irqsave(&info->spinlock);
  743. if ((obj->type & ~RT_Object_Class_Static) != find_arg.type)
  744. {
  745. rt_spin_unlock_irqrestore(&info->spinlock, level);
  746. continue;
  747. }
  748. rt_spin_unlock_irqrestore(&info->spinlock, level);
  749. timer = (struct rt_timer *)obj;
  750. rt_kprintf("%-*.*s 0x%08x 0x%08x ",
  751. maxlen, RT_NAME_MAX,
  752. timer->parent.name,
  753. timer->init_tick,
  754. timer->timeout_tick);
  755. if (timer->parent.flag & RT_TIMER_FLAG_ACTIVATED)
  756. rt_kprintf("activated ");
  757. else
  758. rt_kprintf("deactivated ");
  759. if (timer->parent.flag & RT_TIMER_FLAG_PERIODIC)
  760. rt_kprintf("periodic\n");
  761. else
  762. rt_kprintf("one shot\n");
  763. }
  764. }
  765. }
  766. while (next != (rt_list_t *)RT_NULL);
  767. rt_kprintf("current tick:0x%08x\n", rt_tick_get());
  768. return 0;
  769. }
  770. #ifdef RT_USING_DEVICE
  771. static char *const device_type_str[RT_Device_Class_Unknown] =
  772. {
  773. "Character Device",
  774. "Block Device",
  775. "Network Interface",
  776. "MTD Device",
  777. "CAN Device",
  778. "RTC",
  779. "Sound Device",
  780. "Graphic Device",
  781. "I2C Bus",
  782. "USB Slave Device",
  783. "USB Host Bus",
  784. "USB OTG Bus",
  785. "SPI Bus",
  786. "SPI Device",
  787. "SDIO Bus",
  788. "PM Pseudo Device",
  789. "Pipe",
  790. "Portal Device",
  791. "Timer Device",
  792. "Miscellaneous Device",
  793. "Sensor Device",
  794. "Touch Device",
  795. "Phy Device",
  796. "Security Device",
  797. "WLAN Device",
  798. "Pin Device",
  799. "ADC Device",
  800. "DAC Device",
  801. "WDT Device",
  802. "PWM Device",
  803. "Bus Device",
  804. };
  805. long list_device(void)
  806. {
  807. rt_base_t level;
  808. list_get_next_t find_arg;
  809. struct rt_object_information *info;
  810. rt_list_t *obj_list[LIST_FIND_OBJ_NR];
  811. rt_list_t *next = (rt_list_t *)RT_NULL;
  812. const char *device_type;
  813. int maxlen;
  814. const char *item_title = "device";
  815. list_find_init(&find_arg, RT_Object_Class_Device, obj_list, sizeof(obj_list) / sizeof(obj_list[0]));
  816. info = rt_list_entry(find_arg.list, struct rt_object_information, object_list);
  817. maxlen = RT_NAME_MAX;
  818. rt_kprintf("%-*.*s type ref count\n", maxlen, maxlen, item_title);
  819. object_split(maxlen);
  820. rt_kprintf(" -------------------- ----------\n");
  821. do
  822. {
  823. next = list_get_next(next, &find_arg);
  824. {
  825. int i;
  826. for (i = 0; i < find_arg.nr_out; i++)
  827. {
  828. struct rt_object *obj;
  829. struct rt_device *device;
  830. obj = rt_list_entry(obj_list[i], struct rt_object, list);
  831. level = rt_spin_lock_irqsave(&info->spinlock);
  832. if ((obj->type & ~RT_Object_Class_Static) != find_arg.type)
  833. {
  834. rt_spin_unlock_irqrestore(&info->spinlock, level);
  835. continue;
  836. }
  837. rt_spin_unlock_irqrestore(&info->spinlock, level);
  838. device = (struct rt_device *)obj;
  839. device_type = "Unknown";
  840. if (device->type < RT_Device_Class_Unknown &&
  841. device_type_str[device->type] != RT_NULL)
  842. {
  843. device_type = device_type_str[device->type];
  844. }
  845. rt_kprintf("%-*.*s %-20s %-8d\n",
  846. maxlen, RT_NAME_MAX,
  847. device->parent.name,
  848. device_type,
  849. device->ref_count);
  850. }
  851. }
  852. }
  853. while (next != (rt_list_t *)RT_NULL);
  854. return 0;
  855. }
  856. #endif /* RT_USING_DEVICE */
  857. #ifndef FINSH_USING_OPTION_COMPLETION
  858. static int cmd_list(int argc, char **argv)
  859. {
  860. if(argc == 2)
  861. {
  862. if(rt_strcmp(argv[1], "thread") == 0)
  863. {
  864. list_thread();
  865. }
  866. else if(rt_strcmp(argv[1], "timer") == 0)
  867. {
  868. list_timer();
  869. }
  870. #ifdef RT_USING_SEMAPHORE
  871. else if(rt_strcmp(argv[1], "sem") == 0)
  872. {
  873. list_sem();
  874. }
  875. #endif /* RT_USING_SEMAPHORE */
  876. #ifdef RT_USING_EVENT
  877. else if(rt_strcmp(argv[1], "event") == 0)
  878. {
  879. list_event();
  880. }
  881. #endif /* RT_USING_EVENT */
  882. #ifdef RT_USING_MUTEX
  883. else if(rt_strcmp(argv[1], "mutex") == 0)
  884. {
  885. list_mutex();
  886. }
  887. #endif /* RT_USING_MUTEX */
  888. #ifdef RT_USING_MAILBOX
  889. else if(rt_strcmp(argv[1], "mailbox") == 0)
  890. {
  891. list_mailbox();
  892. }
  893. #endif /* RT_USING_MAILBOX */
  894. #ifdef RT_USING_MESSAGEQUEUE
  895. else if(rt_strcmp(argv[1], "msgqueue") == 0)
  896. {
  897. list_msgqueue();
  898. }
  899. #endif /* RT_USING_MESSAGEQUEUE */
  900. #ifdef RT_USING_MEMHEAP
  901. else if(rt_strcmp(argv[1], "memheap") == 0)
  902. {
  903. list_memheap();
  904. }
  905. #endif /* RT_USING_MEMHEAP */
  906. #ifdef RT_USING_MEMPOOL
  907. else if(rt_strcmp(argv[1], "mempool") == 0)
  908. {
  909. list_mempool();
  910. }
  911. #endif /* RT_USING_MEMPOOL */
  912. #ifdef RT_USING_DEVICE
  913. else if(rt_strcmp(argv[1], "device") == 0)
  914. {
  915. list_device();
  916. }
  917. #endif /* RT_USING_DEVICE */
  918. #ifdef RT_USING_DFS
  919. else if(rt_strcmp(argv[1], "fd") == 0)
  920. {
  921. extern int list_fd(void);
  922. list_fd();
  923. }
  924. #endif /* RT_USING_DFS */
  925. else
  926. {
  927. goto _usage;
  928. }
  929. return 0;
  930. }
  931. _usage:
  932. rt_kprintf("Usage: list [options]\n");
  933. rt_kprintf("[options]:\n");
  934. rt_kprintf(" %-12s - list threads\n", "thread");
  935. rt_kprintf(" %-12s - list timers\n", "timer");
  936. #ifdef RT_USING_SEMAPHORE
  937. rt_kprintf(" %-12s - list semaphores\n", "sem");
  938. #endif /* RT_USING_SEMAPHORE */
  939. #ifdef RT_USING_MUTEX
  940. rt_kprintf(" %-12s - list mutexs\n", "mutex");
  941. #endif /* RT_USING_MUTEX */
  942. #ifdef RT_USING_EVENT
  943. rt_kprintf(" %-12s - list events\n", "event");
  944. #endif /* RT_USING_EVENT */
  945. #ifdef RT_USING_MAILBOX
  946. rt_kprintf(" %-12s - list mailboxs\n", "mailbox");
  947. #endif /* RT_USING_MAILBOX */
  948. #ifdef RT_USING_MESSAGEQUEUE
  949. rt_kprintf(" %-12s - list message queues\n", "msgqueue");
  950. #endif /* RT_USING_MESSAGEQUEUE */
  951. #ifdef RT_USING_MEMHEAP
  952. rt_kprintf(" %-12s - list memory heaps\n", "memheap");
  953. #endif /* RT_USING_MEMHEAP */
  954. #ifdef RT_USING_MEMPOOL
  955. rt_kprintf(" %-12s - list memory pools\n", "mempool");
  956. #endif /* RT_USING_MEMPOOL */
  957. #ifdef RT_USING_DEVICE
  958. rt_kprintf(" %-12s - list devices\n", "device");
  959. #endif /* RT_USING_DEVICE */
  960. #ifdef RT_USING_DFS
  961. rt_kprintf(" %-12s - list file descriptors\n", "fd");
  962. #endif /* RT_USING_DFS */
  963. return 0;
  964. }
  965. #else
  966. CMD_OPTIONS_STATEMENT(cmd_list)
  967. static int cmd_list(int argc, char **argv)
  968. {
  969. if (argc == 2)
  970. {
  971. switch (MSH_OPT_ID_GET(cmd_list))
  972. {
  973. case RT_Object_Class_Thread: list_thread(); break;
  974. case RT_Object_Class_Timer: list_timer(); break;
  975. #ifdef RT_USING_SEMAPHORE
  976. case RT_Object_Class_Semaphore: list_sem(); break;
  977. #endif /* RT_USING_SEMAPHORE */
  978. #ifdef RT_USING_EVENT
  979. case RT_Object_Class_Event: list_event(); break;
  980. #endif /* RT_USING_EVENT */
  981. #ifdef RT_USING_MUTEX
  982. case RT_Object_Class_Mutex: list_mutex(); break;
  983. #endif /* RT_USING_MUTEX */
  984. #ifdef RT_USING_MAILBOX
  985. case RT_Object_Class_MailBox: list_mailbox(); break;
  986. #endif /* RT_USING_MAILBOX */
  987. #ifdef RT_USING_MESSAGEQUEUE
  988. case RT_Object_Class_MessageQueue: list_msgqueue(); break;
  989. #endif /* RT_USING_MESSAGEQUEUE */
  990. #ifdef RT_USING_MEMHEAP
  991. case RT_Object_Class_MemHeap: list_memheap(); break;
  992. #endif /* RT_USING_MEMHEAP */
  993. #ifdef RT_USING_MEMPOOL
  994. case RT_Object_Class_MemPool: list_mempool(); break;
  995. #endif /* RT_USING_MEMPOOL */
  996. #ifdef RT_USING_DEVICE
  997. case RT_Object_Class_Device: list_device(); break;
  998. #endif /* RT_USING_DEVICE */
  999. #ifdef RT_USING_DFS
  1000. case LIST_DFS_OPT_ID:
  1001. {
  1002. extern int list_fd(void);
  1003. list_fd();
  1004. break;
  1005. }
  1006. #endif /* RT_USING_DFS */
  1007. default:
  1008. goto _usage;
  1009. };
  1010. return 0;
  1011. }
  1012. _usage:
  1013. rt_kprintf("Usage: list [options]\n");
  1014. rt_kprintf("[options]:\n");
  1015. MSH_OPT_DUMP(cmd_list);
  1016. return 0;
  1017. }
  1018. CMD_OPTIONS_NODE_START(cmd_list)
  1019. CMD_OPTIONS_NODE(RT_Object_Class_Thread, thread, list threads)
  1020. CMD_OPTIONS_NODE(RT_Object_Class_Timer, timer, list timers)
  1021. #ifdef RT_USING_SEMAPHORE
  1022. CMD_OPTIONS_NODE(RT_Object_Class_Semaphore, sem, list semaphores)
  1023. #endif /* RT_USING_SEMAPHORE */
  1024. #ifdef RT_USING_EVENT
  1025. CMD_OPTIONS_NODE(RT_Object_Class_Event, event, list events)
  1026. #endif /* RT_USING_EVENT */
  1027. #ifdef RT_USING_MUTEX
  1028. CMD_OPTIONS_NODE(RT_Object_Class_Mutex, mutex, list mutexs)
  1029. #endif /* RT_USING_MUTEX */
  1030. #ifdef RT_USING_MAILBOX
  1031. CMD_OPTIONS_NODE(RT_Object_Class_MailBox, mailbox, list mailboxs)
  1032. #endif /* RT_USING_MAILBOX */
  1033. #ifdef RT_USING_MESSAGEQUEUE
  1034. CMD_OPTIONS_NODE(RT_Object_Class_MessageQueue, msgqueue, list message queues)
  1035. #endif /* RT_USING_MESSAGEQUEUE */
  1036. #ifdef RT_USING_MEMHEAP
  1037. CMD_OPTIONS_NODE(RT_Object_Class_MemHeap, memheap, list memory heaps)
  1038. #endif /* RT_USING_MEMHEAP */
  1039. #ifdef RT_USING_MEMPOOL
  1040. CMD_OPTIONS_NODE(RT_Object_Class_MemPool, mempool, list memory pools)
  1041. #endif /* RT_USING_MEMPOOL */
  1042. #ifdef RT_USING_DEVICE
  1043. CMD_OPTIONS_NODE(RT_Object_Class_Device, device, list devices)
  1044. #endif /* RT_USING_DEVICE */
  1045. #ifdef RT_USING_DFS
  1046. CMD_OPTIONS_NODE(LIST_DFS_OPT_ID, fd, list file descriptors)
  1047. #endif /* RT_USING_DFS */
  1048. CMD_OPTIONS_NODE_END
  1049. #endif /* FINSH_USING_OPTION_COMPLETION */
  1050. MSH_CMD_EXPORT_ALIAS(cmd_list, list, list objects, optenable);
  1051. #endif /* RT_USING_FINSH */