Quellcode durchsuchen

add cleanup callback function on thread exit; add IPC object reset command.

git-svn-id: https://rt-thread.googlecode.com/svn/trunk@1043 bbd45198-f89e-11dd-88c7-29a3b14d5316
bernard.xiong vor 14 Jahren
Ursprung
Commit
7018ab0661
4 geänderte Dateien mit 160 neuen und 27 gelöschten Zeilen
  1. 15 11
      include/rtdef.h
  2. 13 5
      src/idle.c
  3. 111 10
      src/ipc.c
  4. 21 1
      src/thread.c

+ 15 - 11
include/rtdef.h

@@ -10,8 +10,9 @@
  * Change Logs:
  * Date           Author       Notes
  * 2007-01-10     Bernard      the first version
- * 2008-07-12     Bernard	  remove all rt_int8, rt_uint32_t etc typedef
+ * 2008-07-12     Bernard	   remove all rt_int8, rt_uint32_t etc typedef
  * 2010-10-26     yi.qiu       add module support
+ * 2010-11-10     Bernard      add cleanup callback function in thread exit.
  */
 #ifndef __RT_DEF_H__
 #define __RT_DEF_H__
@@ -301,14 +302,12 @@ typedef struct rt_timer* rt_timer_t;
  */
 
 /* thread state definitions */
-#define RT_THREAD_RUNNING				0x0				/* Running. 								*/
-#define RT_THREAD_READY					0x1				/* Ready. 									*/
-#define RT_THREAD_SUSPEND				0x2				/* Suspend. 								*/
-#define RT_THREAD_BLOCK					RT_THREAD_SUSPEND	/* Blocked. 							*/
-#define RT_THREAD_CLOSE					0x3				/* Closed. 									*/
-#define RT_THREAD_INIT					RT_THREAD_CLOSE	/* Inited. 									*/
-
-#define RT_THREAD_FLAGS_TIMERSLICE 		0x01
+#define RT_THREAD_INIT					0x00				/* Inited. 									*/
+#define RT_THREAD_READY					0x01				/* Ready. 									*/
+#define RT_THREAD_SUSPEND				0x02				/* Suspend. 								*/
+#define RT_THREAD_RUNNING				0x03				/* Running. 								*/
+#define RT_THREAD_BLOCK					RT_THREAD_SUSPEND	/* Blocked. 								*/
+#define RT_THREAD_CLOSE					0x04				/* Closed. 									*/
 
 #define RT_THREAD_CTRL_STARTUP			0x00			/* Starup thread. 							*/
 #define RT_THREAD_CTRL_CLOSE			0x01			/* Close thread. 							*/
@@ -328,7 +327,7 @@ struct rt_thread
 	rt_uint8_t  flags;									/* thread's flags 							*/
 	
 #ifdef RT_USING_MODULE
-	void* module_id;								/* id of application module					*/
+	void* 		module_id;								/* id of application module					*/
 #endif
 
 	rt_list_t	list;									/* the object list 							*/
@@ -366,6 +365,8 @@ struct rt_thread
 
 	struct rt_timer thread_timer;						/* thread timer 							*/
 
+	void 		(*cleanup)(struct rt_thread* tid);		/* cleanup function when thread exit 		*/
+
 	rt_uint32_t user_data;								/* user data 								*/
 };
 /*@}*/
@@ -407,6 +408,9 @@ typedef struct rt_module* rt_module_t;
 #define RT_IPC_FLAG_FIFO				0x00			/* FIFOed IPC. @ref IPC. 					*/
 #define RT_IPC_FLAG_PRIO				0x01			/* PRIOed IPC. @ref IPC. 					*/
 
+#define RT_IPC_CMD_UNKNOWN				0x00			/* unknown IPC command 						*/
+#define RT_IPC_CMD_RESET				0x01			/* reset IPC object 						*/
+
 #define RT_WAITING_FOREVER				-1				/* Block forever until get resource.		*/
 #define RT_WAITING_NO					0				/* Non-block. 								*/
 
@@ -443,7 +447,7 @@ struct rt_mutex
 {
 	struct rt_ipc_object 	parent;
 
-	rt_uint8_t 				value;						/* value of mutex. 							*/
+	rt_uint16_t 			value;						/* value of mutex. 							*/
 
 	rt_uint8_t 				original_priority;			/* priority of last thread hold the mutex. 	*/
 	rt_uint8_t 				hold;			 			/* numbers of thread hold the mutex. 		*/

+ 13 - 5
src/idle.c

@@ -10,6 +10,7 @@
  * Change Logs:
  * Date           Author       Notes
  * 2006-03-23     Bernard      the first version
+ * 2010-11-10     Bernard      add cleanup callback function in thread exit.
  */
 
 #include <rthw.h>
@@ -74,20 +75,29 @@ void rt_thread_idle_excute(void)
 		{
 			/* get defunct thread */
 			thread = rt_list_entry(rt_thread_defunct.next, struct rt_thread, tlist);
-
 #ifdef RT_USING_MODULE
 			/* get thread's parent module */
 			module = (rt_module_t)thread->module_id;
 
 			/* if the thread is module's main thread */
-			if(module->module_thread == thread)
+			if(module != RT_NULL && module->module_thread == thread)
 			{	
 				/* detach module's main thread */
 				module->module_thread = RT_NULL;
-			}	
+			}
 #endif
 			/* remove defunct thread */
 			rt_list_remove(&(thread->tlist));
+			/* invoke thread cleanup */
+			if (thread->cleanup != RT_NULL) thread->cleanup(thread);
+
+			/* if it's a system object, not delete it */
+			if (rt_object_is_systemobject((rt_object_t)thread) == RT_EOK)
+			{
+				/* enable interrupt */
+				rt_hw_interrupt_enable(lock);
+				return;
+			}
 		}
 		else
 		{
@@ -109,7 +119,6 @@ void rt_thread_idle_excute(void)
 #endif
 		/* release thread's stack */
 		rt_free(thread->stack_addr);
-
 		/* delete thread object */
 		rt_object_delete((rt_object_t)thread);
 
@@ -126,7 +135,6 @@ void rt_thread_idle_excute(void)
 		}
 #endif	//RT_USING_MODULE
 	}
-	
 #endif //RT_USING_HEAP
 }
 

+ 111 - 10
src/ipc.c

@@ -33,6 +33,7 @@
  * 2010-01-20     mbbill       remove rt_ipc_object_decrease function.
  * 2010-04-20     Bernard      move memcpy outside interrupt disable in mq
  * 2010-10-26     yi.qiu       add module support in rt_mp_delete and rt_mq_delete
+ * 2010-11-10     Bernard      add IPC reset command implementation.
  */
 
 #include <rtthread.h>
@@ -448,7 +449,27 @@ rt_err_t rt_sem_release(rt_sem_t sem)
  */
 rt_err_t rt_sem_control(rt_sem_t sem, rt_uint8_t cmd, void* arg)
 {
-	return RT_EOK;
+	rt_ubase_t level;
+	RT_ASSERT(sem != RT_NULL);
+
+	if (cmd == RT_IPC_CMD_RESET)
+	{
+		/* disable interrupt */
+		level = rt_hw_interrupt_disable();
+
+		/* resume all waiting thread */
+		rt_ipc_object_resume_all(&sem->parent);
+
+		/* set new value */
+		sem->value = (rt_uint16_t)arg;
+
+		/* enable interrupt */
+		rt_hw_interrupt_enable(level);
+
+		return RT_EOK;
+	}
+
+	return -RT_ERROR;
 }
 
 #endif /* end of RT_USING_SEMAPHORE */
@@ -738,20 +759,20 @@ rt_err_t rt_mutex_release(rt_mutex_t mutex)
 	if (mutex->hold == 0)
 	{
 		/* change the owner thread to original priority */
-		if (mutex->owner->init_priority != mutex->owner->current_priority)
+		if (mutex->original_priority != mutex->owner->current_priority)
 		{
 			rt_thread_control(mutex->owner, RT_THREAD_CTRL_CHANGE_PRIORITY,
-				&(mutex->owner->init_priority));
+				&(mutex->original_priority));
 		}
 
 		/* wakeup suspended thread */
 		if( !rt_list_isempty(&mutex->parent.suspend_thread) )
 		{
-			/* get thread entry */
+			/* get suspended thread */
 			thread = rt_list_entry(mutex->parent.suspend_thread.next, struct rt_thread, tlist);
 
 #ifdef RT_IPC_DEBUG
-		rt_kprintf("mutex_release: resume thread: %s\n", thread->name);
+			rt_kprintf("mutex_release: resume thread: %s\n", thread->name);
 #endif
 			/* set new owner and priority */
 			mutex->owner = thread;
@@ -770,7 +791,7 @@ rt_err_t rt_mutex_release(rt_mutex_t mutex)
 
 			/* clear owner */
 			mutex->owner = RT_NULL;
-			mutex->original_priority = 0;
+			mutex->original_priority = 0xff;
 		}
 	}
 
@@ -794,7 +815,7 @@ rt_err_t rt_mutex_release(rt_mutex_t mutex)
  */
 rt_err_t rt_mutex_control(rt_mutex_t mutex, rt_uint8_t cmd, void* arg)
 {
-	return RT_EOK;
+	return -RT_ERROR;
 }
 
 #endif /* end of RT_USING_MUTEX */
@@ -1110,7 +1131,27 @@ rt_err_t rt_event_recv(rt_event_t event, rt_uint32_t set, rt_uint8_t option, rt_
  */
 rt_err_t rt_event_control (rt_event_t event, rt_uint8_t cmd, void* arg)
 {
-	return RT_EOK;
+	rt_ubase_t level;
+	RT_ASSERT(event != RT_NULL);
+
+	if (cmd == RT_IPC_CMD_RESET)
+	{
+		/* disable interrupt */
+		level = rt_hw_interrupt_disable();
+
+		/* resume all waiting thread */
+		rt_ipc_object_resume_all(&event->parent);
+
+		/* init event set */
+		event->set = 0;
+
+		/* enable interrupt */
+		rt_hw_interrupt_enable(level);
+
+		return RT_EOK;
+	}
+
+	return -RT_ERROR;
 }
 
 #endif /* end of RT_USING_EVENT */
@@ -1422,7 +1463,29 @@ rt_err_t rt_mb_recv (rt_mailbox_t mb, rt_uint32_t* value, rt_int32_t timeout)
  */
 rt_err_t rt_mb_control(rt_mailbox_t mb, rt_uint8_t cmd, void* arg)
 {
-	return RT_EOK;
+	rt_ubase_t level;
+	RT_ASSERT(mb != RT_NULL);
+
+	if (cmd == RT_IPC_CMD_RESET)
+	{
+		/* disable interrupt */
+		level = rt_hw_interrupt_disable();
+
+		/* resume all waiting thread */
+		rt_ipc_object_resume_all(&mb->parent);
+
+		/* re-init mailbox */
+		mb->entry 	 	= 0;
+		mb->in_offset 	= 0;
+		mb->out_offset 	= 0;
+	
+		/* enable interrupt */
+		rt_hw_interrupt_enable(level);
+
+		return RT_EOK;
+	}
+
+	return -RT_ERROR;
 }
 
 #endif /* end of RT_USING_MAILBOX */
@@ -1894,7 +1957,45 @@ rt_err_t rt_mq_recv (rt_mq_t mq, void* buffer, rt_size_t size, rt_int32_t timeou
  */
 rt_err_t rt_mq_control(rt_mq_t mq, rt_uint8_t cmd, void* arg)
 {
-	return RT_EOK;
+	rt_ubase_t level;
+	struct rt_mq_message *msg;
+
+	RT_ASSERT(mq != RT_NULL);
+
+	if (cmd == RT_IPC_CMD_RESET)
+	{
+		/* disable interrupt */
+		level = rt_hw_interrupt_disable();
+
+		/* resume all waiting thread */
+		rt_ipc_object_resume_all(&mq->parent);
+
+		/* release all message in the queue */
+		while (mq->msg_queue_head != RT_NULL)
+		{
+			/* get message from queue */
+			msg = (struct rt_mq_message*) mq->msg_queue_head;
+
+			/* move message queue head */
+			mq->msg_queue_head = msg->next;
+			/* reach queue tail, set to NULL */
+			if (mq->msg_queue_tail == msg) mq->msg_queue_tail = RT_NULL;
+
+			/* put message to free list */
+			msg->next = (struct rt_mq_message*)mq->msg_queue_free;
+			mq->msg_queue_free = msg;
+		}
+
+		/* clean entry */
+		mq->entry = 0;
+
+		/* enable interrupt */
+		rt_hw_interrupt_enable(level);
+
+		return RT_EOK;
+	}
+
+	return -RT_ERROR;
 }
 
 #endif /* end of RT_USING_MESSAGEQUEUE */

+ 21 - 1
src/thread.c

@@ -19,6 +19,7 @@
  * 2006-09-03     Bernard      implement rt_thread_detach
  * 2008-02-16     Bernard      fix the rt_thread_timeout bug
  * 2010-03-21     Bernard      change the errno of rt_thread_delay/sleep to RT_EOK.
+ * 2010-11-10     Bernard      add cleanup callback function in thread exit.
  */
 
 #include <rtthread.h>
@@ -240,7 +241,8 @@ static void rt_thread_exit()
 	/* enable interrupt */
 	rt_hw_interrupt_enable(temp);
 
-	if (rt_object_is_systemobject((rt_object_t)thread) == RT_EOK)
+	if ((rt_object_is_systemobject((rt_object_t)thread) == RT_EOK) &&
+		thread->cleanup == RT_NULL)
 	{
 		rt_object_detach((rt_object_t)thread);
 	}
@@ -273,6 +275,8 @@ static void rt_thread_exit()
  */
 rt_err_t rt_thread_detach (rt_thread_t thread)
 {
+	rt_base_t lock;
+
 	/* thread check */
 	RT_ASSERT(thread != RT_NULL);
 
@@ -282,8 +286,24 @@ rt_err_t rt_thread_detach (rt_thread_t thread)
 	/* release thread timer */
 	rt_timer_detach(&(thread->thread_timer));
 
+	/* change stat */
+	thread->stat = RT_THREAD_CLOSE;
+
+	/* detach object */
 	rt_object_detach((rt_object_t)thread);
 
+	if (thread->cleanup != RT_NULL)
+	{
+		/* disable interrupt */
+		lock = rt_hw_interrupt_disable();
+
+		/* insert to defunct thread list */
+		rt_list_insert_after(&rt_thread_defunct, &(thread->tlist));
+
+		/* enable interrupt */
+		rt_hw_interrupt_enable(lock);
+	}
+
 	return RT_EOK;
 }