object.c 16.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 30 31 32 33
 */

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

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 62 63 64 65 66 67 68 69 70
/*
 * 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. */
};

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

qiuyiuestc's avatar
qiuyiuestc 已提交
254
#ifdef RT_USING_MODULE
255
    /* get module object information */
B
Bernard Xiong 已提交
256
    information = (rt_module_self() != RT_NULL) ?
257
                  &rt_module_self()->module_object[type] : &rt_object_container[type];
qiuyiuestc's avatar
qiuyiuestc 已提交
258
#else
259
    /* get object information */
260 261
    information = rt_object_get_information(type);
    RT_ASSERT(information != RT_NULL);
qiuyiuestc's avatar
qiuyiuestc 已提交
262
#endif
263

264
    /* initialize object's parameters */
265

266 267
    /* set object type to static */
    object->type = type | RT_Object_Class_Static;
268

269 270
    /* copy name */
    rt_strncpy(object->name, name, RT_NAME_MAX);
271

272
    RT_OBJECT_HOOK_CALL(rt_object_attach_hook, (object));
273

274 275
    /* lock interrupt */
    temp = rt_hw_interrupt_disable();
276

277 278
    /* insert object into information object list */
    rt_list_insert_after(&(information->object_list), &(object->list));
279

280 281
    /* unlock interrupt */
    rt_hw_interrupt_enable(temp);
282 283 284 285 286 287 288 289 290 291
}

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

294 295
    /* object check */
    RT_ASSERT(object != RT_NULL);
296

297
    RT_OBJECT_HOOK_CALL(rt_object_detach_hook, (object));
298

299 300
    /* lock interrupt */
    temp = rt_hw_interrupt_disable();
301

302 303
    /* remove from old list */
    rt_list_remove(&(object->list));
304

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

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

324
    RT_DEBUG_NOT_IN_INTERRUPT;
325

qiuyiuestc's avatar
qiuyiuestc 已提交
326
#ifdef RT_USING_MODULE
327 328 329 330 331 332
    /*
     * get module object information,
     * module object should be managed by kernel object container
     */
    information = (rt_module_self() != RT_NULL && (type != RT_Object_Class_Module)) ?
                  &rt_module_self()->module_object[type] : &rt_object_container[type];
qiuyiuestc's avatar
qiuyiuestc 已提交
333
#else
334
    /* get object information */
335 336
    information = rt_object_get_information(type);
    RT_ASSERT(information != RT_NULL);
qiuyiuestc's avatar
qiuyiuestc 已提交
337
#endif
338

B
Bernard Xiong 已提交
339
    object = (struct rt_object *)RT_KERNEL_MALLOC(information->object_size);
340 341 342 343 344
    if (object == RT_NULL)
    {
        /* no memory can be allocated */
        return RT_NULL;
    }
B
Bernard Xiong 已提交
345

346
    /* initialize object's parameters */
347

348 349
    /* set object type */
    object->type = type;
350

351 352
    /* set object flag */
    object->flag = 0;
qiuyiuestc's avatar
qiuyiuestc 已提交
353 354

#ifdef RT_USING_MODULE
355 356 357 358 359
    if (rt_module_self() != RT_NULL)
    {
        object->flag |= RT_OBJECT_FLAG_MODULE;
    }
    object->module_id = (void *)rt_module_self();
qiuyiuestc's avatar
qiuyiuestc 已提交
360 361
#endif

362 363
    /* copy name */
    rt_strncpy(object->name, name, RT_NAME_MAX);
364

365
    RT_OBJECT_HOOK_CALL(rt_object_attach_hook, (object));
366

367 368
    /* lock interrupt */
    temp = rt_hw_interrupt_disable();
369

370 371
    /* insert object into information object list */
    rt_list_insert_after(&(information->object_list), &(object->list));
372

373 374
    /* unlock interrupt */
    rt_hw_interrupt_enable(temp);
375

376 377
    /* return object */
    return object;
378 379 380 381 382 383 384 385 386
}

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

389 390 391
    /* object check */
    RT_ASSERT(object != RT_NULL);
    RT_ASSERT(!(object->type & RT_Object_Class_Static));
392

393
    RT_OBJECT_HOOK_CALL(rt_object_detach_hook, (object));
394

395 396
    /* lock interrupt */
    temp = rt_hw_interrupt_disable();
397

398 399
    /* remove from old list */
    rt_list_remove(&(object->list));
400

401 402
    /* unlock interrupt */
    rt_hw_interrupt_enable(temp);
403

qiuyiuestc's avatar
qiuyiuestc 已提交
404
#if defined(RT_USING_MODULE) && defined(RT_USING_SLAB)
B
Bernard Xiong 已提交
405
    if (object->flag & RT_OBJECT_FLAG_MODULE)
406 407
        rt_module_free((rt_module_t)object->module_id, object);
    else
qiuyiuestc's avatar
qiuyiuestc 已提交
408 409
#endif

410 411
        /* free the memory of object */
        RT_KERNEL_FREE(object);
412 413 414 415 416 417 418 419 420 421
}
#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.
 *
422
 * @return RT_TRUE if a system object, RT_FALSE for others.
423
 */
424
rt_bool_t rt_object_is_systemobject(rt_object_t object)
425
{
426 427
    /* object check */
    RT_ASSERT(object != RT_NULL);
428

429 430
    if (object->type & RT_Object_Class_Static)
        return RT_TRUE;
431

432
    return RT_FALSE;
433 434
}

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

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

    /* which is invoke in interrupt status */
458 459 460 461 462 463 464
    RT_DEBUG_NOT_IN_INTERRUPT;

#ifdef RT_USING_MODULE
    /* check whether to find a object inside a module. */
    {
        const char *name_ptr;
        int module_name_length;
G
Grissiom 已提交
465

466 467 468 469 470 471
        name_ptr = name;
        while ((*name_ptr != '\0') && (*name_ptr != '/'))
            name_ptr ++;

        if (*name_ptr == '/')
        {
472
            struct rt_module *module = RT_NULL;
473 474 475 476 477 478 479 480

            /* get the name length of module */
            module_name_length = name_ptr - name;

            /* enter critical */
            rt_enter_critical();

            /* find module */
481 482 483
            information = rt_object_get_information(RT_Object_Class_Module);
            RT_ASSERT(information != RT_NULL);

G
Grissiom 已提交
484
            for (node = information->object_list.next;
485 486
                    node != &(information->object_list);
                    node  = node->next)
487 488 489
            {
                object = rt_list_entry(node, struct rt_object, list);
                if ((rt_strncmp(object->name, name, module_name_length) == 0) &&
490
                        (module_name_length == RT_NAME_MAX || object->name[module_name_length] == '\0'))
491 492
                {
                    /* get module */
493
                    module = (struct rt_module *)object;
494 495 496 497 498 499
                    break;
                }
            }
            rt_exit_critical();

            /* there is no this module inside the system */
G
Grissiom 已提交
500
            if (module == RT_NULL) return RT_NULL;
501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517

            /* get the object pool of module */
            information = &(module->module_object[type]);

            /* get object name */
            while ((*name_ptr == '/') && (*name_ptr != '\0')) name_ptr ++;
            if (*name_ptr == '\0')
            {
                if (type == RT_Object_Class_Module) return object;
                return RT_NULL;
            }

            /* point to the object name */
            name = name_ptr;
        }
    }
#endif
518 519 520 521 522

    /* enter critical */
    rt_enter_critical();

    /* try to find object */
523 524 525 526 527
    if (information == RT_NULL)
    {
        information = rt_object_get_information(type);
        RT_ASSERT(information != RT_NULL);
    }
528
    for (node  = information->object_list.next;
529 530
            node != &(information->object_list);
            node  = node->next)
531 532 533 534 535 536 537 538 539 540 541 542 543 544 545
    {
        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;
546
}
D
dzzxzz 已提交
547

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