object.c 14.3 KB
Newer Older
1
/*
2
 * Copyright (c) 2006-2018, RT-Thread Development Team
B
Bernard Xiong 已提交
3
 *
4
 * SPDX-License-Identifier: Apache-2.0
5 6 7 8 9 10 11 12
 *
 * Change Logs:
 * Date           Author       Notes
 * 2006-03-14     Bernard      the first version
 * 2006-04-21     Bernard      change the scheduler lock to interrupt lock
 * 2006-05-18     Bernard      fix the object init bug
 * 2006-08-03     Bernard      add hook support
 * 2007-01-28     Bernard      rename RT_OBJECT_Class_Static to RT_Object_Class_Static
qiuyiuestc's avatar
qiuyiuestc 已提交
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 19 20
 */

#include <rtthread.h>
#include <rthw.h>

21 22 23 24
#ifdef RT_USING_MODULE
#include <dlmodule.h>
#endif

25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
/*
 * define object_info for the number of rt_object_container items.
 */
enum rt_object_info_type
{
    RT_Object_Info_Thread = 0,                         /**< The object is a thread. */
#ifdef RT_USING_SEMAPHORE
    RT_Object_Info_Semaphore,                          /**< The object is a semaphore. */
#endif
#ifdef RT_USING_MUTEX
    RT_Object_Info_Mutex,                              /**< The object is a mutex. */
#endif
#ifdef RT_USING_EVENT
    RT_Object_Info_Event,                              /**< The object is a event. */
#endif
#ifdef RT_USING_MAILBOX
    RT_Object_Info_MailBox,                            /**< The object is a mail box. */
#endif
#ifdef RT_USING_MESSAGEQUEUE
    RT_Object_Info_MessageQueue,                       /**< The object is a message queue. */
#endif
#ifdef RT_USING_MEMHEAP
    RT_Object_Info_MemHeap,                            /**< The object is a memory heap */
#endif
#ifdef RT_USING_MEMPOOL
    RT_Object_Info_MemPool,                            /**< The object is a memory pool. */
#endif
#ifdef RT_USING_DEVICE
    RT_Object_Info_Device,                             /**< The object is a device */
#endif
    RT_Object_Info_Timer,                              /**< The object is a timer. */
#ifdef RT_USING_MODULE
    RT_Object_Info_Module,                             /**< The object is a module. */
#endif
    RT_Object_Info_Unknown,                            /**< The object is unknown. */
};

62 63
#define _OBJ_CONTAINER_LIST_INIT(c)     \
    {&(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 72
#endif
#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 76
#endif
#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 80
#endif
#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 84
#endif
#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 96
#endif
#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 106
#endif
};
107 108

#ifdef RT_USING_HOOK
D
dzzxzz 已提交
109 110 111 112 113
static void (*rt_object_attach_hook)(struct rt_object *object);
static void (*rt_object_detach_hook)(struct rt_object *object);
void (*rt_object_trytake_hook)(struct rt_object *object);
void (*rt_object_take_hook)(struct rt_object *object);
void (*rt_object_put_hook)(struct rt_object *object);
114 115 116 117

/**
 * @addtogroup Hook
 */
D
dzzxzz 已提交
118

D
dogandog 已提交
119
/**@{*/
120 121 122 123

/**
 * This function will set a hook function, which will be invoked when object
 * attaches to kernel object system.
B
bernard.xiong 已提交
124
 *
125 126
 * @param hook the hook function
 */
D
dzzxzz 已提交
127
void rt_object_attach_sethook(void (*hook)(struct rt_object *object))
128
{
129
    rt_object_attach_hook = hook;
130 131 132 133 134
}

/**
 * This function will set a hook function, which will be invoked when object
 * detaches from kernel object system.
B
bernard.xiong 已提交
135
 *
136 137
 * @param hook the hook function
 */
D
dzzxzz 已提交
138
void rt_object_detach_sethook(void (*hook)(struct rt_object *object))
139
{
140
    rt_object_detach_hook = hook;
141 142 143 144 145
}

/**
 * This function will set a hook function, which will be invoked when object
 * is taken from kernel object system.
B
bernard.xiong 已提交
146
 *
B
bernard.xiong@gmail.com 已提交
147
 * The object is taken means:
148 149
 * semaphore - semaphore is taken by thread
 * mutex - mutex is taken by thread
B
bernard.xiong 已提交
150
 * event - event is received by thread
151 152
 * mailbox - mail is received by thread
 * message queue - message is received by thread
B
bernard.xiong 已提交
153
 *
154 155
 * @param hook the hook function
 */
D
dzzxzz 已提交
156
void rt_object_trytake_sethook(void (*hook)(struct rt_object *object))
157
{
158
    rt_object_trytake_hook = hook;
159 160 161 162 163
}

/**
 * This function will set a hook function, which will be invoked when object
 * have been taken from kernel object system.
B
bernard.xiong 已提交
164
 *
B
bernard.xiong@gmail.com 已提交
165
 * The object have been taken means:
166 167
 * semaphore - semaphore have been taken by thread
 * mutex - mutex have been taken by thread
B
bernard.xiong 已提交
168
 * event - event have been received by thread
169 170 171
 * mailbox - mail have been received by thread
 * message queue - message have been received by thread
 * timer - timer is started
B
bernard.xiong 已提交
172
 *
173 174
 * @param hook the hook function
 */
D
dzzxzz 已提交
175
void rt_object_take_sethook(void (*hook)(struct rt_object *object))
176
{
177
    rt_object_take_hook = hook;
178 179 180 181 182
}

/**
 * This function will set a hook function, which will be invoked when object
 * is put to kernel object system.
B
bernard.xiong 已提交
183
 *
184 185
 * @param hook the hook function
 */
D
dzzxzz 已提交
186
void rt_object_put_sethook(void (*hook)(struct rt_object *object))
187
{
188
    rt_object_put_hook = hook;
189 190
}

D
dogandog 已提交
191
/**@}*/
192 193 194 195 196
#endif

/**
 * @ingroup SystemInit
 *
B
bernard.xiong@gmail.com 已提交
197
 * This function will initialize system object management.
198
 *
B
bernard.xiong@gmail.com 已提交
199 200
 * @deprecated since 0.3.0, this function does not need to be invoked
 * in the system initialization.
201 202 203 204 205 206 207 208
 */
void rt_system_object_init(void)
{
}

/**
 * @addtogroup KernelObject
 */
D
dzzxzz 已提交
209

D
dogandog 已提交
210
/**@{*/
211

212 213
/**
 * This function will return the specified type of object information.
B
Bernard Xiong 已提交
214
 *
215 216 217
 * @param type the type of object
 * @return the object type information or RT_NULL
 */
218 219
struct rt_object_information *
rt_object_get_information(enum rt_object_class_type type)
220
{
221
    int index;
222

223 224
    for (index = 0; index < RT_Object_Info_Unknown; index ++)
        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 232
 * This function will initialize an object and add it to object system
 * management.
233 234 235
 *
 * @param object the specified object to be initialized.
 * @param type the object type.
B
bernard.xiong@gmail.com 已提交
236
 * @param name the object name. In system, the object's name must be unique.
237
 */
238 239 240
void rt_object_init(struct rt_object         *object,
                    enum rt_object_class_type type,
                    const char               *name)
241
{
242
    register rt_base_t temp;
243
    struct rt_list_node *node = RT_NULL;
244
    struct rt_object_information *information;
245 246 247
#ifdef RT_USING_MODULE
    struct rt_dlmodule *module = dlmodule_self();
#endif
248

249
    /* get object information */
250 251
    information = rt_object_get_information(type);
    RT_ASSERT(information != RT_NULL);
252

253 254
    /* check object type to avoid re-initialization */

255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
    /* enter critical */
    rt_enter_critical();
    /* try to find object */
    for (node  = information->object_list.next;
            node != &(information->object_list);
            node  = node->next)
    {
        struct rt_object *obj;

        obj = rt_list_entry(node, struct rt_object, list);
        RT_ASSERT(obj != object);
    }
    /* leave critical */
    rt_exit_critical();

    /* initialize object's parameters */
271 272 273 274
    /* set object type to static */
    object->type = type | RT_Object_Class_Static;
    /* copy name */
    rt_strncpy(object->name, name, RT_NAME_MAX);
275

276
    RT_OBJECT_HOOK_CALL(rt_object_attach_hook, (object));
277

278 279
    /* lock interrupt */
    temp = rt_hw_interrupt_disable();
280

281 282 283 284 285 286 287 288 289 290 291 292
#ifdef RT_USING_MODULE
    if (module)
    {
        rt_list_insert_after(&(module->object_list), &(object->list));
        object->module_id = (void *)module;
    }
    else
#endif
    {
        /* insert object into information object list */
        rt_list_insert_after(&(information->object_list), &(object->list));
    }
293

294 295
    /* unlock interrupt */
    rt_hw_interrupt_enable(temp);
296 297 298 299 300 301 302 303 304 305
}

/**
 * This function will detach a static object from object system,
 * and the memory of static object is not freed.
 *
 * @param object the specified object to be detached.
 */
void rt_object_detach(rt_object_t object)
{
306
    register rt_base_t temp;
307

308 309
    /* object check */
    RT_ASSERT(object != RT_NULL);
310

311
    RT_OBJECT_HOOK_CALL(rt_object_detach_hook, (object));
312

313 314 315
    /* reset object type */
    object->type = 0;

316 317
    /* lock interrupt */
    temp = rt_hw_interrupt_disable();
318

319 320
    /* remove from old list */
    rt_list_remove(&(object->list));
321

322 323
    /* unlock interrupt */
    rt_hw_interrupt_enable(temp);
324 325 326 327 328 329 330 331 332 333 334
}

#ifdef RT_USING_HEAP
/**
 * This function will allocate an object from object system
 *
 * @param type the type of object
 * @param name the object name. In system, the object's name must be unique.
 *
 * @return object
 */
D
dzzxzz 已提交
335
rt_object_t rt_object_allocate(enum rt_object_class_type type, const char *name)
336
{
337 338 339
    struct rt_object *object;
    register rt_base_t temp;
    struct rt_object_information *information;
340 341 342
#ifdef RT_USING_MODULE
    struct rt_dlmodule *module = dlmodule_self();
#endif
343

344
    RT_DEBUG_NOT_IN_INTERRUPT;
345

346
    /* get object information */
347 348
    information = rt_object_get_information(type);
    RT_ASSERT(information != RT_NULL);
349

B
Bernard Xiong 已提交
350
    object = (struct rt_object *)RT_KERNEL_MALLOC(information->object_size);
351 352 353 354 355
    if (object == RT_NULL)
    {
        /* no memory can be allocated */
        return RT_NULL;
    }
B
Bernard Xiong 已提交
356

357 358 359
    /* clean memory data of object */
    rt_memset(object, 0x0, information->object_size);

360
    /* initialize object's parameters */
361

362 363
    /* set object type */
    object->type = type;
364

365 366
    /* set object flag */
    object->flag = 0;
qiuyiuestc's avatar
qiuyiuestc 已提交
367

368 369
    /* copy name */
    rt_strncpy(object->name, name, RT_NAME_MAX);
370

371
    RT_OBJECT_HOOK_CALL(rt_object_attach_hook, (object));
372

373 374
    /* lock interrupt */
    temp = rt_hw_interrupt_disable();
375

376 377 378 379 380 381 382 383 384 385 386 387
#ifdef RT_USING_MODULE
    if (module)
    {
        rt_list_insert_after(&(module->object_list), &(object->list));
        object->module_id = (void *)module;
    }
    else
#endif
    {
        /* insert object into information object list */
        rt_list_insert_after(&(information->object_list), &(object->list));
    }
388

389 390
    /* unlock interrupt */
    rt_hw_interrupt_enable(temp);
391

392 393
    /* return object */
    return object;
394 395 396 397 398 399 400 401 402
}

/**
 * This function will delete an object and release object memory.
 *
 * @param object the specified object to be deleted.
 */
void rt_object_delete(rt_object_t object)
{
403
    register rt_base_t temp;
404

405 406 407
    /* object check */
    RT_ASSERT(object != RT_NULL);
    RT_ASSERT(!(object->type & RT_Object_Class_Static));
408

409
    RT_OBJECT_HOOK_CALL(rt_object_detach_hook, (object));
410

411 412 413
    /* reset object type */
    object->type = 0;

414 415
    /* lock interrupt */
    temp = rt_hw_interrupt_disable();
416

417 418
    /* remove from old list */
    rt_list_remove(&(object->list));
419

420 421
    /* unlock interrupt */
    rt_hw_interrupt_enable(temp);
422

423 424
    /* free the memory of object */
    RT_KERNEL_FREE(object);
425 426 427 428 429 430 431 432 433 434
}
#endif

/**
 * This function will judge the object is system object or not.
 * Normally, the system object is a static object and the type
 * of object set to RT_Object_Class_Static.
 *
 * @param object the specified object to be judged.
 *
435
 * @return RT_TRUE if a system object, RT_FALSE for others.
436
 */
437
rt_bool_t rt_object_is_systemobject(rt_object_t object)
438
{
439 440
    /* object check */
    RT_ASSERT(object != RT_NULL);
441

442 443
    if (object->type & RT_Object_Class_Static)
        return RT_TRUE;
444

445
    return RT_FALSE;
446 447
}

448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463
/**
 * This function will return the type of object without
 * RT_Object_Class_Static flag.
 *
 * @param object the specified object to be get type.
 *
 * @return the type of object.
 */
rt_uint8_t rt_object_get_type(rt_object_t object)
{
    /* object check */
    RT_ASSERT(object != RT_NULL);

    return object->type & ~RT_Object_Class_Static;
}

464 465 466 467 468 469 470 471 472 473
/**
 * This function will find specified name object from object
 * container.
 *
 * @param name the specified name of object.
 * @param type the type of object
 *
 * @return the found object or RT_NULL if there is no this object
 * in object container.
 *
B
bernard.xiong@gmail.com 已提交
474
 * @note this function shall not be invoked in interrupt status.
475
 */
D
dzzxzz 已提交
476
rt_object_t rt_object_find(const char *name, rt_uint8_t type)
477
{
B
Bernard Xiong 已提交
478 479
    struct rt_object *object = RT_NULL;
    struct rt_list_node *node = RT_NULL;
480
    struct rt_object_information *information = RT_NULL;
481 482 483 484 485 486

    /* parameter check */
    if ((name == RT_NULL) || (type > RT_Object_Class_Unknown))
        return RT_NULL;

    /* which is invoke in interrupt status */
487 488
    RT_DEBUG_NOT_IN_INTERRUPT;

489 490 491 492
    /* enter critical */
    rt_enter_critical();

    /* try to find object */
493 494
    if (information == RT_NULL)
    {
B
BernardXiong 已提交
495
        information = rt_object_get_information((enum rt_object_class_type)type);
496 497
        RT_ASSERT(information != RT_NULL);
    }
498
    for (node  = information->object_list.next;
499 500
            node != &(information->object_list);
            node  = node->next)
501 502 503 504 505 506 507 508 509 510 511 512 513 514 515
    {
        object = rt_list_entry(node, struct rt_object, list);
        if (rt_strncmp(object->name, name, RT_NAME_MAX) == 0)
        {
            /* leave critical */
            rt_exit_critical();

            return object;
        }
    }

    /* leave critical */
    rt_exit_critical();

    return RT_NULL;
516
}
D
dzzxzz 已提交
517

D
dogandog 已提交
518
/**@}*/