Browse Source

规范signal号,先把所有suspend置于uninterruptible状态

shaojinchun 4 years ago
parent
commit
b3404e9901

+ 1 - 1
bsp/gkipc/armv6/rtos_lib.c

@@ -663,7 +663,7 @@ U32 msleep( U32 msecs )
 
 U32 RTOS_SuspendThread( RTOS_ThreadT threadHandle )
 {
-    return rt_thread_suspend((rt_thread_t)threadHandle);
+    return rt_thread_suspend((rt_thread_t)threadHandle, RT_UNINTERRUPTIBLE);
 }
 
 U32 RTOS_WakeupThread( RTOS_ThreadT threadHandle )

+ 1 - 1
components/dfs/src/poll.c

@@ -95,7 +95,7 @@ static int poll_wait_timeout(struct rt_poll_table *pt, int msec)
 
     if (timeout != 0 && !pt->triggered)
     {
-        rt_thread_suspend(thread);
+        rt_thread_suspend(thread, RT_UNINTERRUPTIBLE);
         if (timeout > 0)
         {
             rt_timer_control(&(thread->thread_timer),

+ 2 - 2
components/drivers/audio/audio_pipe.c

@@ -72,7 +72,7 @@ static rt_size_t rt_pipe_read(rt_device_t dev,
         read_nbytes = rt_ringbuffer_get(&(pipe->ringbuffer), (rt_uint8_t *)buffer, size);
         if (read_nbytes == 0)
         {
-            rt_thread_suspend(thread);
+            rt_thread_suspend(thread, RT_UNINTERRUPTIBLE);
             /* waiting on suspended read list */
             rt_list_insert_before(&(pipe->suspended_read_list),
                                   &(thread->tlist));
@@ -160,7 +160,7 @@ static rt_size_t rt_pipe_write(rt_device_t dev,
         if (write_nbytes == 0)
         {
             /* pipe full, waiting on suspended write list */
-            rt_thread_suspend(thread);
+            rt_thread_suspend(thread, RT_UNINTERRUPTIBLE);
             /* waiting on suspended read list */
             rt_list_insert_before(&(pipe->suspended_write_list),
                                   &(thread->tlist));

+ 1 - 1
components/drivers/src/completion.c

@@ -55,7 +55,7 @@ rt_err_t rt_completion_wait(struct rt_completion *completion,
             thread->error = RT_EOK;
 
             /* suspend thread */
-            rt_thread_suspend(thread);
+            rt_thread_suspend(thread, RT_UNINTERRUPTIBLE);
             /* add to suspended list */
             rt_list_insert_before(&(completion->suspended_list),
                                   &(thread->tlist));

+ 15 - 15
components/drivers/src/dataqueue.c

@@ -62,7 +62,7 @@ rt_err_t rt_data_queue_push(struct rt_data_queue *queue,
     rt_ubase_t  level;
     rt_thread_t thread;
     rt_err_t    result;
-    
+
     RT_ASSERT(queue != RT_NULL);
     RT_ASSERT(queue->magic == DATAQUEUE_MAGIC);
 
@@ -85,9 +85,9 @@ rt_err_t rt_data_queue_push(struct rt_data_queue *queue,
 
         /* reset thread error number */
         thread->error = RT_EOK;
-        
+
         /* suspend thread on the push list */
-        rt_thread_suspend(thread);
+        rt_thread_suspend(thread, RT_UNINTERRUPTIBLE);
         rt_list_insert_before(&(queue->suspended_push_list), &(thread->tlist));
         /* start timer */
         if (timeout > 0)
@@ -155,13 +155,13 @@ RTM_EXPORT(rt_data_queue_push);
 
 rt_err_t rt_data_queue_pop(struct rt_data_queue *queue,
                            const void** data_ptr,
-                           rt_size_t *size, 
+                           rt_size_t *size,
                            rt_int32_t timeout)
 {
     rt_ubase_t  level;
     rt_thread_t thread;
     rt_err_t    result;
-    
+
     RT_ASSERT(queue != RT_NULL);
     RT_ASSERT(queue->magic == DATAQUEUE_MAGIC);
     RT_ASSERT(data_ptr != RT_NULL);
@@ -185,9 +185,9 @@ rt_err_t rt_data_queue_pop(struct rt_data_queue *queue,
 
         /* reset thread error number */
         thread->error = RT_EOK;
-        
+
         /* suspend thread on the pop list */
-        rt_thread_suspend(thread);
+        rt_thread_suspend(thread, RT_UNINTERRUPTIBLE);
         rt_list_insert_before(&(queue->suspended_pop_list), &(thread->tlist));
         /* start timer */
         if (timeout > 0)
@@ -269,11 +269,11 @@ rt_err_t rt_data_queue_peak(struct rt_data_queue *queue,
                             rt_size_t *size)
 {
     rt_ubase_t  level;
-    
+
     RT_ASSERT(queue != RT_NULL);
     RT_ASSERT(queue->magic == DATAQUEUE_MAGIC);
 
-    if (queue->is_empty) 
+    if (queue->is_empty)
     {
         return -RT_EEMPTY;
     }
@@ -293,7 +293,7 @@ void rt_data_queue_reset(struct rt_data_queue *queue)
 {
     rt_ubase_t  level;
     struct rt_thread *thread;
-    
+
     RT_ASSERT(queue != RT_NULL);
     RT_ASSERT(queue->magic == DATAQUEUE_MAGIC);
 
@@ -303,9 +303,9 @@ void rt_data_queue_reset(struct rt_data_queue *queue)
     queue->put_index = 0;
     queue->is_empty = 1;
     queue->is_full = 0;
-    
+
     rt_hw_interrupt_enable(level);
-    
+
     rt_enter_critical();
     /* wakeup all suspend threads */
 
@@ -375,7 +375,7 @@ rt_err_t rt_data_queue_deinit(struct rt_data_queue *queue)
     level = rt_hw_interrupt_disable();
     queue->magic = 0;
     rt_hw_interrupt_enable(level);
-    
+
     rt_free(queue->queue);
 
     return RT_EOK;
@@ -386,7 +386,7 @@ rt_uint16_t rt_data_queue_len(struct rt_data_queue *queue)
 {
     rt_ubase_t level;
     rt_int16_t len;
-    
+
     RT_ASSERT(queue != RT_NULL);
     RT_ASSERT(queue->magic == DATAQUEUE_MAGIC);
 
@@ -405,7 +405,7 @@ rt_uint16_t rt_data_queue_len(struct rt_data_queue *queue)
     {
         len = queue->size + queue->put_index - queue->get_index;
     }
-    
+
     rt_hw_interrupt_enable(level);
 
     return len;

+ 1 - 1
components/drivers/src/waitqueue.c

@@ -103,7 +103,7 @@ int rt_wqueue_wait(rt_wqueue_t *queue, int condition, int msec)
     }
 
     rt_wqueue_add(queue, &__wait);
-    rt_thread_suspend(tid);
+    rt_thread_suspend(tid, RT_UNINTERRUPTIBLE);
 
     /* start timer */
     if (tick != RT_WAITING_FOREVER)

+ 1 - 1
components/drivers/src/workqueue.c

@@ -61,7 +61,7 @@ static void _workqueue_thread_entry(void *parameter)
         if (rt_list_isempty(&(queue->work_list)))
         {
             /* no software timer exist, suspend self. */
-            rt_thread_suspend(rt_thread_self());
+            rt_thread_suspend(rt_thread_self(), RT_UNINTERRUPTIBLE);
             rt_schedule();
         }
 

+ 1 - 1
components/libc/compilers/newlib/syscalls.c

@@ -431,7 +431,7 @@ void abort(void)
         rt_thread_t self = rt_thread_self();
 
         rt_kprintf("thread:%-8.*s abort!\n", RT_NAME_MAX, self->name);
-        rt_thread_suspend(self);
+        rt_thread_suspend(self, RT_UNINTERRUPTIBLE);
 
         rt_schedule();
     }

+ 1 - 1
components/libc/libdl/dlmodule.c

@@ -128,7 +128,7 @@ static void _dlmodule_exit(void)
                     (thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_INIT)
                 {
                     rt_timer_stop(&(thread->thread_timer));
-                    rt_thread_suspend(thread);
+                    rt_thread_suspend(thread, RT_UNINTERRUPTIBLE);
                 }
             }
         }

+ 5 - 0
components/lwp/arch/arm/cortex-a/lwp_arch.h

@@ -28,6 +28,11 @@ void *arch_kernel_mmu_table_get(void);
 void arch_kuser_init(rt_mmu_info *mmu_info, void *vectors);
 int arch_expand_user_stack(void *addr);
 
+rt_inline unsigned long ffz(unsigned long x)
+{
+    return __builtin_ffs(~x) - 1;
+}
+
 #ifdef __cplusplus
 }
 #endif

+ 3 - 3
components/lwp/lwp.h

@@ -81,11 +81,11 @@ struct rt_lwp
     struct dfs_fdtable fdt;
     char cmd[RT_NAME_MAX];
 
-    rt_uint32_t signal;
+    lwp_sigset_t signal;
     lwp_sigset_t signal_mask;
-    lwp_sigset_t signal_mask_bak;
+    int signal_mask_bak;
     rt_uint32_t signal_in_process;
-    lwp_sighandler_t signal_handler[32];
+    lwp_sighandler_t signal_handler[_LWP_NSIG];
 
     rt_list_t object_list;
     struct rt_user_context user_ctx;

+ 1 - 1
components/lwp/lwp_ipc.c

@@ -138,7 +138,7 @@ rt_inline rt_err_t rt_channel_list_resume_all(rt_list_t *list)
 rt_inline rt_err_t rt_channel_list_suspend(rt_list_t *list, struct rt_thread *thread)
 {
     /* suspend thread */
-    rt_thread_suspend(thread);
+    rt_thread_suspend(thread, RT_UNINTERRUPTIBLE);
 
     rt_list_insert_before(list, &(thread->tlist));  /* list end */
 

+ 1 - 1
components/lwp/lwp_pid.c

@@ -410,7 +410,7 @@ pid_t waitpid(pid_t pid, int *status, int options)
             goto quit;
         }
         thread = rt_thread_self();
-        rt_thread_suspend(thread);
+        rt_thread_suspend(thread, RT_UNINTERRUPTIBLE);
         rt_list_insert_before(&lwp->wait_list, &(thread->tlist));
         rt_schedule();
         if (thread->error == RT_EOK)

+ 198 - 66
components/lwp/lwp_signal.c

@@ -12,13 +12,116 @@
 #include <rtthread.h>
 
 #include "lwp.h"
+#include "lwp_arch.h"
+#include "signal.h"
+
+rt_inline void lwp_sigaddset(lwp_sigset_t *set, int _sig)
+{
+    unsigned long sig = _sig - 1;
+
+    if (_LWP_NSIG_WORDS == 1)
+    {
+        set->sig[0] |= 1UL << sig;
+    }
+    else
+    {
+        set->sig[sig / _LWP_NSIG_BPW] |= 1UL << (sig % _LWP_NSIG_BPW);
+    }
+}
+
+rt_inline void lwp_sigdelset(lwp_sigset_t *set, int _sig)
+{
+    unsigned long sig = _sig - 1;
+
+    if (_LWP_NSIG_WORDS == 1)
+    {
+        set->sig[0] &= ~(1UL << sig);
+    }
+    else
+    {
+        set->sig[sig / _LWP_NSIG_BPW] &= ~(1UL << (sig % _LWP_NSIG_BPW));
+    }
+}
+
+rt_inline int lwp_sigisemptyset(lwp_sigset_t *set)
+{
+    switch (_LWP_NSIG_WORDS)
+    {
+        case 4:
+            return (set->sig[3] | set->sig[2] |
+                    set->sig[1] | set->sig[0]) == 0;
+        case 2:
+            return (set->sig[1] | set->sig[0]) == 0;
+        case 1:
+            return set->sig[0] == 0;
+        default:
+            return 1;
+    }
+}
+
+rt_inline int lwp_sigismember(lwp_sigset_t *set, int _sig)
+{
+    unsigned long sig = _sig - 1;
+
+    if (_LWP_NSIG_WORDS == 1)
+    {
+        return 1 & (set->sig[0] >> sig);
+    }
+    else
+    {
+        return 1 & (set->sig[sig / _LWP_NSIG_BPW] >> (sig % _LWP_NSIG_BPW));
+    }
+}
+
+rt_inline int next_signal(lwp_sigset_t *pending, lwp_sigset_t *mask)
+{
+    unsigned long i, *s, *m, x;
+    int sig = 0;
+
+    s = pending->sig;
+    m = mask->sig;
+
+    x = *s & ~*m;
+    if (x)
+    {
+        sig = ffz(~x) + 1;
+        return sig;
+    }
+
+    switch (_LWP_NSIG_WORDS)
+    {
+        default:
+            for (i = 1; i < _LWP_NSIG_WORDS; ++i)
+            {
+                x = *++s &~ *++m;
+                if (!x)
+                    continue;
+                sig = ffz(~x) + i*_LWP_NSIG_BPW + 1;
+                break;
+            }
+            break;
+
+        case 2:
+            x = s[1] &~ m[1];
+            if (!x)
+                break;
+            sig = ffz(~x) + _LWP_NSIG_BPW + 1;
+            break;
+
+        case 1:
+            /* Nothing to do */
+            break;
+    }
+
+    return sig;
+}
 
 int lwp_signal_check(void)
 {
     rt_base_t level;
     struct rt_thread *thread;
     struct rt_lwp *lwp;
-    uint32_t signal = 0;
+    uint32_t have_signal = 0;
 
     level = rt_hw_interrupt_disable();
 
@@ -36,28 +139,28 @@ int lwp_signal_check(void)
         goto out;
     }
 
-    signal = thread->signal;
-    if (signal)
+    have_signal = !lwp_sigisemptyset(&thread->signal);
+    if (have_signal)
     {
         thread->signal_in_process = 1;
         goto out;
     }
-    signal = lwp->signal;
-    if (signal)
+    have_signal = !lwp_sigisemptyset(&lwp->signal);
+    if (have_signal)
     {
         lwp->signal_in_process = 1;
     }
 out:
     rt_hw_interrupt_enable(level);
-    return signal;
+    return have_signal;
 }
 
-uint32_t lwp_signal_backup(void *user_sp, void *user_pc, void* user_flag)
+int lwp_signal_backup(void *user_sp, void *user_pc, void* user_flag)
 {
     rt_base_t level;
     struct rt_thread *thread;
     struct rt_lwp *lwp;
-    uint32_t signal, sig_bit;
+    int signal;
 
     level = rt_hw_interrupt_disable();
     thread = rt_thread_self();
@@ -66,12 +169,12 @@ uint32_t lwp_signal_backup(void *user_sp, void *user_pc, void* user_flag)
         thread->user_ctx.sp = user_sp;
         thread->user_ctx.pc = user_pc;
         thread->user_ctx.flag = user_flag;
-        signal = thread->signal;
-        sig_bit = __builtin_ffs(signal);
-        sig_bit--;
-        thread->signal_mask |= (1 << sig_bit);
-        thread->signal_mask_bak = (1 << sig_bit);
-        thread->signal &= ~(1 << sig_bit);
+
+        signal = next_signal(&thread->signal, &thread->signal_mask);
+        RT_ASSERT(signal != 0);
+        lwp_sigaddset(&thread->signal_mask, signal);
+        thread->signal_mask_bak = signal;
+        lwp_sigdelset(&thread->signal, signal);
     }
     else
     {
@@ -79,15 +182,15 @@ uint32_t lwp_signal_backup(void *user_sp, void *user_pc, void* user_flag)
         lwp->user_ctx.sp = user_sp;
         lwp->user_ctx.pc = user_pc;
         lwp->user_ctx.flag = user_flag;
-        signal = lwp->signal;
-        sig_bit = __builtin_ffs(signal);
-        sig_bit--;
-        lwp->signal_mask |= (1 << sig_bit);
-        lwp->signal_mask_bak = (1 << sig_bit);
-        lwp->signal &= ~(1 << sig_bit);
+
+        signal = next_signal(&lwp->signal, &lwp->signal_mask);
+        RT_ASSERT(signal != 0);
+        lwp_sigaddset(&lwp->signal_mask, signal);
+        lwp->signal_mask_bak = signal;
+        lwp_sigdelset(&lwp->signal, signal);
     }
     rt_hw_interrupt_enable(level);
-    return sig_bit;
+    return signal;
 }
 
 struct rt_user_context *lwp_signal_restore(void)
@@ -103,7 +206,8 @@ struct rt_user_context *lwp_signal_restore(void)
     {
         ctx = &thread->user_ctx;
         thread->signal_in_process = 0;
-        thread->signal_mask &= ~thread->signal_mask_bak;
+
+        lwp_sigdelset(&thread->signal_mask, thread->signal_mask_bak);
         thread->signal_mask_bak = 0;
     }
     else
@@ -112,7 +216,8 @@ struct rt_user_context *lwp_signal_restore(void)
         ctx = &lwp->user_ctx;
         RT_ASSERT(lwp->signal_in_process != 0);
         lwp->signal_in_process = 0;
-        lwp->signal_mask &= ~lwp->signal_mask_bak;
+
+        lwp_sigdelset(&lwp->signal_mask, lwp->signal_mask_bak);
         lwp->signal_mask_bak = 0;
     }
     rt_hw_interrupt_enable(level);
@@ -122,17 +227,19 @@ struct rt_user_context *lwp_signal_restore(void)
 void sys_exit(int value);
 lwp_sighandler_t lwp_sighandler_get(int sig)
 {
-    lwp_sighandler_t func;
+    lwp_sighandler_t func = RT_NULL;
     struct rt_lwp *lwp;
     rt_thread_t thread;
     rt_thread_t main_thread;
     rt_base_t level;
 
+    if (sig == 0 || sig > _LWP_NSIG)
+        return func;
     level = rt_hw_interrupt_disable();
     thread = rt_thread_self();
     if (thread->signal_in_process)
     {
-        func = rt_thread_self()->signal_handler[sig];
+        func = rt_thread_self()->signal_handler[sig - 1];
         if (!func)
         {
             lwp = (struct rt_lwp*)thread->lwp;
@@ -148,7 +255,7 @@ lwp_sighandler_t lwp_sighandler_get(int sig)
                     sub_thread = rt_list_entry(s_list, struct rt_thread, sibling);
                     /* kill all sub threads */
                     s_list = sub_thread->sibling.next;
-                    lwp_thread_kill(sub_thread, 0);
+                    lwp_thread_kill(sub_thread, SIGKILL);
                 }
             }
             sys_exit(0);
@@ -157,11 +264,11 @@ lwp_sighandler_t lwp_sighandler_get(int sig)
     else
     {
         lwp = (struct rt_lwp*)thread->lwp;
-        func = lwp->signal_handler[sig];
+        func = lwp->signal_handler[sig - 1];
         if (!func)
         {
             main_thread = rt_list_entry(lwp->t_grp.prev, struct rt_thread, sibling);
-            lwp_thread_kill(main_thread, 0);
+            lwp_thread_kill(main_thread, SIGKILL);
         }
     }
     rt_hw_interrupt_enable(level);
@@ -172,8 +279,12 @@ void lwp_sighandler_set(int sig, lwp_sighandler_t func)
 {
     rt_base_t level;
 
+    if (sig == 0 || sig > _LWP_NSIG)
+        return;
+    if (sig == SIGKILL || sig == SIGSTOP)
+        return;
     level = rt_hw_interrupt_disable();
-    ((struct rt_lwp*)rt_thread_self()->lwp)->signal_handler[sig] = func;
+    ((struct rt_lwp*)rt_thread_self()->lwp)->signal_handler[sig - 1] = func;
     rt_hw_interrupt_enable(level);
 }
 
@@ -181,11 +292,12 @@ void lwp_thread_sighandler_set(int sig, lwp_sighandler_t func)
 {
     rt_base_t level;
 
+    if (sig == 0 || sig > _LWP_NSIG)
+        return;
+    if (sig == SIGKILL || sig == SIGSTOP)
+        return;
     level = rt_hw_interrupt_disable();
-    if (sig) /* sig 0 is default behavior */
-    {
-        rt_thread_self()->signal_handler[sig] = func;
-    }
+    rt_thread_self()->signal_handler[sig - 1] = func;
     rt_hw_interrupt_enable(level);
 }
 
@@ -204,9 +316,13 @@ int lwp_sigprocmask(const lwp_sigset_t *sigset, lwp_sigset_t *oset)
     {
         goto out;
     }
-    *oset = lwp->signal_mask;
-    lwp->signal_mask = *sigset;
-    lwp->signal_mask_bak &= ~*sigset;
+    if (oset)
+    {
+        oset = rt_memcpy(oset, &lwp->signal_mask, sizeof(lwp_sigset_t));
+    }
+    rt_memcpy(&lwp->signal_mask, sigset, sizeof(lwp_sigset_t));
+    lwp_sigdelset(&lwp->signal_mask, SIGKILL);
+    lwp_sigdelset(&lwp->signal_mask, SIGSTOP);
     ret = 0;
 
 out:
@@ -218,26 +334,58 @@ int lwp_thread_sigprocmask(const lwp_sigset_t *sigset, lwp_sigset_t *oset)
 {
     rt_base_t level;
     struct rt_thread *thread;
-    uint32_t value = *sigset;
 
-    value &= ~(1 << 0); /* thread sig 0 must not be masked */
     level = rt_hw_interrupt_disable();
     thread = rt_thread_self();
-    *oset = thread->signal_mask;
-    thread->signal_mask = value;
-    thread->signal_mask_bak &= ~value;
+
+    if (oset)
+    {
+        oset = rt_memcpy(oset, &thread->signal_mask, sizeof(lwp_sigset_t));
+    }
+    rt_memcpy(&thread->signal_mask, sigset, sizeof(lwp_sigset_t));
+    lwp_sigdelset(&thread->signal_mask, SIGKILL);
+    lwp_sigdelset(&thread->signal_mask, SIGSTOP);
+
     rt_hw_interrupt_enable(level);
     return 0;
 }
 
+static void _do_signal_wakeup(rt_thread_t thread, int sig)
+{
+    if ((thread->stat & RT_THREAD_SUSPEND_MASK) == RT_THREAD_SUSPEND_MASK)
+    {
+        int need_schedule = 1;
+
+        if ((thread->stat & RT_SIGNAL_COMMON_WAKEUP_MASK) != RT_SIGNAL_COMMON_WAKEUP_MASK)
+        {
+            rt_thread_wakeup(thread);
+        }
+        else if ((sig == SIGKILL) && ((thread->stat & RT_SIGNAL_KILL_WAKEUP_MASK) != RT_SIGNAL_KILL_WAKEUP_MASK))
+        {
+            rt_thread_wakeup(thread);
+        }
+        else
+        {
+            need_schedule = 0;
+        }
+
+        /* do schedule */
+        if (need_schedule)
+        {
+            rt_schedule();
+        }
+    }
+}
+
 int lwp_kill(pid_t pid, int sig)
 {
     rt_base_t level;
     struct rt_lwp *lwp;
     int ret = -RT_EINVAL;
-    uint32_t signal;
     rt_thread_t thread;
 
+    if (sig == 0 || sig > _LWP_NSIG)
+        return ret;
     level = rt_hw_interrupt_disable();
     lwp = lwp_from_pid(pid);
     if (!lwp)
@@ -247,21 +395,13 @@ int lwp_kill(pid_t pid, int sig)
 
     /* check main thread */
     thread = rt_list_entry(lwp->t_grp.prev, struct rt_thread, sibling);
-    if ((lwp->signal_mask & (1 << sig)) != 0)
+    if (lwp_sigismember(&lwp->signal_mask, sig)) /* if signal masked */
     {
         goto out;
     }
 
-    signal = (1 << sig);
-    signal &= ~lwp->signal_mask;
-    lwp->signal |= signal;
-    if ((thread->stat & RT_THREAD_SUSPEND_MASK) == RT_THREAD_SUSPEND_MASK)
-    {
-        rt_thread_wakeup(thread);
-
-        /* do schedule */
-        rt_schedule();
-    }
+    lwp_sigaddset(&lwp->signal, sig);
+    _do_signal_wakeup(thread, sig);
     ret = 0;
 out:
     rt_hw_interrupt_enable(level);
@@ -272,28 +412,20 @@ int lwp_thread_kill(rt_thread_t thread, int sig)
 {
     rt_base_t level;
     int ret = -RT_EINVAL;
-    uint32_t signal;
 
     if (!thread) return ret;
 
+    if (sig == 0 || sig > _LWP_NSIG)
+        return ret;
     level = rt_hw_interrupt_disable();
-    if ((thread->signal_mask & (1 << sig)) != 0)
+    if (lwp_sigismember(&thread->signal_mask, sig)) /* if signal masked */
     {
         goto out;
     }
 
-    signal = (1 << sig);
-    signal &= ~thread->signal_mask;
-    thread->signal |= signal;
-    if ((thread->stat & RT_THREAD_SUSPEND_MASK) == RT_THREAD_SUSPEND_MASK)
-    {
-        rt_thread_wakeup(thread);
-
-        /* do schedule */
-        rt_schedule();
-    }
+    lwp_sigaddset(&thread->signal, sig);
+    _do_signal_wakeup(thread, sig);
     ret = 0;
-
 out:
     rt_hw_interrupt_enable(level);
     return ret;

+ 1 - 1
components/lwp/lwp_signal.h

@@ -18,7 +18,7 @@ extern "C" {
 #endif
 
 int lwp_signal_check(void);
-uint32_t lwp_signal_backup(void *user_sp, void *user_pc, void* user_flag);
+int lwp_signal_backup(void *user_sp, void *user_pc, void* user_flag);
 struct rt_user_context *lwp_signal_restore(void);
 lwp_sighandler_t lwp_sighandler_get(int sig);
 void lwp_sighandler_set(int sig, lwp_sighandler_t func);

+ 1 - 1
components/vbus/prio_queue.c

@@ -205,7 +205,7 @@ rt_err_t rt_prio_queue_pop(struct rt_prio_queue *que,
 
         thread = rt_thread_self();
         thread->error = RT_EOK;
-        rt_thread_suspend(thread);
+        rt_thread_suspend(thread, RT_UNINTERRUPTIBLE);
 
         rt_list_insert_before(&(que->suspended_pop_list), &(thread->tlist));
 

+ 2 - 2
components/vbus/vbus.c

@@ -230,7 +230,7 @@ static void _bus_out_entry(void *param)
             /* kick the guest, hoping this could force it do the work */
             rt_vbus_tick(0, RT_VBUS_GUEST_VIRQ);
 
-            rt_thread_suspend(rt_thread_self());
+            rt_thread_suspend(rt_thread_self(), RT_UNINTERRUPTIBLE);
             rt_schedule();
 
             RT_VBUS_OUT_RING->blocked = 0;
@@ -334,7 +334,7 @@ rt_err_t rt_vbus_post(rt_uint8_t id,
         /* We only touch the _chn_suspended_threads in thread, so lock the
          * scheduler is enough. */
         rt_enter_critical();
-        rt_thread_suspend(thread);
+        rt_thread_suspend(thread, RT_UNINTERRUPTIBLE);
 
         rt_list_insert_after(&_chn_suspended_threads[id], &thread->tlist);
         if (timeout > 0)

+ 1 - 1
components/vbus/watermark_queue.h

@@ -63,7 +63,7 @@ rt_inline rt_err_t rt_wm_que_inc(struct rt_watermark_queue *wg,
 
         thread = rt_thread_self();
         thread->error = RT_EOK;
-        rt_thread_suspend(thread);
+        rt_thread_suspend(thread, RT_UNINTERRUPTIBLE);
         rt_list_insert_after(&wg->suspended_threads, &thread->tlist);
         if (timeout > 0)
         {

+ 1 - 1
examples/kernel/thread_resume.c

@@ -18,7 +18,7 @@ static void thread1_entry(void* parameter)
 
     /* 挂起自身 */
     rt_kprintf("suspend thread self\n");
-    rt_thread_suspend(tid1);
+    rt_thread_suspend(tid1, RT_UNINTERRUPTIBLE);
     /* 主动执行线程调度 */
     rt_schedule();
 

+ 1 - 1
examples/kernel/thread_suspend.c

@@ -28,7 +28,7 @@ static void thread2_entry(void* parameter)
     rt_thread_delay(10);
 
     /* 挂起线程1 */
-    rt_thread_suspend(tid1);
+    rt_thread_suspend(tid1, RT_UNINTERRUPTIBLE);
 
     /* 延时10个OS Tick */
     rt_thread_delay(10);

+ 22 - 4
include/rtdef.h

@@ -516,6 +516,16 @@ typedef siginfo_t rt_siginfo_t;
 #define RT_THREAD_READY                      0x02                /**< Ready status */
 #define RT_THREAD_RUNNING                    0x03                /**< Running status */
 
+/*
+ * for rt_thread_set_suspend_state()
+ */
+enum
+{
+    RT_INTERRUPTIBLE = 0,
+    RT_KILLABLE,
+    RT_UNINTERRUPTIBLE,
+};
+
 #define RT_THREAD_SUSPEND_MASK               0x04
 #define RT_SIGNAL_COMMON_WAKEUP_MASK         0x02
 #define RT_SIGNAL_KILL_WAKEUP_MASK           0x01
@@ -589,8 +599,16 @@ struct rt_wakeup
     void *user_data;
 };
 
+#define _LWP_NSIG       64
+#define _LWP_NSIG_BPW   32
+#define _LWP_NSIG_WORDS (_LWP_NSIG / _LWP_NSIG_BPW)
+
 typedef void (*lwp_sighandler_t)(int);
-typedef rt_uint32_t lwp_sigset_t;
+
+typedef struct {
+    unsigned long sig[_LWP_NSIG_WORDS];
+} lwp_sigset_t;
+
 struct rt_user_context
 {
     void *sp;
@@ -691,11 +709,11 @@ struct rt_thread
     rt_uint32_t *kernel_sp;                             /**< kernel stack point */
     rt_list_t   sibling;                                /**< next thread of same process */
 
-    rt_uint32_t signal;
+    lwp_sigset_t signal;
     lwp_sigset_t signal_mask;
-    lwp_sigset_t signal_mask_bak;
+    int signal_mask_bak;
     rt_uint32_t signal_in_process;
-    lwp_sighandler_t signal_handler[32];
+    lwp_sighandler_t signal_handler[_LWP_NSIG];
     struct rt_user_context user_ctx;
 
     struct rt_wakeup wakeup;                            /**< wakeup data */

+ 2 - 1
include/rtthread.h

@@ -147,7 +147,8 @@ rt_err_t rt_thread_delay(rt_tick_t tick);
 rt_err_t rt_thread_delay_until(rt_tick_t *tick, rt_tick_t inc_tick);
 rt_err_t rt_thread_mdelay(rt_int32_t ms);
 rt_err_t rt_thread_control(rt_thread_t thread, int cmd, void *arg);
-rt_err_t rt_thread_suspend(rt_thread_t thread);
+void rt_thread_set_suspend_state(struct rt_thread *thread, int suspend_flag);
+rt_err_t rt_thread_suspend(rt_thread_t thread, int suspend_flag);
 rt_err_t rt_thread_resume(rt_thread_t thread);
 #ifdef RT_USING_LWP
 rt_err_t rt_thread_wakeup(rt_thread_t thread);

+ 1 - 1
libcpu/arm/AT91SAM7X/trap.c

@@ -42,7 +42,7 @@ extern struct rt_thread* rt_current_thread;
 void rt_hw_trap_abort(void)
 {
 	rt_kprintf("Abort occured!!! Thread [%s] suspended.\n",rt_current_thread->name);
-	rt_thread_suspend(rt_current_thread);
+	rt_thread_suspend(rt_current_thread, RT_UNINTERRUPTIBLE);
 	rt_schedule();
 
 }

+ 2 - 2
libcpu/arm/cortex-a/trap.c

@@ -103,12 +103,12 @@ static int check_debug_event(struct rt_hw_exp_stack *regs, uint32_t pc_adj)
             dmb();
             thread_info.thread->debug_suspend = 1;
             dsb();
-            rt_thread_suspend(thread_info.thread);
+            rt_thread_suspend(thread_info.thread, RT_UNINTERRUPTIBLE);
             rt_raw_channel_send(gdb_get_server_channel(), &msg);
             rt_schedule();
             while (thread_info.thread->debug_suspend)
             {
-                rt_thread_suspend(thread_info.thread);
+                rt_thread_suspend(thread_info.thread, RT_UNINTERRUPTIBLE);
                 rt_schedule();
             }
             return ret;

+ 1 - 1
src/ipc.c

@@ -85,7 +85,7 @@ rt_inline rt_err_t rt_ipc_list_suspend(rt_list_t        *list,
                                        rt_uint8_t        flag)
 {
     /* suspend thread */
-    rt_thread_suspend(thread);
+    rt_thread_suspend(thread, RT_UNINTERRUPTIBLE);
 
     switch (flag)
     {

+ 1 - 1
src/mempool.c

@@ -334,7 +334,7 @@ void *rt_mp_alloc(rt_mp_t mp, rt_int32_t time)
         thread->error = RT_EOK;
 
         /* need suspend thread */
-        rt_thread_suspend(thread);
+        rt_thread_suspend(thread, RT_UNINTERRUPTIBLE);
         rt_list_insert_after(&(mp->suspend_thread), &(thread->tlist));
 
         if (time > 0)

+ 1 - 1
src/signal.c

@@ -302,7 +302,7 @@ int rt_signal_wait(const rt_sigset_t *set, rt_siginfo_t *si, rt_int32_t timeout)
     }
 
     /* suspend self thread */
-    rt_thread_suspend(tid);
+    rt_thread_suspend(tid, RT_UNINTERRUPTIBLE);
     /* set thread stat as waiting for signal */
     tid->stat |= RT_THREAD_STAT_SIGNAL_WAIT;
 

+ 36 - 6
src/thread.c

@@ -206,8 +206,8 @@ static rt_err_t _rt_thread_init(struct rt_thread *thread,
 #ifdef RT_USING_LWP
     thread->lwp = RT_NULL;
     rt_list_init(&(thread->sibling));
-    thread->signal = 0;
-    thread->signal_mask = 0;
+    rt_memset(&thread->signal, 0, sizeof(lwp_sigset_t));
+    rt_memset(&thread->signal_mask, 0, sizeof(lwp_sigset_t));
     thread->signal_mask_bak = 0;
     thread->signal_in_process = 0;
     rt_memset(thread->signal_handler, 0, sizeof thread->signal_handler);
@@ -506,6 +506,35 @@ rt_err_t rt_thread_yield(void)
 }
 RTM_EXPORT(rt_thread_yield);
 
+/**
+ * This function will set a thread's suspend status
+ *
+ * @param thread the thread to be suspend
+ * @param status flag of the thread, must be one of RT_INTERRUPTIBLE RT_KILLABLE RT_UNINTERRUPTIBLE
+ */
+void rt_thread_set_suspend_state(struct rt_thread *thread, int suspend_flag)
+{
+    rt_uint8_t stat = RT_THREAD_SUSPEND_UNINTERRUPTIBLE;
+
+    RT_ASSERT(thread != RT_NULL);
+    switch (suspend_flag)
+    {
+    case RT_INTERRUPTIBLE:
+        stat = RT_THREAD_SUSPEND_INTERRUPTIBLE;
+        break;
+    case RT_KILLABLE:
+        stat = RT_THREAD_SUSPEND_KILLABLE;
+        break;
+    case RT_UNINTERRUPTIBLE:
+        stat = RT_THREAD_SUSPEND_UNINTERRUPTIBLE;
+        break;
+    default:
+        RT_ASSERT(0);
+        break;
+    }
+    thread->stat = stat | (thread->stat & ~RT_THREAD_STAT_MASK);
+}
+
 /**
  * This function will let current thread sleep for some ticks.
  *
@@ -527,7 +556,7 @@ rt_err_t rt_thread_sleep(rt_tick_t tick)
     temp = rt_hw_interrupt_disable();
 
     /* suspend thread */
-    rt_thread_suspend(thread);
+    rt_thread_suspend(thread, RT_UNINTERRUPTIBLE);
 
     /* reset the timeout of thread timer and start it */
     rt_timer_control(&(thread->thread_timer), RT_TIMER_CTRL_SET_TIME, &tick);
@@ -586,7 +615,7 @@ rt_err_t rt_thread_delay_until(rt_tick_t *tick, rt_tick_t inc_tick)
         *tick = *tick + inc_tick - rt_tick_get();
 
         /* suspend thread */
-        rt_thread_suspend(thread);
+        rt_thread_suspend(thread, RT_UNINTERRUPTIBLE);
 
         /* reset the timeout of thread timer and start it */
         rt_timer_control(&(thread->thread_timer), RT_TIMER_CTRL_SET_TIME, tick);
@@ -742,13 +771,14 @@ RTM_EXPORT(rt_thread_control);
  * This function will suspend the specified thread.
  *
  * @param thread the thread to be suspended
+ * @param suspend_flag status flag of the thread to be suspended
  *
  * @return the operation status, RT_EOK on OK, -RT_ERROR on error
  *
  * @note if suspend self thread, after this function call, the
  * rt_schedule() must be invoked.
  */
-rt_err_t rt_thread_suspend(rt_thread_t thread)
+rt_err_t rt_thread_suspend(rt_thread_t thread, int suspend_flag)
 {
     register rt_base_t stat;
     register rt_base_t temp;
@@ -777,7 +807,7 @@ rt_err_t rt_thread_suspend(rt_thread_t thread)
 
     /* change thread stat */
     rt_schedule_remove_thread(thread);
-    thread->stat = RT_THREAD_SUSPEND | (thread->stat & ~RT_THREAD_STAT_MASK);
+    rt_thread_set_suspend_state(thread, suspend_flag);
 
     /* stop thread timer anyway */
     rt_timer_stop(&(thread->thread_timer));

+ 1 - 1
src/timer.c

@@ -710,7 +710,7 @@ static void rt_thread_timer_entry(void *parameter)
         if (next_timeout == RT_TICK_MAX)
         {
             /* no software timer exist, suspend self. */
-            rt_thread_suspend(rt_thread_self());
+            rt_thread_suspend(rt_thread_self(), RT_UNINTERRUPTIBLE);
             rt_schedule();
         }
         else