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

📄 ipc.c.svn-base

📁 RT-Thread是发展中的下一代微内核嵌入式实时操作系统
💻 SVN-BASE
📖 第 1 页 / 共 3 页
字号:
/* * 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://www.fayfayspace.org/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 */#include <rtthread.h>#include <rthw.h>#include "kservice.h"/** * @addtogroup Kernel *//*@{*/// #define IPC_DEBUGrt_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;}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;}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;}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/** * @brief init a semaphore * * This function will init a semaphore * * @param sem the semaphore handler * @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 hanpen * * @see rt_sem_init */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;}/** * @brief detach a semaphore * * This function will detach a semaphore from resource management * * @param sem the semaphore handler * * @return the error code * * @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;}/** * @brief create a semaphore * * 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 hanpen * * @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;}/** * @brief delete a semaphore * * This function will delete a semaphore and release the system resource * * @param sem the semaphore handler * * @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;}/** * @brief take a semaphore * * This function will take a semaphore, if the semaphore is * unavailable, the thread shall wait for a specify time. * * @param sem the semaphore handler * @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);	/* 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;			}		}	}	return RT_EOK;}/** * @brief try to take a semaphore * * This function will try to take a semaphore and immediately return * * @param sem the semaphore handler * * @return the error code */rt_err_t rt_sem_trytake(rt_sem_t sem){	return rt_sem_take(sem, 0);}/** * @brief release a semaphore * * This function will release a semaphore * * @param sem the semaphore handler * * @return the error code */rt_err_t rt_sem_release(rt_sem_t sem){	register rt_base_t temp;	/* 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;}/** * @brief control a semaphore execution * * This function can get or set some extra attribute of a semaphore * * @param sem the semaphore handler * @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_MUTEXrt_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;}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;}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;}rt_err_t rt_mutex_delete (rt_mutex_t mutex){	RT_ASSERT(mutex != RT_NULL);	/* wakeup all suspend threads */	rt_ipc_object_resume_all(&(mutex->parent));	/* delete semaphore object */	rt_object_delete(&(mutex->parent.parent));	return RT_EOK;}rt_err_t rt_mutex_take (rt_mutex_t mutex, rt_int32 time){	register rt_base_t temp;	struct rt_thread* thread;	RT_ASSERT(mutex != RT_NULL);	/* disable interrupt */	temp = rt_hw_interrupt_disable();#ifdef IPC_DEBUG	rt_kprintf("mutex_take:mutex value: %d, hold: %d\n", mutex->value, mutex->hold);#endif	/* get current thread */	thread = rt_thread_self();	/* reset thread error */	thread->error = RT_EOK;	if (mutex->owner == thread)	{		/* it's the same thread */		mutex->hold ++;	}	else	{		if (mutex->value > 0)		{			/* mutex is available */			mutex->value --;			/* set mutex owner and original priority */			mutex->owner = thread;			mutex->original_priority = thread->current_priority;			mutex->hold ++;		}		else		{			/* no waiting, return with timeout */			if (time == 0 )			{				/* set error as timeout */				thread->error = -RT_ETIMEOUT;				/* enable interrupt */				rt_hw_interrupt_enable(temp);				return -RT_ETIMEOUT;			}			else			{				/* mutex is unavailable, push to suspend list */				mutex->value --;#ifdef IPC_DEBUG				rt_kprintf("sem take: suspend thread: %s\n", thread->name);#endif				/* change the owner thread priority of mutex */				if (thread->current_priority < mutex->owner->current_priority)				{					/* change the owner thread priority */					rt_thread_control(mutex->owner, RT_THREAD_CTRL_CHANGE_PRIORITY,						&thread->current_priority);				}				/* suspend current thread */				rt_ipc_object_suspend(&(mutex->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 error */					return thread->error;				}				else				{					/* disable interrupt */					temp = rt_hw_interrupt_disable();					/* take mutex */

⌨️ 快捷键说明

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