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