object.c 14.6 KB
Newer Older
1 2 3
/*
 * File      : object.c
 * This file is part of RT-Thread RTOS
D
dzzxzz 已提交
4
 * COPYRIGHT (C) 2006 - 2012, RT-Thread Development Team
5
 *
B
Bernard Xiong 已提交
6 7 8 9 10 11 12 13 14 15 16 17 18
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 20 21 22 23 24 25 26
 *
 * 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 已提交
27
 * 2010-10-26     yi.qiu       add module support in rt_object_allocate and rt_object_free
28
 * 2017-12-10     Bernard      Add object_info enum.
29
 * 2018-01-25     Bernard      Fix the object find issue when enable MODULE.
30 31 32 33 34
 */

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

35 36 37 38
#ifdef RT_USING_MODULE
#include <dlmodule.h>
#endif

39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
/*
 * 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. */
};

76 77
#define _OBJ_CONTAINER_LIST_INIT(c)     \
    {&(rt_object_container[c].object_list), &(rt_object_container[c].object_list)}
78
static struct rt_object_information rt_object_container[RT_Object_Info_Unknown] =
79
{
80
    /* initialize object container - thread */
81
    {RT_Object_Class_Thread, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Thread), sizeof(struct rt_thread)},
82
#ifdef RT_USING_SEMAPHORE
83
    /* initialize object container - semaphore */
84
    {RT_Object_Class_Semaphore, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Semaphore), sizeof(struct rt_semaphore)},
85 86
#endif
#ifdef RT_USING_MUTEX
87
    /* initialize object container - mutex */
88
    {RT_Object_Class_Mutex, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Mutex), sizeof(struct rt_mutex)},
89 90
#endif
#ifdef RT_USING_EVENT
91
    /* initialize object container - event */
92
    {RT_Object_Class_Event, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Event), sizeof(struct rt_event)},
93 94
#endif
#ifdef RT_USING_MAILBOX
95
    /* initialize object container - mailbox */
96
    {RT_Object_Class_MailBox, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MailBox), sizeof(struct rt_mailbox)},
97 98
#endif
#ifdef RT_USING_MESSAGEQUEUE
99
    /* initialize object container - message queue */
100
    {RT_Object_Class_MessageQueue, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MessageQueue), sizeof(struct rt_messagequeue)},
101
#endif
102
#ifdef RT_USING_MEMHEAP
103
    /* initialize object container - memory heap */
104
    {RT_Object_Class_MemHeap, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MemHeap), sizeof(struct rt_memheap)},
105
#endif
106
#ifdef RT_USING_MEMPOOL
107
    /* initialize object container - memory pool */
108
    {RT_Object_Class_MemPool, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MemPool), sizeof(struct rt_mempool)},
109 110
#endif
#ifdef RT_USING_DEVICE
111
    /* initialize object container - device */
112
    {RT_Object_Class_Device, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Device), sizeof(struct rt_device)},
113
#endif
114
    /* initialize object container - timer */
115
    {RT_Object_Class_Timer, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Timer), sizeof(struct rt_timer)},
116
#ifdef RT_USING_MODULE
117
    /* initialize object container - module */
118
    {RT_Object_Class_Module, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Module), sizeof(struct rt_dlmodule)},
119 120
#endif
};
121 122

#ifdef RT_USING_HOOK
D
dzzxzz 已提交
123 124 125 126 127
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);
128 129 130 131

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

D
dogandog 已提交
133
/**@{*/
134 135 136 137

/**
 * This function will set a hook function, which will be invoked when object
 * attaches to kernel object system.
B
bernard.xiong 已提交
138
 *
139 140
 * @param hook the hook function
 */
D
dzzxzz 已提交
141
void rt_object_attach_sethook(void (*hook)(struct rt_object *object))
142
{
143
    rt_object_attach_hook = hook;
144 145 146 147 148
}

/**
 * This function will set a hook function, which will be invoked when object
 * detaches from kernel object system.
B
bernard.xiong 已提交
149
 *
150 151
 * @param hook the hook function
 */
D
dzzxzz 已提交
152
void rt_object_detach_sethook(void (*hook)(struct rt_object *object))
153
{
154
    rt_object_detach_hook = hook;
155 156 157 158 159
}

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

/**
 * This function will set a hook function, which will be invoked when object
 * have been taken from kernel object system.
B
bernard.xiong 已提交
178
 *
B
bernard.xiong@gmail.com 已提交
179
 * The object have been taken means:
180 181
 * semaphore - semaphore have been taken by thread
 * mutex - mutex have been taken by thread
B
bernard.xiong 已提交
182
 * event - event have been received by thread
183 184 185
 * mailbox - mail have been received by thread
 * message queue - message have been received by thread
 * timer - timer is started
B
bernard.xiong 已提交
186
 *
187 188
 * @param hook the hook function
 */
D
dzzxzz 已提交
189
void rt_object_take_sethook(void (*hook)(struct rt_object *object))
190
{
191
    rt_object_take_hook = hook;
192 193 194 195 196
}

/**
 * This function will set a hook function, which will be invoked when object
 * is put to kernel object system.
B
bernard.xiong 已提交
197
 *
198 199
 * @param hook the hook function
 */
D
dzzxzz 已提交
200
void rt_object_put_sethook(void (*hook)(struct rt_object *object))
201
{
202
    rt_object_put_hook = hook;
203 204
}

D
dogandog 已提交
205
/**@}*/
206 207 208 209 210
#endif

/**
 * @ingroup SystemInit
 *
B
bernard.xiong@gmail.com 已提交
211
 * This function will initialize system object management.
212
 *
B
bernard.xiong@gmail.com 已提交
213 214
 * @deprecated since 0.3.0, this function does not need to be invoked
 * in the system initialization.
215 216 217 218 219 220 221 222
 */
void rt_system_object_init(void)
{
}

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

D
dogandog 已提交
224
/**@{*/
225

226 227
/**
 * This function will return the specified type of object information.
B
Bernard Xiong 已提交
228
 *
229 230 231
 * @param type the type of object
 * @return the object type information or RT_NULL
 */
232 233
struct rt_object_information *
rt_object_get_information(enum rt_object_class_type type)
234
{
235
    int index;
236

237 238
    for (index = 0; index < RT_Object_Info_Unknown; index ++)
        if (rt_object_container[index].type == type) return &rt_object_container[index];
239

240
    return RT_NULL;
241
}
242
RTM_EXPORT(rt_object_get_information);
243

244
/**
245 246
 * This function will initialize an object and add it to object system
 * management.
247 248 249
 *
 * @param object the specified object to be initialized.
 * @param type the object type.
B
bernard.xiong@gmail.com 已提交
250
 * @param name the object name. In system, the object's name must be unique.
251
 */
252 253 254
void rt_object_init(struct rt_object         *object,
                    enum rt_object_class_type type,
                    const char               *name)
255
{
256 257
    register rt_base_t temp;
    struct rt_object_information *information;
258 259 260
#ifdef RT_USING_MODULE
    struct rt_dlmodule *module = dlmodule_self();
#endif
261

262
    /* get object information */
263 264
    information = rt_object_get_information(type);
    RT_ASSERT(information != RT_NULL);
265

266
    /* initialize object's parameters */
267

268 269
    /* set object type to static */
    object->type = type | RT_Object_Class_Static;
270

271 272
    /* copy name */
    rt_strncpy(object->name, name, RT_NAME_MAX);
273

274
    RT_OBJECT_HOOK_CALL(rt_object_attach_hook, (object));
275

276 277
    /* lock interrupt */
    temp = rt_hw_interrupt_disable();
278

279 280 281 282 283 284 285 286 287 288 289 290
#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));
    }
291

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

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

306 307
    /* object check */
    RT_ASSERT(object != RT_NULL);
308

309
    RT_OBJECT_HOOK_CALL(rt_object_detach_hook, (object));
310

311 312 313
    /* reset object type */
    object->type = 0;

314 315
    /* lock interrupt */
    temp = rt_hw_interrupt_disable();
316

317 318
    /* remove from old list */
    rt_list_remove(&(object->list));
319

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

#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 已提交
333
rt_object_t rt_object_allocate(enum rt_object_class_type type, const char *name)
334
{
335 336 337
    struct rt_object *object;
    register rt_base_t temp;
    struct rt_object_information *information;
338 339 340
#ifdef RT_USING_MODULE
    struct rt_dlmodule *module = dlmodule_self();
#endif
341

342
    RT_DEBUG_NOT_IN_INTERRUPT;
343

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

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

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

358
    /* initialize object's parameters */
359

360 361
    /* set object type */
    object->type = type;
362

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

366 367
    /* copy name */
    rt_strncpy(object->name, name, RT_NAME_MAX);
368

369
    RT_OBJECT_HOOK_CALL(rt_object_attach_hook, (object));
370

371 372
    /* lock interrupt */
    temp = rt_hw_interrupt_disable();
373

374 375 376 377 378 379 380 381 382 383 384 385
#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));
    }
386

387 388
    /* unlock interrupt */
    rt_hw_interrupt_enable(temp);
389

390 391
    /* return object */
    return object;
392 393 394 395 396 397 398 399 400
}

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

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

407
    RT_OBJECT_HOOK_CALL(rt_object_detach_hook, (object));
408

409 410 411
    /* reset object type */
    object->type = 0;

412 413
    /* lock interrupt */
    temp = rt_hw_interrupt_disable();
414

415 416
    /* remove from old list */
    rt_list_remove(&(object->list));
417

418 419
    /* unlock interrupt */
    rt_hw_interrupt_enable(temp);
420

421 422
    /* free the memory of object */
    RT_KERNEL_FREE(object);
423 424 425 426 427 428 429 430 431 432
}
#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.
 *
433
 * @return RT_TRUE if a system object, RT_FALSE for others.
434
 */
435
rt_bool_t rt_object_is_systemobject(rt_object_t object)
436
{
437 438
    /* object check */
    RT_ASSERT(object != RT_NULL);
439

440 441
    if (object->type & RT_Object_Class_Static)
        return RT_TRUE;
442

443
    return RT_FALSE;
444 445
}

446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461
/**
 * 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;
}

462 463 464 465 466 467 468 469 470 471
/**
 * 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 已提交
472
 * @note this function shall not be invoked in interrupt status.
473
 */
D
dzzxzz 已提交
474
rt_object_t rt_object_find(const char *name, rt_uint8_t type)
475
{
B
Bernard Xiong 已提交
476 477
    struct rt_object *object = RT_NULL;
    struct rt_list_node *node = RT_NULL;
478
    struct rt_object_information *information = RT_NULL;
479 480 481 482 483 484

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

    /* which is invoke in interrupt status */
485 486
    RT_DEBUG_NOT_IN_INTERRUPT;

487 488 489 490
    /* enter critical */
    rt_enter_critical();

    /* try to find object */
491 492
    if (information == RT_NULL)
    {
B
BernardXiong 已提交
493
        information = rt_object_get_information((enum rt_object_class_type)type);
494 495
        RT_ASSERT(information != RT_NULL);
    }
496
    for (node  = information->object_list.next;
497 498
            node != &(information->object_list);
            node  = node->next)
499 500 501 502 503 504 505 506 507 508 509 510 511 512 513
    {
        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;
514
}
D
dzzxzz 已提交
515

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