object.c 17 KB

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