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