RT-Thread RTOS 1.2.0
An open source embedded real-time operating system
载入中...
搜索中...
未找到
object.c
浏览该文件的文档.
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
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
32struct rt_custom_object
33{
34 struct rt_object parent;
35 rt_err_t (*destroy)(void *);
36 void *data;
37};
38
39/*
40 * define object_info for the number of _object_container items.
41 */
43{
45#ifdef RT_USING_SEMAPHORE
47#endif
48#ifdef RT_USING_MUTEX
50#endif
51#ifdef RT_USING_EVENT
53#endif
54#ifdef RT_USING_MAILBOX
56#endif
57#ifdef RT_USING_MESSAGEQUEUE
59#endif
60#ifdef RT_USING_MEMHEAP
61 RT_Object_Info_MemHeap,
62#endif
63#ifdef RT_USING_MEMPOOL
65#endif
66#ifdef RT_USING_DEVICE
68#endif
70#ifdef RT_USING_MODULE
72#endif
73#ifdef RT_USING_HEAP
75#endif
76#ifdef RT_USING_SMART
77 RT_Object_Info_Channel,
78 RT_Object_Info_ProcessGroup,
79 RT_Object_Info_Session,
80#endif
81#ifdef RT_USING_HEAP
83#endif
85};
86
87#define _OBJ_CONTAINER_LIST_INIT(c) \
88 {&(_object_container[c].object_list), &(_object_container[c].object_list)}
89
90static struct rt_object_information _object_container[RT_Object_Info_Unknown] =
91{
92 /* initialize object container - thread */
94#ifdef RT_USING_SEMAPHORE
95 /* initialize object container - semaphore */
97#endif
98#ifdef RT_USING_MUTEX
99 /* initialize object container - mutex */
101#endif
102#ifdef RT_USING_EVENT
103 /* initialize object container - event */
105#endif
106#ifdef RT_USING_MAILBOX
107 /* initialize object container - mailbox */
109#endif
110#ifdef RT_USING_MESSAGEQUEUE
111 /* initialize object container - message queue */
113#endif
114#ifdef RT_USING_MEMHEAP
115 /* initialize object container - memory heap */
116 {RT_Object_Class_MemHeap, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MemHeap), sizeof(struct rt_memheap), RT_SPINLOCK_INIT},
117#endif
118#ifdef RT_USING_MEMPOOL
119 /* initialize object container - memory pool */
121#endif
122#ifdef RT_USING_DEVICE
123 /* initialize object container - device */
125#endif
126 /* initialize object container - timer */
128#ifdef RT_USING_MODULE
129 /* initialize object container - module */
131#endif
132#ifdef RT_USING_HEAP
133 /* initialize object container - small memory */
135#endif
136#ifdef RT_USING_SMART
137 /* initialize object container - module */
138 {RT_Object_Class_Channel, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Channel), sizeof(struct rt_channel), RT_SPINLOCK_INIT},
139 {RT_Object_Class_ProcessGroup, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_ProcessGroup), sizeof(struct rt_processgroup), RT_SPINLOCK_INIT},
140 {RT_Object_Class_Session, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Session), sizeof(struct rt_session), RT_SPINLOCK_INIT},
141#endif
142#ifdef RT_USING_HEAP
144#endif
145};
146
147#if defined(RT_USING_HOOK) && defined(RT_HOOK_USING_FUNC_PTR)
148static void (*rt_object_attach_hook)(struct rt_object *object);
149static void (*rt_object_detach_hook)(struct rt_object *object);
150void (*rt_object_trytake_hook)(struct rt_object *object);
151void (*rt_object_take_hook)(struct rt_object *object);
152void (*rt_object_put_hook)(struct rt_object *object);
153
157
159
166void rt_object_attach_sethook(void (*hook)(struct rt_object *object))
167{
168 rt_object_attach_hook = hook;
169}
170
177void rt_object_detach_sethook(void (*hook)(struct rt_object *object))
178{
179 rt_object_detach_hook = hook;
180}
181
195void rt_object_trytake_sethook(void (*hook)(struct rt_object *object))
196{
197 rt_object_trytake_hook = hook;
198}
199
214void rt_object_take_sethook(void (*hook)(struct rt_object *object))
215{
216 rt_object_take_hook = hook;
217}
218
225void rt_object_put_sethook(void (*hook)(struct rt_object *object))
226{
227 rt_object_put_hook = hook;
228}
229
231#endif /* RT_USING_HOOK */
232
236
238
249{
250 int index;
251
252 type = (enum rt_object_class_type)(type & ~RT_Object_Class_Static);
253
254 for (index = 0; index < RT_Object_Info_Unknown; index ++)
255 if (_object_container[index].type == type) return &_object_container[index];
256
257 return RT_NULL;
258}
260
270{
271 int count = 0;
272 rt_base_t level;
273 struct rt_list_node *node = RT_NULL;
274 struct rt_object_information *information = RT_NULL;
275
276 information = rt_object_get_information((enum rt_object_class_type)type);
277 if (information == RT_NULL) return 0;
278
279 level = rt_spin_lock_irqsave(&(information->spinlock));
280 rt_list_for_each(node, &(information->object_list))
281 {
282 count ++;
283 }
284 rt_spin_unlock_irqrestore(&(information->spinlock), level);
285
286 return count;
287}
289
303int rt_object_get_pointers(enum rt_object_class_type type, rt_object_t *pointers, int maxlen)
304{
305 int index = 0;
306 rt_base_t level;
307
308 struct rt_object *object;
309 struct rt_list_node *node = RT_NULL;
310 struct rt_object_information *information = RT_NULL;
311
312 if (maxlen <= 0) return 0;
313
314 information = rt_object_get_information(type);
315 if (information == RT_NULL) return 0;
316
317 level = rt_spin_lock_irqsave(&(information->spinlock));
318 /* retrieve pointer of object */
319 rt_list_for_each(node, &(information->object_list))
320 {
321 object = rt_list_entry(node, struct rt_object, list);
322
323 pointers[index] = object;
324 index ++;
325
326 if (index >= maxlen) break;
327 }
328 rt_spin_unlock_irqrestore(&(information->spinlock), level);
329
330 return index;
331}
333
344void rt_object_init(struct rt_object *object,
345 enum rt_object_class_type type,
346 const char *name)
347{
348 rt_base_t level;
349#ifdef RT_DEBUGING_ASSERT
350 struct rt_list_node *node = RT_NULL;
351#endif /* RT_DEBUGING_ASSERT */
352 struct rt_object_information *information;
353#ifdef RT_USING_MODULE
354 struct rt_dlmodule *module = dlmodule_self();
355#endif /* RT_USING_MODULE */
356
357 /* get object information */
358 information = rt_object_get_information(type);
359 RT_ASSERT(information != RT_NULL);
360
361#ifdef RT_DEBUGING_ASSERT
362 /* check object type to avoid re-initialization */
363
364 /* enter critical */
365 level = rt_spin_lock_irqsave(&(information->spinlock));
366 /* try to find object */
367 for (node = information->object_list.next;
368 node != &(information->object_list);
369 node = node->next)
370 {
371 struct rt_object *obj;
372
373 obj = rt_list_entry(node, struct rt_object, list);
374 RT_ASSERT(obj != object);
375 }
376 /* leave critical */
377 rt_spin_unlock_irqrestore(&(information->spinlock), level);
378#endif /* RT_DEBUGING_ASSERT */
379
380 /* initialize object's parameters */
381 /* set object type to static */
382 object->type = type | RT_Object_Class_Static;
383#if RT_NAME_MAX > 0
384 rt_strncpy(object->name, name, RT_NAME_MAX); /* copy name */
385#else
386 object->name = name;
387#endif /* RT_NAME_MAX > 0 */
388
389 RT_OBJECT_HOOK_CALL(rt_object_attach_hook, (object));
390
391 level = rt_spin_lock_irqsave(&(information->spinlock));
392
393#ifdef RT_USING_MODULE
394 if (module)
395 {
396 rt_list_insert_after(&(module->object_list), &(object->list));
397 object->module_id = (void *)module;
398 }
399 else
400#endif /* RT_USING_MODULE */
401 {
402 /* insert object into information object list */
403 rt_list_insert_after(&(information->object_list), &(object->list));
404 }
405 rt_spin_unlock_irqrestore(&(information->spinlock), level);
406}
407
415{
416 rt_base_t level;
417 struct rt_object_information *information;
418
419 /* object check */
420 RT_ASSERT(object != RT_NULL);
421
422 RT_OBJECT_HOOK_CALL(rt_object_detach_hook, (object));
423
424 information = rt_object_get_information((enum rt_object_class_type)object->type);
425 RT_ASSERT(information != RT_NULL);
426
427 level = rt_spin_lock_irqsave(&(information->spinlock));
428 /* remove from old list */
429 rt_list_remove(&(object->list));
430 rt_spin_unlock_irqrestore(&(information->spinlock), level);
431
432 object->type = RT_Object_Class_Null;
433}
434
435#ifdef RT_USING_HEAP
446{
447 struct rt_object *object;
448 rt_base_t level;
449 struct rt_object_information *information;
450#ifdef RT_USING_MODULE
451 struct rt_dlmodule *module = dlmodule_self();
452#endif /* RT_USING_MODULE */
453
455
456 /* get object information */
457 information = rt_object_get_information(type);
458 RT_ASSERT(information != RT_NULL);
459
460 object = (struct rt_object *)RT_KERNEL_MALLOC(information->object_size);
461 if (object == RT_NULL)
462 {
463 /* no memory can be allocated */
464 return RT_NULL;
465 }
466
467 /* clean memory data of object */
468 rt_memset(object, 0x0, information->object_size);
469
470 /* initialize object's parameters */
471
472 /* set object type */
473 object->type = type;
474
475 /* set object flag */
476 object->flag = 0;
477
478#if RT_NAME_MAX > 0
479 rt_strncpy(object->name, name, RT_NAME_MAX - 1); /* copy name */
480#else
481 object->name = name;
482#endif /* RT_NAME_MAX > 0 */
483
484 RT_OBJECT_HOOK_CALL(rt_object_attach_hook, (object));
485
486 level = rt_spin_lock_irqsave(&(information->spinlock));
487
488#ifdef RT_USING_MODULE
489 if (module)
490 {
491 rt_list_insert_after(&(module->object_list), &(object->list));
492 object->module_id = (void *)module;
493 }
494 else
495#endif /* RT_USING_MODULE */
496 {
497 /* insert object into information object list */
498 rt_list_insert_after(&(information->object_list), &(object->list));
499 }
500 rt_spin_unlock_irqrestore(&(information->spinlock), level);
501
502 return object;
503}
504
511{
512 rt_base_t level;
513 struct rt_object_information *information;
514
515 /* object check */
516 RT_ASSERT(object != RT_NULL);
518
519 RT_OBJECT_HOOK_CALL(rt_object_detach_hook, (object));
520
521
522 information = rt_object_get_information((enum rt_object_class_type)object->type);
523 RT_ASSERT(information != RT_NULL);
524
525 level = rt_spin_lock_irqsave(&(information->spinlock));
526
527 /* remove from old list */
528 rt_list_remove(&(object->list));
529
530 rt_spin_unlock_irqrestore(&(information->spinlock), level);
531
532 /* reset object type */
533 object->type = RT_Object_Class_Null;
534
535 /* free the memory of object */
536 RT_KERNEL_FREE(object);
537}
538#endif /* RT_USING_HEAP */
539
551{
552 /* object check */
553 RT_ASSERT(object != RT_NULL);
554
555 if (object->type & RT_Object_Class_Static)
556 return RT_TRUE;
557
558 return RT_FALSE;
559}
560
570{
571 /* object check */
572 RT_ASSERT(object != RT_NULL);
573
574 return object->type & ~RT_Object_Class_Static;
575}
576
590{
591 struct rt_object *object = RT_NULL;
592 struct rt_list_node *node = RT_NULL;
593 struct rt_object_information *information = RT_NULL;
594 rt_base_t level;
595 rt_err_t error;
596
597 information = rt_object_get_information((enum rt_object_class_type)type);
598
599 /* parameter check */
600 if (information == RT_NULL)
601 {
602 return -RT_EINVAL;
603 }
604
605 /* which is invoke in interrupt status */
607
608 /* enter critical */
609 level = rt_spin_lock_irqsave(&(information->spinlock));
610
611 /* try to find object */
612 rt_list_for_each(node, &(information->object_list))
613 {
614 object = rt_list_entry(node, struct rt_object, list);
615 if ((error = iter(object, data)) != RT_EOK)
616 {
617 rt_spin_unlock_irqrestore(&(information->spinlock), level);
618
619 return error >= 0 ? RT_EOK : error;
620 }
621 }
622
623 rt_spin_unlock_irqrestore(&(information->spinlock), level);
624
625 return RT_EOK;
626}
627
628struct _obj_find_param
629{
630 const char *match_name;
631 rt_object_t matched_obj;
632};
633
634static rt_err_t _match_name(struct rt_object *obj, void *data)
635{
636 struct _obj_find_param *param = data;
637 const char *name = param->match_name;
638 if (rt_strncmp(obj->name, name, RT_NAME_MAX) == 0)
639 {
640 param->matched_obj = obj;
641
642 /* notify an early break of loop, but not on error */
643 return 1;
644 }
645
646 return RT_EOK;
647}
648
662rt_object_t rt_object_find(const char *name, rt_uint8_t type)
663{
664 struct _obj_find_param param =
665 {
666 .match_name = name,
667 .matched_obj = RT_NULL,
668 };
669
670 /* parameter check */
671 if (name == RT_NULL) return RT_NULL;
672
673 /* which is invoke in interrupt status */
675
676 rt_object_for_each(type, _match_name, &param);
677 return param.matched_obj;
678}
679
691rt_err_t rt_object_get_name(rt_object_t object, char *name, rt_uint8_t name_size)
692{
693 rt_err_t result = -RT_EINVAL;
694 if ((object != RT_NULL) && (name != RT_NULL) && (name_size != 0U))
695 {
696 const char *obj_name = object->name;
697 (void) rt_strncpy(name, obj_name, (rt_size_t)name_size);
698 result = RT_EOK;
699 }
700
701 return result;
702}
703
704#ifdef RT_USING_HEAP
718
719rt_object_t rt_custom_object_create(const char *name, void *data, rt_err_t (*data_destroy)(void *))
720{
721 struct rt_custom_object *cobj = RT_NULL;
722
723 cobj = (struct rt_custom_object *)rt_object_allocate(RT_Object_Class_Custom, name);
724 if (!cobj)
725 {
726 return RT_NULL;
727 }
728 cobj->destroy = data_destroy;
729 cobj->data = data;
730 return (struct rt_object *)cobj;
731}
732
742{
743 rt_err_t ret = -1;
744
745 struct rt_custom_object *cobj = (struct rt_custom_object *)obj;
746
747 if (obj && obj->type == RT_Object_Class_Custom)
748 {
749 if (cobj->destroy)
750 {
751 ret = cobj->destroy(cobj->data);
752 }
753 rt_object_delete(obj);
754 }
755 return ret;
756}
757#endif
758
rt_base_t rt_spin_lock_irqsave(struct rt_spinlock *lock)
This function will disable the local interrupt and then lock the spinlock, will lock the thread sched...
void rt_spin_unlock_irqrestore(struct rt_spinlock *lock, rt_base_t level)
This function will unlock the spinlock and then restore current cpu interrupt status,...
void rt_object_delete(rt_object_t object)
This function will delete an object and release object memory.
void rt_object_init(struct rt_object *object, enum rt_object_class_type type, const char *name)
This function will initialize an object and add it to object system management.
rt_bool_t rt_object_is_systemobject(rt_object_t object)
This function will judge the object is system object or not.
void rt_object_detach_sethook(void(*hook)(struct rt_object *object))
rt_object_class_type
#define RT_OBJECT_HOOK_CALL(func, argv)
rt_err_t rt_object_get_name(rt_object_t object, char *name, rt_uint8_t name_size)
This function will return the name of the specified object container
rt_err_t rt_custom_object_destroy(rt_object_t obj)
rt_object_t rt_object_allocate(enum rt_object_class_type type, const char *name)
This function will allocate an object from object system.
void rt_object_take_sethook(void(*hook)(struct rt_object *object))
rt_object_t rt_object_find(const char *name, rt_uint8_t type)
This function will find specified name object from object container.
rt_object_t rt_custom_object_create(const char *name, void *data, rt_err_t(*data_destroy)(void *))
void rt_object_attach_sethook(void(*hook)(struct rt_object *object))
struct rt_object_information * rt_object_get_information(enum rt_object_class_type type)
This function will return the specified type of object information.
rt_uint8_t rt_object_get_type(rt_object_t object)
This function will return the type of object without RT_Object_Class_Static flag.
struct rt_object * rt_object_t
int rt_object_get_length(enum rt_object_class_type type)
This function will return the length of object list in object container.
rt_err_t rt_object_for_each(rt_uint8_t type, rt_object_iter_t iter, void *data)
This function will iterate through each object from object container.
int rt_object_get_pointers(enum rt_object_class_type type, rt_object_t *pointers, int maxlen)
This function will copy the object pointer of the specified type, with the maximum size specified by ...
void rt_object_trytake_sethook(void(*hook)(struct rt_object *object))
rt_err_t(* rt_object_iter_t)(rt_object_t object, void *data)
void rt_object_put_sethook(void(*hook)(struct rt_object *object))
void rt_object_detach(rt_object_t object)
This function will detach a static object from object system, and the memory of static object is not ...
@ RT_Object_Class_Memory
@ RT_Object_Class_Module
@ RT_Object_Class_MemHeap
@ RT_Object_Class_Timer
@ RT_Object_Class_MessageQueue
@ RT_Object_Class_ProcessGroup
@ RT_Object_Class_MemPool
@ RT_Object_Class_Thread
@ RT_Object_Class_MailBox
@ RT_Object_Class_Channel
@ RT_Object_Class_Semaphore
@ RT_Object_Class_Null
@ RT_Object_Class_Session
@ RT_Object_Class_Event
@ RT_Object_Class_Static
@ RT_Object_Class_Device
@ RT_Object_Class_Custom
@ RT_Object_Class_Mutex
rt_inline void rt_list_remove(rt_list_t *n)
remove node from list.
#define rt_list_for_each(pos, head)
#define rt_list_entry(node, type, member)
get the struct for this entry
#define RT_DEBUG_NOT_IN_INTERRUPT
#define RT_ASSERT(EX)
rt_inline void rt_list_insert_after(rt_list_t *l, rt_list_t *n)
insert a node after a list
#define _OBJ_CONTAINER_LIST_INIT(c)
rt_object_info_type
@ RT_Object_Info_Event
@ RT_Object_Info_Memory
@ RT_Object_Info_MemPool
@ RT_Object_Info_Custom
@ RT_Object_Info_Module
@ RT_Object_Info_Thread
@ RT_Object_Info_MailBox
@ RT_Object_Info_Unknown
@ RT_Object_Info_Timer
@ RT_Object_Info_MessageQueue
@ RT_Object_Info_Mutex
@ RT_Object_Info_Device
@ RT_Object_Info_Semaphore
#define RT_KERNEL_FREE(ptr)
#define RT_KERNEL_MALLOC(sz)
#define RTM_EXPORT(symbol)
定义 rtm.h:33
rt_int32_t rt_base_t
int rt_bool_t
rt_base_t rt_err_t
unsigned char rt_uint8_t
#define RT_TRUE
rt_ubase_t rt_size_t
#define RT_FALSE
#define RT_NULL
#define RT_SPINLOCK_INIT
struct rt_list_node * next
struct rt_spinlock spinlock
rt_list_t list
rt_uint8_t type
const char * name