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

/**
 * 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 102 103 104 105 106
{
	rt_object_detach_hook = hook;
}

/**
 * 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 120 121 122 123 124
{
	rt_object_trytake_hook = hook;
}

/**
 * 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 139 140 141 142 143
{
	rt_object_take_hook = hook;
}

/**
 * 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 150 151 152 153 154 155 156 157
{
	rt_object_put_hook = hook;
}

/*@}*/
#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 179 180 181 182
/**
 * This function will return the specified type of object information.
 * 
 * @param type the type of object
 * @return the object type information or RT_NULL
 */
struct rt_object_information *rt_object_get_information(enum rt_object_class_type type)
{
	return &rt_object_container[type];
}
183
RTM_EXPORT(rt_object_get_information);
184

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

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

B
bernard.xiong@gmail.com 已提交
206
	/* initialize object's parameters */
207 208 209 210 211

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

	/* copy name */
212
	rt_strncpy(object->name, name, RT_NAME_MAX);
213

214
	RT_OBJECT_HOOK_CALL(rt_object_attach_hook, (object));
215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238

	/* lock interrupt */
	temp = rt_hw_interrupt_disable();

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

	/* unlock interrupt */
	rt_hw_interrupt_enable(temp);
}

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

	/* object check */
	RT_ASSERT(object != RT_NULL);

239
	RT_OBJECT_HOOK_CALL(rt_object_detach_hook, (object));
240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259

	/* lock interrupt */
	temp = rt_hw_interrupt_disable();

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

	/* unlock interrupt */
	rt_hw_interrupt_enable(temp);
}

#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 已提交
260
rt_object_t rt_object_allocate(enum rt_object_class_type type, const char *name)
261
{
D
dzzxzz 已提交
262
	struct rt_object *object;
263
	register rt_base_t temp;
D
dzzxzz 已提交
264
	struct rt_object_information *information;
265

266
	RT_DEBUG_NOT_IN_INTERRUPT;
267

qiuyiuestc's avatar
qiuyiuestc 已提交
268
#ifdef RT_USING_MODULE
qiuyiuestc's avatar
qiuyiuestc 已提交
269 270
	/* get module object information, module object should be managed by kernel object container */
	information = (rt_module_self() != RT_NULL && (type != RT_Object_Class_Module)) ? 
qiuyiuestc's avatar
qiuyiuestc 已提交
271
		&rt_module_self()->module_object[type] : &rt_object_container[type];
qiuyiuestc's avatar
qiuyiuestc 已提交
272
#else
273
	/* get object information */
qiuyiuestc's avatar
qiuyiuestc 已提交
274
	information = &rt_object_container[type];
qiuyiuestc's avatar
qiuyiuestc 已提交
275
#endif
276

D
dzzxzz 已提交
277
	object = (struct rt_object *)rt_malloc(information->object_size);
278 279 280 281 282
	if (object == RT_NULL)
	{
		/* no memory can be allocated */
		return RT_NULL;
	}
qiuyiuestc's avatar
qiuyiuestc 已提交
283
	
B
bernard.xiong@gmail.com 已提交
284
	/* initialize object's parameters */
285 286 287 288

	/* set object type */
	object->type = type;

qiuyiuestc's avatar
qiuyiuestc 已提交
289 290 291 292
	/* set object flag */
	object->flag = 0;

#ifdef RT_USING_MODULE
D
dzzxzz 已提交
293
	if (rt_module_self() != RT_NULL)
qiuyiuestc's avatar
qiuyiuestc 已提交
294 295
	{
		object->flag |= RT_OBJECT_FLAG_MODULE;
qiuyiuestc's avatar
qiuyiuestc 已提交
296
	}
D
dzzxzz 已提交
297
	object->module_id = (void *)rt_module_self();
qiuyiuestc's avatar
qiuyiuestc 已提交
298 299
#endif

300
	/* copy name */
301
	rt_strncpy(object->name, name, RT_NAME_MAX);
302

303
	RT_OBJECT_HOOK_CALL(rt_object_attach_hook, (object));
304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330

	/* lock interrupt */
	temp = rt_hw_interrupt_disable();

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

	/* unlock interrupt */
	rt_hw_interrupt_enable(temp);

	/* return object */
	return object;
}

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

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

331
	RT_OBJECT_HOOK_CALL(rt_object_detach_hook, (object));
332 333 334 335 336 337 338 339 340 341

	/* lock interrupt */
	temp = rt_hw_interrupt_disable();

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

	/* unlock interrupt */
	rt_hw_interrupt_enable(temp);

qiuyiuestc's avatar
qiuyiuestc 已提交
342
#if defined(RT_USING_MODULE) && defined(RT_USING_SLAB)
D
dzzxzz 已提交
343
	if (object->flag & RT_OBJECT_FLAG_MODULE) 
qiuyiuestc's avatar
qiuyiuestc 已提交
344 345 346 347
		rt_module_free((rt_module_t)object->module_id, object);
	else
#endif

348 349 350 351 352 353 354 355 356 357 358 359
	/* free the memory of object */
	rt_free(object);
}
#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.
 *
360
 * @return RT_TRUE if a system object, RT_FALSE for others.
361
 */
362
rt_bool_t rt_object_is_systemobject(rt_object_t object)
363 364 365 366
{
	/* object check */
	RT_ASSERT(object != RT_NULL);

D
dzzxzz 已提交
367
	if (object->type & RT_Object_Class_Static)
368
		return RT_TRUE;
369

370
	return RT_FALSE;
371 372
}

373 374 375 376 377 378 379 380 381 382
/**
 * 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 已提交
383
 * @note this function shall not be invoked in interrupt status.
384
 */
D
dzzxzz 已提交
385
rt_object_t rt_object_find(const char *name, rt_uint8_t type)
386
{
D
dzzxzz 已提交
387 388
	struct rt_object *object;
	struct rt_list_node *node;
389 390 391 392
	struct rt_object_information *information;
	extern volatile rt_uint8_t rt_interrupt_nest;

	/* parameter check */
D
dzzxzz 已提交
393
	if ((name == RT_NULL) || (type > RT_Object_Class_Unknown))
394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412
		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();

413
			return object;
414 415 416 417 418 419 420 421
		}
	}

	/* leave critical */
	rt_exit_critical();

	return RT_NULL;
}
D
dzzxzz 已提交
422

423
/*@}*/