⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ipc.c.svn-base

📁 RT-Thread是发展中的下一代微内核嵌入式实时操作系统
💻 SVN-BASE
📖 第 1 页 / 共 4 页
字号:
/* * File      : ipc.c * This file is part of RT-Thread RTOS * COPYRIGHT (C) 2006, RT-Thread Development Team * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at * http://openlab.rt-thread.com/license/LICENSE * * Change Logs: * Date           Author       Notes * 2006-03-14     Bernard      the first version * 2006-04-25     Bernard      implement semaphore * 2006-05-03     Bernard      add IPC_DEBUG *                             modify the type of IPC waiting time to rt_int32 * 2006-05-10     Bernard      fix the semaphore take bug and add IPC object * 2006-05-12     Bernard      implement mailbox and message queue * 2006-05-20     Bernard      implement mutex * 2006-05-23     Bernard      implement fast event * 2006-05-24     Bernard      implement event * 2006-06-03     Bernard      fix the thread timer init bug * 2006-06-05     Bernard      fix the mutex release bug * 2006-06-07     Bernard      fix the message queue send bug * 2006-08-04     Bernard      add hook support */#include <rtthread.h>#include <rthw.h>#include "kservice.h"#ifdef RT_USING_HOOKextern void (*rt_object_trytake_hook)(struct rt_object* object);extern void (*rt_object_take_hook)(struct rt_object* object);extern void (*rt_object_put_hook)(struct rt_object* object);#endif/** * @addtogroup IPC *//*@{*//* #define IPC_DEBUG *//** * This function will initialize an IPC object * * @param ipc the IPC object * * @return the operation status, RT_EOK on successful */rt_inline rt_err_t rt_ipc_object_init(struct rt_ipc_object *ipc){	/* init ipc object */	rt_list_init(&(ipc->suspend_thread));	ipc->suspend_thread_count = 0;	return RT_EOK;}/** * This function will suspend a thread for a specified IPC object and put the  * thread into suspend queue of IPC object * * @param ipc the IPC object * @param thread the thread object to be suspended * * @return the operation status, RT_EOK on successful */rt_inline rt_err_t rt_ipc_object_suspend(struct rt_ipc_object *ipc, struct rt_thread *thread){	/* suspend thread */	rt_thread_suspend(thread);	ipc->suspend_thread_count ++;	switch (ipc->parent.flag)	{	case RT_IPC_FLAG_FIFO:		rt_list_insert_after(&(ipc->suspend_thread), &(thread->tlist));		break;	case RT_IPC_FLAG_PRIO:		{			struct rt_list_node* n;			struct rt_thread* sthread;			/* find a suitable position */			for (n = ipc->suspend_thread.next; n != &(ipc->suspend_thread); 				n = n->next)			{				sthread = rt_list_entry(n, struct rt_thread, tlist);				/* find out */				if (thread->current_priority < sthread->current_priority) break;			}			rt_list_insert_before(&(ipc->suspend_thread), &(thread->tlist));		}		break;	}	return RT_EOK;}/** * This function will resume a thread from an IPC object: * - remove the thread from suspend queue of IPC object * - put the thread into system ready queue * * @param ipc the IPC object * * @return the operation status, RT_EOK on successful */rt_inline rt_err_t rt_ipc_object_resume(struct rt_ipc_object* ipc){	struct rt_thread *thread;	/* get thread entry */	thread = rt_list_entry(ipc->suspend_thread.next, struct rt_thread, tlist);#ifdef IPC_DEBUG	rt_kprintf("resume thread:%s\n", thread->name);#endif	/* resume it */	rt_thread_resume(thread);	/* decrease suspended thread count */	ipc->suspend_thread_count --;	return RT_EOK;}/** * This function will resume all suspended threads in an IPC object. * * @param ipc the IPC object * * @return the operation status, RT_EOK on successful */rt_inline rt_err_t rt_ipc_object_resume_all(struct rt_ipc_object* ipc){	struct rt_thread* thread;	register rt_ubase_t temp;	/* wakeup all suspend threads */	while (!rt_list_isempty(&(ipc->suspend_thread)))	{		/* disable interrupt */		temp = rt_hw_interrupt_disable();		/* get next suspend thread */		thread = rt_list_entry(ipc->suspend_thread.next, struct rt_thread, tlist);		/* set error code to RT_ERROR */		thread->error = -RT_ERROR;		/*		 * resume thread		 * In rt_thread_resume function, it will remove current thread from 		 * suspend list		 */		rt_thread_resume(thread);		/* decrease suspended thread count */		ipc->suspend_thread_count --;		/* enable interrupt */		rt_hw_interrupt_enable(temp);	}	return RT_EOK;}#ifdef RT_USING_SEMAPHORE/** * This function will initialize a semaphore and put it under control of resource * management. * * @param sem the semaphore object * @param name the name of semaphore * @param value the init value of semaphore * @param flag the flag of semaphore * * @return the operation status, RT_EOK on successful */rt_err_t rt_sem_init (rt_sem_t sem, const char* name, rt_uint32 value, rt_uint8 flag){	RT_ASSERT(sem != RT_NULL);	/* init object */	rt_object_init(&(sem->parent.parent), RT_Object_Class_Semaphore, name);	/* init ipc object */	rt_ipc_object_init(&(sem->parent));	/* set init value */	sem->value	= value;	/* set parent */	sem->parent.parent.flag = flag;	return RT_EOK;}/** * This function will detach a semaphore from resource management * * @param sem the semaphore object * * @return the operation status, RT_EOK on successful * * @see rt_sem_delete */rt_err_t rt_sem_detach (rt_sem_t sem){	RT_ASSERT(sem != RT_NULL);	/* wakeup all suspend threads */	rt_ipc_object_resume_all(&(sem->parent));	/* detach semaphore object */	rt_object_detach(&(sem->parent.parent));	return RT_EOK;}#ifdef RT_USING_HEAP/** * This function will create a semaphore from system resource * * @param name the name of semaphore * @param value the init value of semaphore * @param flag the flag of semaphore * * @return the created semaphore, RT_NULL on error happen * * @see rt_sem_init */rt_sem_t rt_sem_create (const char* name, rt_uint32 value, rt_uint8 flag){	rt_sem_t sem;	/* allocate object */	sem = (rt_sem_t) rt_object_allocate(RT_Object_Class_Semaphore, name);	if (sem == RT_NULL) return sem;	/* init ipc object */	rt_ipc_object_init(&(sem->parent));	/* set init value */	sem->value	= value;	/* set parent */	sem->parent.parent.flag = flag;	return sem;}/** * This function will delete a semaphore object and release the memory * * @param sem the semaphore object * * @return the error code * * @see rt_sem_detach */rt_err_t rt_sem_delete (rt_sem_t sem){	RT_ASSERT(sem != RT_NULL);	/* wakeup all suspend threads */	rt_ipc_object_resume_all(&(sem->parent));	/* delete semaphore object */	rt_object_delete(&(sem->parent.parent));	return RT_EOK;}#endif/** * This function will take a semaphore, if the semaphore is unavailable, the  * thread shall wait for a specified time. * * @param sem the semaphore object * @param time the waiting time * * @return the error code */rt_err_t rt_sem_take (rt_sem_t sem, rt_int32 time){	register rt_base_t temp;	struct rt_thread* thread;	RT_ASSERT(sem != RT_NULL);#ifdef RT_USING_HOOK	if (rt_object_trytake_hook != RT_NULL) rt_object_trytake_hook(&(sem->parent.parent));#endif	/* disable interrupt */	temp = rt_hw_interrupt_disable();#ifdef IPC_DEBUG	rt_kprintf("sem_take:sem value: %d\n", sem->value);#endif	if (sem->value > 0)	{		/* semaphore is available */		sem->value --;		/* enable interrupt */		rt_hw_interrupt_enable(temp);	}	else	{		/* no waiting, return with timeout */		if (time == 0 )		{			rt_hw_interrupt_enable(temp);			return -RT_ETIMEOUT;		}		else		{			/* semaphore is unavailable, push to suspend list */			sem->value --;			/* get current thread */			thread = rt_thread_self();			/* reset thread error number */			thread->error = RT_EOK;#ifdef IPC_DEBUG			rt_kprintf("sem take: suspend thread - %s\n", thread->name);#endif			/* suspend thread */			rt_ipc_object_suspend(&(sem->parent), thread);			/* has waiting time, start thread timer */			if (time > 0)			{#ifdef IPC_DEBUG				rt_kprintf("set thread:%s to timer list\n", thread->name);#endif				/* reset the timeout of thread timer and start it */				rt_timer_control(&(thread->thread_timer), RT_TIMER_CTRL_SET_TIME, &time);				rt_timer_start(&(thread->thread_timer));			}			/* enable interrupt */			rt_hw_interrupt_enable(temp);			/* do schedule */			rt_schedule();			if (thread->error != RT_EOK)			{				return thread->error;			}		}	}#ifdef RT_USING_HOOK	if (rt_object_take_hook != RT_NULL) rt_object_take_hook(&(sem->parent.parent));#endif	return RT_EOK;}/** * This function will try to take a semaphore and immediately return * * @param sem the semaphore object * * @return the error code */rt_err_t rt_sem_trytake(rt_sem_t sem){	return rt_sem_take(sem, 0);}/** * This function will release a semaphore, if there are threads suspended on  * semaphore, it will be waked up. * * @param sem the semaphore object * * @return the error code */rt_err_t rt_sem_release(rt_sem_t sem){	register rt_base_t temp;#ifdef RT_USING_HOOK	if (rt_object_put_hook != RT_NULL) rt_object_put_hook(&(sem->parent.parent));#endif	/* disable interrupt */	temp = rt_hw_interrupt_disable();#ifdef IPC_DEBUG	rt_kprintf("sem_release:sem value(%d)\n", sem->value);#endif	if (sem->value <= 0 && sem->parent.suspend_thread_count > 0)	{		rt_ipc_object_resume(&(sem->parent));	}	/* increase value */	sem->value ++;	/* enable interrupt */	rt_hw_interrupt_enable(temp);	rt_schedule();	return RT_EOK;}/** * This function can get or set some extra attributions of a semaphore object. * * @param sem the semaphore object * @param cmd the execution command * @param arg the execution argument * * @return the error code */rt_err_t rt_sem_control(rt_sem_t sem, rt_uint8 cmd, void* arg){	return RT_EOK;}#endif /* end of RT_USING_SEMAPHORE */#ifdef RT_USING_MUTEX/** * This function will initialize a mutex and put it under control of resource * management. * * @param mutex the mutex object * @param name the name of mutex * @param flag the flag of mutex * * @return the operation status, RT_EOK on successful */rt_err_t rt_mutex_init (rt_mutex_t mutex, const char* name, rt_uint8 flag){	RT_ASSERT(mutex != RT_NULL);	/* init object */	rt_object_init(&(mutex->parent.parent), RT_Object_Class_Mutex, name);	/* init ipc object */	rt_ipc_object_init(&(mutex->parent));	mutex->value = 1;	mutex->owner = RT_NULL;	mutex->original_priority = 0xFF;	mutex->hold  = 0;	/* set flag */	mutex->parent.parent.flag = flag;	return RT_EOK;}/** * This function will detach a mutex from resource management * * @param mutex the mutex object * * @return the operation status, RT_EOK on successful * * @see rt_mutex_delete */rt_err_t rt_mutex_detach (rt_mutex_t mutex){	RT_ASSERT(mutex != RT_NULL);	/* wakeup all suspend threads */	rt_ipc_object_resume_all(&(mutex->parent));	/* detach semaphore object */	rt_object_detach(&(mutex->parent.parent));	return RT_EOK;}#ifdef RT_USING_HEAP/** * This function will create a mutex from system resource * * @param name the name of mutex * @param flag the flag of mutex * * @return the created mutex, RT_NULL on error happen * * @see rt_mutex_init */rt_mutex_t rt_mutex_create (const char* name, rt_uint8 flag){	struct rt_mutex *mutex;	/* allocate object */	mutex = (rt_mutex_t) rt_object_allocate(RT_Object_Class_Mutex, name);	if (mutex == RT_NULL) return mutex;	/* init ipc object */	rt_ipc_object_init(&(mutex->parent));	mutex->value = 1;	mutex->owner = RT_NULL;	mutex->original_priority = 0xFF;	mutex->hold  = 0;	/* set flag */	mutex->parent.parent.flag = flag;	return mutex;}/** * This function will delete a mutex object and release the memory * * @param mutex the mutex object * * @return the error code * * @see rt_mutex_detach

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -