|
@@ -11,7 +11,7 @@
|
|
* Date Author Notes
|
|
* Date Author Notes
|
|
* 2006-03-14 Bernard the first version
|
|
* 2006-03-14 Bernard the first version
|
|
* 2006-04-25 Bernard implement semaphore
|
|
* 2006-04-25 Bernard implement semaphore
|
|
- * 2006-05-03 Bernard add IPC_DEBUG
|
|
|
|
|
|
+ * 2006-05-03 Bernard add RT_IPC_DEBUG
|
|
* modify the type of IPC waiting time to rt_int32_t
|
|
* modify the type of IPC waiting time to rt_int32_t
|
|
* 2006-05-10 Bernard fix the semaphore take bug and add IPC object
|
|
* 2006-05-10 Bernard fix the semaphore take bug and add IPC object
|
|
* 2006-05-12 Bernard implement mailbox and message queue
|
|
* 2006-05-12 Bernard implement mailbox and message queue
|
|
@@ -23,8 +23,8 @@
|
|
* 2006-06-07 Bernard fix the message queue send bug
|
|
* 2006-06-07 Bernard fix the message queue send bug
|
|
* 2006-08-04 Bernard add hook support
|
|
* 2006-08-04 Bernard add hook support
|
|
* 2009-05-21 Yi.qiu fix the sem release bug
|
|
* 2009-05-21 Yi.qiu fix the sem release bug
|
|
- * 2009-07-18 Bernard fix the event clear bug
|
|
|
|
- * 2009-08-31 Bernard fix the fast event receive bug
|
|
|
|
|
|
+ * 2009-07-18 Bernard fix the event clear bug
|
|
|
|
+ * 2009-09-09 Bernard remove fast event and fix ipc release bug
|
|
*/
|
|
*/
|
|
|
|
|
|
#include <rtthread.h>
|
|
#include <rtthread.h>
|
|
@@ -32,7 +32,7 @@
|
|
|
|
|
|
#include "kservice.h"
|
|
#include "kservice.h"
|
|
|
|
|
|
-/* #define IPC_DEBUG */
|
|
|
|
|
|
+/* #define RT_IPC_DEBUG */
|
|
|
|
|
|
#ifdef RT_USING_HOOK
|
|
#ifdef RT_USING_HOOK
|
|
extern void (*rt_object_trytake_hook)(struct rt_object* object);
|
|
extern void (*rt_object_trytake_hook)(struct rt_object* object);
|
|
@@ -122,7 +122,7 @@ rt_inline rt_err_t rt_ipc_object_resume(struct rt_ipc_object* ipc)
|
|
/* get thread entry */
|
|
/* get thread entry */
|
|
thread = rt_list_entry(ipc->suspend_thread.next, struct rt_thread, tlist);
|
|
thread = rt_list_entry(ipc->suspend_thread.next, struct rt_thread, tlist);
|
|
|
|
|
|
-#ifdef IPC_DEBUG
|
|
|
|
|
|
+#ifdef RT_IPC_DEBUG
|
|
rt_kprintf("resume thread:%s\n", thread->name);
|
|
rt_kprintf("resume thread:%s\n", thread->name);
|
|
#endif
|
|
#endif
|
|
|
|
|
|
@@ -321,8 +321,8 @@ rt_err_t rt_sem_take (rt_sem_t sem, rt_int32_t time)
|
|
/* disable interrupt */
|
|
/* disable interrupt */
|
|
temp = rt_hw_interrupt_disable();
|
|
temp = rt_hw_interrupt_disable();
|
|
|
|
|
|
-#ifdef IPC_DEBUG
|
|
|
|
- rt_kprintf("thread %s take sem:%s, which value is: %d\n", rt_thread_self()->name,
|
|
|
|
|
|
+#ifdef RT_IPC_DEBUG
|
|
|
|
+ rt_kprintf("thread %s take sem:%s, which value is: %d\n", rt_thread_self()->name,
|
|
((struct rt_object*)sem)->name, sem->value);
|
|
((struct rt_object*)sem)->name, sem->value);
|
|
#endif
|
|
#endif
|
|
if (sem->value > 0)
|
|
if (sem->value > 0)
|
|
@@ -352,7 +352,7 @@ rt_err_t rt_sem_take (rt_sem_t sem, rt_int32_t time)
|
|
/* reset thread error number */
|
|
/* reset thread error number */
|
|
thread->error = RT_EOK;
|
|
thread->error = RT_EOK;
|
|
|
|
|
|
-#ifdef IPC_DEBUG
|
|
|
|
|
|
+#ifdef RT_IPC_DEBUG
|
|
rt_kprintf("sem take: suspend thread - %s\n", thread->name);
|
|
rt_kprintf("sem take: suspend thread - %s\n", thread->name);
|
|
#endif
|
|
#endif
|
|
|
|
|
|
@@ -362,7 +362,7 @@ rt_err_t rt_sem_take (rt_sem_t sem, rt_int32_t time)
|
|
/* has waiting time, start thread timer */
|
|
/* has waiting time, start thread timer */
|
|
if (time > 0)
|
|
if (time > 0)
|
|
{
|
|
{
|
|
-#ifdef IPC_DEBUG
|
|
|
|
|
|
+#ifdef RT_IPC_DEBUG
|
|
rt_kprintf("set thread:%s to timer list\n", thread->name);
|
|
rt_kprintf("set thread:%s to timer list\n", thread->name);
|
|
#endif
|
|
#endif
|
|
/* reset the timeout of thread timer and start it */
|
|
/* reset the timeout of thread timer and start it */
|
|
@@ -423,15 +423,17 @@ rt_err_t rt_sem_release(rt_sem_t sem)
|
|
/* disable interrupt */
|
|
/* disable interrupt */
|
|
temp = rt_hw_interrupt_disable();
|
|
temp = rt_hw_interrupt_disable();
|
|
|
|
|
|
-#ifdef IPC_DEBUG
|
|
|
|
- rt_kprintf("thread %s releases sem:%s, which value is: %d\n", rt_thread_self()->name,
|
|
|
|
|
|
+#ifdef RT_IPC_DEBUG
|
|
|
|
+ rt_kprintf("thread %s releases sem:%s, which value is: %d\n", rt_thread_self()->name,
|
|
((struct rt_object*)sem)->name, sem->value);
|
|
((struct rt_object*)sem)->name, sem->value);
|
|
#endif
|
|
#endif
|
|
|
|
+
|
|
/* increase value */
|
|
/* increase value */
|
|
sem->value ++;
|
|
sem->value ++;
|
|
|
|
|
|
if (sem->value <= 0 && sem->parent.suspend_thread_count > 0)
|
|
if (sem->value <= 0 && sem->parent.suspend_thread_count > 0)
|
|
{
|
|
{
|
|
|
|
+ /* resume the suspended thread */
|
|
rt_ipc_object_resume(&(sem->parent));
|
|
rt_ipc_object_resume(&(sem->parent));
|
|
|
|
|
|
/* enable interrupt */
|
|
/* enable interrupt */
|
|
@@ -591,20 +593,21 @@ rt_err_t rt_mutex_take (rt_mutex_t mutex, rt_int32_t time)
|
|
|
|
|
|
RT_ASSERT(mutex != RT_NULL);
|
|
RT_ASSERT(mutex != RT_NULL);
|
|
|
|
|
|
-#ifdef RT_USING_HOOK
|
|
|
|
- if (rt_object_trytake_hook != RT_NULL) rt_object_trytake_hook(&(mutex->parent.parent));
|
|
|
|
-#endif
|
|
|
|
-
|
|
|
|
/* disable interrupt */
|
|
/* disable interrupt */
|
|
temp = rt_hw_interrupt_disable();
|
|
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 */
|
|
/* get current thread */
|
|
thread = rt_thread_self();
|
|
thread = rt_thread_self();
|
|
|
|
|
|
|
|
+#ifdef RT_USING_HOOK
|
|
|
|
+ if (rt_object_trytake_hook != RT_NULL) rt_object_trytake_hook(&(mutex->parent.parent));
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+#ifdef RT_IPC_DEBUG
|
|
|
|
+ rt_kprintf("mutex_take: current thread %s, mutex value: %d, hold: %d\n",
|
|
|
|
+ thread->name, mutex->value, mutex->hold);
|
|
|
|
+#endif
|
|
|
|
+
|
|
/* reset thread error */
|
|
/* reset thread error */
|
|
thread->error = RT_EOK;
|
|
thread->error = RT_EOK;
|
|
|
|
|
|
@@ -615,6 +618,9 @@ rt_err_t rt_mutex_take (rt_mutex_t mutex, rt_int32_t time)
|
|
}
|
|
}
|
|
else
|
|
else
|
|
{
|
|
{
|
|
|
|
+ /* in initialization status, the value is 1. Therefore, if the
|
|
|
|
+ * value is great than 1, which indicates the mutex is avaible.
|
|
|
|
+ */
|
|
if (mutex->value > 0)
|
|
if (mutex->value > 0)
|
|
{
|
|
{
|
|
/* mutex is available */
|
|
/* mutex is available */
|
|
@@ -643,8 +649,8 @@ rt_err_t rt_mutex_take (rt_mutex_t mutex, rt_int32_t time)
|
|
/* mutex is unavailable, push to suspend list */
|
|
/* mutex is unavailable, push to suspend list */
|
|
mutex->value --;
|
|
mutex->value --;
|
|
|
|
|
|
-#ifdef IPC_DEBUG
|
|
|
|
- rt_kprintf("sem take: suspend thread: %s\n", thread->name);
|
|
|
|
|
|
+#ifdef RT_IPC_DEBUG
|
|
|
|
+ rt_kprintf("mutex_take: suspend thread: %s\n", thread->name);
|
|
#endif
|
|
#endif
|
|
/* change the owner thread priority of mutex */
|
|
/* change the owner thread priority of mutex */
|
|
if (thread->current_priority < mutex->owner->current_priority)
|
|
if (thread->current_priority < mutex->owner->current_priority)
|
|
@@ -660,8 +666,8 @@ rt_err_t rt_mutex_take (rt_mutex_t mutex, rt_int32_t time)
|
|
/* has waiting time, start thread timer */
|
|
/* has waiting time, start thread timer */
|
|
if (time > 0)
|
|
if (time > 0)
|
|
{
|
|
{
|
|
-#ifdef IPC_DEBUG
|
|
|
|
- rt_kprintf("set thread:%s to timer list\n", thread->name);
|
|
|
|
|
|
+#ifdef RT_IPC_DEBUG
|
|
|
|
+ rt_kprintf("mutex_take: start the timer of thread:%s\n", thread->name);
|
|
#endif
|
|
#endif
|
|
/* reset the timeout of thread timer and start it */
|
|
/* reset the timeout of thread timer and start it */
|
|
rt_timer_control(&(thread->thread_timer), RT_TIMER_CTRL_SET_TIME, &time);
|
|
rt_timer_control(&(thread->thread_timer), RT_TIMER_CTRL_SET_TIME, &time);
|
|
@@ -684,13 +690,11 @@ rt_err_t rt_mutex_take (rt_mutex_t mutex, rt_int32_t time)
|
|
}
|
|
}
|
|
else
|
|
else
|
|
{
|
|
{
|
|
|
|
+ /* the mutex is taken successfully. */
|
|
|
|
+
|
|
/* disable interrupt */
|
|
/* disable interrupt */
|
|
temp = rt_hw_interrupt_disable();
|
|
temp = rt_hw_interrupt_disable();
|
|
|
|
|
|
- /* take mutex */
|
|
|
|
- mutex->owner = thread;
|
|
|
|
- mutex->hold ++;
|
|
|
|
-
|
|
|
|
/* set thread error */
|
|
/* set thread error */
|
|
thread->error = RT_EOK;
|
|
thread->error = RT_EOK;
|
|
}
|
|
}
|
|
@@ -724,18 +728,19 @@ rt_err_t rt_mutex_release(rt_mutex_t mutex)
|
|
/* disable interrupt */
|
|
/* disable interrupt */
|
|
temp = rt_hw_interrupt_disable();
|
|
temp = rt_hw_interrupt_disable();
|
|
|
|
|
|
-#ifdef IPC_DEBUG
|
|
|
|
- rt_kprintf("mutex_release:mutex value: %d, hold: %d\n", mutex->value, mutex->hold);
|
|
|
|
|
|
+ /* get current thread */
|
|
|
|
+ thread = rt_thread_self();
|
|
|
|
+
|
|
|
|
+#ifdef RT_IPC_DEBUG
|
|
|
|
+ rt_kprintf("mutex_release:current thread %s, mutex value: %d, hold: %d\n",
|
|
|
|
+ thread->name, mutex->value, mutex->hold);
|
|
#endif
|
|
#endif
|
|
|
|
|
|
#ifdef RT_USING_HOOK
|
|
#ifdef RT_USING_HOOK
|
|
if (rt_object_put_hook != RT_NULL) rt_object_put_hook(&(mutex->parent.parent));
|
|
if (rt_object_put_hook != RT_NULL) rt_object_put_hook(&(mutex->parent.parent));
|
|
#endif
|
|
#endif
|
|
|
|
|
|
- /* get current thread */
|
|
|
|
- thread = rt_thread_self();
|
|
|
|
-
|
|
|
|
- /* mutex is only released by owner */
|
|
|
|
|
|
+ /* mutex only can be released by owner */
|
|
if (thread != mutex->owner)
|
|
if (thread != mutex->owner)
|
|
{
|
|
{
|
|
thread->error = -RT_ERROR;
|
|
thread->error = -RT_ERROR;
|
|
@@ -762,21 +767,30 @@ rt_err_t rt_mutex_release(rt_mutex_t mutex)
|
|
/* wakeup suspended thread */
|
|
/* wakeup suspended thread */
|
|
if (mutex->value <= 0 && mutex->parent.suspend_thread_count > 0)
|
|
if (mutex->value <= 0 && mutex->parent.suspend_thread_count > 0)
|
|
{
|
|
{
|
|
-#ifdef IPC_DEBUG
|
|
|
|
- rt_kprintf("mutex release: resume thread: %s\n", thread->name);
|
|
|
|
|
|
+ /* get thread entry */
|
|
|
|
+ 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);
|
|
#endif
|
|
#endif
|
|
|
|
+ /* set new owner and priority */
|
|
|
|
+ mutex->owner = thread;
|
|
|
|
+ mutex->original_priority = thread->current_priority;
|
|
|
|
+ mutex->hold ++;
|
|
|
|
|
|
/* resume thread */
|
|
/* resume thread */
|
|
rt_ipc_object_resume(&(mutex->parent));
|
|
rt_ipc_object_resume(&(mutex->parent));
|
|
}
|
|
}
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ /* increase value */
|
|
|
|
+ mutex->value ++;
|
|
|
|
+ }
|
|
|
|
|
|
- /* increase value */
|
|
|
|
- mutex->value ++;
|
|
|
|
-
|
|
|
|
- /* enable interrupt */
|
|
|
|
- rt_hw_interrupt_enable(temp);
|
|
|
|
|
|
+ /* enable interrupt */
|
|
|
|
+ rt_hw_interrupt_enable(temp);
|
|
|
|
|
|
- rt_schedule();
|
|
|
|
|
|
+ rt_schedule();
|
|
return RT_EOK;
|
|
return RT_EOK;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -802,372 +816,6 @@ rt_err_t rt_mutex_control(rt_mutex_t mutex, rt_uint8_t cmd, void* arg)
|
|
|
|
|
|
#endif /* end of RT_USING_MUTEX */
|
|
#endif /* end of RT_USING_MUTEX */
|
|
|
|
|
|
-#ifdef RT_USING_FASTEVENT
|
|
|
|
-
|
|
|
|
-/**
|
|
|
|
- * This function will initialize a fast event and put it under control of resource
|
|
|
|
- * management.
|
|
|
|
- *
|
|
|
|
- * @param event the fast event object
|
|
|
|
- * @param name the name of fast event
|
|
|
|
- * @param flag the flag of fast event
|
|
|
|
- *
|
|
|
|
- * @return the operation status, RT_EOK on successful
|
|
|
|
- */
|
|
|
|
-rt_err_t rt_fast_event_init(rt_fast_event_t event, const char* name, rt_uint8_t flag)
|
|
|
|
-{
|
|
|
|
- register rt_base_t offset;
|
|
|
|
- RT_ASSERT(event != RT_NULL);
|
|
|
|
-
|
|
|
|
- /* init object */
|
|
|
|
- rt_object_init(&(event->parent), RT_Object_Class_FastEvent, name);
|
|
|
|
-
|
|
|
|
- /* set parent */
|
|
|
|
- event->parent.flag = flag;
|
|
|
|
-
|
|
|
|
- /* clear event set */
|
|
|
|
- event->set = 0x00;
|
|
|
|
-
|
|
|
|
- /* init thread list */
|
|
|
|
- for (offset = 0; offset < 32; offset ++)
|
|
|
|
- {
|
|
|
|
- rt_list_init(&(event->thread_list[offset]));
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return RT_EOK;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-/**
|
|
|
|
- * This function will detach a fast event from resource management
|
|
|
|
- *
|
|
|
|
- * @param event the fast event object
|
|
|
|
- *
|
|
|
|
- * @return the operation status, RT_EOK on successful
|
|
|
|
- */
|
|
|
|
-rt_err_t rt_fast_event_detach(rt_fast_event_t event)
|
|
|
|
-{
|
|
|
|
- register rt_base_t bit;
|
|
|
|
- struct rt_thread* thread;
|
|
|
|
- register rt_ubase_t level;
|
|
|
|
-
|
|
|
|
- RT_ASSERT(event != RT_NULL);
|
|
|
|
-
|
|
|
|
- for (bit = 0; bit < RT_EVENT_LENGTH; bit ++)
|
|
|
|
- {
|
|
|
|
- /* resume all suspend thread */
|
|
|
|
- if (!rt_list_isempty(&(event->thread_list[bit])))
|
|
|
|
- {
|
|
|
|
- /* wakeup all suspend threads */
|
|
|
|
- while (!rt_list_isempty(&(event->thread_list[bit])))
|
|
|
|
- {
|
|
|
|
- /* disable interrupt */
|
|
|
|
- level = rt_hw_interrupt_disable();
|
|
|
|
-
|
|
|
|
- /* get next suspend thread */
|
|
|
|
- thread = rt_list_entry(event->thread_list[bit].next, struct rt_thread, tlist);
|
|
|
|
- /* set error code to RT_ERROR */
|
|
|
|
- thread->error = -RT_ERROR;
|
|
|
|
-
|
|
|
|
- /* resume thread */
|
|
|
|
- rt_thread_resume(thread);
|
|
|
|
-
|
|
|
|
- /* enable interrupt */
|
|
|
|
- rt_hw_interrupt_enable(level);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /* detach event object */
|
|
|
|
- rt_object_detach(&(event->parent));
|
|
|
|
-
|
|
|
|
- return RT_EOK;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-#ifdef RT_USING_HEAP
|
|
|
|
-/**
|
|
|
|
- * This function will create a fast event object from system resource
|
|
|
|
- *
|
|
|
|
- * @param name the name of fast event
|
|
|
|
- * @param flag the flag of fast event
|
|
|
|
- *
|
|
|
|
- * @return the created fast event, RT_NULL on error happen
|
|
|
|
- */
|
|
|
|
-rt_fast_event_t rt_fast_event_create (const char* name, rt_uint8_t flag)
|
|
|
|
-{
|
|
|
|
- rt_fast_event_t event;
|
|
|
|
- register rt_base_t offset;
|
|
|
|
-
|
|
|
|
- /* allocate object */
|
|
|
|
- event = (rt_fast_event_t) rt_object_allocate(RT_Object_Class_FastEvent, name);
|
|
|
|
- if (event == RT_NULL) return event;
|
|
|
|
-
|
|
|
|
- /* set parent */
|
|
|
|
- event->parent.flag = flag;
|
|
|
|
-
|
|
|
|
- /* clear event set */
|
|
|
|
- event->set = 0x00;
|
|
|
|
-
|
|
|
|
- /* init thread list */
|
|
|
|
- for (offset = 0; offset < 32; offset ++)
|
|
|
|
- {
|
|
|
|
- rt_list_init(&(event->thread_list[offset]));
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return event;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-/**
|
|
|
|
- * This function will delete a fast event object and release the memory
|
|
|
|
- *
|
|
|
|
- * @param event the fast event object
|
|
|
|
- *
|
|
|
|
- * @return the error code
|
|
|
|
- */
|
|
|
|
-rt_err_t rt_fast_event_delete (rt_fast_event_t event)
|
|
|
|
-{
|
|
|
|
- register rt_base_t bit;
|
|
|
|
- struct rt_thread* thread;
|
|
|
|
- register rt_ubase_t level;
|
|
|
|
-
|
|
|
|
- RT_ASSERT(event != RT_NULL);
|
|
|
|
-
|
|
|
|
- for (bit = 0; bit < RT_EVENT_LENGTH; bit ++)
|
|
|
|
- {
|
|
|
|
- /* resume all suspend thread */
|
|
|
|
- if (!rt_list_isempty(&(event->thread_list[bit])))
|
|
|
|
- {
|
|
|
|
- /* wakeup all suspend threads */
|
|
|
|
- while (!rt_list_isempty(&(event->thread_list[bit])))
|
|
|
|
- {
|
|
|
|
- /* disable interrupt */
|
|
|
|
- level = rt_hw_interrupt_disable();
|
|
|
|
-
|
|
|
|
- /* get next suspend thread */
|
|
|
|
- thread = rt_list_entry(event->thread_list[bit].next, struct rt_thread, tlist);
|
|
|
|
- /* set error code to RT_ERROR */
|
|
|
|
- thread->error = -RT_ERROR;
|
|
|
|
-
|
|
|
|
- /* resume thread */
|
|
|
|
- rt_thread_resume(thread);
|
|
|
|
-
|
|
|
|
- /* enable interrupt */
|
|
|
|
- rt_hw_interrupt_enable(level);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /* detach semaphore object */
|
|
|
|
- rt_object_delete(&(event->parent));
|
|
|
|
-
|
|
|
|
- return RT_EOK;
|
|
|
|
-}
|
|
|
|
-#endif
|
|
|
|
-
|
|
|
|
-/**
|
|
|
|
- * This function will send an event to the fast event object, if there are threads
|
|
|
|
- * suspended on fast event object, it will be waked up.
|
|
|
|
- *
|
|
|
|
- * @param event the fast event object
|
|
|
|
- * @param bit the event bit
|
|
|
|
- *
|
|
|
|
- * @return the error code
|
|
|
|
- */
|
|
|
|
-rt_err_t rt_fast_event_send(rt_fast_event_t event, rt_uint8_t bit)
|
|
|
|
-{
|
|
|
|
- rt_uint32_t offset;
|
|
|
|
- register rt_ubase_t level;
|
|
|
|
- struct rt_thread *thread;
|
|
|
|
- struct rt_list_node *n;
|
|
|
|
- rt_bool_t need_schedule;
|
|
|
|
-
|
|
|
|
- /* parameter check */
|
|
|
|
- RT_ASSERT(event != RT_NULL);
|
|
|
|
- RT_ASSERT(bit < RT_EVENT_LENGTH);
|
|
|
|
-
|
|
|
|
- offset = 1 << bit;
|
|
|
|
-
|
|
|
|
-#ifdef RT_USING_HOOK
|
|
|
|
- if (rt_object_put_hook != RT_NULL) rt_object_put_hook(&(event->parent));
|
|
|
|
-#endif
|
|
|
|
-
|
|
|
|
- /* disable interrupt */
|
|
|
|
- level = rt_hw_interrupt_disable();
|
|
|
|
-
|
|
|
|
- event->set |= offset;
|
|
|
|
-
|
|
|
|
- /* does not schedule */
|
|
|
|
- need_schedule = RT_FALSE;
|
|
|
|
-
|
|
|
|
- /* if thread list at offset is not empty */
|
|
|
|
- n = event->thread_list[bit].next;
|
|
|
|
- while (n != &(event->thread_list[bit]))
|
|
|
|
- {
|
|
|
|
- /* get thread */
|
|
|
|
- thread = rt_list_entry(n, struct rt_thread, tlist);
|
|
|
|
-
|
|
|
|
- /* move to next node */
|
|
|
|
- n = n->next;
|
|
|
|
-
|
|
|
|
- /* resume thread */
|
|
|
|
- rt_thread_resume(thread);
|
|
|
|
-
|
|
|
|
- /* need do a scheduling */
|
|
|
|
- need_schedule = RT_TRUE;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /* enable interrupt */
|
|
|
|
- rt_hw_interrupt_enable(level);
|
|
|
|
-
|
|
|
|
- /* do a schedule */
|
|
|
|
- if (need_schedule == RT_TRUE)
|
|
|
|
- rt_schedule();
|
|
|
|
-
|
|
|
|
- return RT_EOK;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-/**
|
|
|
|
- * This function will receive an event from fast event object, if the event is
|
|
|
|
- * unavailable, the thread shall wait for a specified time.
|
|
|
|
- *
|
|
|
|
- * @param event the fast event object
|
|
|
|
- * @param bit the interested event
|
|
|
|
- * @param option the receive option
|
|
|
|
- * @param timeout the waiting time
|
|
|
|
- *
|
|
|
|
- * @return the error code
|
|
|
|
- */
|
|
|
|
-rt_err_t rt_fast_event_recv(rt_fast_event_t event, rt_uint8_t bit, rt_uint8_t option, rt_int32_t timeout)
|
|
|
|
-{
|
|
|
|
- rt_base_t offset;
|
|
|
|
- struct rt_thread* thread;
|
|
|
|
- register rt_ubase_t level;
|
|
|
|
-
|
|
|
|
- /* parameter check */
|
|
|
|
- RT_ASSERT(event != RT_NULL);
|
|
|
|
- RT_ASSERT(bit < RT_EVENT_LENGTH);
|
|
|
|
-
|
|
|
|
- offset = 1 << bit;
|
|
|
|
-
|
|
|
|
-#ifdef RT_USING_HOOK
|
|
|
|
- if (rt_object_trytake_hook != RT_NULL) rt_object_trytake_hook(&(event->parent));
|
|
|
|
-#endif
|
|
|
|
-
|
|
|
|
- /* disable interrupt */
|
|
|
|
- level = rt_hw_interrupt_disable();
|
|
|
|
-
|
|
|
|
- /* get current thread */
|
|
|
|
- thread = rt_thread_self();
|
|
|
|
- thread->error = RT_EOK;
|
|
|
|
-
|
|
|
|
- /* get event successfully */
|
|
|
|
- if (event->set & offset)
|
|
|
|
- {
|
|
|
|
- if (option & RT_EVENT_FLAG_CLEAR)
|
|
|
|
- event->set &= ~ offset;
|
|
|
|
-
|
|
|
|
- /* enable interrupt */
|
|
|
|
- rt_hw_interrupt_enable(level);
|
|
|
|
-
|
|
|
|
- return RT_EOK;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /* no event happen */
|
|
|
|
-
|
|
|
|
- /* check waiting time */
|
|
|
|
- if (timeout == 0)
|
|
|
|
- {
|
|
|
|
- /* no waiting */
|
|
|
|
- thread->error = -RT_ETIMEOUT;
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- /* there are no event, suspend thread */
|
|
|
|
- rt_thread_suspend(thread);
|
|
|
|
-
|
|
|
|
- /* set event info in thread */
|
|
|
|
- thread->event_info = option;
|
|
|
|
-
|
|
|
|
- switch (event->parent.flag)
|
|
|
|
- {
|
|
|
|
- case RT_IPC_FLAG_FIFO:
|
|
|
|
- rt_list_insert_after(&(event->thread_list[bit]), &(thread->tlist));
|
|
|
|
- break;
|
|
|
|
-
|
|
|
|
- case RT_IPC_FLAG_PRIO:
|
|
|
|
- {
|
|
|
|
- struct rt_list_node* n;
|
|
|
|
- struct rt_thread* sthread;
|
|
|
|
-
|
|
|
|
- /* find a suitable position */
|
|
|
|
- for (n = event->thread_list[bit].next; n != &(event->thread_list[bit]); n = n->next)
|
|
|
|
- {
|
|
|
|
- sthread = rt_list_entry(n, struct rt_thread, tlist);
|
|
|
|
-
|
|
|
|
- /* find out */
|
|
|
|
- if (thread->current_priority < sthread->current_priority) break;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /* insert thread */
|
|
|
|
- rt_list_insert_before(&(event->thread_list[bit]), &(thread->tlist));
|
|
|
|
- }
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /* if there is timeout, active thread timer */
|
|
|
|
- if (timeout > 0)
|
|
|
|
- {
|
|
|
|
- /* reset the timeout of thread timer and start it */
|
|
|
|
- rt_timer_control(&(thread->thread_timer), RT_TIMER_CTRL_SET_TIME, &timeout);
|
|
|
|
- rt_timer_start(&(thread->thread_timer));
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /* enable interrupt */
|
|
|
|
- rt_hw_interrupt_enable(level);
|
|
|
|
-
|
|
|
|
- /* do a schedule */
|
|
|
|
- rt_schedule();
|
|
|
|
-
|
|
|
|
- /* receive a fast event */
|
|
|
|
- if (thread->error != RT_EOK)
|
|
|
|
- {
|
|
|
|
- return thread->error;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /* received a event, disable interrupt to protect */
|
|
|
|
- level = rt_hw_interrupt_disable();
|
|
|
|
-
|
|
|
|
- /* clear event */
|
|
|
|
- if (option & RT_EVENT_FLAG_CLEAR)
|
|
|
|
- event->set &= ~offset;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /* enable interrupt */
|
|
|
|
- rt_hw_interrupt_enable(level);
|
|
|
|
-
|
|
|
|
-#ifdef RT_USING_HOOK
|
|
|
|
- if (rt_object_take_hook != RT_NULL) rt_object_take_hook(&(event->parent));
|
|
|
|
-#endif
|
|
|
|
-
|
|
|
|
- return thread->error;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-/**
|
|
|
|
- * This function can get or set some extra attributions of a fast event object.
|
|
|
|
- *
|
|
|
|
- * @param event the event object
|
|
|
|
- * @param cmd the execution command
|
|
|
|
- * @param arg the execution argument
|
|
|
|
- *
|
|
|
|
- * @return the error code
|
|
|
|
- */
|
|
|
|
-rt_err_t rt_fast_event_control (rt_fast_event_t event, rt_uint8_t cmd, void* arg)
|
|
|
|
-{
|
|
|
|
- return RT_EOK;
|
|
|
|
-}
|
|
|
|
-#endif
|
|
|
|
-
|
|
|
|
#ifdef RT_USING_EVENT
|
|
#ifdef RT_USING_EVENT
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -1317,7 +965,7 @@ rt_err_t rt_event_send(rt_event_t event, rt_uint32_t set)
|
|
{
|
|
{
|
|
if ((thread->event_set & event->set) == thread->event_set)
|
|
if ((thread->event_set & event->set) == thread->event_set)
|
|
{
|
|
{
|
|
- /* received a AND event */
|
|
|
|
|
|
+ /* received an AND event */
|
|
status = RT_EOK;
|
|
status = RT_EOK;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -1325,7 +973,10 @@ rt_err_t rt_event_send(rt_event_t event, rt_uint32_t set)
|
|
{
|
|
{
|
|
if (thread->event_set & event->set)
|
|
if (thread->event_set & event->set)
|
|
{
|
|
{
|
|
- /* received a OR event */
|
|
|
|
|
|
+ /* save recieved event set */
|
|
|
|
+ thread->event_set = thread->event_set & event->set;
|
|
|
|
+
|
|
|
|
+ /* received an OR event */
|
|
status = RT_EOK;
|
|
status = RT_EOK;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -1336,6 +987,10 @@ rt_err_t rt_event_send(rt_event_t event, rt_uint32_t set)
|
|
/* condition is satisfied, resume thread */
|
|
/* condition is satisfied, resume thread */
|
|
if (status == RT_EOK)
|
|
if (status == RT_EOK)
|
|
{
|
|
{
|
|
|
|
+ /* clear event */
|
|
|
|
+ if (thread->event_info & RT_EVENT_FLAG_CLEAR)
|
|
|
|
+ event->set &= ~thread->event_set;
|
|
|
|
+
|
|
/* resume thread, and thread list breaks out */
|
|
/* resume thread, and thread list breaks out */
|
|
rt_thread_resume(thread);
|
|
rt_thread_resume(thread);
|
|
|
|
|
|
@@ -1353,7 +1008,7 @@ rt_err_t rt_event_send(rt_event_t event, rt_uint32_t set)
|
|
|
|
|
|
/* do a schedule */
|
|
/* do a schedule */
|
|
if (need_schedule == RT_TRUE)
|
|
if (need_schedule == RT_TRUE)
|
|
- rt_schedule();
|
|
|
|
|
|
+ rt_schedule();
|
|
|
|
|
|
return RT_EOK;
|
|
return RT_EOK;
|
|
}
|
|
}
|
|
@@ -1407,7 +1062,7 @@ rt_err_t rt_event_recv(rt_event_t event, rt_uint32_t set, rt_uint8_t option, rt_
|
|
if (status == RT_EOK)
|
|
if (status == RT_EOK)
|
|
{
|
|
{
|
|
/* set received event */
|
|
/* set received event */
|
|
- *recved = event->set;
|
|
|
|
|
|
+ *recved = (event->set & set);
|
|
|
|
|
|
/* received event */
|
|
/* received event */
|
|
if (option & RT_EVENT_FLAG_CLEAR) event->set &= ~set;
|
|
if (option & RT_EVENT_FLAG_CLEAR) event->set &= ~set;
|
|
@@ -1447,15 +1102,11 @@ rt_err_t rt_event_recv(rt_event_t event, rt_uint32_t set, rt_uint8_t option, rt_
|
|
return thread->error;
|
|
return thread->error;
|
|
}
|
|
}
|
|
|
|
|
|
- /* received a event, disable interrupt to protect */
|
|
|
|
|
|
+ /* received an event, disable interrupt to protect */
|
|
level = rt_hw_interrupt_disable();
|
|
level = rt_hw_interrupt_disable();
|
|
|
|
|
|
- /* get received event */
|
|
|
|
- *recved = event->set;
|
|
|
|
-
|
|
|
|
- /* clear event */
|
|
|
|
- if (option & RT_EVENT_FLAG_CLEAR)
|
|
|
|
- event->set &= ~set;
|
|
|
|
|
|
+ /* set received event */
|
|
|
|
+ *recved = thread->event_set;
|
|
}
|
|
}
|
|
|
|
|
|
/* enable interrupt */
|
|
/* enable interrupt */
|
|
@@ -1680,6 +1331,7 @@ rt_err_t rt_mb_recv (rt_mailbox_t mb, rt_uint32_t* value, rt_int32_t timeout)
|
|
{
|
|
{
|
|
struct rt_thread *thread;
|
|
struct rt_thread *thread;
|
|
register rt_ubase_t temp;
|
|
register rt_ubase_t temp;
|
|
|
|
+ rt_uint32_t tick_delta;
|
|
|
|
|
|
/* parameter check */
|
|
/* parameter check */
|
|
RT_ASSERT(mb != RT_NULL);
|
|
RT_ASSERT(mb != RT_NULL);
|
|
@@ -1691,12 +1343,12 @@ rt_err_t rt_mb_recv (rt_mailbox_t mb, rt_uint32_t* value, rt_int32_t timeout)
|
|
/* disable interrupt */
|
|
/* disable interrupt */
|
|
temp = rt_hw_interrupt_disable();
|
|
temp = rt_hw_interrupt_disable();
|
|
|
|
|
|
|
|
+ /* get current thread */
|
|
|
|
+ thread = rt_thread_self();
|
|
|
|
+
|
|
/* mailbox is empty */
|
|
/* mailbox is empty */
|
|
- if (mb->entry == 0)
|
|
|
|
|
|
+ while (mb->entry == 0)
|
|
{
|
|
{
|
|
- /* get current thread */
|
|
|
|
- thread = rt_thread_self();
|
|
|
|
-
|
|
|
|
/* reset error number in thread */
|
|
/* reset error number in thread */
|
|
thread->error = RT_EOK;
|
|
thread->error = RT_EOK;
|
|
|
|
|
|
@@ -1716,8 +1368,11 @@ rt_err_t rt_mb_recv (rt_mailbox_t mb, rt_uint32_t* value, rt_int32_t timeout)
|
|
/* has waiting time, start thread timer */
|
|
/* has waiting time, start thread timer */
|
|
if (timeout > 0)
|
|
if (timeout > 0)
|
|
{
|
|
{
|
|
-#ifdef IPC_DEBUG
|
|
|
|
- rt_kprintf("set thread:%s to timer list\n", thread->name);
|
|
|
|
|
|
+ /* get the start tick of timer */
|
|
|
|
+ tick_delta = rt_tick_get();
|
|
|
|
+
|
|
|
|
+#ifdef RT_IPC_DEBUG
|
|
|
|
+ rt_kprintf("mb_recv: start timer of thread:%s\n", thread->name);
|
|
#endif
|
|
#endif
|
|
/* reset the timeout of thread timer and start it */
|
|
/* reset the timeout of thread timer and start it */
|
|
rt_timer_control(&(thread->thread_timer), RT_TIMER_CTRL_SET_TIME, &timeout);
|
|
rt_timer_control(&(thread->thread_timer), RT_TIMER_CTRL_SET_TIME, &timeout);
|
|
@@ -1730,16 +1385,23 @@ rt_err_t rt_mb_recv (rt_mailbox_t mb, rt_uint32_t* value, rt_int32_t timeout)
|
|
/* re-schedule */
|
|
/* re-schedule */
|
|
rt_schedule();
|
|
rt_schedule();
|
|
|
|
|
|
- /* recv message */
|
|
|
|
|
|
+ /* resume from suspend state */
|
|
if (thread->error != RT_EOK)
|
|
if (thread->error != RT_EOK)
|
|
{
|
|
{
|
|
- /* decrease suspended thread count */
|
|
|
|
|
|
+ /* can't recv message, decrease suspended thread count */
|
|
rt_ipc_object_decrease(&(mb->parent));
|
|
rt_ipc_object_decrease(&(mb->parent));
|
|
return thread->error;
|
|
return thread->error;
|
|
}
|
|
}
|
|
|
|
|
|
/* disable interrupt */
|
|
/* disable interrupt */
|
|
temp = rt_hw_interrupt_disable();
|
|
temp = rt_hw_interrupt_disable();
|
|
|
|
+
|
|
|
|
+ /* re-calculate timeout tick */
|
|
|
|
+ if (timeout > 0)
|
|
|
|
+ {
|
|
|
|
+ tick_delta = rt_tick_get() - tick_delta;
|
|
|
|
+ timeout -= tick_delta;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
/* fill ptr */
|
|
/* fill ptr */
|
|
@@ -2116,6 +1778,7 @@ rt_err_t rt_mq_recv (rt_mq_t mq, void* buffer, rt_size_t size, rt_int32_t timeou
|
|
struct rt_thread *thread;
|
|
struct rt_thread *thread;
|
|
register rt_ubase_t temp;
|
|
register rt_ubase_t temp;
|
|
struct rt_mq_message *msg;
|
|
struct rt_mq_message *msg;
|
|
|
|
+ rt_uint32_t tick_delta;
|
|
|
|
|
|
#ifdef RT_USING_HOOK
|
|
#ifdef RT_USING_HOOK
|
|
if (rt_object_trytake_hook != RT_NULL) rt_object_trytake_hook(&(mq->parent.parent));
|
|
if (rt_object_trytake_hook != RT_NULL) rt_object_trytake_hook(&(mq->parent.parent));
|
|
@@ -2124,12 +1787,12 @@ rt_err_t rt_mq_recv (rt_mq_t mq, void* buffer, rt_size_t size, rt_int32_t timeou
|
|
/* disable interrupt */
|
|
/* disable interrupt */
|
|
temp = rt_hw_interrupt_disable();
|
|
temp = rt_hw_interrupt_disable();
|
|
|
|
|
|
- /* mailbox is empty */
|
|
|
|
- if (mq->entry == 0)
|
|
|
|
|
|
+ /* get current thread */
|
|
|
|
+ thread = rt_thread_self();
|
|
|
|
+
|
|
|
|
+ /* message queue is empty */
|
|
|
|
+ while (mq->entry == 0)
|
|
{
|
|
{
|
|
- /* get current thread */
|
|
|
|
- thread = rt_thread_self();
|
|
|
|
-
|
|
|
|
/* reset error number in thread */
|
|
/* reset error number in thread */
|
|
thread->error = RT_EOK;
|
|
thread->error = RT_EOK;
|
|
|
|
|
|
@@ -2149,7 +1812,10 @@ rt_err_t rt_mq_recv (rt_mq_t mq, void* buffer, rt_size_t size, rt_int32_t timeou
|
|
/* has waiting time, start thread timer */
|
|
/* has waiting time, start thread timer */
|
|
if (timeout > 0)
|
|
if (timeout > 0)
|
|
{
|
|
{
|
|
-#ifdef IPC_DEBUG
|
|
|
|
|
|
+ /* get the start tick of timer */
|
|
|
|
+ tick_delta = rt_tick_get();
|
|
|
|
+
|
|
|
|
+#ifdef RT_IPC_DEBUG
|
|
rt_kprintf("set thread:%s to timer list\n", thread->name);
|
|
rt_kprintf("set thread:%s to timer list\n", thread->name);
|
|
#endif
|
|
#endif
|
|
/* reset the timeout of thread timer and start it */
|
|
/* reset the timeout of thread timer and start it */
|
|
@@ -2173,6 +1839,13 @@ rt_err_t rt_mq_recv (rt_mq_t mq, void* buffer, rt_size_t size, rt_int32_t timeou
|
|
|
|
|
|
/* disable interrupt */
|
|
/* disable interrupt */
|
|
temp = rt_hw_interrupt_disable();
|
|
temp = rt_hw_interrupt_disable();
|
|
|
|
+
|
|
|
|
+ /* re-calculate timeout tick */
|
|
|
|
+ if (timeout > 0)
|
|
|
|
+ {
|
|
|
|
+ tick_delta = rt_tick_get() - tick_delta;
|
|
|
|
+ timeout -= tick_delta;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
/* get message from queue */
|
|
/* get message from queue */
|
|
@@ -2221,13 +1894,4 @@ rt_err_t rt_mq_control(rt_mq_t mq, rt_uint8_t cmd, void* arg)
|
|
|
|
|
|
#endif /* end of RT_USING_MESSAGEQUEUE */
|
|
#endif /* end of RT_USING_MESSAGEQUEUE */
|
|
|
|
|
|
-/**
|
|
|
|
- * @ingroup SystemInit
|
|
|
|
- * This function will init IPC module.
|
|
|
|
- */
|
|
|
|
-void rt_system_ipc_init()
|
|
|
|
-{
|
|
|
|
- /* nothing to be done */
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
/*@}*/
|
|
/*@}*/
|