cmd.c 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009
  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. */
  34. #include <rthw.h>
  35. #include <rtthread.h>
  36. #include <string.h>
  37. #ifdef RT_USING_FINSH
  38. #include <finsh.h>
  39. #define LIST_FIND_OBJ_NR 8
  40. static long clear(void)
  41. {
  42. rt_kprintf("\x1b[2J\x1b[H");
  43. return 0;
  44. }
  45. MSH_CMD_EXPORT(clear, clear the terminal screen);
  46. extern void rt_show_version(void);
  47. long version(void)
  48. {
  49. rt_show_version();
  50. return 0;
  51. }
  52. MSH_CMD_EXPORT(version, show RT-Thread version information);
  53. rt_inline void object_split(int len)
  54. {
  55. while (len--) rt_kprintf("-");
  56. }
  57. typedef struct
  58. {
  59. rt_list_t *list;
  60. rt_list_t **array;
  61. rt_uint8_t type;
  62. int nr; /* input: max nr, can't be 0 */
  63. int nr_out; /* out: got nr */
  64. } list_get_next_t;
  65. static void list_find_init(list_get_next_t *p, rt_uint8_t type, rt_list_t **array, int nr)
  66. {
  67. struct rt_object_information *info;
  68. rt_list_t *list;
  69. info = rt_object_get_information((enum rt_object_class_type)type);
  70. list = &info->object_list;
  71. p->list = list;
  72. p->type = type;
  73. p->array = array;
  74. p->nr = nr;
  75. p->nr_out = 0;
  76. }
  77. static rt_list_t *list_get_next(rt_list_t *current, list_get_next_t *arg)
  78. {
  79. int first_flag = 0;
  80. rt_base_t level;
  81. rt_list_t *node, *list;
  82. rt_list_t **array;
  83. int nr;
  84. arg->nr_out = 0;
  85. if (!arg->nr || !arg->type)
  86. {
  87. return (rt_list_t *)RT_NULL;
  88. }
  89. list = arg->list;
  90. if (!current) /* find first */
  91. {
  92. node = list;
  93. first_flag = 1;
  94. }
  95. else
  96. {
  97. node = current;
  98. }
  99. level = rt_hw_interrupt_disable();
  100. if (!first_flag)
  101. {
  102. struct rt_object *obj;
  103. /* The node in the list? */
  104. obj = rt_list_entry(node, struct rt_object, list);
  105. if ((obj->type & ~RT_Object_Class_Static) != arg->type)
  106. {
  107. rt_hw_interrupt_enable(level);
  108. return (rt_list_t *)RT_NULL;
  109. }
  110. }
  111. nr = 0;
  112. array = arg->array;
  113. while (1)
  114. {
  115. node = node->next;
  116. if (node == list)
  117. {
  118. node = (rt_list_t *)RT_NULL;
  119. break;
  120. }
  121. nr++;
  122. *array++ = node;
  123. if (nr == arg->nr)
  124. {
  125. break;
  126. }
  127. }
  128. rt_hw_interrupt_enable(level);
  129. arg->nr_out = nr;
  130. return node;
  131. }
  132. long list_thread(void)
  133. {
  134. rt_base_t level;
  135. list_get_next_t find_arg;
  136. rt_list_t *obj_list[LIST_FIND_OBJ_NR];
  137. rt_list_t *next = (rt_list_t *)RT_NULL;
  138. const char *item_title = "thread";
  139. int maxlen;
  140. list_find_init(&find_arg, RT_Object_Class_Thread, obj_list, sizeof(obj_list) / sizeof(obj_list[0]));
  141. maxlen = RT_NAME_MAX;
  142. #ifdef RT_USING_SMP
  143. rt_kprintf("%-*.*s cpu bind pri status sp stack size max used left tick error\n", maxlen, maxlen, item_title);
  144. object_split(maxlen);
  145. rt_kprintf(" --- ---- --- ------- ---------- ---------- ------ ---------- ---\n");
  146. #else
  147. rt_kprintf("%-*.*s pri status sp stack size max used left tick error\n", maxlen, maxlen, item_title);
  148. object_split(maxlen);
  149. rt_kprintf(" --- ------- ---------- ---------- ------ ---------- ---\n");
  150. #endif /*RT_USING_SMP*/
  151. do
  152. {
  153. next = list_get_next(next, &find_arg);
  154. {
  155. int i;
  156. for (i = 0; i < find_arg.nr_out; i++)
  157. {
  158. struct rt_object *obj;
  159. struct rt_thread thread_info, *thread;
  160. obj = rt_list_entry(obj_list[i], struct rt_object, list);
  161. level = rt_hw_interrupt_disable();
  162. if ((obj->type & ~RT_Object_Class_Static) != find_arg.type)
  163. {
  164. rt_hw_interrupt_enable(level);
  165. continue;
  166. }
  167. /* copy info */
  168. rt_memcpy(&thread_info, obj, sizeof thread_info);
  169. rt_hw_interrupt_enable(level);
  170. thread = (struct rt_thread *)obj;
  171. {
  172. rt_uint8_t stat;
  173. rt_uint8_t *ptr;
  174. #ifdef RT_USING_SMP
  175. if (thread->oncpu != RT_CPU_DETACHED)
  176. rt_kprintf("%-*.*s %3d %3d %4d ", maxlen, RT_NAME_MAX, thread->parent.name, thread->oncpu, thread->bind_cpu, thread->current_priority);
  177. else
  178. rt_kprintf("%-*.*s N/A %3d %4d ", maxlen, RT_NAME_MAX, thread->parent.name, thread->bind_cpu, thread->current_priority);
  179. #else
  180. rt_kprintf("%-*.*s %3d ", maxlen, RT_NAME_MAX, thread->parent.name, thread->current_priority);
  181. #endif /*RT_USING_SMP*/
  182. stat = (thread->stat & RT_THREAD_STAT_MASK);
  183. if (stat == RT_THREAD_READY) rt_kprintf(" ready ");
  184. else if ((stat & RT_THREAD_SUSPEND_MASK) == RT_THREAD_SUSPEND_MASK) rt_kprintf(" suspend");
  185. else if (stat == RT_THREAD_INIT) rt_kprintf(" init ");
  186. else if (stat == RT_THREAD_CLOSE) rt_kprintf(" close ");
  187. else if (stat == RT_THREAD_RUNNING) rt_kprintf(" running");
  188. #if defined(ARCH_CPU_STACK_GROWS_UPWARD)
  189. ptr = (rt_uint8_t *)thread->stack_addr + thread->stack_size - 1;
  190. while (*ptr == '#')ptr --;
  191. rt_kprintf(" 0x%08x 0x%08x %02d%% 0x%08x %03d\n",
  192. ((rt_ubase_t)thread->sp - (rt_ubase_t)thread->stack_addr),
  193. thread->stack_size,
  194. ((rt_ubase_t)ptr - (rt_ubase_t)thread->stack_addr) * 100 / thread->stack_size,
  195. thread->remaining_tick,
  196. thread->error);
  197. #else
  198. ptr = (rt_uint8_t *)thread->stack_addr;
  199. while (*ptr == '#') ptr ++;
  200. rt_kprintf(" 0x%08x 0x%08x %02d%% 0x%08x %s\n",
  201. thread->stack_size + ((rt_ubase_t)thread->stack_addr - (rt_ubase_t)thread->sp),
  202. thread->stack_size,
  203. (thread->stack_size - ((rt_ubase_t) ptr - (rt_ubase_t) thread->stack_addr)) * 100
  204. / thread->stack_size,
  205. thread->remaining_tick,
  206. rt_strerror(thread->error));
  207. #endif
  208. }
  209. }
  210. }
  211. }
  212. while (next != (rt_list_t *)RT_NULL);
  213. return 0;
  214. }
  215. static void show_wait_queue(struct rt_list_node *list)
  216. {
  217. struct rt_thread *thread;
  218. struct rt_list_node *node;
  219. for (node = list->next; node != list; node = node->next)
  220. {
  221. thread = rt_list_entry(node, struct rt_thread, tlist);
  222. rt_kprintf("%.*s", RT_NAME_MAX, thread->parent.name);
  223. if (node->next != list)
  224. rt_kprintf("/");
  225. }
  226. }
  227. #ifdef RT_USING_SEMAPHORE
  228. long list_sem(void)
  229. {
  230. rt_base_t level;
  231. list_get_next_t find_arg;
  232. rt_list_t *obj_list[LIST_FIND_OBJ_NR];
  233. rt_list_t *next = (rt_list_t *)RT_NULL;
  234. int maxlen;
  235. const char *item_title = "semaphore";
  236. list_find_init(&find_arg, RT_Object_Class_Semaphore, obj_list, sizeof(obj_list) / sizeof(obj_list[0]));
  237. maxlen = RT_NAME_MAX;
  238. rt_kprintf("%-*.*s v suspend thread\n", maxlen, maxlen, item_title);
  239. object_split(maxlen);
  240. rt_kprintf(" --- --------------\n");
  241. do
  242. {
  243. next = list_get_next(next, &find_arg);
  244. {
  245. int i;
  246. for (i = 0; i < find_arg.nr_out; i++)
  247. {
  248. struct rt_object *obj;
  249. struct rt_semaphore *sem;
  250. obj = rt_list_entry(obj_list[i], struct rt_object, list);
  251. level = rt_hw_interrupt_disable();
  252. if ((obj->type & ~RT_Object_Class_Static) != find_arg.type)
  253. {
  254. rt_hw_interrupt_enable(level);
  255. continue;
  256. }
  257. rt_hw_interrupt_enable(level);
  258. sem = (struct rt_semaphore *)obj;
  259. if (!rt_list_isempty(&sem->parent.suspend_thread))
  260. {
  261. rt_kprintf("%-*.*s %03d %d:",
  262. maxlen, RT_NAME_MAX,
  263. sem->parent.parent.name,
  264. sem->value,
  265. rt_list_len(&sem->parent.suspend_thread));
  266. show_wait_queue(&(sem->parent.suspend_thread));
  267. rt_kprintf("\n");
  268. }
  269. else
  270. {
  271. rt_kprintf("%-*.*s %03d %d\n",
  272. maxlen, RT_NAME_MAX,
  273. sem->parent.parent.name,
  274. sem->value,
  275. rt_list_len(&sem->parent.suspend_thread));
  276. }
  277. }
  278. }
  279. }
  280. while (next != (rt_list_t *)RT_NULL);
  281. return 0;
  282. }
  283. #endif /* RT_USING_SEMAPHORE */
  284. #ifdef RT_USING_EVENT
  285. long list_event(void)
  286. {
  287. rt_base_t level;
  288. list_get_next_t find_arg;
  289. rt_list_t *obj_list[LIST_FIND_OBJ_NR];
  290. rt_list_t *next = (rt_list_t *)RT_NULL;
  291. int maxlen;
  292. const char *item_title = "event";
  293. list_find_init(&find_arg, RT_Object_Class_Event, obj_list, sizeof(obj_list) / sizeof(obj_list[0]));
  294. maxlen = RT_NAME_MAX;
  295. rt_kprintf("%-*.*s set suspend thread\n", maxlen, maxlen, item_title);
  296. object_split(maxlen);
  297. rt_kprintf(" ---------- --------------\n");
  298. do
  299. {
  300. next = list_get_next(next, &find_arg);
  301. {
  302. int i;
  303. for (i = 0; i < find_arg.nr_out; i++)
  304. {
  305. struct rt_object *obj;
  306. struct rt_event *e;
  307. obj = rt_list_entry(obj_list[i], struct rt_object, list);
  308. level = rt_hw_interrupt_disable();
  309. if ((obj->type & ~RT_Object_Class_Static) != find_arg.type)
  310. {
  311. rt_hw_interrupt_enable(level);
  312. continue;
  313. }
  314. rt_hw_interrupt_enable(level);
  315. e = (struct rt_event *)obj;
  316. if (!rt_list_isempty(&e->parent.suspend_thread))
  317. {
  318. rt_kprintf("%-*.*s 0x%08x %03d:",
  319. maxlen, RT_NAME_MAX,
  320. e->parent.parent.name,
  321. e->set,
  322. rt_list_len(&e->parent.suspend_thread));
  323. show_wait_queue(&(e->parent.suspend_thread));
  324. rt_kprintf("\n");
  325. }
  326. else
  327. {
  328. rt_kprintf("%-*.*s 0x%08x 0\n",
  329. maxlen, RT_NAME_MAX, e->parent.parent.name, e->set);
  330. }
  331. }
  332. }
  333. }
  334. while (next != (rt_list_t *)RT_NULL);
  335. return 0;
  336. }
  337. #endif /* RT_USING_EVENT */
  338. #ifdef RT_USING_MUTEX
  339. long list_mutex(void)
  340. {
  341. rt_base_t level;
  342. list_get_next_t find_arg;
  343. rt_list_t *obj_list[LIST_FIND_OBJ_NR];
  344. rt_list_t *next = (rt_list_t *)RT_NULL;
  345. int maxlen;
  346. const char *item_title = "mutex";
  347. list_find_init(&find_arg, RT_Object_Class_Mutex, obj_list, sizeof(obj_list) / sizeof(obj_list[0]));
  348. maxlen = RT_NAME_MAX;
  349. rt_kprintf("%-*.*s owner hold priority suspend thread \n", maxlen, maxlen, item_title);
  350. object_split(maxlen);
  351. rt_kprintf(" -------- ---- -------- --------------\n");
  352. do
  353. {
  354. next = list_get_next(next, &find_arg);
  355. {
  356. int i;
  357. for (i = 0; i < find_arg.nr_out; i++)
  358. {
  359. struct rt_object *obj;
  360. struct rt_mutex *m;
  361. obj = rt_list_entry(obj_list[i], struct rt_object, list);
  362. level = rt_hw_interrupt_disable();
  363. if ((obj->type & ~RT_Object_Class_Static) != find_arg.type)
  364. {
  365. rt_hw_interrupt_enable(level);
  366. continue;
  367. }
  368. rt_hw_interrupt_enable(level);
  369. m = (struct rt_mutex *)obj;
  370. if (!rt_list_isempty(&m->parent.suspend_thread))
  371. {
  372. rt_kprintf("%-*.*s %-8.*s %04d %8d %04d ",
  373. maxlen, RT_NAME_MAX,
  374. m->parent.parent.name,
  375. RT_NAME_MAX,
  376. m->owner->parent.name,
  377. m->hold,
  378. m->priority,
  379. rt_list_len(&m->parent.suspend_thread));
  380. show_wait_queue(&(m->parent.suspend_thread));
  381. rt_kprintf("\n");
  382. }
  383. else
  384. {
  385. rt_kprintf("%-*.*s %-8.*s %04d %8d %04d\n",
  386. maxlen, RT_NAME_MAX,
  387. m->parent.parent.name,
  388. RT_NAME_MAX,
  389. m->owner->parent.name,
  390. m->hold,
  391. m->priority,
  392. rt_list_len(&m->parent.suspend_thread));
  393. }
  394. }
  395. }
  396. }
  397. while (next != (rt_list_t *)RT_NULL);
  398. return 0;
  399. }
  400. #endif /* RT_USING_MUTEX */
  401. #ifdef RT_USING_MAILBOX
  402. long list_mailbox(void)
  403. {
  404. rt_base_t level;
  405. list_get_next_t find_arg;
  406. rt_list_t *obj_list[LIST_FIND_OBJ_NR];
  407. rt_list_t *next = (rt_list_t *)RT_NULL;
  408. int maxlen;
  409. const char *item_title = "mailbox";
  410. list_find_init(&find_arg, RT_Object_Class_MailBox, obj_list, sizeof(obj_list) / sizeof(obj_list[0]));
  411. maxlen = RT_NAME_MAX;
  412. rt_kprintf("%-*.*s entry size suspend thread\n", maxlen, maxlen, item_title);
  413. object_split(maxlen);
  414. rt_kprintf(" ---- ---- --------------\n");
  415. do
  416. {
  417. next = list_get_next(next, &find_arg);
  418. {
  419. int i;
  420. for (i = 0; i < find_arg.nr_out; i++)
  421. {
  422. struct rt_object *obj;
  423. struct rt_mailbox *m;
  424. obj = rt_list_entry(obj_list[i], struct rt_object, list);
  425. level = rt_hw_interrupt_disable();
  426. if ((obj->type & ~RT_Object_Class_Static) != find_arg.type)
  427. {
  428. rt_hw_interrupt_enable(level);
  429. continue;
  430. }
  431. rt_hw_interrupt_enable(level);
  432. m = (struct rt_mailbox *)obj;
  433. if (!rt_list_isempty(&m->parent.suspend_thread))
  434. {
  435. rt_kprintf("%-*.*s %04d %04d %d:",
  436. maxlen, RT_NAME_MAX,
  437. m->parent.parent.name,
  438. m->entry,
  439. m->size,
  440. rt_list_len(&m->parent.suspend_thread));
  441. show_wait_queue(&(m->parent.suspend_thread));
  442. rt_kprintf("\n");
  443. }
  444. else
  445. {
  446. rt_kprintf("%-*.*s %04d %04d %d\n",
  447. maxlen, RT_NAME_MAX,
  448. m->parent.parent.name,
  449. m->entry,
  450. m->size,
  451. rt_list_len(&m->parent.suspend_thread));
  452. }
  453. }
  454. }
  455. }
  456. while (next != (rt_list_t *)RT_NULL);
  457. return 0;
  458. }
  459. #endif /* RT_USING_MAILBOX */
  460. #ifdef RT_USING_MESSAGEQUEUE
  461. long list_msgqueue(void)
  462. {
  463. rt_base_t level;
  464. list_get_next_t find_arg;
  465. rt_list_t *obj_list[LIST_FIND_OBJ_NR];
  466. rt_list_t *next = (rt_list_t *)RT_NULL;
  467. int maxlen;
  468. const char *item_title = "msgqueue";
  469. list_find_init(&find_arg, RT_Object_Class_MessageQueue, obj_list, sizeof(obj_list) / sizeof(obj_list[0]));
  470. maxlen = RT_NAME_MAX;
  471. rt_kprintf("%-*.*s entry suspend thread\n", maxlen, maxlen, item_title);
  472. object_split(maxlen);
  473. rt_kprintf(" ---- --------------\n");
  474. do
  475. {
  476. next = list_get_next(next, &find_arg);
  477. {
  478. int i;
  479. for (i = 0; i < find_arg.nr_out; i++)
  480. {
  481. struct rt_object *obj;
  482. struct rt_messagequeue *m;
  483. obj = rt_list_entry(obj_list[i], struct rt_object, list);
  484. level = rt_hw_interrupt_disable();
  485. if ((obj->type & ~RT_Object_Class_Static) != find_arg.type)
  486. {
  487. rt_hw_interrupt_enable(level);
  488. continue;
  489. }
  490. rt_hw_interrupt_enable(level);
  491. m = (struct rt_messagequeue *)obj;
  492. if (!rt_list_isempty(&m->parent.suspend_thread))
  493. {
  494. rt_kprintf("%-*.*s %04d %d:",
  495. maxlen, RT_NAME_MAX,
  496. m->parent.parent.name,
  497. m->entry,
  498. rt_list_len(&m->parent.suspend_thread));
  499. show_wait_queue(&(m->parent.suspend_thread));
  500. rt_kprintf("\n");
  501. }
  502. else
  503. {
  504. rt_kprintf("%-*.*s %04d %d\n",
  505. maxlen, RT_NAME_MAX,
  506. m->parent.parent.name,
  507. m->entry,
  508. rt_list_len(&m->parent.suspend_thread));
  509. }
  510. }
  511. }
  512. }
  513. while (next != (rt_list_t *)RT_NULL);
  514. return 0;
  515. }
  516. #endif /* RT_USING_MESSAGEQUEUE */
  517. #ifdef RT_USING_MEMHEAP
  518. long list_memheap(void)
  519. {
  520. rt_base_t level;
  521. list_get_next_t find_arg;
  522. rt_list_t *obj_list[LIST_FIND_OBJ_NR];
  523. rt_list_t *next = (rt_list_t *)RT_NULL;
  524. int maxlen;
  525. const char *item_title = "memheap";
  526. list_find_init(&find_arg, RT_Object_Class_MemHeap, obj_list, sizeof(obj_list) / sizeof(obj_list[0]));
  527. maxlen = RT_NAME_MAX;
  528. rt_kprintf("%-*.*s pool size max used size available size\n", maxlen, maxlen, item_title);
  529. object_split(maxlen);
  530. rt_kprintf(" ---------- ------------- --------------\n");
  531. do
  532. {
  533. next = list_get_next(next, &find_arg);
  534. {
  535. int i;
  536. for (i = 0; i < find_arg.nr_out; i++)
  537. {
  538. struct rt_object *obj;
  539. struct rt_memheap *mh;
  540. obj = rt_list_entry(obj_list[i], struct rt_object, list);
  541. level = rt_hw_interrupt_disable();
  542. if ((obj->type & ~RT_Object_Class_Static) != find_arg.type)
  543. {
  544. rt_hw_interrupt_enable(level);
  545. continue;
  546. }
  547. rt_hw_interrupt_enable(level);
  548. mh = (struct rt_memheap *)obj;
  549. rt_kprintf("%-*.*s %-010d %-013d %-05d\n",
  550. maxlen, RT_NAME_MAX,
  551. mh->parent.name,
  552. mh->pool_size,
  553. mh->max_used_size,
  554. mh->available_size);
  555. }
  556. }
  557. }
  558. while (next != (rt_list_t *)RT_NULL);
  559. return 0;
  560. }
  561. #endif /* RT_USING_MEMHEAP */
  562. #ifdef RT_USING_MEMPOOL
  563. long list_mempool(void)
  564. {
  565. rt_base_t level;
  566. list_get_next_t find_arg;
  567. rt_list_t *obj_list[LIST_FIND_OBJ_NR];
  568. rt_list_t *next = (rt_list_t *)RT_NULL;
  569. int maxlen;
  570. const char *item_title = "mempool";
  571. list_find_init(&find_arg, RT_Object_Class_MemPool, obj_list, sizeof(obj_list) / sizeof(obj_list[0]));
  572. maxlen = RT_NAME_MAX;
  573. rt_kprintf("%-*.*s block total free suspend thread\n", maxlen, maxlen, item_title);
  574. object_split(maxlen);
  575. rt_kprintf(" ---- ---- ---- --------------\n");
  576. do
  577. {
  578. next = list_get_next(next, &find_arg);
  579. {
  580. int i;
  581. for (i = 0; i < find_arg.nr_out; i++)
  582. {
  583. struct rt_object *obj;
  584. struct rt_mempool *mp;
  585. int suspend_thread_count;
  586. rt_list_t *node;
  587. obj = rt_list_entry(obj_list[i], struct rt_object, list);
  588. level = rt_hw_interrupt_disable();
  589. if ((obj->type & ~RT_Object_Class_Static) != find_arg.type)
  590. {
  591. rt_hw_interrupt_enable(level);
  592. continue;
  593. }
  594. rt_hw_interrupt_enable(level);
  595. mp = (struct rt_mempool *)obj;
  596. suspend_thread_count = 0;
  597. rt_list_for_each(node, &mp->suspend_thread)
  598. {
  599. suspend_thread_count++;
  600. }
  601. if (suspend_thread_count > 0)
  602. {
  603. rt_kprintf("%-*.*s %04d %04d %04d %d:",
  604. maxlen, RT_NAME_MAX,
  605. mp->parent.name,
  606. mp->block_size,
  607. mp->block_total_count,
  608. mp->block_free_count,
  609. suspend_thread_count);
  610. show_wait_queue(&(mp->suspend_thread));
  611. rt_kprintf("\n");
  612. }
  613. else
  614. {
  615. rt_kprintf("%-*.*s %04d %04d %04d %d\n",
  616. maxlen, RT_NAME_MAX,
  617. mp->parent.name,
  618. mp->block_size,
  619. mp->block_total_count,
  620. mp->block_free_count,
  621. suspend_thread_count);
  622. }
  623. }
  624. }
  625. }
  626. while (next != (rt_list_t *)RT_NULL);
  627. return 0;
  628. }
  629. #endif /* RT_USING_MEMPOOL */
  630. long list_timer(void)
  631. {
  632. rt_base_t level;
  633. list_get_next_t find_arg;
  634. rt_list_t *obj_list[LIST_FIND_OBJ_NR];
  635. rt_list_t *next = (rt_list_t *)RT_NULL;
  636. int maxlen;
  637. const char *item_title = "timer";
  638. list_find_init(&find_arg, RT_Object_Class_Timer, obj_list, sizeof(obj_list) / sizeof(obj_list[0]));
  639. maxlen = RT_NAME_MAX;
  640. rt_kprintf("%-*.*s periodic timeout activated mode\n", maxlen, maxlen, item_title);
  641. object_split(maxlen);
  642. rt_kprintf(" ---------- ---------- ----------- ---------\n");
  643. do
  644. {
  645. next = list_get_next(next, &find_arg);
  646. {
  647. int i;
  648. for (i = 0; i < find_arg.nr_out; i++)
  649. {
  650. struct rt_object *obj;
  651. struct rt_timer *timer;
  652. obj = rt_list_entry(obj_list[i], struct rt_object, list);
  653. level = rt_hw_interrupt_disable();
  654. if ((obj->type & ~RT_Object_Class_Static) != find_arg.type)
  655. {
  656. rt_hw_interrupt_enable(level);
  657. continue;
  658. }
  659. rt_hw_interrupt_enable(level);
  660. timer = (struct rt_timer *)obj;
  661. rt_kprintf("%-*.*s 0x%08x 0x%08x ",
  662. maxlen, RT_NAME_MAX,
  663. timer->parent.name,
  664. timer->init_tick,
  665. timer->timeout_tick);
  666. if (timer->parent.flag & RT_TIMER_FLAG_ACTIVATED)
  667. rt_kprintf("activated ");
  668. else
  669. rt_kprintf("deactivated ");
  670. if (timer->parent.flag & RT_TIMER_FLAG_PERIODIC)
  671. rt_kprintf("periodic\n");
  672. else
  673. rt_kprintf("one shot\n");
  674. }
  675. }
  676. }
  677. while (next != (rt_list_t *)RT_NULL);
  678. rt_kprintf("current tick:0x%08x\n", rt_tick_get());
  679. return 0;
  680. }
  681. #ifdef RT_USING_DEVICE
  682. static char *const device_type_str[RT_Device_Class_Unknown] =
  683. {
  684. "Character Device",
  685. "Block Device",
  686. "Network Interface",
  687. "MTD Device",
  688. "CAN Device",
  689. "RTC",
  690. "Sound Device",
  691. "Graphic Device",
  692. "I2C Bus",
  693. "USB Slave Device",
  694. "USB Host Bus",
  695. "USB OTG Bus",
  696. "SPI Bus",
  697. "SPI Device",
  698. "SDIO Bus",
  699. "PM Pseudo Device",
  700. "Pipe",
  701. "Portal Device",
  702. "Timer Device",
  703. "Miscellaneous Device",
  704. "Sensor Device",
  705. "Touch Device",
  706. "Phy Device",
  707. "Security Device",
  708. "WLAN Device",
  709. "Pin Device",
  710. "ADC Device",
  711. "DAC Device",
  712. "WDT Device",
  713. "PWM Device",
  714. };
  715. long list_device(void)
  716. {
  717. rt_base_t level;
  718. list_get_next_t find_arg;
  719. rt_list_t *obj_list[LIST_FIND_OBJ_NR];
  720. rt_list_t *next = (rt_list_t *)RT_NULL;
  721. const char *device_type;
  722. int maxlen;
  723. const char *item_title = "device";
  724. list_find_init(&find_arg, RT_Object_Class_Device, obj_list, sizeof(obj_list) / sizeof(obj_list[0]));
  725. maxlen = RT_NAME_MAX;
  726. rt_kprintf("%-*.*s type ref count\n", maxlen, maxlen, item_title);
  727. object_split(maxlen);
  728. rt_kprintf(" -------------------- ----------\n");
  729. do
  730. {
  731. next = list_get_next(next, &find_arg);
  732. {
  733. int i;
  734. for (i = 0; i < find_arg.nr_out; i++)
  735. {
  736. struct rt_object *obj;
  737. struct rt_device *device;
  738. obj = rt_list_entry(obj_list[i], struct rt_object, list);
  739. level = rt_hw_interrupt_disable();
  740. if ((obj->type & ~RT_Object_Class_Static) != find_arg.type)
  741. {
  742. rt_hw_interrupt_enable(level);
  743. continue;
  744. }
  745. rt_hw_interrupt_enable(level);
  746. device = (struct rt_device *)obj;
  747. device_type = "Unknown";
  748. if (device->type < RT_Device_Class_Unknown &&
  749. device_type_str[device->type] != RT_NULL)
  750. {
  751. device_type = device_type_str[device->type];
  752. }
  753. rt_kprintf("%-*.*s %-20s %-8d\n",
  754. maxlen, RT_NAME_MAX,
  755. device->parent.name,
  756. device_type,
  757. device->ref_count);
  758. }
  759. }
  760. }
  761. while (next != (rt_list_t *)RT_NULL);
  762. return 0;
  763. }
  764. #endif /* RT_USING_DEVICE */
  765. int cmd_list(int argc, char **argv)
  766. {
  767. if(argc == 2)
  768. {
  769. if(strcmp(argv[1], "thread") == 0)
  770. {
  771. list_thread();
  772. }
  773. else if(strcmp(argv[1], "timer") == 0)
  774. {
  775. list_timer();
  776. }
  777. #ifdef RT_USING_SEMAPHORE
  778. else if(strcmp(argv[1], "sem") == 0)
  779. {
  780. list_sem();
  781. }
  782. #endif /* RT_USING_SEMAPHORE */
  783. #ifdef RT_USING_EVENT
  784. else if(strcmp(argv[1], "event") == 0)
  785. {
  786. list_event();
  787. }
  788. #endif /* RT_USING_EVENT */
  789. #ifdef RT_USING_MUTEX
  790. else if(strcmp(argv[1], "mutex") == 0)
  791. {
  792. list_mutex();
  793. }
  794. #endif /* RT_USING_MUTEX */
  795. #ifdef RT_USING_MAILBOX
  796. else if(strcmp(argv[1], "mailbox") == 0)
  797. {
  798. list_mailbox();
  799. }
  800. #endif /* RT_USING_MAILBOX */
  801. #ifdef RT_USING_MESSAGEQUEUE
  802. else if(strcmp(argv[1], "msgqueue") == 0)
  803. {
  804. list_msgqueue();
  805. }
  806. #endif /* RT_USING_MESSAGEQUEUE */
  807. #ifdef RT_USING_MEMHEAP
  808. else if(strcmp(argv[1], "memheap") == 0)
  809. {
  810. list_memheap();
  811. }
  812. #endif /* RT_USING_MEMHEAP */
  813. #ifdef RT_USING_MEMPOOL
  814. else if(strcmp(argv[1], "mempool") == 0)
  815. {
  816. list_mempool();
  817. }
  818. #endif /* RT_USING_MEMPOOL */
  819. #ifdef RT_USING_DEVICE
  820. else if(strcmp(argv[1], "device") == 0)
  821. {
  822. list_device();
  823. }
  824. #endif /* RT_USING_DEVICE */
  825. #ifdef RT_USING_DFS
  826. else if(strcmp(argv[1], "fd") == 0)
  827. {
  828. extern int list_fd(void);
  829. list_fd();
  830. }
  831. #endif /* RT_USING_DFS */
  832. else
  833. {
  834. goto _usage;
  835. }
  836. return 0;
  837. }
  838. _usage:
  839. rt_kprintf("Usage: list [options]\n");
  840. rt_kprintf("[options]:\n");
  841. rt_kprintf(" %-12s - list threads\n", "thread");
  842. rt_kprintf(" %-12s - list timers\n", "timer");
  843. #ifdef RT_USING_SEMAPHORE
  844. rt_kprintf(" %-12s - list semaphores\n", "sem");
  845. #endif /* RT_USING_SEMAPHORE */
  846. #ifdef RT_USING_MUTEX
  847. rt_kprintf(" %-12s - list mutexs\n", "mutex");
  848. #endif /* RT_USING_MUTEX */
  849. #ifdef RT_USING_EVENT
  850. rt_kprintf(" %-12s - list events\n", "event");
  851. #endif /* RT_USING_EVENT */
  852. #ifdef RT_USING_MAILBOX
  853. rt_kprintf(" %-12s - list mailboxs\n", "mailbox");
  854. #endif /* RT_USING_MAILBOX */
  855. #ifdef RT_USING_MESSAGEQUEUE
  856. rt_kprintf(" %-12s - list message queues\n", "msgqueue");
  857. #endif /* RT_USING_MESSAGEQUEUE */
  858. #ifdef RT_USING_MEMHEAP
  859. rt_kprintf(" %-12s - list memory heaps\n", "memheap");
  860. #endif /* RT_USING_MEMHEAP */
  861. #ifdef RT_USING_MEMPOOL
  862. rt_kprintf(" %-12s - list memory pools\n", "mempool");
  863. #endif /* RT_USING_MEMPOOL */
  864. #ifdef RT_USING_DEVICE
  865. rt_kprintf(" %-12s - list devices\n", "device");
  866. #endif /* RT_USING_DEVICE */
  867. #ifdef RT_USING_DFS
  868. rt_kprintf(" %-12s - list file descriptors\n", "fd");
  869. #endif /* RT_USING_DFS */
  870. return 0;
  871. }
  872. MSH_CMD_EXPORT_ALIAS(cmd_list, list, list objects);
  873. #endif /* RT_USING_FINSH */