object.c 16.2 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 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
#endif /* RT_USING_HOOK */
193 194 195 196

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

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

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

213 214
    for (index = 0; index < RT_Object_Info_Unknown; index ++)
        if (rt_object_container[index].type == type) return &rt_object_container[index];
215

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

220 221 222
/**
 * This function will return the length of object list in object container.
 *
mysterywolf's avatar
mysterywolf 已提交
223
 * @param type the type of object, which can be
224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249
 *             RT_Object_Class_Thread/Semaphore/Mutex... etc
 * @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);

/**
mysterywolf's avatar
mysterywolf 已提交
250
 * This function will copy the object pointer of the specified type,
251 252
 * with the maximum size specified by maxlen.
 *
mysterywolf's avatar
mysterywolf 已提交
253
 * @param type the type of object, which can be
254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281
 *             RT_Object_Class_Thread/Semaphore/Mutex... etc
 * @param pointers the pointers will be saved to
 * @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 ++;
282 283

        if (index >= maxlen) break;
284 285 286 287 288 289 290
    }
    rt_hw_interrupt_enable(level);

    return index;
}
RTM_EXPORT(rt_object_get_pointers);

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

310
    /* get object information */
311 312
    information = rt_object_get_information(type);
    RT_ASSERT(information != RT_NULL);
313

314 315
    /* check object type to avoid re-initialization */

316 317 318 319 320 321 322 323 324 325
    /* 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);
326 327 328 329
        if (obj) /* skip warning when disable debug */
        {
            RT_ASSERT(obj != object);
        }
330 331 332 333 334
    }
    /* leave critical */
    rt_exit_critical();

    /* initialize object's parameters */
335 336 337 338
    /* set object type to static */
    object->type = type | RT_Object_Class_Static;
    /* copy name */
    rt_strncpy(object->name, name, RT_NAME_MAX);
339

340
    RT_OBJECT_HOOK_CALL(rt_object_attach_hook, (object));
341

342 343
    /* lock interrupt */
    temp = rt_hw_interrupt_disable();
344

345 346 347 348 349 350 351
#ifdef RT_USING_MODULE
    if (module)
    {
        rt_list_insert_after(&(module->object_list), &(object->list));
        object->module_id = (void *)module;
    }
    else
352
#endif /* RT_USING_MODULE */
353 354 355 356
    {
        /* insert object into information object list */
        rt_list_insert_after(&(information->object_list), &(object->list));
    }
357

358 359
    /* unlock interrupt */
    rt_hw_interrupt_enable(temp);
360 361 362 363 364 365 366 367 368 369
}

/**
 * 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)
{
370
    register rt_base_t temp;
371

372 373
    /* object check */
    RT_ASSERT(object != RT_NULL);
374

375
    RT_OBJECT_HOOK_CALL(rt_object_detach_hook, (object));
376

377 378 379
    /* reset object type */
    object->type = 0;

380 381
    /* lock interrupt */
    temp = rt_hw_interrupt_disable();
382

383 384
    /* remove from old list */
    rt_list_remove(&(object->list));
385

386 387
    /* unlock interrupt */
    rt_hw_interrupt_enable(temp);
388 389 390 391 392 393 394 395 396 397 398
}

#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 已提交
399
rt_object_t rt_object_allocate(enum rt_object_class_type type, const char *name)
400
{
401 402 403
    struct rt_object *object;
    register rt_base_t temp;
    struct rt_object_information *information;
404 405
#ifdef RT_USING_MODULE
    struct rt_dlmodule *module = dlmodule_self();
406
#endif /* RT_USING_MODULE */
407

408
    RT_DEBUG_NOT_IN_INTERRUPT;
409

410
    /* get object information */
411 412
    information = rt_object_get_information(type);
    RT_ASSERT(information != RT_NULL);
413

B
Bernard Xiong 已提交
414
    object = (struct rt_object *)RT_KERNEL_MALLOC(information->object_size);
415 416 417 418 419
    if (object == RT_NULL)
    {
        /* no memory can be allocated */
        return RT_NULL;
    }
B
Bernard Xiong 已提交
420

421 422 423
    /* clean memory data of object */
    rt_memset(object, 0x0, information->object_size);

424
    /* initialize object's parameters */
425

426 427
    /* set object type */
    object->type = type;
428

429 430
    /* set object flag */
    object->flag = 0;
qiuyiuestc's avatar
qiuyiuestc 已提交
431

432 433
    /* copy name */
    rt_strncpy(object->name, name, RT_NAME_MAX);
434

435
    RT_OBJECT_HOOK_CALL(rt_object_attach_hook, (object));
436

437 438
    /* lock interrupt */
    temp = rt_hw_interrupt_disable();
439

440 441 442 443 444 445 446
#ifdef RT_USING_MODULE
    if (module)
    {
        rt_list_insert_after(&(module->object_list), &(object->list));
        object->module_id = (void *)module;
    }
    else
447
#endif /* RT_USING_MODULE */
448 449 450 451
    {
        /* insert object into information object list */
        rt_list_insert_after(&(information->object_list), &(object->list));
    }
452

453 454
    /* unlock interrupt */
    rt_hw_interrupt_enable(temp);
455

456 457
    /* return object */
    return object;
458 459 460 461 462 463 464 465 466
}

/**
 * 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)
{
467
    register rt_base_t temp;
468

469 470 471
    /* object check */
    RT_ASSERT(object != RT_NULL);
    RT_ASSERT(!(object->type & RT_Object_Class_Static));
472

473
    RT_OBJECT_HOOK_CALL(rt_object_detach_hook, (object));
474

475
    /* reset object type */
476
    object->type = RT_Object_Class_Null;
477

478 479
    /* lock interrupt */
    temp = rt_hw_interrupt_disable();
480

481 482
    /* remove from old list */
    rt_list_remove(&(object->list));
483

484 485
    /* unlock interrupt */
    rt_hw_interrupt_enable(temp);
486

487 488
    /* free the memory of object */
    RT_KERNEL_FREE(object);
489
}
490
#endif /* RT_USING_HEAP */
491 492 493 494 495 496 497 498

/**
 * 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.
 *
499
 * @return RT_TRUE if a system object, RT_FALSE for others.
500
 */
501
rt_bool_t rt_object_is_systemobject(rt_object_t object)
502
{
503 504
    /* object check */
    RT_ASSERT(object != RT_NULL);
505

506 507
    if (object->type & RT_Object_Class_Static)
        return RT_TRUE;
508

509
    return RT_FALSE;
510 511
}

512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527
/**
 * 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;
}

528 529 530 531 532 533 534 535 536 537
/**
 * 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 已提交
538
 * @note this function shall not be invoked in interrupt status.
539
 */
D
dzzxzz 已提交
540
rt_object_t rt_object_find(const char *name, rt_uint8_t type)
541
{
B
Bernard Xiong 已提交
542 543
    struct rt_object *object = RT_NULL;
    struct rt_list_node *node = RT_NULL;
544
    struct rt_object_information *information = RT_NULL;
545

546 547
    information = rt_object_get_information((enum rt_object_class_type)type);

548
    /* parameter check */
549
    if ((name == RT_NULL) || (information == RT_NULL)) return RT_NULL;
550 551

    /* which is invoke in interrupt status */
552 553
    RT_DEBUG_NOT_IN_INTERRUPT;

554 555 556 557
    /* enter critical */
    rt_enter_critical();

    /* try to find object */
558
    rt_list_for_each(node, &(information->object_list))
559 560 561 562 563 564 565 566 567 568 569 570 571 572 573
    {
        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;
574
}
D
dzzxzz 已提交
575

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