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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 * 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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