object.c 16.6 KB
Newer Older
1
/*
mysterywolf's avatar
mysterywolf 已提交
2
 * Copyright (c) 2006-2021, 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
#ifdef RT_USING_MODULE
#include <dlmodule.h>
23
#endif /* RT_USING_MODULE */
24

25
/*
mysterywolf's avatar
mysterywolf 已提交
26
 * define object_info for the number of _object_container items.
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
 */
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
#define _OBJ_CONTAINER_LIST_INIT(c)     \
mysterywolf's avatar
mysterywolf 已提交
63 64 65
    {&(_object_container[c].object_list), &(_object_container[c].object_list)}

static struct rt_object_information _object_container[RT_Object_Info_Unknown] =
66
{
67
    /* initialize object container - thread */
68
    {RT_Object_Class_Thread, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Thread), sizeof(struct rt_thread)},
69
#ifdef RT_USING_SEMAPHORE
70
    /* initialize object container - semaphore */
71
    {RT_Object_Class_Semaphore, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Semaphore), sizeof(struct rt_semaphore)},
72 73
#endif
#ifdef RT_USING_MUTEX
74
    /* initialize object container - mutex */
75
    {RT_Object_Class_Mutex, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Mutex), sizeof(struct rt_mutex)},
76 77
#endif
#ifdef RT_USING_EVENT
78
    /* initialize object container - event */
79
    {RT_Object_Class_Event, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Event), sizeof(struct rt_event)},
80 81
#endif
#ifdef RT_USING_MAILBOX
82
    /* initialize object container - mailbox */
83
    {RT_Object_Class_MailBox, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MailBox), sizeof(struct rt_mailbox)},
84 85
#endif
#ifdef RT_USING_MESSAGEQUEUE
86
    /* initialize object container - message queue */
87
    {RT_Object_Class_MessageQueue, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MessageQueue), sizeof(struct rt_messagequeue)},
88
#endif
89
#ifdef RT_USING_MEMHEAP
90
    /* initialize object container - memory heap */
91
    {RT_Object_Class_MemHeap, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MemHeap), sizeof(struct rt_memheap)},
92
#endif
93
#ifdef RT_USING_MEMPOOL
94
    /* initialize object container - memory pool */
95
    {RT_Object_Class_MemPool, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MemPool), sizeof(struct rt_mempool)},
96 97
#endif
#ifdef RT_USING_DEVICE
98
    /* initialize object container - device */
99
    {RT_Object_Class_Device, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Device), sizeof(struct rt_device)},
100
#endif
101
    /* initialize object container - timer */
102
    {RT_Object_Class_Timer, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Timer), sizeof(struct rt_timer)},
103
#ifdef RT_USING_MODULE
104
    /* initialize object container - module */
105
    {RT_Object_Class_Module, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Module), sizeof(struct rt_dlmodule)},
106 107
#endif
};
108 109

#ifdef RT_USING_HOOK
D
dzzxzz 已提交
110 111 112 113 114
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);
115 116 117 118

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

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

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

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

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

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

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

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

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

D
dogandog 已提交
199
/**@{*/
200

201
/**
202
 * @brief This function will return the specified type of object information.
B
Bernard Xiong 已提交
203
 *
mysterywolf's avatar
mysterywolf 已提交
204
 * @param type the type of object, which can be
205 206
 *             RT_Object_Class_Thread/Semaphore/Mutex... etc
 *
207 208
 * @return the object type information or RT_NULL
 */
209 210
struct rt_object_information *
rt_object_get_information(enum rt_object_class_type type)
211
{
212
    int index;
213

214
    for (index = 0; index < RT_Object_Info_Unknown; index ++)
mysterywolf's avatar
mysterywolf 已提交
215
        if (_object_container[index].type == type) return &_object_container[index];
216

217
    return RT_NULL;
218
}
219
RTM_EXPORT(rt_object_get_information);
220

221
/**
222
 * @brief This function will return the length of object list in object container.
223
 *
mysterywolf's avatar
mysterywolf 已提交
224
 * @param type the type of object, which can be
225
 *             RT_Object_Class_Thread/Semaphore/Mutex... etc
226
 *
227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251
 * @return the length of object list
 */
int rt_object_get_length(enum rt_object_class_type type)
{
    int count = 0;
    rt_ubase_t level;
    struct rt_list_node *node = RT_NULL;
    struct rt_object_information *information = RT_NULL;

    information = rt_object_get_information((enum rt_object_class_type)type);
    if (information == RT_NULL) return 0;

    level = rt_hw_interrupt_disable();
    /* get the count of objects */
    rt_list_for_each(node, &(information->object_list))
    {
        count ++;
    }
    rt_hw_interrupt_enable(level);

    return count;
}
RTM_EXPORT(rt_object_get_length);

/**
252 253
 * @brief This function will copy the object pointer of the specified type,
 *        with the maximum size specified by maxlen.
254
 *
mysterywolf's avatar
mysterywolf 已提交
255
 * @param type the type of object, which can be
256
 *             RT_Object_Class_Thread/Semaphore/Mutex... etc
257
 *
258
 * @param pointers the pointers will be saved to
259
 *
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285
 * @param maxlen the maximum number of pointers can be saved
 *
 * @return the copied number of object pointers
 */
int rt_object_get_pointers(enum rt_object_class_type type, rt_object_t *pointers, int maxlen)
{
    int index = 0;
    rt_ubase_t level;

    struct rt_object *object;
    struct rt_list_node *node = RT_NULL;
    struct rt_object_information *information = RT_NULL;

    if (maxlen <= 0) return 0;

    information = rt_object_get_information((enum rt_object_class_type)type);
    if (information == RT_NULL) return 0;

    level = rt_hw_interrupt_disable();
    /* retrieve pointer of object */
    rt_list_for_each(node, &(information->object_list))
    {
        object = rt_list_entry(node, struct rt_object, list);

        pointers[index] = object;
        index ++;
286 287

        if (index >= maxlen) break;
288 289 290 291 292 293 294
    }
    rt_hw_interrupt_enable(level);

    return index;
}
RTM_EXPORT(rt_object_get_pointers);

295
/**
296 297
 * @brief This function will initialize an object and add it to object system
 *        management.
298 299
 *
 * @param object the specified object to be initialized.
300
 *
301
 * @param type the object type.
302
 *
B
bernard.xiong@gmail.com 已提交
303
 * @param name the object name. In system, the object's name must be unique.
304
 */
305 306 307
void rt_object_init(struct rt_object         *object,
                    enum rt_object_class_type type,
                    const char               *name)
308
{
309
    register rt_base_t temp;
310
    struct rt_list_node *node = RT_NULL;
311
    struct rt_object_information *information;
312 313
#ifdef RT_USING_MODULE
    struct rt_dlmodule *module = dlmodule_self();
314
#endif /* RT_USING_MODULE */
315

316
    /* get object information */
317 318
    information = rt_object_get_information(type);
    RT_ASSERT(information != RT_NULL);
319

320 321
    /* check object type to avoid re-initialization */

322 323 324 325 326 327 328 329 330 331
    /* 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);
332 333 334 335
        if (obj) /* skip warning when disable debug */
        {
            RT_ASSERT(obj != object);
        }
336 337 338 339 340
    }
    /* leave critical */
    rt_exit_critical();

    /* initialize object's parameters */
341 342 343 344
    /* set object type to static */
    object->type = type | RT_Object_Class_Static;
    /* copy name */
    rt_strncpy(object->name, name, RT_NAME_MAX);
345

346
    RT_OBJECT_HOOK_CALL(rt_object_attach_hook, (object));
347

348 349
    /* lock interrupt */
    temp = rt_hw_interrupt_disable();
350

351 352 353 354 355 356 357
#ifdef RT_USING_MODULE
    if (module)
    {
        rt_list_insert_after(&(module->object_list), &(object->list));
        object->module_id = (void *)module;
    }
    else
358
#endif /* RT_USING_MODULE */
359 360 361 362
    {
        /* insert object into information object list */
        rt_list_insert_after(&(information->object_list), &(object->list));
    }
363

364 365
    /* unlock interrupt */
    rt_hw_interrupt_enable(temp);
366 367 368
}

/**
369 370
 * @brief This function will detach a static object from object system,
 *        and the memory of static object is not freed.
371 372 373 374 375
 *
 * @param object the specified object to be detached.
 */
void rt_object_detach(rt_object_t object)
{
376
    register rt_base_t temp;
377

378 379
    /* object check */
    RT_ASSERT(object != RT_NULL);
380

381
    RT_OBJECT_HOOK_CALL(rt_object_detach_hook, (object));
382

383 384 385
    /* reset object type */
    object->type = 0;

386 387
    /* lock interrupt */
    temp = rt_hw_interrupt_disable();
388

389 390
    /* remove from old list */
    rt_list_remove(&(object->list));
391

392 393
    /* unlock interrupt */
    rt_hw_interrupt_enable(temp);
394 395 396 397
}

#ifdef RT_USING_HEAP
/**
398
 * @brief This function will allocate an object from object system.
399 400
 *
 * @param type the type of object
401
 *
402 403 404 405
 * @param name the object name. In system, the object's name must be unique.
 *
 * @return object
 */
D
dzzxzz 已提交
406
rt_object_t rt_object_allocate(enum rt_object_class_type type, const char *name)
407
{
408 409 410
    struct rt_object *object;
    register rt_base_t temp;
    struct rt_object_information *information;
411 412
#ifdef RT_USING_MODULE
    struct rt_dlmodule *module = dlmodule_self();
413
#endif /* RT_USING_MODULE */
414

415
    RT_DEBUG_NOT_IN_INTERRUPT;
416

417
    /* get object information */
418 419
    information = rt_object_get_information(type);
    RT_ASSERT(information != RT_NULL);
420

B
Bernard Xiong 已提交
421
    object = (struct rt_object *)RT_KERNEL_MALLOC(information->object_size);
422 423 424 425 426
    if (object == RT_NULL)
    {
        /* no memory can be allocated */
        return RT_NULL;
    }
B
Bernard Xiong 已提交
427

428 429 430
    /* clean memory data of object */
    rt_memset(object, 0x0, information->object_size);

431
    /* initialize object's parameters */
432

433 434
    /* set object type */
    object->type = type;
435

436 437
    /* set object flag */
    object->flag = 0;
qiuyiuestc's avatar
qiuyiuestc 已提交
438

439 440
    /* copy name */
    rt_strncpy(object->name, name, RT_NAME_MAX);
441

442
    RT_OBJECT_HOOK_CALL(rt_object_attach_hook, (object));
443

444 445
    /* lock interrupt */
    temp = rt_hw_interrupt_disable();
446

447 448 449 450 451 452 453
#ifdef RT_USING_MODULE
    if (module)
    {
        rt_list_insert_after(&(module->object_list), &(object->list));
        object->module_id = (void *)module;
    }
    else
454
#endif /* RT_USING_MODULE */
455 456 457 458
    {
        /* insert object into information object list */
        rt_list_insert_after(&(information->object_list), &(object->list));
    }
459

460 461
    /* unlock interrupt */
    rt_hw_interrupt_enable(temp);
462

463 464
    /* return object */
    return object;
465 466 467
}

/**
468
 * @brief This function will delete an object and release object memory.
469 470 471 472 473
 *
 * @param object the specified object to be deleted.
 */
void rt_object_delete(rt_object_t object)
{
474
    register rt_base_t temp;
475

476 477 478
    /* object check */
    RT_ASSERT(object != RT_NULL);
    RT_ASSERT(!(object->type & RT_Object_Class_Static));
479

480
    RT_OBJECT_HOOK_CALL(rt_object_detach_hook, (object));
481

482
    /* reset object type */
483
    object->type = RT_Object_Class_Null;
484

485 486
    /* lock interrupt */
    temp = rt_hw_interrupt_disable();
487

488 489
    /* remove from old list */
    rt_list_remove(&(object->list));
490

491 492
    /* unlock interrupt */
    rt_hw_interrupt_enable(temp);
493

494 495
    /* free the memory of object */
    RT_KERNEL_FREE(object);
496
}
497
#endif /* RT_USING_HEAP */
498 499

/**
500 501 502 503
 * @brief This function will judge the object is system object or not.
 *
 * @note  Normally, the system object is a static object and the type
 *        of object set to RT_Object_Class_Static.
504 505 506
 *
 * @param object the specified object to be judged.
 *
507
 * @return RT_TRUE if a system object, RT_FALSE for others.
508
 */
509
rt_bool_t rt_object_is_systemobject(rt_object_t object)
510
{
511 512
    /* object check */
    RT_ASSERT(object != RT_NULL);
513

514 515
    if (object->type & RT_Object_Class_Static)
        return RT_TRUE;
516

517
    return RT_FALSE;
518 519
}

520
/**
521 522
 * @brief This function will return the type of object without
 *        RT_Object_Class_Static flag.
523 524 525 526 527 528 529 530 531 532 533 534 535
 *
 * @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;
}

536
/**
537 538
 * @brief This function will find specified name object from object
 *        container.
539 540
 *
 * @param name the specified name of object.
541
 *
542 543 544 545 546
 * @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 已提交
547
 * @note this function shall not be invoked in interrupt status.
548
 */
D
dzzxzz 已提交
549
rt_object_t rt_object_find(const char *name, rt_uint8_t type)
550
{
B
Bernard Xiong 已提交
551 552
    struct rt_object *object = RT_NULL;
    struct rt_list_node *node = RT_NULL;
553
    struct rt_object_information *information = RT_NULL;
554

555 556
    information = rt_object_get_information((enum rt_object_class_type)type);

557
    /* parameter check */
558
    if ((name == RT_NULL) || (information == RT_NULL)) return RT_NULL;
559 560

    /* which is invoke in interrupt status */
561 562
    RT_DEBUG_NOT_IN_INTERRUPT;

563 564 565 566
    /* enter critical */
    rt_enter_critical();

    /* try to find object */
567
    rt_list_for_each(node, &(information->object_list))
568 569 570 571 572 573 574 575 576 577 578 579 580 581 582
    {
        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;
583
}
D
dzzxzz 已提交
584

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