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, ¶m);
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