object.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796
  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. * 2022-01-07 Gabriel Moving __on_rt_xxxxx_hook to object.c
  17. * 2023-09-15 xqyjlj perf rt_hw_interrupt_disable/enable
  18. * 2023-11-17 xqyjlj add process group and session support
  19. */
  20. #include <rtthread.h>
  21. #include <rthw.h>
  22. #ifdef RT_USING_MODULE
  23. #include <dlmodule.h>
  24. #endif /* RT_USING_MODULE */
  25. #ifdef RT_USING_SMART
  26. #include <lwp.h>
  27. #endif
  28. struct rt_custom_object
  29. {
  30. struct rt_object parent;
  31. rt_err_t (*destroy)(void *);
  32. void *data;
  33. };
  34. /*
  35. * define object_info for the number of _object_container items.
  36. */
  37. enum rt_object_info_type
  38. {
  39. RT_Object_Info_Thread = 0, /**< The object is a thread. */
  40. #ifdef RT_USING_SEMAPHORE
  41. RT_Object_Info_Semaphore, /**< The object is a semaphore. */
  42. #endif
  43. #ifdef RT_USING_MUTEX
  44. RT_Object_Info_Mutex, /**< The object is a mutex. */
  45. #endif
  46. #ifdef RT_USING_EVENT
  47. RT_Object_Info_Event, /**< The object is a event. */
  48. #endif
  49. #ifdef RT_USING_MAILBOX
  50. RT_Object_Info_MailBox, /**< The object is a mail box. */
  51. #endif
  52. #ifdef RT_USING_MESSAGEQUEUE
  53. RT_Object_Info_MessageQueue, /**< The object is a message queue. */
  54. #endif
  55. #ifdef RT_USING_MEMHEAP
  56. RT_Object_Info_MemHeap, /**< The object is a memory heap */
  57. #endif
  58. #ifdef RT_USING_MEMPOOL
  59. RT_Object_Info_MemPool, /**< The object is a memory pool. */
  60. #endif
  61. #ifdef RT_USING_DEVICE
  62. RT_Object_Info_Device, /**< The object is a device */
  63. #endif
  64. RT_Object_Info_Timer, /**< The object is a timer. */
  65. #ifdef RT_USING_MODULE
  66. RT_Object_Info_Module, /**< The object is a module. */
  67. #endif
  68. #ifdef RT_USING_HEAP
  69. RT_Object_Info_Memory, /**< The object is a memory. */
  70. #endif
  71. #ifdef RT_USING_SMART
  72. RT_Object_Info_Channel, /**< The object is a IPC channel */
  73. RT_Object_Info_ProcessGroup, /**< The object is a process group */
  74. RT_Object_Info_Session, /**< The object is a session */
  75. #endif
  76. #ifdef RT_USING_HEAP
  77. RT_Object_Info_Custom, /**< The object is a custom object */
  78. #endif
  79. RT_Object_Info_Unknown, /**< The object is unknown. */
  80. };
  81. #define _OBJ_CONTAINER_LIST_INIT(c) \
  82. {&(_object_container[c].object_list), &(_object_container[c].object_list)}
  83. static struct rt_object_information _object_container[RT_Object_Info_Unknown] =
  84. {
  85. /* initialize object container - thread */
  86. {RT_Object_Class_Thread, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Thread), sizeof(struct rt_thread), RT_SPINLOCK_INIT},
  87. #ifdef RT_USING_SEMAPHORE
  88. /* initialize object container - semaphore */
  89. {RT_Object_Class_Semaphore, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Semaphore), sizeof(struct rt_semaphore), RT_SPINLOCK_INIT},
  90. #endif
  91. #ifdef RT_USING_MUTEX
  92. /* initialize object container - mutex */
  93. {RT_Object_Class_Mutex, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Mutex), sizeof(struct rt_mutex), RT_SPINLOCK_INIT},
  94. #endif
  95. #ifdef RT_USING_EVENT
  96. /* initialize object container - event */
  97. {RT_Object_Class_Event, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Event), sizeof(struct rt_event), RT_SPINLOCK_INIT},
  98. #endif
  99. #ifdef RT_USING_MAILBOX
  100. /* initialize object container - mailbox */
  101. {RT_Object_Class_MailBox, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MailBox), sizeof(struct rt_mailbox), RT_SPINLOCK_INIT},
  102. #endif
  103. #ifdef RT_USING_MESSAGEQUEUE
  104. /* initialize object container - message queue */
  105. {RT_Object_Class_MessageQueue, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MessageQueue), sizeof(struct rt_messagequeue), RT_SPINLOCK_INIT},
  106. #endif
  107. #ifdef RT_USING_MEMHEAP
  108. /* initialize object container - memory heap */
  109. {RT_Object_Class_MemHeap, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MemHeap), sizeof(struct rt_memheap), RT_SPINLOCK_INIT},
  110. #endif
  111. #ifdef RT_USING_MEMPOOL
  112. /* initialize object container - memory pool */
  113. {RT_Object_Class_MemPool, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MemPool), sizeof(struct rt_mempool), RT_SPINLOCK_INIT},
  114. #endif
  115. #ifdef RT_USING_DEVICE
  116. /* initialize object container - device */
  117. {RT_Object_Class_Device, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Device), sizeof(struct rt_device), RT_SPINLOCK_INIT},
  118. #endif
  119. /* initialize object container - timer */
  120. {RT_Object_Class_Timer, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Timer), sizeof(struct rt_timer), RT_SPINLOCK_INIT},
  121. #ifdef RT_USING_MODULE
  122. /* initialize object container - module */
  123. {RT_Object_Class_Module, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Module), sizeof(struct rt_dlmodule), RT_SPINLOCK_INIT},
  124. #endif
  125. #ifdef RT_USING_HEAP
  126. /* initialize object container - small memory */
  127. {RT_Object_Class_Memory, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Memory), sizeof(struct rt_memory), RT_SPINLOCK_INIT},
  128. #endif
  129. #ifdef RT_USING_SMART
  130. /* initialize object container - module */
  131. {RT_Object_Class_Channel, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Channel), sizeof(struct rt_channel), RT_SPINLOCK_INIT},
  132. {RT_Object_Class_ProcessGroup, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_ProcessGroup), sizeof(struct rt_processgroup), RT_SPINLOCK_INIT},
  133. {RT_Object_Class_Session, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Session), sizeof(struct rt_session), RT_SPINLOCK_INIT},
  134. #endif
  135. #ifdef RT_USING_HEAP
  136. {RT_Object_Class_Custom, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Custom), sizeof(struct rt_custom_object), RT_SPINLOCK_INIT},
  137. #endif
  138. };
  139. #if defined(RT_USING_HOOK) && defined(RT_HOOK_USING_FUNC_PTR)
  140. static void (*rt_object_attach_hook)(struct rt_object *object);
  141. static void (*rt_object_detach_hook)(struct rt_object *object);
  142. void (*rt_object_trytake_hook)(struct rt_object *object);
  143. void (*rt_object_take_hook)(struct rt_object *object);
  144. void (*rt_object_put_hook)(struct rt_object *object);
  145. /**
  146. * @addtogroup group_hook
  147. */
  148. /**@{*/
  149. /**
  150. * @brief This function will set a hook function, which will be invoked when object
  151. * attaches to kernel object system.
  152. *
  153. * @param hook is the hook function.
  154. */
  155. void rt_object_attach_sethook(void (*hook)(struct rt_object *object))
  156. {
  157. rt_object_attach_hook = hook;
  158. }
  159. /**
  160. * @brief This function will set a hook function, which will be invoked when object
  161. * detaches from kernel object system.
  162. *
  163. * @param hook is the hook function
  164. */
  165. void rt_object_detach_sethook(void (*hook)(struct rt_object *object))
  166. {
  167. rt_object_detach_hook = hook;
  168. }
  169. /**
  170. * @brief This function will set a hook function, which will be invoked when object
  171. * is taken from kernel object system.
  172. *
  173. * The object is taken means:
  174. * semaphore - semaphore is taken by thread
  175. * mutex - mutex is taken by thread
  176. * event - event is received by thread
  177. * mailbox - mail is received by thread
  178. * message queue - message is received by thread
  179. *
  180. * @param hook is the hook function.
  181. */
  182. void rt_object_trytake_sethook(void (*hook)(struct rt_object *object))
  183. {
  184. rt_object_trytake_hook = hook;
  185. }
  186. /**
  187. * @brief This function will set a hook function, which will be invoked when object
  188. * have been taken from kernel object system.
  189. *
  190. * The object have been taken means:
  191. * semaphore - semaphore have been taken by thread
  192. * mutex - mutex have been taken by thread
  193. * event - event have been received by thread
  194. * mailbox - mail have been received by thread
  195. * message queue - message have been received by thread
  196. * timer - timer is started
  197. *
  198. * @param hook the hook function.
  199. */
  200. void rt_object_take_sethook(void (*hook)(struct rt_object *object))
  201. {
  202. rt_object_take_hook = hook;
  203. }
  204. /**
  205. * @brief This function will set a hook function, which will be invoked when object
  206. * is put to kernel object system.
  207. *
  208. * @param hook is the hook function
  209. */
  210. void rt_object_put_sethook(void (*hook)(struct rt_object *object))
  211. {
  212. rt_object_put_hook = hook;
  213. }
  214. /**@}*/
  215. #endif /* RT_USING_HOOK */
  216. /**
  217. * @addtogroup group_kernel_object
  218. */
  219. /**@{*/
  220. /**
  221. * @brief This function will return the specified type of object information.
  222. *
  223. * @param type is the type of object, which can be
  224. * RT_Object_Class_Thread/Semaphore/Mutex... etc
  225. *
  226. * @return the object type information or RT_NULL
  227. */
  228. struct rt_object_information *
  229. rt_object_get_information(enum rt_object_class_type type)
  230. {
  231. int index;
  232. type = (enum rt_object_class_type)(type & ~RT_Object_Class_Static);
  233. for (index = 0; index < RT_Object_Info_Unknown; index ++)
  234. if (_object_container[index].type == type) return &_object_container[index];
  235. return RT_NULL;
  236. }
  237. RTM_EXPORT(rt_object_get_information);
  238. /**
  239. * @brief This function will return the length of object list in object container.
  240. *
  241. * @param type is the type of object, which can be
  242. * RT_Object_Class_Thread/Semaphore/Mutex... etc
  243. *
  244. * @return the length of object list
  245. */
  246. int rt_object_get_length(enum rt_object_class_type type)
  247. {
  248. int count = 0;
  249. rt_base_t level;
  250. struct rt_list_node *node = RT_NULL;
  251. struct rt_object_information *information = RT_NULL;
  252. information = rt_object_get_information((enum rt_object_class_type)type);
  253. if (information == RT_NULL) return 0;
  254. level = rt_spin_lock_irqsave(&(information->spinlock));
  255. rt_list_for_each(node, &(information->object_list))
  256. {
  257. count ++;
  258. }
  259. rt_spin_unlock_irqrestore(&(information->spinlock), level);
  260. return count;
  261. }
  262. RTM_EXPORT(rt_object_get_length);
  263. /**
  264. * @brief This function will copy the object pointer of the specified type,
  265. * with the maximum size specified by maxlen.
  266. *
  267. * @param type is the type of object, which can be
  268. * RT_Object_Class_Thread/Semaphore/Mutex... etc
  269. *
  270. * @param pointers is the pointer will be saved to.
  271. *
  272. * @param maxlen is the maximum number of pointers can be saved.
  273. *
  274. * @return the copied number of object pointers.
  275. */
  276. int rt_object_get_pointers(enum rt_object_class_type type, rt_object_t *pointers, int maxlen)
  277. {
  278. int index = 0;
  279. rt_base_t level;
  280. struct rt_object *object;
  281. struct rt_list_node *node = RT_NULL;
  282. struct rt_object_information *information = RT_NULL;
  283. if (maxlen <= 0) return 0;
  284. information = rt_object_get_information(type);
  285. if (information == RT_NULL) return 0;
  286. level = rt_spin_lock_irqsave(&(information->spinlock));
  287. /* retrieve pointer of object */
  288. rt_list_for_each(node, &(information->object_list))
  289. {
  290. object = rt_list_entry(node, struct rt_object, list);
  291. pointers[index] = object;
  292. index ++;
  293. if (index >= maxlen) break;
  294. }
  295. rt_spin_unlock_irqrestore(&(information->spinlock), level);
  296. return index;
  297. }
  298. RTM_EXPORT(rt_object_get_pointers);
  299. /**
  300. * @brief This function will initialize an object and add it to object system
  301. * management.
  302. *
  303. * @param object The specified object to be initialized.
  304. * The object pointer that needs to be initialized must point to
  305. * a specific object memory block, not a null pointer or a wild pointer.
  306. *
  307. * @param type The object type. The type of the object must be a enumeration
  308. * type listed in rt_object_class_type, RT_Object_Class_Static
  309. * excluded. (For static objects, or objects initialized with the
  310. * rt_object_init interface, the system identifies it as an
  311. * RT_Object_Class_Static type)
  312. *
  313. * @param name Name of the object. In system, the object's name must be unique.
  314. * Each object can be set to a name, and the maximum length for the
  315. * name is specified by RT_NAME_MAX. The system does not care if it
  316. * uses '\0' as a terminal symbol.
  317. */
  318. void rt_object_init(struct rt_object *object,
  319. enum rt_object_class_type type,
  320. const char *name)
  321. {
  322. rt_base_t level;
  323. rt_size_t len;
  324. #ifdef RT_DEBUGING_ASSERT
  325. struct rt_list_node *node = RT_NULL;
  326. #endif /* RT_DEBUGING_ASSERT */
  327. struct rt_object_information *information;
  328. #ifdef RT_USING_MODULE
  329. struct rt_dlmodule *module = dlmodule_self();
  330. #endif /* RT_USING_MODULE */
  331. /* get object information */
  332. information = rt_object_get_information(type);
  333. RT_ASSERT(information != RT_NULL);
  334. #ifdef RT_DEBUGING_ASSERT
  335. /* check object type to avoid re-initialization */
  336. /* enter critical */
  337. level = rt_spin_lock_irqsave(&(information->spinlock));
  338. /* try to find object */
  339. for (node = information->object_list.next;
  340. node != &(information->object_list);
  341. node = node->next)
  342. {
  343. struct rt_object *obj;
  344. obj = rt_list_entry(node, struct rt_object, list);
  345. RT_ASSERT(obj != object);
  346. }
  347. /* leave critical */
  348. rt_spin_unlock_irqrestore(&(information->spinlock), level);
  349. #endif /* RT_DEBUGING_ASSERT */
  350. /* initialize object's parameters */
  351. /* set object type to static */
  352. object->type = type | RT_Object_Class_Static;
  353. #if RT_NAME_MAX > 0
  354. if (name)
  355. {
  356. len = rt_strlen(name);
  357. len = len > RT_NAME_MAX - 1 ? RT_NAME_MAX - 1 : len;
  358. rt_memcpy(object->name, name, len);
  359. object->name[len] = '\0';
  360. }
  361. else
  362. {
  363. object->name[0] = '\0';
  364. }
  365. #else
  366. object->name = name;
  367. #endif
  368. RT_OBJECT_HOOK_CALL(rt_object_attach_hook, (object));
  369. level = rt_spin_lock_irqsave(&(information->spinlock));
  370. #ifdef RT_USING_MODULE
  371. if (module)
  372. {
  373. rt_list_insert_after(&(module->object_list), &(object->list));
  374. object->module_id = (void *)module;
  375. }
  376. else
  377. #endif /* RT_USING_MODULE */
  378. {
  379. /* insert object into information object list */
  380. rt_list_insert_after(&(information->object_list), &(object->list));
  381. }
  382. rt_spin_unlock_irqrestore(&(information->spinlock), level);
  383. }
  384. /**
  385. * @brief This function will detach a static object from object system,
  386. * and the memory of static object is not freed.
  387. *
  388. * @param object the specified object to be detached.
  389. */
  390. void rt_object_detach(rt_object_t object)
  391. {
  392. rt_base_t level;
  393. struct rt_object_information *information;
  394. /* object check */
  395. RT_ASSERT(object != RT_NULL);
  396. RT_OBJECT_HOOK_CALL(rt_object_detach_hook, (object));
  397. information = rt_object_get_information((enum rt_object_class_type)object->type);
  398. RT_ASSERT(information != RT_NULL);
  399. level = rt_spin_lock_irqsave(&(information->spinlock));
  400. /* remove from old list */
  401. rt_list_remove(&(object->list));
  402. rt_spin_unlock_irqrestore(&(information->spinlock), level);
  403. object->type = RT_Object_Class_Null;
  404. }
  405. #ifdef RT_USING_HEAP
  406. /**
  407. * @brief This function will allocate an object from object system.
  408. *
  409. * @param type Type of object. The type of the allocated object can only be of
  410. * type rt_object_class_type other than RT_Object_Class_Static.
  411. * In addition, the type of object allocated through this interface
  412. * is dynamic, not static.
  413. *
  414. * @param name Name of the object. In system, the object's name must be unique.
  415. * Each object can be set to a name, and the maximum length for the
  416. * name is specified by RT_NAME_MAX. The system does not care if it
  417. * uses '\0' as a terminal symbol.
  418. *
  419. * @return object handle allocated successfully, or RT_NULL if no memory can be allocated.
  420. */
  421. rt_object_t rt_object_allocate(enum rt_object_class_type type, const char *name)
  422. {
  423. struct rt_object *object;
  424. rt_base_t level;
  425. rt_size_t len;
  426. struct rt_object_information *information;
  427. #ifdef RT_USING_MODULE
  428. struct rt_dlmodule *module = dlmodule_self();
  429. #endif /* RT_USING_MODULE */
  430. RT_DEBUG_NOT_IN_INTERRUPT;
  431. /* get object information */
  432. information = rt_object_get_information(type);
  433. RT_ASSERT(information != RT_NULL);
  434. object = (struct rt_object *)RT_KERNEL_MALLOC(information->object_size);
  435. if (object == RT_NULL)
  436. {
  437. /* no memory can be allocated */
  438. return RT_NULL;
  439. }
  440. /* clean memory data of object */
  441. rt_memset(object, 0x0, information->object_size);
  442. /* initialize object's parameters */
  443. /* set object type */
  444. object->type = type;
  445. /* set object flag */
  446. object->flag = 0;
  447. #if RT_NAME_MAX > 0
  448. if (name)
  449. {
  450. len = rt_strlen(name);
  451. len = len > RT_NAME_MAX - 1 ? RT_NAME_MAX - 1 : len;
  452. rt_memcpy(object->name, name, len);
  453. object->name[len] = '\0';
  454. }
  455. else
  456. {
  457. object->name[0] = '\0';
  458. }
  459. #else
  460. object->name = name;
  461. #endif
  462. RT_OBJECT_HOOK_CALL(rt_object_attach_hook, (object));
  463. level = rt_spin_lock_irqsave(&(information->spinlock));
  464. #ifdef RT_USING_MODULE
  465. if (module)
  466. {
  467. rt_list_insert_after(&(module->object_list), &(object->list));
  468. object->module_id = (void *)module;
  469. }
  470. else
  471. #endif /* RT_USING_MODULE */
  472. {
  473. /* insert object into information object list */
  474. rt_list_insert_after(&(information->object_list), &(object->list));
  475. }
  476. rt_spin_unlock_irqrestore(&(information->spinlock), level);
  477. return object;
  478. }
  479. /**
  480. * @brief This function will delete an object and release object memory.
  481. *
  482. * @param object The specified object to be deleted.
  483. */
  484. void rt_object_delete(rt_object_t object)
  485. {
  486. rt_base_t level;
  487. struct rt_object_information *information;
  488. /* object check */
  489. RT_ASSERT(object != RT_NULL);
  490. RT_ASSERT(!(object->type & RT_Object_Class_Static));
  491. RT_OBJECT_HOOK_CALL(rt_object_detach_hook, (object));
  492. information = rt_object_get_information((enum rt_object_class_type)object->type);
  493. RT_ASSERT(information != RT_NULL);
  494. level = rt_spin_lock_irqsave(&(information->spinlock));
  495. /* remove from old list */
  496. rt_list_remove(&(object->list));
  497. rt_spin_unlock_irqrestore(&(information->spinlock), level);
  498. /* reset object type */
  499. object->type = RT_Object_Class_Null;
  500. /* free the memory of object */
  501. RT_KERNEL_FREE(object);
  502. }
  503. #endif /* RT_USING_HEAP */
  504. /**
  505. * @brief This function will judge the object is system object or not.
  506. *
  507. * @note Normally, the system object is a static object and the type
  508. * of object set to RT_Object_Class_Static.
  509. *
  510. * @param object The specified object to be judged.
  511. *
  512. * @return RT_TRUE if a system object, RT_FALSE for others.
  513. */
  514. rt_bool_t rt_object_is_systemobject(rt_object_t object)
  515. {
  516. /* object check */
  517. RT_ASSERT(object != RT_NULL);
  518. if (object->type & RT_Object_Class_Static)
  519. return RT_TRUE;
  520. return RT_FALSE;
  521. }
  522. /**
  523. * @brief This function will return the type of object without
  524. * RT_Object_Class_Static flag.
  525. *
  526. * @param object is the specified object to be get type.
  527. *
  528. * @return the type of object.
  529. */
  530. rt_uint8_t rt_object_get_type(rt_object_t object)
  531. {
  532. /* object check */
  533. RT_ASSERT(object != RT_NULL);
  534. return object->type & ~RT_Object_Class_Static;
  535. }
  536. /**
  537. * @brief This function will iterate through each object from object
  538. * container.
  539. *
  540. * @param type is the type of object
  541. * @param iter is the iterator
  542. * @param data is the specified data passed to iterator
  543. *
  544. * @return RT_EOK on succeed, otherwise the error from `iter`
  545. *
  546. * @note this function shall not be invoked in interrupt status.
  547. */
  548. rt_err_t rt_object_for_each(rt_uint8_t type, rt_object_iter_t iter, void *data)
  549. {
  550. struct rt_object *object = RT_NULL;
  551. struct rt_list_node *node = RT_NULL;
  552. struct rt_object_information *information = RT_NULL;
  553. rt_base_t level;
  554. rt_err_t error;
  555. information = rt_object_get_information((enum rt_object_class_type)type);
  556. /* parameter check */
  557. if (information == RT_NULL)
  558. {
  559. return -RT_EINVAL;
  560. }
  561. /* which is invoke in interrupt status */
  562. RT_DEBUG_NOT_IN_INTERRUPT;
  563. /* enter critical */
  564. level = rt_spin_lock_irqsave(&(information->spinlock));
  565. /* try to find object */
  566. rt_list_for_each(node, &(information->object_list))
  567. {
  568. object = rt_list_entry(node, struct rt_object, list);
  569. if ((error = iter(object, data)) != RT_EOK)
  570. {
  571. rt_spin_unlock_irqrestore(&(information->spinlock), level);
  572. return error >= 0 ? RT_EOK : error;
  573. }
  574. }
  575. rt_spin_unlock_irqrestore(&(information->spinlock), level);
  576. return RT_EOK;
  577. }
  578. struct _obj_find_param
  579. {
  580. const char *match_name;
  581. rt_object_t matched_obj;
  582. };
  583. static rt_err_t _match_name(struct rt_object *obj, void *data)
  584. {
  585. struct _obj_find_param *param = data;
  586. const char *name = param->match_name;
  587. if (rt_strncmp(obj->name, name, RT_NAME_MAX) == 0)
  588. {
  589. param->matched_obj = obj;
  590. /* notify an early break of loop, but not on error */
  591. return 1;
  592. }
  593. return RT_EOK;
  594. }
  595. /**
  596. * @brief This function will find specified name object from object
  597. * container.
  598. *
  599. * @param name is the specified name of object.
  600. *
  601. * @param type is the type of object
  602. *
  603. * @return the found object or RT_NULL if there is no this object
  604. * in object container.
  605. *
  606. * @note this function shall not be invoked in interrupt status.
  607. */
  608. rt_object_t rt_object_find(const char *name, rt_uint8_t type)
  609. {
  610. struct _obj_find_param param =
  611. {
  612. .match_name = name,
  613. .matched_obj = RT_NULL,
  614. };
  615. /* parameter check */
  616. if (name == RT_NULL) return RT_NULL;
  617. /* which is invoke in interrupt status */
  618. RT_DEBUG_NOT_IN_INTERRUPT;
  619. rt_object_for_each(type, _match_name, &param);
  620. return param.matched_obj;
  621. }
  622. /**
  623. * @brief This function will return the name of the specified object container
  624. *
  625. * @param object the specified object to be get name
  626. * @param name buffer to store the object name string
  627. * @param name_size maximum size of the buffer to store object name
  628. *
  629. * @return -RT_EINVAL if any parameter is invalid or RT_EOK if the operation is successfully executed
  630. *
  631. * @note this function shall not be invoked in interrupt status
  632. */
  633. rt_err_t rt_object_get_name(rt_object_t object, char *name, rt_uint8_t name_size)
  634. {
  635. rt_err_t result = -RT_EINVAL;
  636. if ((object != RT_NULL) && (name != RT_NULL) && (name_size != 0U))
  637. {
  638. const char *obj_name = object->name;
  639. (void) rt_strncpy(name, obj_name, (rt_size_t)name_size);
  640. result = RT_EOK;
  641. }
  642. return result;
  643. }
  644. #ifdef RT_USING_HEAP
  645. /**
  646. * This function will create a custom object
  647. * container.
  648. *
  649. * @param name the specified name of object.
  650. * @param data the custom data
  651. * @param data_destroy the custom object destroy callback
  652. *
  653. * @return the found object or RT_NULL if there is no this object
  654. * in object container.
  655. *
  656. * @note this function shall not be invoked in interrupt status.
  657. */
  658. rt_object_t rt_custom_object_create(const char *name, void *data, rt_err_t (*data_destroy)(void *))
  659. {
  660. struct rt_custom_object *cobj = RT_NULL;
  661. cobj = (struct rt_custom_object *)rt_object_allocate(RT_Object_Class_Custom, name);
  662. if (!cobj)
  663. {
  664. return RT_NULL;
  665. }
  666. cobj->destroy = data_destroy;
  667. cobj->data = data;
  668. return (struct rt_object *)cobj;
  669. }
  670. /**
  671. * This function will destroy a custom object
  672. * container.
  673. *
  674. * @param obj the specified name of object.
  675. *
  676. * @note this function shall not be invoked in interrupt status.
  677. */
  678. rt_err_t rt_custom_object_destroy(rt_object_t obj)
  679. {
  680. rt_err_t ret = -1;
  681. struct rt_custom_object *cobj = (struct rt_custom_object *)obj;
  682. if (obj && obj->type == RT_Object_Class_Custom)
  683. {
  684. if (cobj->destroy)
  685. {
  686. ret = cobj->destroy(cobj->data);
  687. }
  688. rt_object_delete(obj);
  689. }
  690. return ret;
  691. }
  692. #endif
  693. /**@}*/