object.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619
  1. /*
  2. * Copyright (c) 2006-2018, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2006-03-14 Bernard the first version
  9. * 2006-04-21 Bernard change the scheduler lock to interrupt lock
  10. * 2006-05-18 Bernard fix the object init bug
  11. * 2006-08-03 Bernard add hook support
  12. * 2007-01-28 Bernard rename RT_OBJECT_Class_Static to RT_Object_Class_Static
  13. * 2010-10-26 yi.qiu add module support in rt_object_allocate and rt_object_free
  14. * 2017-12-10 Bernard Add object_info enum.
  15. * 2018-01-25 Bernard Fix the object find issue when enable MODULE.
  16. */
  17. #include <rtthread.h>
  18. #include <rthw.h>
  19. #ifdef RT_USING_MODULE
  20. #include <dlmodule.h>
  21. #endif
  22. #ifdef RT_USING_LWP
  23. #include <lwp.h>
  24. #endif
  25. /*
  26. * define object_info for the number of rt_object_container items.
  27. */
  28. enum rt_object_info_type
  29. {
  30. RT_Object_Info_Thread = 0, /**< The object is a thread. */
  31. #ifdef RT_USING_SEMAPHORE
  32. RT_Object_Info_Semaphore, /**< The object is a semaphore. */
  33. #endif
  34. #ifdef RT_USING_MUTEX
  35. RT_Object_Info_Mutex, /**< The object is a mutex. */
  36. #endif
  37. #ifdef RT_USING_EVENT
  38. RT_Object_Info_Event, /**< The object is a event. */
  39. #endif
  40. #ifdef RT_USING_MAILBOX
  41. RT_Object_Info_MailBox, /**< The object is a mail box. */
  42. #endif
  43. #ifdef RT_USING_MESSAGEQUEUE
  44. RT_Object_Info_MessageQueue, /**< The object is a message queue. */
  45. #endif
  46. #ifdef RT_USING_MEMHEAP
  47. RT_Object_Info_MemHeap, /**< The object is a memory heap */
  48. #endif
  49. #ifdef RT_USING_MEMPOOL
  50. RT_Object_Info_MemPool, /**< The object is a memory pool. */
  51. #endif
  52. #ifdef RT_USING_DEVICE
  53. RT_Object_Info_Device, /**< The object is a device */
  54. #endif
  55. RT_Object_Info_Timer, /**< The object is a timer. */
  56. #ifdef RT_USING_MODULE
  57. RT_Object_Info_Module, /**< The object is a module. */
  58. #endif
  59. #ifdef RT_USING_LWP
  60. RT_Object_Info_Channel, /**< The object is a IPC channel */
  61. #endif
  62. RT_Object_Info_Unknown, /**< The object is unknown. */
  63. };
  64. #define _OBJ_CONTAINER_LIST_INIT(c) \
  65. {&(rt_object_container[c].object_list), &(rt_object_container[c].object_list)}
  66. static struct rt_object_information rt_object_container[RT_Object_Info_Unknown] =
  67. {
  68. /* initialize object container - thread */
  69. {RT_Object_Class_Thread, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Thread), sizeof(struct rt_thread)},
  70. #ifdef RT_USING_SEMAPHORE
  71. /* initialize object container - semaphore */
  72. {RT_Object_Class_Semaphore, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Semaphore), sizeof(struct rt_semaphore)},
  73. #endif
  74. #ifdef RT_USING_MUTEX
  75. /* initialize object container - mutex */
  76. {RT_Object_Class_Mutex, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Mutex), sizeof(struct rt_mutex)},
  77. #endif
  78. #ifdef RT_USING_EVENT
  79. /* initialize object container - event */
  80. {RT_Object_Class_Event, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Event), sizeof(struct rt_event)},
  81. #endif
  82. #ifdef RT_USING_MAILBOX
  83. /* initialize object container - mailbox */
  84. {RT_Object_Class_MailBox, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MailBox), sizeof(struct rt_mailbox)},
  85. #endif
  86. #ifdef RT_USING_MESSAGEQUEUE
  87. /* initialize object container - message queue */
  88. {RT_Object_Class_MessageQueue, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MessageQueue), sizeof(struct rt_messagequeue)},
  89. #endif
  90. #ifdef RT_USING_MEMHEAP
  91. /* initialize object container - memory heap */
  92. {RT_Object_Class_MemHeap, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MemHeap), sizeof(struct rt_memheap)},
  93. #endif
  94. #ifdef RT_USING_MEMPOOL
  95. /* initialize object container - memory pool */
  96. {RT_Object_Class_MemPool, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MemPool), sizeof(struct rt_mempool)},
  97. #endif
  98. #ifdef RT_USING_DEVICE
  99. /* initialize object container - device */
  100. {RT_Object_Class_Device, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Device), sizeof(struct rt_device)},
  101. #endif
  102. /* initialize object container - timer */
  103. {RT_Object_Class_Timer, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Timer), sizeof(struct rt_timer)},
  104. #ifdef RT_USING_MODULE
  105. /* initialize object container - module */
  106. {RT_Object_Class_Module, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Module), sizeof(struct rt_dlmodule)},
  107. #endif
  108. #ifdef RT_USING_LWP
  109. /* initialize object container - module */
  110. {RT_Object_Class_Channel, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Channel), sizeof(struct rt_channel)},
  111. #endif
  112. };
  113. #ifdef RT_USING_HOOK
  114. static void (*rt_object_attach_hook)(struct rt_object *object);
  115. static void (*rt_object_detach_hook)(struct rt_object *object);
  116. void (*rt_object_trytake_hook)(struct rt_object *object);
  117. void (*rt_object_take_hook)(struct rt_object *object);
  118. void (*rt_object_put_hook)(struct rt_object *object);
  119. /**
  120. * @addtogroup Hook
  121. */
  122. /**@{*/
  123. /**
  124. * This function will set a hook function, which will be invoked when object
  125. * attaches to kernel object system.
  126. *
  127. * @param hook the hook function
  128. */
  129. void rt_object_attach_sethook(void (*hook)(struct rt_object *object))
  130. {
  131. rt_object_attach_hook = hook;
  132. }
  133. /**
  134. * This function will set a hook function, which will be invoked when object
  135. * detaches from kernel object system.
  136. *
  137. * @param hook the hook function
  138. */
  139. void rt_object_detach_sethook(void (*hook)(struct rt_object *object))
  140. {
  141. rt_object_detach_hook = hook;
  142. }
  143. /**
  144. * This function will set a hook function, which will be invoked when object
  145. * is taken from kernel object system.
  146. *
  147. * The object is taken means:
  148. * semaphore - semaphore is taken by thread
  149. * mutex - mutex is taken by thread
  150. * event - event is received by thread
  151. * mailbox - mail is received by thread
  152. * message queue - message is received by thread
  153. *
  154. * @param hook the hook function
  155. */
  156. void rt_object_trytake_sethook(void (*hook)(struct rt_object *object))
  157. {
  158. rt_object_trytake_hook = hook;
  159. }
  160. /**
  161. * This function will set a hook function, which will be invoked when object
  162. * have been taken from kernel object system.
  163. *
  164. * The object have been taken means:
  165. * semaphore - semaphore have been taken by thread
  166. * mutex - mutex have been taken by thread
  167. * event - event have been received by thread
  168. * mailbox - mail have been received by thread
  169. * message queue - message have been received by thread
  170. * timer - timer is started
  171. *
  172. * @param hook the hook function
  173. */
  174. void rt_object_take_sethook(void (*hook)(struct rt_object *object))
  175. {
  176. rt_object_take_hook = hook;
  177. }
  178. /**
  179. * This function will set a hook function, which will be invoked when object
  180. * is put to kernel object system.
  181. *
  182. * @param hook the hook function
  183. */
  184. void rt_object_put_sethook(void (*hook)(struct rt_object *object))
  185. {
  186. rt_object_put_hook = hook;
  187. }
  188. /**@}*/
  189. #endif
  190. /**
  191. * @ingroup SystemInit
  192. *
  193. * This function will initialize system object management.
  194. *
  195. * @deprecated since 0.3.0, this function does not need to be invoked
  196. * in the system initialization.
  197. */
  198. void rt_system_object_init(void)
  199. {
  200. }
  201. /**
  202. * @addtogroup KernelObject
  203. */
  204. /**@{*/
  205. /**
  206. * This function will return the specified type of object information.
  207. *
  208. * @param type the type of object, which can be
  209. * RT_Object_Class_Thread/Semaphore/Mutex... etc
  210. *
  211. * @return the object type information or RT_NULL
  212. */
  213. struct rt_object_information *
  214. rt_object_get_information(enum rt_object_class_type type)
  215. {
  216. int index;
  217. for (index = 0; index < RT_Object_Info_Unknown; index ++)
  218. if (rt_object_container[index].type == type) return &rt_object_container[index];
  219. return RT_NULL;
  220. }
  221. RTM_EXPORT(rt_object_get_information);
  222. /**
  223. * This function will return the length of object list in object container.
  224. *
  225. * @param type the type of object, which can be
  226. * RT_Object_Class_Thread/Semaphore/Mutex... etc
  227. * @return the length of object list
  228. */
  229. int rt_object_get_length(enum rt_object_class_type type)
  230. {
  231. int count = 0;
  232. rt_ubase_t level;
  233. struct rt_list_node *node = RT_NULL;
  234. struct rt_object_information *information = RT_NULL;
  235. information = rt_object_get_information((enum rt_object_class_type)type);
  236. if (information == RT_NULL) return 0;
  237. level = rt_hw_interrupt_disable();
  238. /* get the count of objects */
  239. rt_list_for_each(node, &(information->object_list))
  240. {
  241. count ++;
  242. }
  243. rt_hw_interrupt_enable(level);
  244. return count;
  245. }
  246. RTM_EXPORT(rt_object_get_length);
  247. /**
  248. * This function will copy the object pointer of the specified type,
  249. * with the maximum size specified by maxlen.
  250. *
  251. * @param type the type of object, which can be
  252. * RT_Object_Class_Thread/Semaphore/Mutex... etc
  253. * @param pointers the pointers will be saved to
  254. * @param maxlen the maximum number of pointers can be saved
  255. *
  256. * @return the copied number of object pointers
  257. */
  258. int rt_object_get_pointers(enum rt_object_class_type type, rt_object_t *pointers, int maxlen)
  259. {
  260. int index = 0;
  261. rt_ubase_t level;
  262. struct rt_object *object;
  263. struct rt_list_node *node = RT_NULL;
  264. struct rt_object_information *information = RT_NULL;
  265. if (maxlen <= 0) return 0;
  266. information = rt_object_get_information((enum rt_object_class_type)type);
  267. if (information == RT_NULL) return 0;
  268. level = rt_hw_interrupt_disable();
  269. /* retrieve pointer of object */
  270. rt_list_for_each(node, &(information->object_list))
  271. {
  272. object = rt_list_entry(node, struct rt_object, list);
  273. pointers[index] = object;
  274. index ++;
  275. if (index >= maxlen) break;
  276. }
  277. rt_hw_interrupt_enable(level);
  278. return index;
  279. }
  280. RTM_EXPORT(rt_object_get_pointers);
  281. /**
  282. * This function will initialize an object and add it to object system
  283. * management.
  284. *
  285. * @param object the specified object to be initialized.
  286. * @param type the object type.
  287. * @param name the object name. In system, the object's name must be unique.
  288. */
  289. void rt_object_init(struct rt_object *object,
  290. enum rt_object_class_type type,
  291. const char *name)
  292. {
  293. register rt_base_t temp;
  294. struct rt_list_node *node = RT_NULL;
  295. struct rt_object_information *information;
  296. #ifdef RT_USING_MODULE
  297. struct rt_dlmodule *module = dlmodule_self();
  298. #endif
  299. /* get object information */
  300. information = rt_object_get_information(type);
  301. RT_ASSERT(information != RT_NULL);
  302. /* check object type to avoid re-initialization */
  303. /* enter critical */
  304. rt_enter_critical();
  305. /* try to find object */
  306. for (node = information->object_list.next;
  307. node != &(information->object_list);
  308. node = node->next)
  309. {
  310. struct rt_object *obj;
  311. obj = rt_list_entry(node, struct rt_object, list);
  312. if (obj) /* skip warning when disable debug */
  313. {
  314. RT_ASSERT(obj != object);
  315. }
  316. }
  317. /* leave critical */
  318. rt_exit_critical();
  319. /* initialize object's parameters */
  320. /* set object type to static */
  321. object->type = type | RT_Object_Class_Static;
  322. /* copy name */
  323. rt_strncpy(object->name, name, RT_NAME_MAX);
  324. RT_OBJECT_HOOK_CALL(rt_object_attach_hook, (object));
  325. /* lock interrupt */
  326. temp = rt_hw_interrupt_disable();
  327. #ifdef RT_USING_MODULE
  328. if (module)
  329. {
  330. rt_list_insert_after(&(module->object_list), &(object->list));
  331. object->module_id = (void *)module;
  332. }
  333. else
  334. #endif
  335. {
  336. /* insert object into information object list */
  337. rt_list_insert_after(&(information->object_list), &(object->list));
  338. }
  339. /* unlock interrupt */
  340. rt_hw_interrupt_enable(temp);
  341. }
  342. /**
  343. * This function will detach a static object from object system,
  344. * and the memory of static object is not freed.
  345. *
  346. * @param object the specified object to be detached.
  347. */
  348. void rt_object_detach(rt_object_t object)
  349. {
  350. register rt_base_t temp;
  351. /* object check */
  352. RT_ASSERT(object != RT_NULL);
  353. RT_OBJECT_HOOK_CALL(rt_object_detach_hook, (object));
  354. /* reset object type */
  355. object->type = 0;
  356. /* lock interrupt */
  357. temp = rt_hw_interrupt_disable();
  358. /* remove from old list */
  359. rt_list_remove(&(object->list));
  360. /* unlock interrupt */
  361. rt_hw_interrupt_enable(temp);
  362. }
  363. #ifdef RT_USING_HEAP
  364. /**
  365. * This function will allocate an object from object system
  366. *
  367. * @param type the type of object
  368. * @param name the object name. In system, the object's name must be unique.
  369. *
  370. * @return object
  371. */
  372. rt_object_t rt_object_allocate(enum rt_object_class_type type, const char *name)
  373. {
  374. struct rt_object *object;
  375. register rt_base_t temp;
  376. struct rt_object_information *information;
  377. #ifdef RT_USING_MODULE
  378. struct rt_dlmodule *module = dlmodule_self();
  379. #endif
  380. RT_DEBUG_NOT_IN_INTERRUPT;
  381. /* get object information */
  382. information = rt_object_get_information(type);
  383. RT_ASSERT(information != RT_NULL);
  384. object = (struct rt_object *)RT_KERNEL_MALLOC(information->object_size);
  385. if (object == RT_NULL)
  386. {
  387. /* no memory can be allocated */
  388. return RT_NULL;
  389. }
  390. /* clean memory data of object */
  391. rt_memset(object, 0x0, information->object_size);
  392. /* initialize object's parameters */
  393. /* set object type */
  394. object->type = type;
  395. /* set object flag */
  396. object->flag = 0;
  397. /* copy name */
  398. rt_strncpy(object->name, name, RT_NAME_MAX);
  399. RT_OBJECT_HOOK_CALL(rt_object_attach_hook, (object));
  400. /* lock interrupt */
  401. temp = rt_hw_interrupt_disable();
  402. #ifdef RT_USING_MODULE
  403. if (module)
  404. {
  405. rt_list_insert_after(&(module->object_list), &(object->list));
  406. object->module_id = (void *)module;
  407. }
  408. else
  409. #endif
  410. {
  411. /* insert object into information object list */
  412. rt_list_insert_after(&(information->object_list), &(object->list));
  413. }
  414. #ifdef RT_USING_LWP
  415. {
  416. struct rt_lwp *lwp = lwp_self();
  417. if (lwp)
  418. {
  419. /* insert object into lwP object list */
  420. rt_list_insert_after(&(lwp->object_list), &(object->lwp_obj_list));
  421. }
  422. else
  423. {
  424. rt_list_init(&(object->lwp_obj_list));
  425. }
  426. }
  427. #endif
  428. /* unlock interrupt */
  429. rt_hw_interrupt_enable(temp);
  430. /* return object */
  431. return object;
  432. }
  433. /**
  434. * This function will delete an object and release object memory.
  435. *
  436. * @param object the specified object to be deleted.
  437. */
  438. void rt_object_delete(rt_object_t object)
  439. {
  440. register rt_base_t temp;
  441. /* object check */
  442. RT_ASSERT(object != RT_NULL);
  443. RT_ASSERT(!(object->type & RT_Object_Class_Static));
  444. RT_OBJECT_HOOK_CALL(rt_object_detach_hook, (object));
  445. /* reset object type */
  446. object->type = 0;
  447. /* lock interrupt */
  448. temp = rt_hw_interrupt_disable();
  449. /* remove from old list */
  450. rt_list_remove(&(object->list));
  451. #ifdef RT_USING_LWP
  452. /* remove from the object list of lwP */
  453. rt_list_remove(&(object->lwp_obj_list));
  454. #endif
  455. /* unlock interrupt */
  456. rt_hw_interrupt_enable(temp);
  457. /* free the memory of object */
  458. RT_KERNEL_FREE(object);
  459. }
  460. #endif
  461. /**
  462. * This function will judge the object is system object or not.
  463. * Normally, the system object is a static object and the type
  464. * of object set to RT_Object_Class_Static.
  465. *
  466. * @param object the specified object to be judged.
  467. *
  468. * @return RT_TRUE if a system object, RT_FALSE for others.
  469. */
  470. rt_bool_t rt_object_is_systemobject(rt_object_t object)
  471. {
  472. /* object check */
  473. RT_ASSERT(object != RT_NULL);
  474. if (object->type & RT_Object_Class_Static)
  475. return RT_TRUE;
  476. return RT_FALSE;
  477. }
  478. /**
  479. * This function will return the type of object without
  480. * RT_Object_Class_Static flag.
  481. *
  482. * @param object the specified object to be get type.
  483. *
  484. * @return the type of object.
  485. */
  486. rt_uint8_t rt_object_get_type(rt_object_t object)
  487. {
  488. /* object check */
  489. RT_ASSERT(object != RT_NULL);
  490. return object->type & ~RT_Object_Class_Static;
  491. }
  492. /**
  493. * This function will find specified name object from object
  494. * container.
  495. *
  496. * @param name the specified name of object.
  497. * @param type the type of object
  498. *
  499. * @return the found object or RT_NULL if there is no this object
  500. * in object container.
  501. *
  502. * @note this function shall not be invoked in interrupt status.
  503. */
  504. rt_object_t rt_object_find(const char *name, rt_uint8_t type)
  505. {
  506. struct rt_object *object = RT_NULL;
  507. struct rt_list_node *node = RT_NULL;
  508. struct rt_object_information *information = RT_NULL;
  509. information = rt_object_get_information((enum rt_object_class_type)type);
  510. /* parameter check */
  511. if ((name == RT_NULL) || (information == RT_NULL)) return RT_NULL;
  512. /* which is invoke in interrupt status */
  513. RT_DEBUG_NOT_IN_INTERRUPT;
  514. /* enter critical */
  515. rt_enter_critical();
  516. /* try to find object */
  517. rt_list_for_each(node, &(information->object_list))
  518. {
  519. object = rt_list_entry(node, struct rt_object, list);
  520. if (rt_strncmp(object->name, name, RT_NAME_MAX) == 0)
  521. {
  522. /* leave critical */
  523. rt_exit_critical();
  524. return object;
  525. }
  526. }
  527. /* leave critical */
  528. rt_exit_critical();
  529. return RT_NULL;
  530. }
  531. /**@}*/