object.c 14.2 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

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 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

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
    /* free the memory of object */
B
Bernard Xiong 已提交
366
    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
{
404 405
    struct rt_object *object;
    struct rt_list_node *node;
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 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470
    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;
        
        name_ptr = name;
        while ((*name_ptr != '\0') && (*name_ptr != '/'))
            name_ptr ++;

        if (*name_ptr == '/')
        {
            struct rt_module* module = RT_NULL;

            /* 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];
            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, module_name_length) == 0) &&
                    module_name_length == RT_NAME_MAX || object->name[module_name_length] == '\0')
                {
                    /* get module */
                    module = (struct rt_module*)object;
                    break;
                }
            }
            rt_exit_critical();

            /* there is no this module inside the system */
            if (module == RT_NULL) return RT_NULL; 

            /* 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

497
/*@}*/