summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorbernard.xiong <[email protected]>2010-11-12 10:16:33 +0000
committerbernard.xiong <[email protected]>2010-11-12 10:16:33 +0000
commit7018ab0661e5a5c4be00283a5ab9eabc5d3ab0ee (patch)
treed70c7e6b1b6cb495d680eaa876d1dedabc7e28d9 /src
parent5837cd792ccd5862bd9de0a2b0909b580116aa90 (diff)
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
Diffstat (limited to 'src')
-rw-r--r--src/idle.c18
-rw-r--r--src/ipc.c121
-rw-r--r--src/thread.c22
3 files changed, 145 insertions, 16 deletions
diff --git a/src/idle.c b/src/idle.c
index a0a87677e2..82ed7cec49 100644
--- a/src/idle.c
+++ b/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
}
diff --git a/src/ipc.c b/src/ipc.c
index 96b11410c1..15a2f99b2f 100644
--- a/src/ipc.c
+++ b/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 */
diff --git a/src/thread.c b/src/thread.c
index 05eb403b56..32471bad3f 100644
--- a/src/thread.c
+++ b/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;
}