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

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

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

#ifdef RT_USING_HOOK
D
dzzxzz 已提交
80 81 82 83 84
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);
85 86 87 88

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

D
dogandog 已提交
90
/**@{*/
91 92 93 94

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

/**
 * This function will set a hook function, which will be invoked when object
 * detaches from kernel object system.
B
bernard.xiong 已提交
106
 *
107 108
 * @param hook the hook function
 */
D
dzzxzz 已提交
109
void rt_object_detach_sethook(void (*hook)(struct rt_object *object))
110
{
111
    rt_object_detach_hook = hook;
112 113 114 115 116
}

/**
 * This function will set a hook function, which will be invoked when object
 * is taken from kernel object system.
B
bernard.xiong 已提交
117
 *
B
bernard.xiong@gmail.com 已提交
118
 * The object is taken means:
119 120
 * semaphore - semaphore is taken by thread
 * mutex - mutex is taken by thread
B
bernard.xiong 已提交
121
 * event - event is received by thread
122 123
 * mailbox - mail is received by thread
 * message queue - message is received by thread
B
bernard.xiong 已提交
124
 *
125 126
 * @param hook the hook function
 */
D
dzzxzz 已提交
127
void rt_object_trytake_sethook(void (*hook)(struct rt_object *object))
128
{
129
    rt_object_trytake_hook = hook;
130 131 132 133 134
}

/**
 * This function will set a hook function, which will be invoked when object
 * have been taken from kernel object system.
B
bernard.xiong 已提交
135
 *
B
bernard.xiong@gmail.com 已提交
136
 * The object have been taken means:
137 138
 * semaphore - semaphore have been taken by thread
 * mutex - mutex have been taken by thread
B
bernard.xiong 已提交
139
 * event - event have been received by thread
140 141 142
 * mailbox - mail have been received by thread
 * message queue - message have been received by thread
 * timer - timer is started
B
bernard.xiong 已提交
143
 *
144 145
 * @param hook the hook function
 */
D
dzzxzz 已提交
146
void rt_object_take_sethook(void (*hook)(struct rt_object *object))
147
{
148
    rt_object_take_hook = hook;
149 150 151 152 153
}

/**
 * This function will set a hook function, which will be invoked when object
 * is put to kernel object system.
B
bernard.xiong 已提交
154
 *
155 156
 * @param hook the hook function
 */
D
dzzxzz 已提交
157
void rt_object_put_sethook(void (*hook)(struct rt_object *object))
158
{
159
    rt_object_put_hook = hook;
160 161
}

D
dogandog 已提交
162
/**@}*/
163 164 165 166 167
#endif

/**
 * @ingroup SystemInit
 *
B
bernard.xiong@gmail.com 已提交
168
 * This function will initialize system object management.
169
 *
B
bernard.xiong@gmail.com 已提交
170 171
 * @deprecated since 0.3.0, this function does not need to be invoked
 * in the system initialization.
172 173 174 175 176 177 178 179
 */
void rt_system_object_init(void)
{
}

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

D
dogandog 已提交
181
/**@{*/
182

183 184
/**
 * This function will return the specified type of object information.
B
Bernard Xiong 已提交
185
 *
186 187 188
 * @param type the type of object
 * @return the object type information or RT_NULL
 */
189 190
struct rt_object_information *
rt_object_get_information(enum rt_object_class_type type)
191
{
192
    return &rt_object_container[type];
193
}
194
RTM_EXPORT(rt_object_get_information);
195

196
/**
197 198
 * This function will initialize an object and add it to object system
 * management.
199 200 201
 *
 * @param object the specified object to be initialized.
 * @param type the object type.
B
bernard.xiong@gmail.com 已提交
202
 * @param name the object name. In system, the object's name must be unique.
203
 */
204 205 206
void rt_object_init(struct rt_object         *object,
                    enum rt_object_class_type type,
                    const char               *name)
207
{
208 209
    register rt_base_t temp;
    struct rt_object_information *information;
210

qiuyiuestc's avatar
qiuyiuestc 已提交
211
#ifdef RT_USING_MODULE
212
    /* get module object information */
B
Bernard Xiong 已提交
213
    information = (rt_module_self() != RT_NULL) ?
214
                  &rt_module_self()->module_object[type] : &rt_object_container[type];
qiuyiuestc's avatar
qiuyiuestc 已提交
215
#else
216 217
    /* get object information */
    information = &rt_object_container[type];
qiuyiuestc's avatar
qiuyiuestc 已提交
218
#endif
219

220
    /* initialize object's parameters */
221

222 223
    /* set object type to static */
    object->type = type | RT_Object_Class_Static;
224

225 226
    /* copy name */
    rt_strncpy(object->name, name, RT_NAME_MAX);
227

228
    RT_OBJECT_HOOK_CALL(rt_object_attach_hook, (object));
229

230 231
    /* lock interrupt */
    temp = rt_hw_interrupt_disable();
232

233 234
    /* insert object into information object list */
    rt_list_insert_after(&(information->object_list), &(object->list));
235

236 237
    /* unlock interrupt */
    rt_hw_interrupt_enable(temp);
238 239 240 241 242 243 244 245 246 247
}

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

250 251
    /* object check */
    RT_ASSERT(object != RT_NULL);
252

253
    RT_OBJECT_HOOK_CALL(rt_object_detach_hook, (object));
254

255 256
    /* lock interrupt */
    temp = rt_hw_interrupt_disable();
257

258 259
    /* remove from old list */
    rt_list_remove(&(object->list));
260

261 262
    /* unlock interrupt */
    rt_hw_interrupt_enable(temp);
263 264 265 266 267 268 269 270 271 272 273
}

#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 已提交
274
rt_object_t rt_object_allocate(enum rt_object_class_type type, const char *name)
275
{
276 277 278
    struct rt_object *object;
    register rt_base_t temp;
    struct rt_object_information *information;
279

280
    RT_DEBUG_NOT_IN_INTERRUPT;
281

qiuyiuestc's avatar
qiuyiuestc 已提交
282
#ifdef RT_USING_MODULE
283 284 285 286 287 288
    /*
     * 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 已提交
289
#else
290 291
    /* get object information */
    information = &rt_object_container[type];
qiuyiuestc's avatar
qiuyiuestc 已提交
292
#endif
293

B
Bernard Xiong 已提交
294
    object = (struct rt_object *)RT_KERNEL_MALLOC(information->object_size);
295 296 297 298 299
    if (object == RT_NULL)
    {
        /* no memory can be allocated */
        return RT_NULL;
    }
B
Bernard Xiong 已提交
300

301
    /* initialize object's parameters */
302

303 304
    /* set object type */
    object->type = type;
305

306 307
    /* set object flag */
    object->flag = 0;
qiuyiuestc's avatar
qiuyiuestc 已提交
308 309

#ifdef RT_USING_MODULE
310 311 312 313 314
    if (rt_module_self() != RT_NULL)
    {
        object->flag |= RT_OBJECT_FLAG_MODULE;
    }
    object->module_id = (void *)rt_module_self();
qiuyiuestc's avatar
qiuyiuestc 已提交
315 316
#endif

317 318
    /* copy name */
    rt_strncpy(object->name, name, RT_NAME_MAX);
319

320
    RT_OBJECT_HOOK_CALL(rt_object_attach_hook, (object));
321

322 323
    /* lock interrupt */
    temp = rt_hw_interrupt_disable();
324

325 326
    /* insert object into information object list */
    rt_list_insert_after(&(information->object_list), &(object->list));
327

328 329
    /* unlock interrupt */
    rt_hw_interrupt_enable(temp);
330

331 332
    /* return object */
    return object;
333 334 335 336 337 338 339 340 341
}

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

344 345 346
    /* object check */
    RT_ASSERT(object != RT_NULL);
    RT_ASSERT(!(object->type & RT_Object_Class_Static));
347

348
    RT_OBJECT_HOOK_CALL(rt_object_detach_hook, (object));
349

350 351
    /* lock interrupt */
    temp = rt_hw_interrupt_disable();
352

353 354
    /* remove from old list */
    rt_list_remove(&(object->list));
355

356 357
    /* unlock interrupt */
    rt_hw_interrupt_enable(temp);
358

qiuyiuestc's avatar
qiuyiuestc 已提交
359
#if defined(RT_USING_MODULE) && defined(RT_USING_SLAB)
B
Bernard Xiong 已提交
360
    if (object->flag & RT_OBJECT_FLAG_MODULE)
361 362
        rt_module_free((rt_module_t)object->module_id, object);
    else
qiuyiuestc's avatar
qiuyiuestc 已提交
363 364
#endif

365 366
        /* free the memory of object */
        RT_KERNEL_FREE(object);
367 368 369 370 371 372 373 374 375 376
}
#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.
 *
377
 * @return RT_TRUE if a system object, RT_FALSE for others.
378
 */
379
rt_bool_t rt_object_is_systemobject(rt_object_t object)
380
{
381 382
    /* object check */
    RT_ASSERT(object != RT_NULL);
383

384 385
    if (object->type & RT_Object_Class_Static)
        return RT_TRUE;
386

387
    return RT_FALSE;
388 389
}

390 391 392 393 394 395 396 397 398 399
/**
 * 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 已提交
400
 * @note this function shall not be invoked in interrupt status.
401
 */
D
dzzxzz 已提交
402
rt_object_t rt_object_find(const char *name, rt_uint8_t type)
403
{
B
Bernard Xiong 已提交
404 405
    struct rt_object *object = RT_NULL;
    struct rt_list_node *node = RT_NULL;
406
    struct rt_object_information *information = RT_NULL;
407 408 409 410 411 412

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

    /* which is invoke in interrupt status */
413 414 415 416 417 418 419
    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 已提交
420

421 422 423 424 425 426
        name_ptr = name;
        while ((*name_ptr != '\0') && (*name_ptr != '/'))
            name_ptr ++;

        if (*name_ptr == '/')
        {
427
            struct rt_module *module = RT_NULL;
428 429 430 431 432 433 434 435 436

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

            /* enter critical */
            rt_enter_critical();

            /* find module */
            information = &rt_object_container[RT_Object_Class_Module];
G
Grissiom 已提交
437
            for (node = information->object_list.next;
438 439
                 node != &(information->object_list);
                 node  = node->next)
440 441 442
            {
                object = rt_list_entry(node, struct rt_object, list);
                if ((rt_strncmp(object->name, name, module_name_length) == 0) &&
G
Grissiom 已提交
443
                    (module_name_length == RT_NAME_MAX || object->name[module_name_length] == '\0'))
444 445
                {
                    /* get module */
446
                    module = (struct rt_module *)object;
447 448 449 450 451 452
                    break;
                }
            }
            rt_exit_critical();

            /* there is no this module inside the system */
G
Grissiom 已提交
453
            if (module == RT_NULL) return RT_NULL;
454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470

            /* 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
471 472 473 474 475

    /* enter critical */
    rt_enter_critical();

    /* try to find object */
476
    if (information == RT_NULL) information = &rt_object_container[type];
477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494
    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;
495
}
D
dzzxzz 已提交
496

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