1 /*
2  * Copyright (C) 2015-2020 Alibaba Group Holding Limited
3  */
4 
5 
6 #include "device/object.h"
7 #include "device/aos_device.h"
8 
9 #include "aos/kernel.h"
10 #include "k_api.h"
11 
12 #define OBJ_ASSERT(test)
13 #define AOS_USING_DEVICE
14 
15 #ifdef AOS_USING_HOOK
16 static void (*aos_object_attach_hook)(struct aos_object *object);
17 static void (*aos_object_detach_hook)(struct aos_object *object);
18 #endif
19 
20 /*
21  * define object_info for the number of aos_object_container items.
22  */
23 enum aos_object_info_type
24 {
25     AOS_Object_Info_Thread = 0,                         /**< The object is a thread. */
26 #ifdef AOS_USING_SEMAPHORE
27     AOS_Object_Info_Semaphore,                          /**< The object is a semaphore. */
28 #endif
29 #ifdef AOS_USING_MUTEX
30     AOS_Object_Info_Mutex,                              /**< The object is a mutex. */
31 #endif
32 #ifdef AOS_USING_EVENT
33     AOS_Object_Info_Event,                              /**< The object is a event. */
34 #endif
35 #ifdef AOS_USING_MAILBOX
36     AOS_Object_Info_MailBox,                            /**< The object is a mail box. */
37 #endif
38 #ifdef AOS_USING_MESSAGEQUEUE
39     AOS_Object_Info_MessageQueue,                       /**< The object is a message queue. */
40 #endif
41 #ifdef AOS_USING_MEMHEAP
42     AOS_Object_Info_MemHeap,                            /**< The object is a memory heap */
43 #endif
44 #ifdef AOS_USING_MEMPOOL
45     AOS_Object_Info_MemPool,                            /**< The object is a memory pool. */
46 #endif
47 #ifdef AOS_USING_DEVICE
48     AOS_Object_Info_Device,                             /**< The object is a device */
49 #endif
50     AOS_Object_Info_Timer,                              /**< The object is a timer. */
51 #ifdef AOS_USING_MODULE
52     AOS_Object_Info_Module,                             /**< The object is a module. */
53 #endif
54     AOS_Object_Info_Unknown,                            /**< The object is unknown. */
55 };
56 
57 #define _OBJ_CONTAINER_LIST_INIT(c)     \
58     {&(aos_object_container[c].object_list), &(aos_object_container[c].object_list)}
59 static struct aos_object_information aos_object_container[AOS_Object_Info_Unknown] =
60 {
61     /* initialize object container - thread */
62     {AOS_Object_Class_Thread, _OBJ_CONTAINER_LIST_INIT(AOS_Object_Info_Thread), sizeof(aos_task_t)},
63 #ifdef AOS_USING_SEMAPHORE
64     /* initialize object container - semaphore */
65     {AOS_Object_Class_Semaphore, _OBJ_CONTAINER_LIST_INIT(AOS_Object_Info_Semaphore), sizeof(aos_semt_t)},
66 #endif
67 #ifdef AOS_USING_MUTEX
68     /* initialize object container - mutex */
69     {AOS_Object_Class_Mutex, _OBJ_CONTAINER_LIST_INIT(AOS_Object_Info_Mutex), sizeof(aos_mutex_t)},
70 #endif
71 #ifdef AOS_USING_EVENT
72     /* initialize object container - event */
73     {AOS_Object_Class_Event, _OBJ_CONTAINER_LIST_INIT(AOS_Object_Info_Event), sizeof(aos_event_t)},
74 #endif
75 #ifdef AOS_USING_MAILBOX
76     /* initialize object container - mailbox */
77     {AOS_Object_Class_MailBox, _OBJ_CONTAINER_LIST_INIT(AOS_Object_Info_MailBox), sizeof(aos_queue_t)},
78 #endif
79 #ifdef AOS_USING_MESSAGEQUEUE
80     /* initialize object container - message queue */
81     {AOS_Object_Class_MessageQueue, _OBJ_CONTAINER_LIST_INIT(AOS_Object_Info_MessageQueue), sizeof(struct aos_messagequeue)},
82 #endif
83 #ifdef AOS_USING_MEMHEAP
84     /* initialize object container - memory heap */
85     {AOS_Object_Class_MemHeap, _OBJ_CONTAINER_LIST_INIT(AOS_Object_Info_MemHeap), sizeof(struct memheap)},
86 #endif
87 #ifdef AOS_USING_MEMPOOL
88     /* initialize object container - memory pool */
89     {AOS_Object_Class_MemPool, _OBJ_CONTAINER_LIST_INIT(AOS_Object_Info_MemPool), sizeof(struct aos_mempool)},
90 #endif
91 #ifdef AOS_USING_DEVICE
92     /* initialize object container - device */
93     {AOS_Object_Class_Device, _OBJ_CONTAINER_LIST_INIT(AOS_Object_Info_Device), sizeof(struct aos_device)},
94 #endif
95     /* initialize object container - timer */
96     {AOS_Object_Class_Timer, _OBJ_CONTAINER_LIST_INIT(AOS_Object_Info_Timer), sizeof(aos_timer_t)},
97 #ifdef AOS_USING_MODULE
98     /* initialize object container - module */
99     {AOS_Object_Class_Module, _OBJ_CONTAINER_LIST_INIT(AOS_Object_Info_Module), sizeof(struct aos_dlmodule)},
100 #endif
101 };
102 
103 #ifdef AOS_USING_HOOK
104 static void (*aos_object_attach_hook)(struct aos_object *object);
105 static void (*aos_object_detach_hook)(struct aos_object *object);
106 void (*aos_object_trytake_hook)(struct aos_object *object);
107 void (*aos_object_take_hook)(struct aos_object *object);
108 void (*aos_object_put_hook)(struct aos_object *object);
109 
110 /**
111  * @addtogroup Hook
112  */
113 
114 /**@{*/
115 
116 /**
117  * This function will set a hook function, which will be invoked when object
118  * attaches to kernel object system.
119  *
120  * @param hook the hook function
121  */
aos_object_attach_sethook(void (* hook)(struct aos_object * object))122 void aos_object_attach_sethook(void (*hook)(struct aos_object *object))
123 {
124     aos_object_attach_hook = hook;
125 }
126 
127 /**
128  * This function will set a hook function, which will be invoked when object
129  * detaches from kernel object system.
130  *
131  * @param hook the hook function
132  */
aos_object_detach_sethook(void (* hook)(struct aos_object * object))133 void aos_object_detach_sethook(void (*hook)(struct aos_object *object))
134 {
135     aos_object_detach_hook = hook;
136 }
137 
138 /**
139  * This function will set a hook function, which will be invoked when object
140  * is taken from kernel object system.
141  *
142  * The object is taken means:
143  * semaphore - semaphore is taken by thread
144  * mutex - mutex is taken by thread
145  * event - event is received by thread
146  * mailbox - mail is received by thread
147  * message queue - message is received by thread
148  *
149  * @param hook the hook function
150  */
aos_object_trytake_sethook(void (* hook)(struct aos_object * object))151 void aos_object_trytake_sethook(void (*hook)(struct aos_object *object))
152 {
153     aos_object_trytake_hook = hook;
154 }
155 
156 /**
157  * This function will set a hook function, which will be invoked when object
158  * have been taken from kernel object system.
159  *
160  * The object have been taken means:
161  * semaphore - semaphore have been taken by thread
162  * mutex - mutex have been taken by thread
163  * event - event have been received by thread
164  * mailbox - mail have been received by thread
165  * message queue - message have been received by thread
166  * timer - timer is started
167  *
168  * @param hook the hook function
169  */
aos_object_take_sethook(void (* hook)(struct aos_object * object))170 void aos_object_take_sethook(void (*hook)(struct aos_object *object))
171 {
172     aos_object_take_hook = hook;
173 }
174 
175 /**
176  * This function will set a hook function, which will be invoked when object
177  * is put to kernel object system.
178  *
179  * @param hook the hook function
180  */
aos_object_put_sethook(void (* hook)(struct aos_object * object))181 void aos_object_put_sethook(void (*hook)(struct aos_object *object))
182 {
183     aos_object_put_hook = hook;
184 }
185 
186 /**@}*/
187 #endif
188 
189 /**
190  * @ingroup SystemInit
191  *
192  * This function will initialize system object management.
193  *
194  * @deprecated since 0.3.0, this function does not need to be invoked
195  * in the system initialization.
196  */
aos_system_object_init(void)197 void aos_system_object_init(void)
198 {
199 }
200 
201 /**
202  * @addtogroup KernelObject
203  */
204 
205 /**@{*/
206 
207 /**
208  * This function will return the specified type of object information.
209  *
210  * @param type the type of object
211  * @return the object type information or NULL
212  */
213 struct aos_object_information *
aos_object_get_information(enum aos_object_class_type type)214 aos_object_get_information(enum aos_object_class_type type)
215 {
216     int index;
217 
218     for (index = 0; index < AOS_Object_Info_Unknown; index ++)
219         if (aos_object_container[index].type == type) return &aos_object_container[index];
220 
221     return NULL;
222 }
223 
224 
225 /**
226  * This function will initialize an object and add it to object system
227  * management.
228  *
229  * @param object the specified object to be initialized.
230  * @param type the object type.
231  * @param name the object name. In system, the object's name must be unique.
232  */
aos_object_init(struct aos_object * object,enum aos_object_class_type type,const char * name)233 void aos_object_init(struct aos_object         *object,
234                     enum aos_object_class_type type,
235                     const char               *name)
236 {
237     struct dlist_s *node = NULL;
238     struct aos_object_information *information;
239 #ifdef AOS_USING_MODULE
240     struct aos_dlmodule *module = dlmodule_self();
241 #endif
242 
243     CPSR_ALLOC();
244 
245     /* get object information */
246     information = aos_object_get_information(type);
247     OBJ_ASSERT(information != NULL);
248 
249     /* check object type to avoid re-initialization */
250 
251     RHINO_CRITICAL_ENTER();
252 
253     /* try to find object */
254     for (node  = information->object_list.next;
255             node != &(information->object_list);
256             node  = node->next)
257     {
258         struct aos_object *obj;
259 
260         obj = dlist_entry(node, struct aos_object, list);
261         if (obj) /* skip warning when disable debug */
262         {
263             OBJ_ASSERT(obj != object);
264         }
265     }
266     /* leave critical */
267     RHINO_CRITICAL_EXIT();
268 
269     /* initialize object's parameters */
270     /* set object type to static */
271     object->type = type | AOS_Object_Class_Static;
272     /* copy name */
273     strncpy(object->name, name, AOS_OBJ_NAME_MAX - 1);
274 
275 #ifdef AOS_USING_HOOK
276     AOS_OBJECT_HOOK_CALL(aos_object_attach_hook, (object));
277 #endif
278 
279     /* lock interrupt */
280     RHINO_CRITICAL_ENTER();
281 
282 #ifdef AOS_USING_MODULE
283     if (module)
284     {
285         dlist_add_tail(&(module->object_list), &(object->list));
286         object->module_id = (void *)module;
287     }
288     else
289 #endif
290     {
291         /* insert object into information object list */
292         dlist_add_tail( &(object->list),&(information->object_list));
293     }
294 
295     /* unlock interrupt */
296     RHINO_CRITICAL_EXIT();
297 }
298 
299 /**
300  * This function will detach a static object from object system,
301  * and the memory of static object is not freed.
302  *
303  * @param object the specified object to be detached.
304  */
aos_object_detach(aos_object_t object)305 void aos_object_detach(aos_object_t object)
306 {
307     /* object check */
308     OBJ_ASSERT(object != NULL);
309 
310 #ifdef AOS_USING_HOOK
311     AOS_OBJECT_HOOK_CALL(aos_object_detach_hook, (object));
312 #endif
313 
314     CPSR_ALLOC();
315 
316     /* reset object type */
317     object->type = 0;
318 
319     /* enter critical */
320     RHINO_CRITICAL_ENTER();
321 
322     /* remove from old list */
323     dlist_del(&(object->list));
324 
325     RHINO_CRITICAL_EXIT();
326 }
327 
328 /**
329  * This function will judge the object is system object or not.
330  * Normally, the system object is a static object and the type
331  * of object set to RT_Object_Class_Static.
332  *
333  * @param object the specified object to be judged.
334  *
335  * @return RT_TRUE if a system object, RT_FALSE for others.
336  */
aos_object_is_systemobject(aos_object_t object)337 bool aos_object_is_systemobject(aos_object_t object)
338 {
339     /* object check */
340     OBJ_ASSERT(object != NULL);
341 
342     if (object->type & AOS_Object_Class_Static)
343         return true;
344 
345     return false;
346 }
347 
348 /**
349  * This function will return the type of object without
350  * RT_Object_Class_Static flag.
351  *
352  * @param object the specified object to be get type.
353  *
354  * @return the type of object.
355  */
aos_object_get_type(aos_object_t object)356 uint8_t aos_object_get_type(aos_object_t object)
357 {
358     /* object check */
359     OBJ_ASSERT(object != NULL);
360 
361     return object->type & ~AOS_Object_Class_Static;
362 }
363 
364 /**
365  * This function will find specified name object from object
366  * container.
367  *
368  * @param name the specified name of object.
369  * @param type the type of object
370  *
371  * @return the found object or RT_NULL if there is no this object
372  * in object container.
373  *
374  * @note this function shall not be invoked in interrupt status.
375  */
aos_object_find(const char * name,uint8_t type)376 aos_object_t aos_object_find(const char *name, uint8_t type)
377 {
378     aos_object_t object = NULL;
379     struct dlist_s *node = NULL;
380     struct aos_object_information *information = NULL;
381 
382     CPSR_ALLOC();
383 
384     /* parameter check */
385     if ((name == NULL) || (type > AOS_Object_Class_Unknown))
386         return NULL;
387 
388     /* enter critical */
389     RHINO_CRITICAL_ENTER();
390 
391     /* try to find object */
392     if (information == NULL)
393     {
394         information = aos_object_get_information((enum aos_object_class_type)type);
395         OBJ_ASSERT(information != NULL);
396     }
397     for (node  = information->object_list.next;
398             node != &(information->object_list);
399             node  = node->next)
400     {
401         object = dlist_entry(node, struct aos_object, list);
402         if (strncmp(object->name, name, AOS_OBJ_NAME_MAX) == 0)
403         {
404             /* leave critical */
405             RHINO_CRITICAL_EXIT();
406 
407             return object;
408         }
409     }
410 
411     /* leave critical */
412     RHINO_CRITICAL_EXIT();
413 
414     return NULL;
415 }
416 
417 /**@}*/
418