object.c 25 KB

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