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
This commit is contained in:
bernard.xiong 2010-11-12 10:16:33 +00:00
parent 5837cd792c
commit 7018ab0661
4 changed files with 160 additions and 27 deletions

View File

@ -10,8 +10,9 @@
* Change Logs: * Change Logs:
* Date Author Notes * Date Author Notes
* 2007-01-10 Bernard the first version * 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-10-26 yi.qiu add module support
* 2010-11-10 Bernard add cleanup callback function in thread exit.
*/ */
#ifndef __RT_DEF_H__ #ifndef __RT_DEF_H__
#define __RT_DEF_H__ #define __RT_DEF_H__
@ -301,14 +302,12 @@ typedef struct rt_timer* rt_timer_t;
*/ */
/* thread state definitions */ /* thread state definitions */
#define RT_THREAD_RUNNING 0x0 /* Running. */ #define RT_THREAD_INIT 0x00 /* Inited. */
#define RT_THREAD_READY 0x1 /* Ready. */ #define RT_THREAD_READY 0x01 /* Ready. */
#define RT_THREAD_SUSPEND 0x2 /* Suspend. */ #define RT_THREAD_SUSPEND 0x02 /* Suspend. */
#define RT_THREAD_BLOCK RT_THREAD_SUSPEND /* Blocked. */ #define RT_THREAD_RUNNING 0x03 /* Running. */
#define RT_THREAD_CLOSE 0x3 /* Closed. */ #define RT_THREAD_BLOCK RT_THREAD_SUSPEND /* Blocked. */
#define RT_THREAD_INIT RT_THREAD_CLOSE /* Inited. */ #define RT_THREAD_CLOSE 0x04 /* Closed. */
#define RT_THREAD_FLAGS_TIMERSLICE 0x01
#define RT_THREAD_CTRL_STARTUP 0x00 /* Starup thread. */ #define RT_THREAD_CTRL_STARTUP 0x00 /* Starup thread. */
#define RT_THREAD_CTRL_CLOSE 0x01 /* Close thread. */ #define RT_THREAD_CTRL_CLOSE 0x01 /* Close thread. */
@ -328,7 +327,7 @@ struct rt_thread
rt_uint8_t flags; /* thread's flags */ rt_uint8_t flags; /* thread's flags */
#ifdef RT_USING_MODULE #ifdef RT_USING_MODULE
void* module_id; /* id of application module */ void* module_id; /* id of application module */
#endif #endif
rt_list_t list; /* the object list */ rt_list_t list; /* the object list */
@ -366,6 +365,8 @@ struct rt_thread
struct rt_timer thread_timer; /* thread timer */ 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 */ 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_FIFO 0x00 /* FIFOed IPC. @ref IPC. */
#define RT_IPC_FLAG_PRIO 0x01 /* PRIOed 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_FOREVER -1 /* Block forever until get resource. */
#define RT_WAITING_NO 0 /* Non-block. */ #define RT_WAITING_NO 0 /* Non-block. */
@ -443,7 +447,7 @@ struct rt_mutex
{ {
struct rt_ipc_object parent; 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 original_priority; /* priority of last thread hold the mutex. */
rt_uint8_t hold; /* numbers of thread hold the mutex. */ rt_uint8_t hold; /* numbers of thread hold the mutex. */

View File

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

121
src/ipc.c
View File

@ -33,6 +33,7 @@
* 2010-01-20 mbbill remove rt_ipc_object_decrease function. * 2010-01-20 mbbill remove rt_ipc_object_decrease function.
* 2010-04-20 Bernard move memcpy outside interrupt disable in mq * 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-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> #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) 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 */ #endif /* end of RT_USING_SEMAPHORE */
@ -738,20 +759,20 @@ rt_err_t rt_mutex_release(rt_mutex_t mutex)
if (mutex->hold == 0) if (mutex->hold == 0)
{ {
/* change the owner thread to original priority */ /* 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, rt_thread_control(mutex->owner, RT_THREAD_CTRL_CHANGE_PRIORITY,
&(mutex->owner->init_priority)); &(mutex->original_priority));
} }
/* wakeup suspended thread */ /* wakeup suspended thread */
if( !rt_list_isempty(&mutex->parent.suspend_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); thread = rt_list_entry(mutex->parent.suspend_thread.next, struct rt_thread, tlist);
#ifdef RT_IPC_DEBUG #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 #endif
/* set new owner and priority */ /* set new owner and priority */
mutex->owner = thread; mutex->owner = thread;
@ -770,7 +791,7 @@ rt_err_t rt_mutex_release(rt_mutex_t mutex)
/* clear owner */ /* clear owner */
mutex->owner = RT_NULL; 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) 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 */ #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) 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 */ #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) 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 */ #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) 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 */ #endif /* end of RT_USING_MESSAGEQUEUE */

View File

@ -19,6 +19,7 @@
* 2006-09-03 Bernard implement rt_thread_detach * 2006-09-03 Bernard implement rt_thread_detach
* 2008-02-16 Bernard fix the rt_thread_timeout bug * 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-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> #include <rtthread.h>
@ -240,7 +241,8 @@ static void rt_thread_exit()
/* enable interrupt */ /* enable interrupt */
rt_hw_interrupt_enable(temp); 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); 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_err_t rt_thread_detach (rt_thread_t thread)
{ {
rt_base_t lock;
/* thread check */ /* thread check */
RT_ASSERT(thread != RT_NULL); RT_ASSERT(thread != RT_NULL);
@ -282,8 +286,24 @@ rt_err_t rt_thread_detach (rt_thread_t thread)
/* release thread timer */ /* release thread timer */
rt_timer_detach(&(thread->thread_timer)); rt_timer_detach(&(thread->thread_timer));
/* change stat */
thread->stat = RT_THREAD_CLOSE;
/* detach object */
rt_object_detach((rt_object_t)thread); 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; return RT_EOK;
} }