浏览代码

[Kernel] Add signal implementation.

1. Add signal implementation;
2. Change the 'rt_uint8_t' of cmd to 'int';
bernard 7 年之前
父节点
当前提交
b27c7e4826
共有 11 个文件被更改,包括 479 次插入34 次删除
  1. 8 1
      src/KConfig
  2. 12 2
      src/clock.c
  3. 5 0
      src/components.c
  4. 13 3
      src/device.c
  5. 4 0
      src/idle.c
  6. 15 13
      src/ipc.c
  7. 3 1
      src/kservice.c
  8. 17 4
      src/scheduler.c
  9. 382 0
      src/signal.c
  10. 19 9
      src/thread.c
  11. 1 1
      src/timer.c

+ 8 - 1
src/KConfig

@@ -39,7 +39,7 @@ config RT_USING_OVERFLOW_CHECK
 
 config RT_DEBUG_INIT
     int "Enable system initialization informat print"
-    default 1
+    default 0
     help
         print the procedure name of initialization
 
@@ -100,6 +100,13 @@ config RT_USING_MESSAGEQUEUE
     bool "Enable message queue"
     default y
 
+config RT_USING_SIGNALS
+    bool "Enable signals"
+    select RT_USING_MEMPOOL
+    default n
+    help
+        A signal is an asynchronous notification sent to a specific thread 
+        in order to notify it of an event that occurred.
 endmenu
 
 menu "Memory Management"

+ 12 - 2
src/clock.c

@@ -108,13 +108,23 @@ void rt_tick_increase(void)
  * This function will calculate the tick from millisecond.
  *
  * @param ms the specified millisecond
+ *           - Negative Number wait forever
+ *           - Zero not wait
+ *           - Max 0x7fffffff
  *
  * @return the calculated tick
  */
-rt_tick_t rt_tick_from_millisecond(rt_uint32_t ms)
+int rt_tick_from_millisecond(rt_int32_t ms)
 {
+    int tick;
+
+    if (ms < 0)
+        tick = RT_WAITING_FOREVER;
+    else
+        tick = (RT_TICK_PER_SECOND * ms + 999) / 1000;
+
     /* return the calculated tick */
-    return (RT_TICK_PER_SECOND * ms + 999) / 1000;
+    return tick;
 }
 RTM_EXPORT(rt_tick_from_millisecond);
 

+ 5 - 0
src/components.c

@@ -237,6 +237,11 @@ int rtthread_startup(void)
     /* scheduler system initialization */
     rt_system_scheduler_init();
 
+#ifdef RT_USING_SIGNALS
+    /* signal system initialization */
+    rt_system_signal_init();
+#endif
+
     /* create init_thread */
     rt_application_init();
 

+ 13 - 3
src/device.c

@@ -56,6 +56,11 @@ rt_err_t rt_device_register(rt_device_t dev,
     dev->ref_count = 0;
     dev->open_flag = 0;
 
+#if defined(RT_USING_DFS) && defined(RT_USING_DFS_DEVFS)
+    dev->fops = RT_NULL;
+    rt_list_init(&(dev->wait_queue));
+#endif
+
     return RT_EOK;
 }
 RTM_EXPORT(rt_device_register);
@@ -213,11 +218,16 @@ rt_err_t rt_device_open(rt_device_t dev, rt_uint16_t oflag)
     {
         result = dev->open(dev, oflag);
     }
+    else
+    {
+        /* set open flag */
+        dev->open_flag = (oflag & RT_DEVICE_OFLAG_MASK);
+    }
 
     /* set open flag */
     if (result == RT_EOK || result == -RT_ENOSYS)
     {
-        dev->open_flag = oflag | RT_DEVICE_OFLAG_OPEN;
+        dev->open_flag |= RT_DEVICE_OFLAG_OPEN;
 
         dev->ref_count++;
         /* don't let bad things happen silently. If you are bitten by this assert,
@@ -349,7 +359,7 @@ RTM_EXPORT(rt_device_write);
  *
  * @return the result
  */
-rt_err_t rt_device_control(rt_device_t dev, rt_uint8_t cmd, void *arg)
+rt_err_t rt_device_control(rt_device_t dev, int cmd, void *arg)
 {
     RT_ASSERT(dev != RT_NULL);
 
@@ -359,7 +369,7 @@ rt_err_t rt_device_control(rt_device_t dev, rt_uint8_t cmd, void *arg)
         return dev->control(dev, cmd, arg);
     }
 
-    return RT_EOK;
+    return -RT_ENOSYS;
 }
 RTM_EXPORT(rt_device_control);
 

+ 4 - 0
src/idle.c

@@ -127,6 +127,10 @@ void rt_thread_idle_excute(void)
             if (thread->cleanup != RT_NULL)
                 thread->cleanup(thread);
 
+#ifdef RT_USING_SIGNALS
+            rt_thread_free_sig(thread);
+#endif
+
             /* if it's a system object, not delete it */
             if (rt_object_is_systemobject((rt_object_t)thread) == RT_TRUE)
             {

+ 15 - 13
src/ipc.c

@@ -478,7 +478,7 @@ RTM_EXPORT(rt_sem_release);
  *
  * @return the error code
  */
-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, int cmd, void *arg)
 {
     rt_ubase_t level;
     RT_ASSERT(sem != RT_NULL);
@@ -644,14 +644,13 @@ rt_err_t rt_mutex_take(rt_mutex_t mutex, rt_int32_t time)
     register rt_base_t temp;
     struct rt_thread *thread;
 
+    /* this function must not be used in interrupt even if time = 0 */
+    RT_DEBUG_IN_THREAD_CONTEXT;
+
     RT_ASSERT(mutex != RT_NULL);
 
     /* get current thread */
     thread = rt_thread_self();
-    if (!thread) return RT_EOK; /* return directory if scheduler not started */
-
-    /* this function must not be used in interrupt even if time = 0 */
-    RT_DEBUG_IN_THREAD_CONTEXT;
 
     /* disable interrupt */
     temp = rt_hw_interrupt_disable();
@@ -672,6 +671,7 @@ rt_err_t rt_mutex_take(rt_mutex_t mutex, rt_int32_t time)
     }
     else
     {
+__again:
         /* The value of mutex is 1 in initial status. Therefore, if the
          * value is great than 0, it indicates the mutex is avaible.
          */
@@ -740,6 +740,9 @@ rt_err_t rt_mutex_take(rt_mutex_t mutex, rt_int32_t time)
 
                 if (thread->error != RT_EOK)
                 {
+                	/* interrupt by signal, try it again */
+                	if (thread->error == -RT_EINTR) goto __again;
+
                     /* return error */
                     return thread->error;
                 }
@@ -778,13 +781,12 @@ rt_err_t rt_mutex_release(rt_mutex_t mutex)
 
     need_schedule = RT_FALSE;
 
-    /* get current thread */
-    thread = rt_thread_self();
-    if (!thread) return RT_EOK;
-
     /* only thread could release mutex because we need test the ownership */
     RT_DEBUG_IN_THREAD_CONTEXT;
 
+    /* get current thread */
+    thread = rt_thread_self();
+
     /* disable interrupt */
     temp = rt_hw_interrupt_disable();
 
@@ -870,7 +872,7 @@ RTM_EXPORT(rt_mutex_release);
  *
  * @return the error code
  */
-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, int cmd, void *arg)
 {
     return -RT_ERROR;
 }
@@ -1212,7 +1214,7 @@ RTM_EXPORT(rt_event_recv);
  *
  * @return the error code
  */
-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, int cmd, void *arg)
 {
     rt_ubase_t level;
     RT_ASSERT(event != RT_NULL);
@@ -1687,7 +1689,7 @@ RTM_EXPORT(rt_mb_recv);
  *
  * @return the error code
  */
-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, int cmd, void *arg)
 {
     rt_ubase_t level;
     RT_ASSERT(mb != RT_NULL);
@@ -2235,7 +2237,7 @@ RTM_EXPORT(rt_mq_recv);
  *
  * @return the error code
  */
-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, int cmd, void *arg)
 {
     rt_ubase_t level;
     struct rt_mq_message *msg;

+ 3 - 1
src/kservice.c

@@ -1114,6 +1114,8 @@ RTM_EXPORT(rt_hw_console_output);
  */
 void rt_kputs(const char *str)
 {
+    if (!str) return;
+
 #ifdef RT_USING_DEVICE
     if (_console_device == RT_NULL)
     {
@@ -1265,7 +1267,7 @@ const rt_uint8_t __lowest_bit_bitmap[] =
  * @return return the index of the first bit set. If value is 0, then this function
  * shall return 0.
  */
-rt_ubase_t __rt_ffs(rt_ubase_t value)
+int __rt_ffs(int value)
 {
     if (value == 0) return 0;
 

+ 17 - 4
src/scheduler.c

@@ -42,7 +42,6 @@
 
 static rt_int16_t rt_scheduler_lock_nest;
 extern volatile rt_uint8_t rt_interrupt_nest;
-extern rt_ubase_t __rt_ffs(rt_ubase_t value);
 
 rt_list_t rt_thread_priority_table[RT_THREAD_PRIORITY_MAX];
 struct rt_thread *rt_current_thread;
@@ -241,8 +240,18 @@ void rt_schedule(void)
 
             if (rt_interrupt_nest == 0)
             {
+                extern void rt_thread_handle_sig(rt_bool_t clean_state);
+
                 rt_hw_context_switch((rt_uint32_t)&from_thread->sp,
                                      (rt_uint32_t)&to_thread->sp);
+
+                /* enable interrupt */
+                rt_hw_interrupt_enable(level);
+
+#ifdef RT_USING_SIGNALS
+                /* check signal status */
+                rt_thread_handle_sig(RT_TRUE);
+#endif
             }
             else
             {
@@ -250,12 +259,16 @@ void rt_schedule(void)
 
                 rt_hw_context_switch_interrupt((rt_uint32_t)&from_thread->sp,
                                                (rt_uint32_t)&to_thread->sp);
+                /* enable interrupt */
+                rt_hw_interrupt_enable(level);
             }
         }
+        else 
+        {
+            /* enable interrupt */
+            rt_hw_interrupt_enable(level);
+        }
     }
-
-    /* enable interrupt */
-    rt_hw_interrupt_enable(level);
 }
 
 /*

+ 382 - 0
src/signal.c

@@ -0,0 +1,382 @@
+/*
+ * File      : signal.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2017, RT-Thread Development Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2017/10/5      Bernard      the first version
+ */
+
+#include <stdint.h>
+#include <string.h>
+
+#include <rthw.h>
+#include <rtthread.h>
+
+#ifdef RT_USING_SIGNALS
+
+#ifndef RT_SIG_INFO_MAX
+#define RT_SIG_INFO_MAX	32
+#endif
+
+// #define DBG_ENABLE
+#define DBG_SECTION_NAME    "[SIGN]"
+#define DBG_COLOR
+#define DBG_LEVEL           DBG_LOG
+#include <rtdbg.h>
+
+#define sig_mask(sig_no)    (1u << sig_no)
+#define sig_valid(sig_no)   (sig_no >= 0 && sig_no < RT_SIG_MAX)
+
+struct siginfo_node
+{
+    struct siginfo si;
+    struct rt_slist_node list;
+};
+
+static struct rt_mempool *_rt_siginfo_pool;
+static void _signal_deliver(rt_thread_t tid);
+void rt_thread_handle_sig(rt_bool_t clean_state);
+
+static void _signal_default_handler(int signo)
+{
+    dbg_log(DBG_INFO, "handled signo[%d] with default action.\n", signo);
+    return ;
+}
+
+static void _signal_entry(void* parameter)
+{
+    rt_thread_t tid = rt_thread_self();
+
+    dbg_enter;
+
+    /* handle signal */
+    rt_thread_handle_sig(RT_FALSE);
+
+	/* never come back... */
+	rt_hw_interrupt_disable();
+    /* return to thread */
+    tid->sp = tid->sig_ret;
+    tid->sig_ret = RT_NULL;
+
+    dbg_log(DBG_LOG, "switch back to: 0x%08x\n", tid->sp);
+    tid->stat &= ~RT_THREAD_STAT_SIGNAL;
+
+    rt_hw_context_switch_to((rt_uint32_t)&(tid->sp));
+}
+
+static void _signal_deliver(rt_thread_t tid)
+{
+    rt_ubase_t level;
+
+    /* thread is not interested in pended signals */
+    if (!(tid->sig_pending & tid->sig_mask)) return;
+
+    level = rt_hw_interrupt_disable();
+    if (tid->stat == RT_THREAD_SUSPEND)
+    {
+        /* resume thread to handle signal */
+        rt_thread_resume(tid);
+		/* add signal state */
+		tid->stat |= RT_THREAD_STAT_SIGNAL;
+
+        rt_hw_interrupt_enable(level);
+
+        /* re-schedule */
+        rt_schedule();
+    }
+    else
+    {
+        if (tid == rt_thread_self())
+        {
+			/* add signal state */
+			tid->stat |= RT_THREAD_STAT_SIGNAL;
+            rt_hw_interrupt_enable(level);
+
+            /* do signal action in self thread context */
+            rt_thread_handle_sig(RT_TRUE);
+        }
+        else if (!(tid->stat & RT_THREAD_STAT_SIGNAL))
+        {
+            tid->stat |= RT_THREAD_STAT_SIGNAL;
+            /* point to the signal handle entry */
+            tid->sig_ret = tid->sp;
+            tid->sp = rt_hw_stack_init((void*)_signal_entry, RT_NULL, 
+                (void *)((char *)tid->sig_ret - 32), RT_NULL);
+
+            rt_hw_interrupt_enable(level);
+            dbg_log(DBG_LOG, "signal stack pointer @ 0x%08x\n", tid->sp);
+
+            /* re-schedule */
+            rt_schedule();
+        }
+        else
+        {
+            rt_hw_interrupt_enable(level);
+        }
+    }
+}
+
+rt_sighandler_t rt_signal_install(int signo, rt_sighandler_t handler)
+{
+    rt_sighandler_t old;
+    rt_thread_t tid = rt_thread_self();
+
+	if (!sig_valid(signo)) return SIG_ERR;
+
+    rt_enter_critical();
+    if (tid->sig_vectors == RT_NULL)
+    {
+        rt_thread_alloc_sig(tid);
+    }
+
+    if (tid->sig_vectors)
+    {
+        old = tid->sig_vectors[signo];
+
+        if (handler == SIG_IGN) tid->sig_vectors[signo] = RT_NULL;
+        else if (handler == SIG_DFL) tid->sig_vectors[signo] = _signal_default_handler;
+        else tid->sig_vectors[signo] = handler;
+    }
+    rt_exit_critical();
+
+    return old;
+}
+
+void rt_signal_mask(int signo)
+{
+    rt_base_t level;
+    rt_thread_t tid = rt_thread_self();
+
+    level = rt_hw_interrupt_disable();
+
+    tid->sig_mask &= ~sig_mask(signo);
+
+    rt_hw_interrupt_enable(level);
+}
+
+void rt_signal_unmask(int signo)
+{
+    rt_base_t level;
+    rt_thread_t tid = rt_thread_self();
+
+    level = rt_hw_interrupt_disable();
+
+    tid->sig_mask |= sig_mask(signo);
+
+    /* let thread handle pended signals */
+    if (tid->sig_mask & tid->sig_pending)
+    {
+        rt_hw_interrupt_enable(level);
+        _signal_deliver(tid);
+    }
+    else 
+    {
+        rt_hw_interrupt_enable(level);
+    }
+}
+
+void rt_thread_handle_sig(rt_bool_t clean_state)
+{
+	rt_base_t level;
+
+    rt_thread_t tid = rt_thread_self();
+    struct siginfo_node *si_node;
+
+	level = rt_hw_interrupt_disable();
+    while (tid->sig_pending & tid->sig_mask)
+    {
+        int signo, error;
+        rt_sighandler_t handler;
+
+		si_node = (struct siginfo_node *)tid->si_list;
+		if (!si_node) break;
+
+		/* remove this sig info node from list */
+        if (si_node->list.next == RT_NULL)
+            tid->si_list = RT_NULL;
+        else
+            tid->si_list = (void*)rt_slist_entry(si_node->list.next, struct siginfo_node, list);
+
+        signo   = si_node->si.si_signo;
+        handler = tid->sig_vectors[signo];
+		rt_hw_interrupt_enable(level);
+
+        dbg_log(DBG_LOG, "handle signal: %d, handler 0x%08x\n", signo, handler);
+        if (handler) handler(signo);
+
+		level = rt_hw_interrupt_disable();
+        tid->sig_pending &= ~sig_mask(signo);
+        error = si_node->si.si_errno;
+
+        rt_mp_free(si_node); /* release this siginfo node */
+        /* set errno in thread tcb */
+        tid->error = error;
+    }
+
+	/* whether clean signal status */
+	if (clean_state == RT_TRUE) tid->stat &= ~RT_THREAD_STAT_SIGNAL;
+
+	rt_hw_interrupt_enable(level);
+}
+
+void rt_thread_alloc_sig(rt_thread_t tid)
+{
+    int index;
+    rt_base_t level;
+    rt_sighandler_t *vectors;
+
+    vectors = (rt_sighandler_t *)RT_KERNEL_MALLOC(sizeof(rt_sighandler_t) * RT_SIG_MAX);
+    RT_ASSERT(vectors != RT_NULL);
+
+    for (index = 0; index < RT_SIG_MAX; index ++)
+    {
+        vectors[index] = _signal_default_handler;
+    }
+
+    level = rt_hw_interrupt_disable();
+    tid->sig_vectors = vectors;
+    rt_hw_interrupt_enable(level);
+}
+
+void rt_thread_free_sig(rt_thread_t tid)
+{
+    rt_base_t level;
+    struct siginfo_node *si_list;
+    rt_sighandler_t *sig_vectors;
+
+    level = rt_hw_interrupt_disable();
+    si_list = (struct siginfo_node*)tid->si_list;
+    tid->si_list = RT_NULL;
+    
+    sig_vectors = tid->sig_vectors;
+    tid->sig_vectors = RT_NULL;
+    rt_hw_interrupt_enable(level);
+
+    if (si_list)
+    {
+        struct rt_slist_node *node;
+        struct siginfo_node  *si_node;
+
+        dbg_log(DBG_LOG, "free signal info list\n");
+        node = &(si_list->list);
+        do {
+            si_node = rt_slist_entry(node, struct siginfo_node, list);
+            rt_mp_free(si_node);
+
+            node = node->next;
+        } while (node);
+    }
+
+    if (sig_vectors)
+    {
+        RT_KERNEL_FREE(sig_vectors);
+    }
+}
+
+int rt_thread_kill(rt_thread_t tid, int sig)
+{
+    siginfo_t si;
+	rt_base_t level;
+	struct siginfo_node *si_node;
+
+    RT_ASSERT(tid != RT_NULL);
+    if (!sig_valid(sig)) return -RT_EINVAL;
+
+    dbg_log(DBG_INFO, "send signal: %d\n", sig);
+    si.si_errno = RT_EINTR;
+    si.si_signo = sig;
+    si.si_code  = SI_USER;
+    si.si_value.sival_ptr = RT_NULL;
+
+	level = rt_hw_interrupt_disable();
+    if (tid->sig_pending & sig_mask(sig))
+    {
+        /* whether already emits this signal? */
+        struct rt_slist_node *node;
+        struct siginfo_node  *entry;
+
+		node = (struct rt_slist_node *)tid->si_list;
+		rt_hw_interrupt_enable(level);
+
+		/* update sig infor */
+		rt_enter_critical();
+        for (; (node) != RT_NULL; node = node->next)
+        {
+            entry = rt_slist_entry(node, struct siginfo_node, list);
+            if (entry->si.si_signo == sig)
+            {
+                memcpy(&(entry->si), &si, sizeof(siginfo_t));
+				rt_exit_critical();
+                return 0;
+            }
+        }
+		rt_exit_critical();
+
+		/* disable interrupt to protect tcb */
+		level = rt_hw_interrupt_disable();
+    }
+	else
+	{
+		/* a new signal */
+	    tid->sig_pending |= sig_mask(sig);
+	}
+	rt_hw_interrupt_enable(level);
+
+    si_node = (struct siginfo_node*) rt_mp_alloc(_rt_siginfo_pool, 0);
+    if (si_node)
+    {
+        rt_slist_init(&(si_node->list));
+        memcpy(&(si_node->si), &si, sizeof(siginfo_t));
+
+		level = rt_hw_interrupt_disable();
+        if (!tid->si_list) tid->si_list = si_node;
+        else 
+        {
+        	struct siginfo_node *si_list;
+
+            si_list = (struct siginfo_node*)tid->si_list;
+            rt_slist_append(&(si_list->list), &(si_node->list));
+        }
+		rt_hw_interrupt_enable(level);
+    }
+    else
+    {
+        dbg_log(DBG_ERROR, "The allocation of signal infor node failed.\n");
+    }
+
+    /* deliver signal to this thread */
+    _signal_deliver(tid);
+
+    return RT_EOK;
+}
+
+int rt_system_signal_init(void)
+{
+    _rt_siginfo_pool = rt_mp_create("signal", RT_SIG_INFO_MAX, sizeof(struct siginfo_node));
+    if (_rt_siginfo_pool == RT_NULL)
+    {
+        dbg_log(DBG_ERROR, "create memory pool for signal info failed.\n");
+        RT_ASSERT(0);
+    }
+
+    return 0;
+}
+
+#endif
+

+ 19 - 9
src/thread.c

@@ -185,6 +185,16 @@ static rt_err_t _rt_thread_init(struct rt_thread *thread,
                   0,
                   RT_TIMER_FLAG_ONE_SHOT);
 
+    /* initialize signal */
+#ifdef RT_USING_SIGNALS
+    thread->sig_mask    = 0x00;
+    thread->sig_pending = 0x00;
+
+    thread->sig_ret     = RT_NULL;
+    thread->sig_vectors = RT_NULL;
+    thread->si_list     = RT_NULL;
+#endif
+
     RT_OBJECT_HOOK_CALL(rt_thread_inited_hook, (thread));
 
     return RT_EOK;
@@ -260,7 +270,7 @@ rt_err_t rt_thread_startup(rt_thread_t thread)
 {
     /* thread check */
     RT_ASSERT(thread != RT_NULL);
-    RT_ASSERT(thread->stat == RT_THREAD_INIT);
+    RT_ASSERT((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_INIT);
 
     /* set current priority to init priority */
     thread->current_priority = thread->init_priority;
@@ -305,7 +315,7 @@ rt_err_t rt_thread_detach(rt_thread_t thread)
     /* thread check */
     RT_ASSERT(thread != RT_NULL);
 
-    if (thread->stat != RT_THREAD_INIT)
+    if ((thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_INIT)
     {
         /* remove from schedule */
         rt_schedule_remove_thread(thread);
@@ -403,7 +413,7 @@ rt_err_t rt_thread_delete(rt_thread_t thread)
     /* thread check */
     RT_ASSERT(thread != RT_NULL);
 
-    if (thread->stat != RT_THREAD_INIT)
+    if ((thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_INIT)
     {
         /* remove from schedule */
         rt_schedule_remove_thread(thread);
@@ -448,7 +458,7 @@ rt_err_t rt_thread_yield(void)
     thread = rt_current_thread;
 
     /* if the thread stat is READY and on ready queue list */
-    if (thread->stat == RT_THREAD_READY &&
+    if ((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_READY &&
         thread->tlist.next != thread->tlist.prev)
     {
         /* remove thread from thread list */
@@ -535,7 +545,7 @@ RTM_EXPORT(rt_thread_delay);
  *
  * @return RT_EOK
  */
-rt_err_t rt_thread_control(rt_thread_t thread, rt_uint8_t cmd, void *arg)
+rt_err_t rt_thread_control(rt_thread_t thread, int cmd, void *arg)
 {
     register rt_base_t temp;
 
@@ -549,7 +559,7 @@ rt_err_t rt_thread_control(rt_thread_t thread, rt_uint8_t cmd, void *arg)
         temp = rt_hw_interrupt_disable();
 
         /* for ready thread, change queue */
-        if (thread->stat == RT_THREAD_READY)
+        if ((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_READY)
         {
             /* remove thread from schedule queue first */
             rt_schedule_remove_thread(thread);
@@ -622,7 +632,7 @@ rt_err_t rt_thread_suspend(rt_thread_t thread)
 
     RT_DEBUG_LOG(RT_DEBUG_THREAD, ("thread suspend:  %s\n", thread->name));
 
-    if (thread->stat != RT_THREAD_READY)
+    if ((thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_READY)
     {
         RT_DEBUG_LOG(RT_DEBUG_THREAD, ("thread suspend: thread disorder, %d\n",
                                        thread->stat));
@@ -664,7 +674,7 @@ rt_err_t rt_thread_resume(rt_thread_t thread)
 
     RT_DEBUG_LOG(RT_DEBUG_THREAD, ("thread resume:  %s\n", thread->name));
 
-    if (thread->stat != RT_THREAD_SUSPEND)
+    if ((thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_SUSPEND)
     {
         RT_DEBUG_LOG(RT_DEBUG_THREAD, ("thread resume: thread disorder, %d\n",
                                        thread->stat));
@@ -705,7 +715,7 @@ void rt_thread_timeout(void *parameter)
 
     /* thread check */
     RT_ASSERT(thread != RT_NULL);
-    RT_ASSERT(thread->stat == RT_THREAD_SUSPEND);
+    RT_ASSERT((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_SUSPEND);
 
     /* set error number */
     thread->error = -RT_ETIMEOUT;

+ 1 - 1
src/timer.c

@@ -451,7 +451,7 @@ RTM_EXPORT(rt_timer_stop);
  *
  * @return RT_EOK
  */
-rt_err_t rt_timer_control(rt_timer_t timer, rt_uint8_t cmd, void *arg)
+rt_err_t rt_timer_control(rt_timer_t timer, int cmd, void *arg)
 {
     /* timer check */
     RT_ASSERT(timer != RT_NULL);