object.c 11.9 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 6 7
 *
 * The license and distribution terms for this file may be
 * found in the file LICENSE in this distribution or at
B
bernard.xiong 已提交
8
 * http://www.rt-thread.org/license/LICENSE
9 10 11 12 13 14 15 16
 *
 * 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 已提交
17
 * 2010-10-26     yi.qiu       add module support in rt_object_allocate and rt_object_free
18 19 20 21 22
 */

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

23 24
#define _OBJ_CONTAINER_LIST_INIT(c)     \
    {&(rt_object_container[c].object_list), &(rt_object_container[c].object_list)}
25 26
struct rt_object_information rt_object_container[RT_Object_Class_Unknown] =
{
27 28
    /* initialize object container - thread */
    {RT_Object_Class_Thread, _OBJ_CONTAINER_LIST_INIT(RT_Object_Class_Thread), sizeof(struct rt_thread)},
29
#ifdef RT_USING_SEMAPHORE
30 31
    /* initialize object container - semaphore */
    {RT_Object_Class_Semaphore, _OBJ_CONTAINER_LIST_INIT(RT_Object_Class_Semaphore), sizeof(struct rt_semaphore)},
32 33
#endif
#ifdef RT_USING_MUTEX
34 35
    /* initialize object container - mutex */
    {RT_Object_Class_Mutex, _OBJ_CONTAINER_LIST_INIT(RT_Object_Class_Mutex), sizeof(struct rt_mutex)},
36 37
#endif
#ifdef RT_USING_EVENT
38 39
    /* initialize object container - event */
    {RT_Object_Class_Event, _OBJ_CONTAINER_LIST_INIT(RT_Object_Class_Event), sizeof(struct rt_event)},
40 41
#endif
#ifdef RT_USING_MAILBOX
42 43
    /* initialize object container - mailbox */
    {RT_Object_Class_MailBox, _OBJ_CONTAINER_LIST_INIT(RT_Object_Class_MailBox), sizeof(struct rt_mailbox)},
44 45
#endif
#ifdef RT_USING_MESSAGEQUEUE
46 47
    /* initialize object container - message queue */
    {RT_Object_Class_MessageQueue, _OBJ_CONTAINER_LIST_INIT(RT_Object_Class_MessageQueue), sizeof(struct rt_messagequeue)},
48
#endif
49
#ifdef RT_USING_MEMHEAP
50 51
    /* initialize object container - memory heap */
    {RT_Object_Class_MemHeap, _OBJ_CONTAINER_LIST_INIT(RT_Object_Class_MemHeap), sizeof(struct rt_memheap)},
52
#endif
53
#ifdef RT_USING_MEMPOOL
54 55
    /* initialize object container - memory pool */
    {RT_Object_Class_MemPool, _OBJ_CONTAINER_LIST_INIT(RT_Object_Class_MemPool), sizeof(struct rt_mempool)},
56 57
#endif
#ifdef RT_USING_DEVICE
58 59
    /* initialize object container - device */
    {RT_Object_Class_Device, _OBJ_CONTAINER_LIST_INIT(RT_Object_Class_Device), sizeof(struct rt_device)},
60
#endif
61 62
    /* initialize object container - timer */
    {RT_Object_Class_Timer, _OBJ_CONTAINER_LIST_INIT(RT_Object_Class_Timer), sizeof(struct rt_timer)},
63
#ifdef RT_USING_MODULE
64 65
    /* initialize object container - module */
    {RT_Object_Class_Module, _OBJ_CONTAINER_LIST_INIT(RT_Object_Class_Module), sizeof(struct rt_module)},
66 67
#endif
};
68 69

#ifdef RT_USING_HOOK
D
dzzxzz 已提交
70 71 72 73 74
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);
75 76 77 78

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

80 81 82 83 84
/*@{*/

/**
 * This function will set a hook function, which will be invoked when object
 * attaches to kernel object system.
B
bernard.xiong 已提交
85
 *
86 87
 * @param hook the hook function
 */
D
dzzxzz 已提交
88
void rt_object_attach_sethook(void (*hook)(struct rt_object *object))
89
{
90
    rt_object_attach_hook = hook;
91 92 93 94 95
}

/**
 * This function will set a hook function, which will be invoked when object
 * detaches from kernel object system.
B
bernard.xiong 已提交
96
 *
97 98
 * @param hook the hook function
 */
D
dzzxzz 已提交
99
void rt_object_detach_sethook(void (*hook)(struct rt_object *object))
100
{
101
    rt_object_detach_hook = hook;
102 103 104 105 106
}

/**
 * This function will set a hook function, which will be invoked when object
 * is taken from kernel object system.
B
bernard.xiong 已提交
107
 *
B
bernard.xiong@gmail.com 已提交
108
 * The object is taken means:
109 110
 * semaphore - semaphore is taken by thread
 * mutex - mutex is taken by thread
B
bernard.xiong 已提交
111
 * event - event is received by thread
112 113
 * mailbox - mail is received by thread
 * message queue - message is received by thread
B
bernard.xiong 已提交
114
 *
115 116
 * @param hook the hook function
 */
D
dzzxzz 已提交
117
void rt_object_trytake_sethook(void (*hook)(struct rt_object *object))
118
{
119
    rt_object_trytake_hook = hook;
120 121 122 123 124
}

/**
 * This function will set a hook function, which will be invoked when object
 * have been taken from kernel object system.
B
bernard.xiong 已提交
125
 *
B
bernard.xiong@gmail.com 已提交
126
 * The object have been taken means:
127 128
 * semaphore - semaphore have been taken by thread
 * mutex - mutex have been taken by thread
B
bernard.xiong 已提交
129
 * event - event have been received by thread
130 131 132
 * mailbox - mail have been received by thread
 * message queue - message have been received by thread
 * timer - timer is started
B
bernard.xiong 已提交
133
 *
134 135
 * @param hook the hook function
 */
D
dzzxzz 已提交
136
void rt_object_take_sethook(void (*hook)(struct rt_object *object))
137
{
138
    rt_object_take_hook = hook;
139 140 141 142 143
}

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

/*@}*/
#endif

/**
 * @ingroup SystemInit
 *
B
bernard.xiong@gmail.com 已提交
158
 * This function will initialize system object management.
159
 *
B
bernard.xiong@gmail.com 已提交
160 161
 * @deprecated since 0.3.0, this function does not need to be invoked
 * in the system initialization.
162 163 164 165 166 167 168 169
 */
void rt_system_object_init(void)
{
}

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

171 172
/*@{*/

173 174 175 176 177 178
/**
 * This function will return the specified type of object information.
 * 
 * @param type the type of object
 * @return the object type information or RT_NULL
 */
179 180
struct rt_object_information *
rt_object_get_information(enum rt_object_class_type type)
181
{
182
    return &rt_object_container[type];
183
}
184
RTM_EXPORT(rt_object_get_information);
185

186
/**
187 188
 * This function will initialize an object and add it to object system
 * management.
189 190 191
 *
 * @param object the specified object to be initialized.
 * @param type the object type.
B
bernard.xiong@gmail.com 已提交
192
 * @param name the object name. In system, the object's name must be unique.
193
 */
194 195 196
void rt_object_init(struct rt_object         *object,
                    enum rt_object_class_type type,
                    const char               *name)
197
{
198 199
    register rt_base_t temp;
    struct rt_object_information *information;
200

qiuyiuestc's avatar
qiuyiuestc 已提交
201
#ifdef RT_USING_MODULE
202 203 204
    /* get module object information */
    information = (rt_module_self() != RT_NULL) ? 
        &rt_module_self()->module_object[type] : &rt_object_container[type];
qiuyiuestc's avatar
qiuyiuestc 已提交
205
#else
206 207
    /* get object information */
    information = &rt_object_container[type];
qiuyiuestc's avatar
qiuyiuestc 已提交
208
#endif
209

210
    /* initialize object's parameters */
211

212 213
    /* set object type to static */
    object->type = type | RT_Object_Class_Static;
214

215 216
    /* copy name */
    rt_strncpy(object->name, name, RT_NAME_MAX);
217

218
    RT_OBJECT_HOOK_CALL(rt_object_attach_hook, (object));
219

220 221
    /* lock interrupt */
    temp = rt_hw_interrupt_disable();
222

223 224
    /* insert object into information object list */
    rt_list_insert_after(&(information->object_list), &(object->list));
225

226 227
    /* unlock interrupt */
    rt_hw_interrupt_enable(temp);
228 229 230 231 232 233 234 235 236 237
}

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

240 241
    /* object check */
    RT_ASSERT(object != RT_NULL);
242

243
    RT_OBJECT_HOOK_CALL(rt_object_detach_hook, (object));
244

245 246
    /* lock interrupt */
    temp = rt_hw_interrupt_disable();
247

248 249
    /* remove from old list */
    rt_list_remove(&(object->list));
250

251 252
    /* unlock interrupt */
    rt_hw_interrupt_enable(temp);
253 254 255 256 257 258 259 260 261 262 263
}

#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 已提交
264
rt_object_t rt_object_allocate(enum rt_object_class_type type, const char *name)
265
{
266 267 268
    struct rt_object *object;
    register rt_base_t temp;
    struct rt_object_information *information;
269

270
    RT_DEBUG_NOT_IN_INTERRUPT;
271

qiuyiuestc's avatar
qiuyiuestc 已提交
272
#ifdef RT_USING_MODULE
273 274 275 276 277 278
    /*
     * 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 已提交
279
#else
280 281
    /* get object information */
    information = &rt_object_container[type];
qiuyiuestc's avatar
qiuyiuestc 已提交
282
#endif
283

284 285 286 287 288 289 290 291
    object = (struct rt_object *)rt_malloc(information->object_size);
    if (object == RT_NULL)
    {
        /* no memory can be allocated */
        return RT_NULL;
    }
    
    /* initialize object's parameters */
292

293 294
    /* set object type */
    object->type = type;
295

296 297
    /* set object flag */
    object->flag = 0;
qiuyiuestc's avatar
qiuyiuestc 已提交
298 299

#ifdef RT_USING_MODULE
300 301 302 303 304
    if (rt_module_self() != RT_NULL)
    {
        object->flag |= RT_OBJECT_FLAG_MODULE;
    }
    object->module_id = (void *)rt_module_self();
qiuyiuestc's avatar
qiuyiuestc 已提交
305 306
#endif

307 308
    /* copy name */
    rt_strncpy(object->name, name, RT_NAME_MAX);
309

310
    RT_OBJECT_HOOK_CALL(rt_object_attach_hook, (object));
311

312 313
    /* lock interrupt */
    temp = rt_hw_interrupt_disable();
314

315 316
    /* insert object into information object list */
    rt_list_insert_after(&(information->object_list), &(object->list));
317

318 319
    /* unlock interrupt */
    rt_hw_interrupt_enable(temp);
320

321 322
    /* return object */
    return object;
323 324 325 326 327 328 329 330 331
}

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

334 335 336
    /* object check */
    RT_ASSERT(object != RT_NULL);
    RT_ASSERT(!(object->type & RT_Object_Class_Static));
337

338
    RT_OBJECT_HOOK_CALL(rt_object_detach_hook, (object));
339

340 341
    /* lock interrupt */
    temp = rt_hw_interrupt_disable();
342

343 344
    /* remove from old list */
    rt_list_remove(&(object->list));
345

346 347
    /* unlock interrupt */
    rt_hw_interrupt_enable(temp);
348

qiuyiuestc's avatar
qiuyiuestc 已提交
349
#if defined(RT_USING_MODULE) && defined(RT_USING_SLAB)
350 351 352
    if (object->flag & RT_OBJECT_FLAG_MODULE) 
        rt_module_free((rt_module_t)object->module_id, object);
    else
qiuyiuestc's avatar
qiuyiuestc 已提交
353 354
#endif

355 356
    /* free the memory of object */
    rt_free(object);
357 358 359 360 361 362 363 364 365 366
}
#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.
 *
367
 * @return RT_TRUE if a system object, RT_FALSE for others.
368
 */
369
rt_bool_t rt_object_is_systemobject(rt_object_t object)
370
{
371 372
    /* object check */
    RT_ASSERT(object != RT_NULL);
373

374 375
    if (object->type & RT_Object_Class_Static)
        return RT_TRUE;
376

377
    return RT_FALSE;
378 379
}

380 381 382 383 384 385 386 387 388 389
/**
 * 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 已提交
390
 * @note this function shall not be invoked in interrupt status.
391
 */
D
dzzxzz 已提交
392
rt_object_t rt_object_find(const char *name, rt_uint8_t type)
393
{
394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429
    struct rt_object *object;
    struct rt_list_node *node;
    struct rt_object_information *information;
    extern volatile rt_uint8_t rt_interrupt_nest;

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

    /* which is invoke in interrupt status */
    if (rt_interrupt_nest != 0)
        RT_ASSERT(0);

    /* enter critical */
    rt_enter_critical();

    /* try to find object */
    information = &rt_object_container[type];
    for (node  = information->object_list.next;
         node != &(information->object_list);
         node  = node->next)
    {
        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;
430
}
D
dzzxzz 已提交
431

432
/*@}*/