xref: /nrf52832-nimble/rt-thread/src/object.c (revision 104654410c56c573564690304ae786df310c91fc)
1 /*
2  * Copyright (c) 2006-2018, 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  */
17 
18 #include <rtthread.h>
19 #include <rthw.h>
20 
21 #ifdef RT_USING_MODULE
22 #include <dlmodule.h>
23 #endif
24 
25 /*
26  * define object_info for the number of rt_object_container items.
27  */
28 enum rt_object_info_type
29 {
30     RT_Object_Info_Thread = 0,                         /**< The object is a thread. */
31 #ifdef RT_USING_SEMAPHORE
32     RT_Object_Info_Semaphore,                          /**< The object is a semaphore. */
33 #endif
34 #ifdef RT_USING_MUTEX
35     RT_Object_Info_Mutex,                              /**< The object is a mutex. */
36 #endif
37 #ifdef RT_USING_EVENT
38     RT_Object_Info_Event,                              /**< The object is a event. */
39 #endif
40 #ifdef RT_USING_MAILBOX
41     RT_Object_Info_MailBox,                            /**< The object is a mail box. */
42 #endif
43 #ifdef RT_USING_MESSAGEQUEUE
44     RT_Object_Info_MessageQueue,                       /**< The object is a message queue. */
45 #endif
46 #ifdef RT_USING_MEMHEAP
47     RT_Object_Info_MemHeap,                            /**< The object is a memory heap */
48 #endif
49 #ifdef RT_USING_MEMPOOL
50     RT_Object_Info_MemPool,                            /**< The object is a memory pool. */
51 #endif
52 #ifdef RT_USING_DEVICE
53     RT_Object_Info_Device,                             /**< The object is a device */
54 #endif
55     RT_Object_Info_Timer,                              /**< The object is a timer. */
56 #ifdef RT_USING_MODULE
57     RT_Object_Info_Module,                             /**< The object is a module. */
58 #endif
59     RT_Object_Info_Unknown,                            /**< The object is unknown. */
60 };
61 
62 #define _OBJ_CONTAINER_LIST_INIT(c)     \
63     {&(rt_object_container[c].object_list), &(rt_object_container[c].object_list)}
64 static struct rt_object_information rt_object_container[RT_Object_Info_Unknown] =
65 {
66     /* initialize object container - thread */
67     {RT_Object_Class_Thread, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Thread), sizeof(struct rt_thread)},
68 #ifdef RT_USING_SEMAPHORE
69     /* initialize object container - semaphore */
70     {RT_Object_Class_Semaphore, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Semaphore), sizeof(struct rt_semaphore)},
71 #endif
72 #ifdef RT_USING_MUTEX
73     /* initialize object container - mutex */
74     {RT_Object_Class_Mutex, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Mutex), sizeof(struct rt_mutex)},
75 #endif
76 #ifdef RT_USING_EVENT
77     /* initialize object container - event */
78     {RT_Object_Class_Event, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Event), sizeof(struct rt_event)},
79 #endif
80 #ifdef RT_USING_MAILBOX
81     /* initialize object container - mailbox */
82     {RT_Object_Class_MailBox, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MailBox), sizeof(struct rt_mailbox)},
83 #endif
84 #ifdef RT_USING_MESSAGEQUEUE
85     /* initialize object container - message queue */
86     {RT_Object_Class_MessageQueue, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MessageQueue), sizeof(struct rt_messagequeue)},
87 #endif
88 #ifdef RT_USING_MEMHEAP
89     /* initialize object container - memory heap */
90     {RT_Object_Class_MemHeap, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MemHeap), sizeof(struct rt_memheap)},
91 #endif
92 #ifdef RT_USING_MEMPOOL
93     /* initialize object container - memory pool */
94     {RT_Object_Class_MemPool, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MemPool), sizeof(struct rt_mempool)},
95 #endif
96 #ifdef RT_USING_DEVICE
97     /* initialize object container - device */
98     {RT_Object_Class_Device, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Device), sizeof(struct rt_device)},
99 #endif
100     /* initialize object container - timer */
101     {RT_Object_Class_Timer, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Timer), sizeof(struct rt_timer)},
102 #ifdef RT_USING_MODULE
103     /* initialize object container - module */
104     {RT_Object_Class_Module, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Module), sizeof(struct rt_dlmodule)},
105 #endif
106 };
107 
108 #ifdef RT_USING_HOOK
109 static void (*rt_object_attach_hook)(struct rt_object *object);
110 static void (*rt_object_detach_hook)(struct rt_object *object);
111 void (*rt_object_trytake_hook)(struct rt_object *object);
112 void (*rt_object_take_hook)(struct rt_object *object);
113 void (*rt_object_put_hook)(struct rt_object *object);
114 
115 /**
116  * @addtogroup Hook
117  */
118 
119 /**@{*/
120 
121 /**
122  * This function will set a hook function, which will be invoked when object
123  * attaches to kernel object system.
124  *
125  * @param hook the hook function
126  */
rt_object_attach_sethook(void (* hook)(struct rt_object * object))127 void rt_object_attach_sethook(void (*hook)(struct rt_object *object))
128 {
129     rt_object_attach_hook = hook;
130 }
131 
132 /**
133  * This function will set a hook function, which will be invoked when object
134  * detaches from kernel object system.
135  *
136  * @param hook the hook function
137  */
rt_object_detach_sethook(void (* hook)(struct rt_object * object))138 void rt_object_detach_sethook(void (*hook)(struct rt_object *object))
139 {
140     rt_object_detach_hook = hook;
141 }
142 
143 /**
144  * This function will set a hook function, which will be invoked when object
145  * is taken from kernel object system.
146  *
147  * The object is taken means:
148  * semaphore - semaphore is taken by thread
149  * mutex - mutex is taken by thread
150  * event - event is received by thread
151  * mailbox - mail is received by thread
152  * message queue - message is received by thread
153  *
154  * @param hook the hook function
155  */
rt_object_trytake_sethook(void (* hook)(struct rt_object * object))156 void rt_object_trytake_sethook(void (*hook)(struct rt_object *object))
157 {
158     rt_object_trytake_hook = hook;
159 }
160 
161 /**
162  * This function will set a hook function, which will be invoked when object
163  * have been taken from kernel object system.
164  *
165  * The object have been taken means:
166  * semaphore - semaphore have been taken by thread
167  * mutex - mutex have been taken by thread
168  * event - event have been received by thread
169  * mailbox - mail have been received by thread
170  * message queue - message have been received by thread
171  * timer - timer is started
172  *
173  * @param hook the hook function
174  */
rt_object_take_sethook(void (* hook)(struct rt_object * object))175 void rt_object_take_sethook(void (*hook)(struct rt_object *object))
176 {
177     rt_object_take_hook = hook;
178 }
179 
180 /**
181  * This function will set a hook function, which will be invoked when object
182  * is put to kernel object system.
183  *
184  * @param hook the hook function
185  */
rt_object_put_sethook(void (* hook)(struct rt_object * object))186 void rt_object_put_sethook(void (*hook)(struct rt_object *object))
187 {
188     rt_object_put_hook = hook;
189 }
190 
191 /**@}*/
192 #endif
193 
194 /**
195  * @ingroup SystemInit
196  *
197  * This function will initialize system object management.
198  *
199  * @deprecated since 0.3.0, this function does not need to be invoked
200  * in the system initialization.
201  */
rt_system_object_init(void)202 void rt_system_object_init(void)
203 {
204 }
205 
206 /**
207  * @addtogroup KernelObject
208  */
209 
210 /**@{*/
211 
212 /**
213  * This function will return the specified type of object information.
214  *
215  * @param type the type of object
216  * @return the object type information or RT_NULL
217  */
218 struct rt_object_information *
rt_object_get_information(enum rt_object_class_type type)219 rt_object_get_information(enum rt_object_class_type type)
220 {
221     int index;
222 
223     for (index = 0; index < RT_Object_Info_Unknown; index ++)
224         if (rt_object_container[index].type == type) return &rt_object_container[index];
225 
226     return RT_NULL;
227 }
228 RTM_EXPORT(rt_object_get_information);
229 
230 /**
231  * This function will initialize an object and add it to object system
232  * management.
233  *
234  * @param object the specified object to be initialized.
235  * @param type the object type.
236  * @param name the object name. In system, the object's name must be unique.
237  */
rt_object_init(struct rt_object * object,enum rt_object_class_type type,const char * name)238 void rt_object_init(struct rt_object         *object,
239                     enum rt_object_class_type type,
240                     const char               *name)
241 {
242     register rt_base_t temp;
243     struct rt_object_information *information;
244 #ifdef RT_USING_MODULE
245     struct rt_dlmodule *module = dlmodule_self();
246 #endif
247 
248     /* get object information */
249     information = rt_object_get_information(type);
250     RT_ASSERT(information != RT_NULL);
251 
252     /* initialize object's parameters */
253 
254     /* set object type to static */
255     object->type = type | RT_Object_Class_Static;
256 
257     /* copy name */
258     rt_strncpy(object->name, name, RT_NAME_MAX);
259 
260     RT_OBJECT_HOOK_CALL(rt_object_attach_hook, (object));
261 
262     /* lock interrupt */
263     temp = rt_hw_interrupt_disable();
264 
265 #ifdef RT_USING_MODULE
266     if (module)
267     {
268         rt_list_insert_after(&(module->object_list), &(object->list));
269         object->module_id = (void *)module;
270     }
271     else
272 #endif
273     {
274         /* insert object into information object list */
275         rt_list_insert_after(&(information->object_list), &(object->list));
276     }
277 
278     /* unlock interrupt */
279     rt_hw_interrupt_enable(temp);
280 }
281 
282 /**
283  * This function will detach a static object from object system,
284  * and the memory of static object is not freed.
285  *
286  * @param object the specified object to be detached.
287  */
rt_object_detach(rt_object_t object)288 void rt_object_detach(rt_object_t object)
289 {
290     register rt_base_t temp;
291 
292     /* object check */
293     RT_ASSERT(object != RT_NULL);
294 
295     RT_OBJECT_HOOK_CALL(rt_object_detach_hook, (object));
296 
297     /* reset object type */
298     object->type = 0;
299 
300     /* lock interrupt */
301     temp = rt_hw_interrupt_disable();
302 
303     /* remove from old list */
304     rt_list_remove(&(object->list));
305 
306     /* unlock interrupt */
307     rt_hw_interrupt_enable(temp);
308 }
309 
310 #ifdef RT_USING_HEAP
311 /**
312  * This function will allocate an object from object system
313  *
314  * @param type the type of object
315  * @param name the object name. In system, the object's name must be unique.
316  *
317  * @return object
318  */
rt_object_allocate(enum rt_object_class_type type,const char * name)319 rt_object_t rt_object_allocate(enum rt_object_class_type type, const char *name)
320 {
321     struct rt_object *object;
322     register rt_base_t temp;
323     struct rt_object_information *information;
324 #ifdef RT_USING_MODULE
325     struct rt_dlmodule *module = dlmodule_self();
326 #endif
327 
328     RT_DEBUG_NOT_IN_INTERRUPT;
329 
330     /* get object information */
331     information = rt_object_get_information(type);
332     RT_ASSERT(information != RT_NULL);
333 
334     object = (struct rt_object *)RT_KERNEL_MALLOC(information->object_size);
335     if (object == RT_NULL)
336     {
337         /* no memory can be allocated */
338         return RT_NULL;
339     }
340 
341     /* clean memory data of object */
342     rt_memset(object, 0x0, information->object_size);
343 
344     /* initialize object's parameters */
345 
346     /* set object type */
347     object->type = type;
348 
349     /* set object flag */
350     object->flag = 0;
351 
352     /* copy name */
353     rt_strncpy(object->name, name, RT_NAME_MAX);
354 
355     RT_OBJECT_HOOK_CALL(rt_object_attach_hook, (object));
356 
357     /* lock interrupt */
358     temp = rt_hw_interrupt_disable();
359 
360 #ifdef RT_USING_MODULE
361     if (module)
362     {
363         rt_list_insert_after(&(module->object_list), &(object->list));
364         object->module_id = (void *)module;
365     }
366     else
367 #endif
368     {
369         /* insert object into information object list */
370         rt_list_insert_after(&(information->object_list), &(object->list));
371     }
372 
373     /* unlock interrupt */
374     rt_hw_interrupt_enable(temp);
375 
376     /* return object */
377     return object;
378 }
379 
380 /**
381  * This function will delete an object and release object memory.
382  *
383  * @param object the specified object to be deleted.
384  */
rt_object_delete(rt_object_t object)385 void rt_object_delete(rt_object_t object)
386 {
387     register rt_base_t temp;
388 
389     /* object check */
390     RT_ASSERT(object != RT_NULL);
391     RT_ASSERT(!(object->type & RT_Object_Class_Static));
392 
393     RT_OBJECT_HOOK_CALL(rt_object_detach_hook, (object));
394 
395     /* reset object type */
396     object->type = 0;
397 
398     /* lock interrupt */
399     temp = rt_hw_interrupt_disable();
400 
401     /* remove from old list */
402     rt_list_remove(&(object->list));
403 
404     /* unlock interrupt */
405     rt_hw_interrupt_enable(temp);
406 
407     /* free the memory of object */
408     RT_KERNEL_FREE(object);
409 }
410 #endif
411 
412 /**
413  * This function will judge the object is system object or not.
414  * Normally, the system object is a static object and the type
415  * of object set to RT_Object_Class_Static.
416  *
417  * @param object the specified object to be judged.
418  *
419  * @return RT_TRUE if a system object, RT_FALSE for others.
420  */
rt_object_is_systemobject(rt_object_t object)421 rt_bool_t rt_object_is_systemobject(rt_object_t object)
422 {
423     /* object check */
424     RT_ASSERT(object != RT_NULL);
425 
426     if (object->type & RT_Object_Class_Static)
427         return RT_TRUE;
428 
429     return RT_FALSE;
430 }
431 
432 /**
433  * This function will return the type of object without
434  * RT_Object_Class_Static flag.
435  *
436  * @param object the specified object to be get type.
437  *
438  * @return the type of object.
439  */
rt_object_get_type(rt_object_t object)440 rt_uint8_t rt_object_get_type(rt_object_t object)
441 {
442     /* object check */
443     RT_ASSERT(object != RT_NULL);
444 
445     return object->type & ~RT_Object_Class_Static;
446 }
447 
448 /**
449  * This function will find specified name object from object
450  * container.
451  *
452  * @param name the specified name of object.
453  * @param type the type of object
454  *
455  * @return the found object or RT_NULL if there is no this object
456  * in object container.
457  *
458  * @note this function shall not be invoked in interrupt status.
459  */
rt_object_find(const char * name,rt_uint8_t type)460 rt_object_t rt_object_find(const char *name, rt_uint8_t type)
461 {
462     struct rt_object *object = RT_NULL;
463     struct rt_list_node *node = RT_NULL;
464     struct rt_object_information *information = RT_NULL;
465 
466     /* parameter check */
467     if ((name == RT_NULL) || (type > RT_Object_Class_Unknown))
468         return RT_NULL;
469 
470     /* which is invoke in interrupt status */
471     RT_DEBUG_NOT_IN_INTERRUPT;
472 
473     /* enter critical */
474     rt_enter_critical();
475 
476     /* try to find object */
477     if (information == RT_NULL)
478     {
479         information = rt_object_get_information((enum rt_object_class_type)type);
480         RT_ASSERT(information != RT_NULL);
481     }
482     for (node  = information->object_list.next;
483             node != &(information->object_list);
484             node  = node->next)
485     {
486         object = rt_list_entry(node, struct rt_object, list);
487         if (rt_strncmp(object->name, name, RT_NAME_MAX) == 0)
488         {
489             /* leave critical */
490             rt_exit_critical();
491 
492             return object;
493         }
494     }
495 
496     /* leave critical */
497     rt_exit_critical();
498 
499     return RT_NULL;
500 }
501 
502 /**@}*/
503