object.c 14.1 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 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
/*
 * 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. */
};

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

#ifdef RT_USING_HOOK
D
dzzxzz 已提交
119 120 121 122 123
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);
124 125 126 127

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

D
dogandog 已提交
129
/**@{*/
130 131 132 133

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

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

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

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

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

D
dogandog 已提交
201
/**@}*/
202 203 204 205 206
#endif

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

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

D
dogandog 已提交
220
/**@{*/
221

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

233 234
    for (index = 0; index < RT_Object_Info_Unknown; index ++)
        if (rt_object_container[index].type == type) return &rt_object_container[index];
235

236
    return RT_NULL;
237
}
238
RTM_EXPORT(rt_object_get_information);
239

240
/**
241 242
 * This function will initialize an object and add it to object system
 * management.
243 244 245
 *
 * @param object the specified object to be initialized.
 * @param type the object type.
B
bernard.xiong@gmail.com 已提交
246
 * @param name the object name. In system, the object's name must be unique.
247
 */
248 249 250
void rt_object_init(struct rt_object         *object,
                    enum rt_object_class_type type,
                    const char               *name)
251
{
252 253
    register rt_base_t temp;
    struct rt_object_information *information;
254

255
    /* get object information */
256 257
    information = rt_object_get_information(type);
    RT_ASSERT(information != RT_NULL);
258

259
    /* initialize object's parameters */
260

261 262
    /* set object type to static */
    object->type = type | RT_Object_Class_Static;
263

264 265
    /* copy name */
    rt_strncpy(object->name, name, RT_NAME_MAX);
266

267
    RT_OBJECT_HOOK_CALL(rt_object_attach_hook, (object));
268

269 270
    /* lock interrupt */
    temp = rt_hw_interrupt_disable();
271

272 273
    /* insert object into information object list */
    rt_list_insert_after(&(information->object_list), &(object->list));
274

275 276
    /* unlock interrupt */
    rt_hw_interrupt_enable(temp);
277 278 279 280 281 282 283 284 285 286
}

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

289 290
    /* object check */
    RT_ASSERT(object != RT_NULL);
291

292
    RT_OBJECT_HOOK_CALL(rt_object_detach_hook, (object));
293

294 295 296
    /* reset object type */
    object->type = 0;

297 298
    /* lock interrupt */
    temp = rt_hw_interrupt_disable();
299

300 301
    /* remove from old list */
    rt_list_remove(&(object->list));
302

303 304
    /* unlock interrupt */
    rt_hw_interrupt_enable(temp);
305 306 307 308 309 310 311 312 313 314 315
}

#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 已提交
316
rt_object_t rt_object_allocate(enum rt_object_class_type type, const char *name)
317
{
318 319 320
    struct rt_object *object;
    register rt_base_t temp;
    struct rt_object_information *information;
321

322
    RT_DEBUG_NOT_IN_INTERRUPT;
323

324
    /* get object information */
325 326
    information = rt_object_get_information(type);
    RT_ASSERT(information != RT_NULL);
327

B
Bernard Xiong 已提交
328
    object = (struct rt_object *)RT_KERNEL_MALLOC(information->object_size);
329 330 331 332 333
    if (object == RT_NULL)
    {
        /* no memory can be allocated */
        return RT_NULL;
    }
B
Bernard Xiong 已提交
334

335
    /* initialize object's parameters */
336

337 338
    /* set object type */
    object->type = type;
339

340 341
    /* set object flag */
    object->flag = 0;
qiuyiuestc's avatar
qiuyiuestc 已提交
342 343

#ifdef RT_USING_MODULE
344 345 346 347 348
    if (rt_module_self() != RT_NULL)
    {
        object->flag |= RT_OBJECT_FLAG_MODULE;
    }
    object->module_id = (void *)rt_module_self();
qiuyiuestc's avatar
qiuyiuestc 已提交
349 350
#endif

351 352
    /* copy name */
    rt_strncpy(object->name, name, RT_NAME_MAX);
353

354
    RT_OBJECT_HOOK_CALL(rt_object_attach_hook, (object));
355

356 357
    /* lock interrupt */
    temp = rt_hw_interrupt_disable();
358

359 360
    /* insert object into information object list */
    rt_list_insert_after(&(information->object_list), &(object->list));
361

362 363
    /* unlock interrupt */
    rt_hw_interrupt_enable(temp);
364

365 366
    /* return object */
    return object;
367 368 369 370 371 372 373 374 375
}

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

378 379 380
    /* object check */
    RT_ASSERT(object != RT_NULL);
    RT_ASSERT(!(object->type & RT_Object_Class_Static));
381

382
    RT_OBJECT_HOOK_CALL(rt_object_detach_hook, (object));
383

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

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

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

393 394
    /* unlock interrupt */
    rt_hw_interrupt_enable(temp);
395

396 397
    /* free the memory of object */
    RT_KERNEL_FREE(object);
398 399 400 401 402 403 404 405 406 407
}
#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.
 *
408
 * @return RT_TRUE if a system object, RT_FALSE for others.
409
 */
410
rt_bool_t rt_object_is_systemobject(rt_object_t object)
411
{
412 413
    /* object check */
    RT_ASSERT(object != RT_NULL);
414

415 416
    if (object->type & RT_Object_Class_Static)
        return RT_TRUE;
417

418
    return RT_FALSE;
419 420
}

421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436
/**
 * 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;
}

437 438 439 440 441 442 443 444 445 446
/**
 * 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 已提交
447
 * @note this function shall not be invoked in interrupt status.
448
 */
D
dzzxzz 已提交
449
rt_object_t rt_object_find(const char *name, rt_uint8_t type)
450
{
B
Bernard Xiong 已提交
451 452
    struct rt_object *object = RT_NULL;
    struct rt_list_node *node = RT_NULL;
453
    struct rt_object_information *information = RT_NULL;
454 455 456 457 458 459

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

    /* which is invoke in interrupt status */
460 461
    RT_DEBUG_NOT_IN_INTERRUPT;

462 463 464 465
    /* enter critical */
    rt_enter_critical();

    /* try to find object */
466 467
    if (information == RT_NULL)
    {
B
BernardXiong 已提交
468
        information = rt_object_get_information((enum rt_object_class_type)type);
469 470
        RT_ASSERT(information != RT_NULL);
    }
471
    for (node  = information->object_list.next;
472 473
            node != &(information->object_list);
            node  = node->next)
474 475 476 477 478 479 480 481 482 483 484 485 486 487 488
    {
        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;
489
}
D
dzzxzz 已提交
490

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