Просмотр исходного кода

!89 signal第一步处理
Merge pull request !89 from jesven/fix_signal

bernard 5 лет назад
Родитель
Сommit
b00fb5d9d9
46 измененных файлов с 1039 добавлено и 336 удалено
  1. 3 3
      bsp/gkipc/armv6/rtos_lib.c
  2. 1 1
      bsp/gkipc/armv6/trap.c
  3. 13 11
      components/dfs/src/poll.c
  4. 2 2
      components/drivers/audio/audio_pipe.c
  5. 2 0
      components/drivers/include/ipc/waitqueue.h
  6. 10 2
      components/drivers/serial/serial.c
  7. 1 1
      components/drivers/src/completion.c
  8. 15 15
      components/drivers/src/dataqueue.c
  9. 24 2
      components/drivers/src/waitqueue.c
  10. 1 1
      components/drivers/src/workqueue.c
  11. 1 1
      components/finsh/cmd.c
  12. 1 1
      components/libc/compilers/newlib/syscalls.c
  13. 1 1
      components/libc/libdl/dlmodule.c
  14. 12 12
      components/lwp/arch/arm/common/reloc.c
  15. 1 1
      components/lwp/arch/arm/cortex-a/arch_user_stack.c
  16. 5 0
      components/lwp/arch/arm/cortex-a/lwp_arch.h
  17. 8 8
      components/lwp/lwp.c
  18. 3 3
      components/lwp/lwp.h
  19. 16 2
      components/lwp/lwp_console.c
  20. 35 15
      components/lwp/lwp_ipc.c
  21. 4 4
      components/lwp/lwp_pid.c
  22. 3 3
      components/lwp/lwp_shm.c
  23. 256 80
      components/lwp/lwp_signal.c
  24. 1 1
      components/lwp/lwp_signal.h
  25. 146 46
      components/lwp/lwp_syscall.c
  26. 41 25
      components/lwp/lwp_user_mm.c
  27. 1 1
      components/lwp/lwp_user_mm.h
  28. 1 1
      components/net/lwip-2.0.2/src/arch/sys_arch.c
  29. 1 1
      components/vbus/prio_queue.c
  30. 2 2
      components/vbus/vbus.c
  31. 1 1
      components/vbus/watermark_queue.h
  32. 1 1
      examples/kernel/thread_resume.c
  33. 1 1
      examples/kernel/thread_suspend.c
  34. 36 11
      include/rtdef.h
  35. 41 0
      include/rtthread.h
  36. 1 1
      libcpu/arm/AT91SAM7X/trap.c
  37. 3 3
      libcpu/arm/cortex-a/backtrace.c
  38. 3 3
      libcpu/arm/cortex-a/mmu.c
  39. 2 2
      libcpu/arm/cortex-a/page.c
  40. 2 2
      libcpu/arm/cortex-a/trap.c
  41. 278 49
      src/ipc.c
  42. 1 1
      src/mempool.c
  43. 2 2
      src/scheduler.c
  44. 3 3
      src/signal.c
  45. 51 8
      src/thread.c
  46. 2 2
      src/timer.c

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

@@ -524,7 +524,7 @@ void RTOS_SetErrno(const int err)
 }
 int RTOS_GetErrno()
 {
-    int err;
+    int err = 0;
 #if 0
     rt_base_t level;
     level = rt_hw_interrupt_disable();
@@ -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_witch_flag((rt_thread_t)threadHandle, RT_UNINTERRUPTIBLE);
 }
 
 U32 RTOS_WakeupThread( RTOS_ThreadT threadHandle )
@@ -720,7 +720,7 @@ void thread_statistics()
         rt_kprintf("%-32.*s %3d", RT_NAME_MAX, thread->name, priority);
 #endif
         if (thread->stat == RT_THREAD_READY)        rt_kprintf("   ready");
-        else if (thread->stat == RT_THREAD_SUSPEND) rt_kprintf(" suspend");
+        else if ((thread->stat & RT_THREAD_SUSPEND_MASK) == RT_THREAD_SUSPEND_MASK) rt_kprintf(" suspend");
         else if (thread->stat == RT_THREAD_INIT)    rt_kprintf("    init");
         else if (thread->stat == RT_THREAD_CLOSE)   rt_kprintf("   close");
 

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

@@ -88,7 +88,7 @@ static void _rtt_statistics()
         rt_kprintf("%-32.*s %03d", RT_NAME_MAX, thread->name, priority);
 #endif
         if (thread->stat == RT_THREAD_READY)        rt_kprintf(" ready  ");
-        else if (thread->stat == RT_THREAD_SUSPEND) rt_kprintf(" suspend");
+        else if ((thread->stat & RT_THREAD_SUSPEND_MASK) == RT_THREAD_SUSPEND_MASK) rt_kprintf(" suspend");
         else if (thread->stat == RT_THREAD_INIT)    rt_kprintf(" init   ");
         else if (thread->stat == RT_THREAD_CLOSE)   rt_kprintf(" close  ");
 

+ 13 - 11
components/dfs/src/poll.c

@@ -95,20 +95,22 @@ static int poll_wait_timeout(struct rt_poll_table *pt, int msec)
 
     if (timeout != 0 && !pt->triggered)
     {
-        rt_thread_suspend(thread);
-        if (timeout > 0)
+        if (rt_thread_suspend_with_flag(thread, RT_INTERRUPTIBLE) == RT_EOK)
         {
-            rt_timer_control(&(thread->thread_timer),
-                             RT_TIMER_CTRL_SET_TIME,
-                             &timeout);
-            rt_timer_start(&(thread->thread_timer));
-        }
+            if (timeout > 0)
+            {
+                rt_timer_control(&(thread->thread_timer),
+                        RT_TIMER_CTRL_SET_TIME,
+                        &timeout);
+                rt_timer_start(&(thread->thread_timer));
+            }
 
-        rt_hw_interrupt_enable(level);
+            rt_hw_interrupt_enable(level);
 
-        rt_schedule();
+            rt_schedule();
 
-        level = rt_hw_interrupt_disable();
+            level = rt_hw_interrupt_disable();
+        }
     }
 
     ret = !pt->triggered;
@@ -140,7 +142,7 @@ static int do_pollfd(struct pollfd *pollfd, rt_pollreq_t *req)
 
                 /* dealwith the device return error -1*/
                 if (mask < 0)
-                {   
+                {
                     fd_put(f);
                     pollfd->revents = 0;
                     return mask;

+ 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_with_flag(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_with_flag(thread, RT_UNINTERRUPTIBLE);
             /* waiting on suspended read list */
             rt_list_insert_before(&(pipe->suspended_write_list),
                                   &(thread->tlist));

+ 2 - 0
components/drivers/include/ipc/waitqueue.h

@@ -43,6 +43,8 @@ rt_inline void rt_wqueue_init(rt_wqueue_t *queue)
 void rt_wqueue_add(rt_wqueue_t *queue, struct rt_wqueue_node *node);
 void rt_wqueue_remove(struct rt_wqueue_node *node);
 int  rt_wqueue_wait(rt_wqueue_t *queue, int condition, int timeout);
+int  rt_wqueue_wait_killable(rt_wqueue_t *queue, int condition, int timeout);
+int  rt_wqueue_wait_interruptible(rt_wqueue_t *queue, int condition, int timeout);
 void rt_wqueue_wakeup(rt_wqueue_t *queue, void *key);
 
 #define DEFINE_WAIT_FUNC(name, function)                \

+ 10 - 2
components/drivers/serial/serial.c

@@ -127,6 +127,7 @@ static int serial_fops_read(struct dfs_fd *fd, void *buf, size_t count)
 {
     int size = 0;
     rt_device_t device;
+    int wait_ret;
 
     device = (rt_device_t)fd->data;
 
@@ -137,14 +138,21 @@ static int serial_fops_read(struct dfs_fd *fd, void *buf, size_t count)
         {
             if (fd->flags & O_NONBLOCK)
             {
-                size = -EAGAIN;
                 break;
             }
 
-            rt_wqueue_wait(&(device->wait_queue), 0, RT_WAITING_FOREVER);
+            wait_ret = rt_wqueue_wait_interruptible(&(device->wait_queue), 0, RT_WAITING_FOREVER);
+            if (wait_ret != RT_EOK)
+            {
+                break;
+            }
         }
     }while (size <= 0);
 
+    if (size < 0)
+    {
+        size = 0;
+    }
     return size;
 }
 

+ 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_with_flag(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_with_flag(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_with_flag(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;

+ 24 - 2
components/drivers/src/waitqueue.c

@@ -74,13 +74,14 @@ void rt_wqueue_wakeup(rt_wqueue_t *queue, void *key)
         rt_schedule();
 }
 
-int rt_wqueue_wait(rt_wqueue_t *queue, int condition, int msec)
+static int _rt_wqueue_wait(rt_wqueue_t *queue, int condition, int msec, int suspend_flag)
 {
     int tick;
     rt_thread_t tid = rt_thread_self();
     rt_timer_t  tmr = &(tid->thread_timer);
     struct rt_wqueue_node __wait;
     rt_base_t level;
+    rt_err_t ret;
 
     /* current context checking */
     RT_DEBUG_NOT_IN_INTERRUPT;
@@ -102,8 +103,14 @@ int rt_wqueue_wait(rt_wqueue_t *queue, int condition, int msec)
         goto __exit_wakeup;
     }
 
+    ret = rt_thread_suspend_with_flag(tid, RT_INTERRUPTIBLE);
+    if (ret != RT_EOK)
+    {
+        rt_hw_interrupt_enable(level);
+        /* suspend failed */
+        return -RT_EINTR;
+    }
     rt_wqueue_add(queue, &__wait);
-    rt_thread_suspend(tid);
 
     /* start timer */
     if (tick != RT_WAITING_FOREVER)
@@ -128,3 +135,18 @@ __exit_wakeup:
 
     return 0;
 }
+
+int rt_wqueue_wait(rt_wqueue_t *queue, int condition, int msec)
+{
+    return _rt_wqueue_wait(queue, condition, msec, RT_UNINTERRUPTIBLE);
+}
+
+int rt_wqueue_wait_killable(rt_wqueue_t *queue, int condition, int msec)
+{
+    return _rt_wqueue_wait(queue, condition, msec, RT_KILLABLE);
+}
+
+int rt_wqueue_wait_interruptible(rt_wqueue_t *queue, int condition, int msec)
+{
+    return _rt_wqueue_wait(queue, condition, msec, RT_INTERRUPTIBLE);
+}

+ 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_with_flag(rt_thread_self(), RT_UNINTERRUPTIBLE);
             rt_schedule();
         }
 

+ 1 - 1
components/finsh/cmd.c

@@ -221,7 +221,7 @@ long list_thread(void)
 #endif /*RT_USING_SMP*/
                     stat = (thread->stat & RT_THREAD_STAT_MASK);
                     if (stat == RT_THREAD_READY)        rt_kprintf(" ready  ");
-                    else if (stat == RT_THREAD_SUSPEND) rt_kprintf(" suspend");
+                    else if ((stat & RT_THREAD_SUSPEND_MASK) == RT_THREAD_SUSPEND_MASK) rt_kprintf(" suspend");
                     else if (stat == RT_THREAD_INIT)    rt_kprintf(" init   ");
                     else if (stat == RT_THREAD_CLOSE)   rt_kprintf(" close  ");
                     else if (stat == RT_THREAD_RUNNING) rt_kprintf(" running");

+ 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_with_flag(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_with_flag(thread, RT_UNINTERRUPTIBLE);
                 }
             }
         }

+ 12 - 12
components/lwp/arch/arm/common/reloc.c

@@ -36,15 +36,15 @@ void lwp_elf_reloc(rt_mmu_info *m_info, void *text_start, void *rel_dyn_start, s
         memcpy(&v2, rel_dyn_start + rel_off + 4, 4);
         */
 
-        addr = rt_hw_mmu_v2p(m_info, rel_dyn_start + rel_off);
-        addr -= PV_OFFSET;
+        addr = rt_hw_mmu_v2p(m_info, (void*)((char*)rel_dyn_start + rel_off));
+        addr = (void*)((char*)addr - PV_OFFSET);
         memcpy(&v1, addr, 4);
-        addr = rt_hw_mmu_v2p(m_info, rel_dyn_start + rel_off + 4);
-        addr -= PV_OFFSET;
+        addr = rt_hw_mmu_v2p(m_info, (void*)((char*)rel_dyn_start + rel_off + 4));
+        addr = (void*)((char*)addr - PV_OFFSET);
         memcpy(&v2, addr, 4);
 
-        addr = rt_hw_mmu_v2p(m_info, text_start + v1);
-        addr -= PV_OFFSET;
+        addr = rt_hw_mmu_v2p(m_info, (void*)((char*)text_start + v1));
+        addr = (void*)((char*)addr - PV_OFFSET);
         if ((v2 & 0xff) == R_ARM_RELATIVE)
         {
             // *(uint32_t*)(text_start + v1) += (uint32_t)text_start;
@@ -57,7 +57,7 @@ void lwp_elf_reloc(rt_mmu_info *m_info, void *text_start, void *rel_dyn_start, s
             if (t) /* 0 is UDF */
             {
                 // *(uint32_t*)(text_start + v1) = (uint32_t)(text_start + dynsym[t].st_value);
-                *(uint32_t*)addr = (uint32_t)(text_start + dynsym[t].st_value);
+                *(uint32_t*)addr = (uint32_t)((char*)text_start + dynsym[t].st_value);
             }
         }
     }
@@ -70,7 +70,7 @@ void lwp_elf_reloc(rt_mmu_info *m_info, void *text_start, void *rel_dyn_start, s
         {
             //*got_item += (uint32_t)text_start;
             addr = rt_hw_mmu_v2p(m_info, got_item);
-            addr -= PV_OFFSET;
+            addr = (void*)((char*)addr - PV_OFFSET);
             *(uint32_t *)addr += (uint32_t)text_start;
         }
     }
@@ -89,12 +89,12 @@ void lwp_elf_reloc(void *text_start, void *rel_dyn_start, size_t rel_dyn_size, v
     {
         uint32_t v1, v2;
 
-        memcpy(&v1, rel_dyn_start + rel_off, 4);
-        memcpy(&v2, rel_dyn_start + rel_off + 4, 4);
+        memcpy(&v1, (void*)((char*)rel_dyn_start + rel_off), 4);
+        memcpy(&v2, (void*)((char*)rel_dyn_start + rel_off + 4), 4);
 
         if ((v2 & 0xff) == R_ARM_RELATIVE)
         {
-            *(uint32_t*)(text_start + v1) += (uint32_t)text_start;
+            *(uint32_t*)((char*)text_start + v1) += (uint32_t)text_start;
         }
         else if ((v2 & 0xff) == R_ARM_ABS32)
         {
@@ -102,7 +102,7 @@ void lwp_elf_reloc(void *text_start, void *rel_dyn_start, size_t rel_dyn_size, v
             t = (v2 >> 8);
             if (t) /* 0 is UDF */
             {
-                *(uint32_t*)(text_start + v1) = (uint32_t)(text_start + dynsym[t].st_value);
+                *(uint32_t*)((char*)text_start + v1) = (uint32_t)((char*)text_start + dynsym[t].st_value);
             }
         }
     }

+ 1 - 1
components/lwp/arch/arm/cortex-a/arch_user_stack.c

@@ -29,7 +29,7 @@ int arch_expand_user_stack(void *addr)
     {
         void *map = lwp_map_user(lwp_self(), (void*)stack_addr, ARCH_PAGE_SIZE);
 
-        if (map || lwp_data_access_ok(&lwp_self()->mmu_info, addr, 1))
+        if (map || lwp_user_accessable(addr, 1))
         {
             ret = 1;
         }

+ 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

+ 8 - 8
components/lwp/lwp.c

@@ -410,7 +410,7 @@ static int load_elf(int fd, int len, struct rt_lwp *lwp, uint8_t *load_addr, str
         if (!va)
             return -RT_ERROR;
         pa = rt_hw_mmu_v2p(m_info, va);
-        process_header = pa - PV_OFFSET;
+        process_header = (uint8_t*)pa - PV_OFFSET;
 #else
         process_header = (uint8_t *)rt_malloc(process_header_size);
         if (!process_header)
@@ -523,14 +523,14 @@ static int load_elf(int fd, int len, struct rt_lwp *lwp, uint8_t *load_addr, str
                     while (size)
                     {
                         pa = rt_hw_mmu_v2p(m_info, va);
-                        va_self = pa - PV_OFFSET;
+                        va_self = (void*)((char*)pa - PV_OFFSET);
                         LOG_D("va_self = %p pa = %p", va_self, pa);
                         tmp_len = (size < ARCH_PAGE_SIZE) ? size : ARCH_PAGE_SIZE;
                         tmp_len = load_fread(va_self, 1, tmp_len, fd);
                         rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, va_self, tmp_len);
                         read_len += tmp_len;
                         size -= tmp_len;
-                        va += ARCH_PAGE_SIZE;
+                        va = (void*)((char*)va + ARCH_PAGE_SIZE);
                     }
                 }
 #else
@@ -541,7 +541,7 @@ static int load_elf(int fd, int len, struct rt_lwp *lwp, uint8_t *load_addr, str
             if (pheader.p_filesz < pheader.p_memsz)
             {
 #ifdef RT_USING_USERSPACE
-                void *va = lwp->text_entry + pheader.p_filesz;
+                void *va = (void*)((char*)lwp->text_entry + pheader.p_filesz);
                 void *va_self;
                 void *pa;
                 uint32_t size = pheader.p_memsz - pheader.p_filesz;
@@ -554,12 +554,12 @@ static int load_elf(int fd, int len, struct rt_lwp *lwp, uint8_t *load_addr, str
                 {
                     size_s = (size < ARCH_PAGE_SIZE - off) ? size : ARCH_PAGE_SIZE - off;
                     pa = rt_hw_mmu_v2p(m_info, va);
-                    va_self = pa - PV_OFFSET;
-                    memset(va_self + off, 0, size_s);
-                    rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, va_self + off, size_s);
+                    va_self = (void*)((char*)pa - PV_OFFSET);
+                    memset((void*)((char*)va_self + off), 0, size_s);
+                    rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, (void*)((char*)va_self + off), size_s);
                     off = 0;
                     size -= size_s;
-                    va += ARCH_PAGE_SIZE;
+                    va = (void*)((char*)va + ARCH_PAGE_SIZE);
                 }
 #else
                 memset((uint8_t *)lwp->text_entry + pheader.p_filesz, 0, (size_t)(pheader.p_memsz - pheader.p_filesz));

+ 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;

+ 16 - 2
components/lwp/lwp_console.c

@@ -78,7 +78,12 @@ static void console_rx_notify(struct rt_device *dev)
         }
         else if (ch == CHAR_CTRL_C) /* ctrl-c */
         {
-            lwp_terminate(console->foreground);
+            struct rt_lwp *lwp = console->foreground;
+
+            if (lwp)
+            {
+                lwp_kill(lwp_to_pid(lwp), SIGINT);
+            }
         }
         else
         {
@@ -235,6 +240,7 @@ static int console_fops_read(struct dfs_fd *fd, void *buf, size_t count)
     struct rt_console_device *console;
     struct rt_lwp *lwp;
     struct rt_wqueue *wq;
+    int wait_ret;
 
     console = (struct rt_console_device *)fd->data;
     RT_ASSERT(console != RT_NULL);
@@ -256,9 +262,17 @@ static int console_fops_read(struct dfs_fd *fd, void *buf, size_t count)
         {
             break;
         }
-        rt_wqueue_wait(wq, 0, RT_WAITING_FOREVER);
+        wait_ret = rt_wqueue_wait_interruptible(wq, 0, RT_WAITING_FOREVER);
+        if (wait_ret != 0)
+        {
+            break;
+        }
     }
     rt_hw_interrupt_enable(level);
+    if (size < 0)
+    {
+        size = 0;
+    }
     return size;
 }
 

+ 35 - 15
components/lwp/lwp_ipc.c

@@ -138,11 +138,14 @@ 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_err_t ret = rt_thread_suspend_with_flag(thread, RT_INTERRUPTIBLE);
 
-    rt_list_insert_before(list, &(thread->tlist));  /* list end */
+    if (ret == RT_EOK)
+    {
+        rt_list_insert_before(list, &(thread->tlist));  /* list end */
+    }
 
-    return RT_EOK;
+    return ret;
 }
 
 
@@ -407,15 +410,16 @@ static rt_err_t _rt_raw_channel_send_recv_timeout(rt_channel_t ch, rt_channel_ms
     {
         case RT_IPC_STAT_IDLE:
         case RT_IPC_STAT_ACTIVE:
-            /*
-             * If there is no thread waiting for messages, chain the message
-             * into the list.
-             */
-            rt_list_insert_before(&ch->wait_msg, &msg->mlist);
             if (need_reply)
             {
+                ret = rt_channel_list_suspend(&ch->wait_thread, thread_send);
+                if (ret != RT_EOK)
+                {
+                    _ipc_msg_free(msg);
+                    rt_hw_interrupt_enable(temp);
+                    return ret;
+                }
                 rt_thread_wakeup_set(thread_send, wakeup_sender_wait_recv, (void*)ch);
-                rt_channel_list_suspend(&ch->wait_thread, thread_send);
                 if (time > 0)
                 {
                     rt_timer_control(&(thread_send->thread_timer),
@@ -431,6 +435,11 @@ static rt_err_t _rt_raw_channel_send_recv_timeout(rt_channel_t ch, rt_channel_ms
                     rt_timer_start(&(thread_send->thread_timer));
                 }
             }
+            /*
+             * If there is no thread waiting for messages, chain the message
+             * into the list.
+             */
+            rt_list_insert_before(&ch->wait_msg, &msg->mlist);
             break;
         case RT_IPC_STAT_WAIT:
             /*
@@ -440,16 +449,18 @@ static rt_err_t _rt_raw_channel_send_recv_timeout(rt_channel_t ch, rt_channel_ms
              */
             RT_ASSERT(ch->parent.suspend_thread.next != &ch->parent.suspend_thread);
 
-            thread_recv = rt_list_entry(ch->parent.suspend_thread.next, struct rt_thread, tlist);
-            thread_recv->msg_ret = msg;     /* to the first suspended receiver */
-            thread_recv->error = RT_EOK;
-            rt_channel_list_resume(&ch->parent.suspend_thread);
             if (need_reply)
             {
+                ret = rt_channel_list_suspend(&ch->wait_thread, thread_send);
+                if (ret != RT_EOK)
+                {
+                    _ipc_msg_free(msg);
+                    rt_hw_interrupt_enable(temp);
+                    return ret;
+                }
                 ch->reply = thread_send;    /* record the current waiting sender */
                 ch->stat = RT_IPC_STAT_ACTIVE;
                 rt_thread_wakeup_set(thread_send, wakeup_sender_wait_reply, (void*)ch);
-                rt_channel_list_suspend(&ch->wait_thread, thread_send);
                 if (time > 0)
                 {
                     rt_timer_control(&(thread_send->thread_timer),
@@ -469,6 +480,10 @@ static rt_err_t _rt_raw_channel_send_recv_timeout(rt_channel_t ch, rt_channel_ms
             {
                 ch->stat = RT_IPC_STAT_IDLE;
             }
+            thread_recv = rt_list_entry(ch->parent.suspend_thread.next, struct rt_thread, tlist);
+            thread_recv->msg_ret = msg;     /* to the first suspended receiver */
+            thread_recv->error = RT_EOK;
+            rt_channel_list_resume(&ch->parent.suspend_thread);
             break;
         default:
             break;
@@ -683,8 +698,13 @@ static rt_err_t _rt_raw_channel_recv_timeout(rt_channel_t ch, rt_channel_msg_t d
         /* no valid message, we must wait */
         thread = rt_thread_self();
 
+        ret = rt_channel_list_suspend(&ch->parent.suspend_thread, thread);
+        if (ret != RT_EOK)
+        {
+            rt_hw_interrupt_enable(temp);
+            return ret;
+        }
         rt_thread_wakeup_set(thread, wakeup_receiver, (void*)ch);
-        rt_channel_list_suspend(&ch->parent.suspend_thread, thread);
         ch->stat = RT_IPC_STAT_WAIT;/* no valid suspended senders */
         thread->error = RT_EOK;
         if (time > 0)

+ 4 - 4
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_with_flag(thread, RT_UNINTERRUPTIBLE);
         rt_list_insert_before(&lwp->wait_list, &(thread->tlist));
         rt_schedule();
         if (thread->error == RT_EOK)
@@ -464,7 +464,7 @@ static void print_thread_info(struct rt_thread* thread, int maxlen)
 
     stat = (thread->stat & RT_THREAD_STAT_MASK);
     if (stat == RT_THREAD_READY)        rt_kprintf(" ready  ");
-    else if (stat == RT_THREAD_SUSPEND) rt_kprintf(" suspend");
+    else if ((stat & RT_THREAD_SUSPEND_MASK) == RT_THREAD_SUSPEND_MASK) rt_kprintf(" suspend");
     else if (stat == RT_THREAD_INIT)    rt_kprintf(" init   ");
     else if (stat == RT_THREAD_CLOSE)   rt_kprintf(" close  ");
     else if (stat == RT_THREAD_RUNNING) rt_kprintf(" running");
@@ -694,7 +694,7 @@ void lwp_request_thread_exit(rt_thread_t thread_to_exit)
         {
             thread->exit_request = LWP_EXIT_REQUEST_TRIGGERED;
         }
-        if ((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_SUSPEND)
+        if ((thread->stat & RT_THREAD_SUSPEND_MASK) == RT_THREAD_SUSPEND_MASK)
         {
             thread->error = RT_EINTR;
             dsb();
@@ -734,7 +734,7 @@ void lwp_terminate(struct rt_lwp *lwp)
         {
             thread->exit_request = LWP_EXIT_REQUEST_TRIGGERED;
         }
-        if ((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_SUSPEND)
+        if ((thread->stat & RT_THREAD_SUSPEND_MASK) == RT_THREAD_SUSPEND_MASK)
         {
             thread->error = RT_EINTR;
             dsb();

+ 3 - 3
components/lwp/lwp_shm.c

@@ -101,7 +101,7 @@ static int _lwp_shmget(size_t key, size_t size, int create)
         {
             goto err;
         }
-        page_addr_p = page_addr + PV_OFFSET;    /* physical address */
+        page_addr_p = (void*)((char*)page_addr + PV_OFFSET);    /* physical address */
 
         /* initialize the shared memory structure */
         p = _shm_ary + id;
@@ -198,7 +198,7 @@ static int _lwp_shmrm(int id)
         return 0;
     }
     bit = rt_page_bits(p->size);
-    rt_pages_free((void*)p->addr - PV_OFFSET, bit);
+    rt_pages_free((void*)((char*)p->addr - PV_OFFSET), bit);
     lwp_avl_remove(node_key, &shm_tree_key);
     node_pa = node_key + 1;
     lwp_avl_remove(node_pa, &shm_tree_pa);
@@ -327,7 +327,7 @@ void *_lwp_shminfo(int id)
     }
     p = (struct lwp_shm_struct*)node_key->data; /* p = _shm_ary[id]; */
 
-    return (void *)p->addr - PV_OFFSET;     /* get the virtual address */
+    return (void*)((char*)p->addr - PV_OFFSET);     /* get the virtual address */
 }
 
 /* A wrapping function: get the virtual address of a shared memory. */

+ 256 - 80
components/lwp/lwp_signal.c

@@ -12,13 +12,155 @@
 #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_suspend_sigcheck(rt_thread_t thread, int suspend_flag)
+{
+    struct rt_lwp *lwp = (struct rt_lwp*)thread->lwp;
+    int ret = 0;
+
+    switch (suspend_flag)
+    {
+        case RT_INTERRUPTIBLE:
+            if (!lwp_sigisemptyset(&thread->signal))
+            {
+                break;
+            }
+            if (thread->lwp && !lwp_sigisemptyset(&lwp->signal))
+            {
+                break;
+            }
+            ret = 1;
+            break;
+        case RT_KILLABLE:
+            if (lwp_sigismember(&thread->signal, SIGKILL))
+            {
+                break;
+            }
+            if (thread->lwp && lwp_sigismember(&thread->signal, SIGKILL))
+            {
+                break;
+            }
+            ret = 1;
+            break;
+        case RT_UNINTERRUPTIBLE:
+            ret = 1;
+            break;
+        default:
+            RT_ASSERT(0);
+            break;
+    }
+    return ret;
+}
 
 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 +178,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 +208,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 +221,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 +245,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,44 +255,43 @@ 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);
     return ctx;
 }
 
+rt_inline int _lwp_check_ignore(int sig)
+{
+    if (sig == SIGCHLD || sig == SIGCONT)
+    {
+        return 1;
+    }
+    return 0;
+}
+
 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;
-            main_thread = rt_list_entry(lwp->t_grp.prev, struct rt_thread, sibling);
-            if (thread == main_thread)
+            if (_lwp_check_ignore(sig))
             {
-                rt_thread_t sub_thread;
-                rt_list_t *s_list = lwp->t_grp.next;
-                rt_list_t *m_list = lwp->t_grp.prev;
-
-                while (s_list != m_list)
-                {
-                    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);
-                }
+                goto out;
             }
             sys_exit(0);
         }
@@ -157,13 +299,18 @@ 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);
+            if (_lwp_check_ignore(sig))
+            {
+                goto out;
+            }
+            lwp_terminate(lwp);
+            sys_exit(0);
         }
     }
+out:
     rt_hw_interrupt_enable(level);
     return func;
 }
@@ -172,8 +319,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 +332,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 +356,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)
+    {
+        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 +374,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)
+    {
+        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 +435,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_STAT_MASK) == RT_THREAD_SUSPEND)
-    {
-        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 +452,24 @@ 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 (!thread->lwp)
     {
         goto out;
     }
-
-    signal = (1 << sig);
-    signal &= ~thread->signal_mask;
-    thread->signal |= signal;
-    if ((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_SUSPEND)
+    if (lwp_sigismember(&thread->signal_mask, sig)) /* if signal masked */
     {
-        rt_thread_wakeup(thread);
-
-        /* do schedule */
-        rt_schedule();
+        goto out;
     }
-    ret = 0;
 
+    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);

+ 146 - 46
components/lwp/lwp_syscall.c

@@ -275,7 +275,7 @@ ssize_t sys_read(int fd, void *buf, size_t nbyte)
     if (!nbyte)
         return 0;
 
-    if (!lwp_data_access_ok(&lwp_self()->mmu_info, (void*)buf, nbyte))
+    if (!lwp_user_accessable((void*)buf, nbyte))
         return 0;
 
     kmem = kmem_get(nbyte);
@@ -284,7 +284,7 @@ ssize_t sys_read(int fd, void *buf, size_t nbyte)
 
     ret = read(fd, kmem, nbyte);
     if (ret)
-        lwp_data_put(&lwp_self()->mmu_info, buf, kmem, ret);
+        lwp_put_to_user(buf, kmem, ret);
 
     kmem_put(kmem);
     return ret;
@@ -303,14 +303,14 @@ ssize_t sys_write(int fd, const void *buf, size_t nbyte)
     if (!nbyte)
         return 0;
 
-    if (!lwp_data_access_ok(&lwp_self()->mmu_info, (void*)buf, nbyte))
+    if (!lwp_user_accessable((void*)buf, nbyte))
         return 0;
 
     kmem = kmem_get(nbyte);
     if (!kmem)
         return 0;
 
-    lwp_data_get(&lwp_self()->mmu_info, kmem, (void *)buf, nbyte);
+    lwp_get_from_user(kmem, (void *)buf, nbyte);
     ret = write(fd, kmem, nbyte);
 
     kmem_put(kmem);
@@ -334,7 +334,7 @@ int sys_open(const char *name, int flag, ...)
     rt_size_t len;
     char *kname;
 
-    if (!lwp_data_access_ok(&lwp_self()->mmu_info, (void*)name, 1))
+    if (!lwp_user_accessable((void*)name, 1))
         return -1;
 
     len = rt_strlen(name);
@@ -345,7 +345,7 @@ int sys_open(const char *name, int flag, ...)
     if (!kname)
         return -1;
 
-    lwp_data_get(&lwp_self()->mmu_info, kname, (void *)name, len + 1);
+    lwp_get_from_user(kname, (void *)name, len + 1);
     ret = open(kname, flag, 0);
 
     kmem_put(kname);
@@ -378,7 +378,7 @@ int sys_fstat(int file, struct stat *buf)
     struct stat statbuff;
 
     ret = fstat(file, &statbuff);
-    lwp_data_put(&lwp_self()->mmu_info, buf, &statbuff, sizeof statbuff);
+    lwp_put_to_user(buf, &statbuff, sizeof statbuff);
     return ret;
 #else
     return fstat(file, buf);
@@ -391,16 +391,16 @@ int sys_poll(struct pollfd *fds, nfds_t nfds, int timeout)
     int ret;
     struct pollfd *kfds;
 
-    if (!lwp_data_access_ok(&lwp_self()->mmu_info, (void*)fds, nfds * sizeof *fds))
+    if (!lwp_user_accessable((void*)fds, nfds * sizeof *fds))
         return -1;
 
     kfds = (struct pollfd *)kmem_get(nfds * sizeof *kfds);
     if (!kfds)
         return -1;
 
-    lwp_data_get(&lwp_self()->mmu_info, kfds, fds, nfds * sizeof *kfds);
+    lwp_get_from_user(kfds, fds, nfds * sizeof *kfds);
     ret = poll(kfds, nfds, timeout);
-    lwp_data_put(&lwp_self()->mmu_info, fds, kfds, nfds * sizeof *kfds);
+    lwp_put_to_user(fds, kfds, nfds * sizeof *kfds);
 
     kmem_put(kfds);
     return ret;
@@ -417,7 +417,7 @@ int sys_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, s
 
     if (readfds)
     {
-        if (!lwp_data_access_ok(&lwp_self()->mmu_info, (void*)readfds, sizeof *readfds))
+        if (!lwp_user_accessable((void*)readfds, sizeof *readfds))
         {
             return -1;
         }
@@ -426,11 +426,11 @@ int sys_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, s
         {
             goto quit;
         }
-        lwp_data_get(&lwp_self()->mmu_info, kreadfds, readfds, sizeof *kreadfds);
+        lwp_get_from_user(kreadfds, readfds, sizeof *kreadfds);
     }
     if (writefds)
     {
-        if (!lwp_data_access_ok(&lwp_self()->mmu_info, (void*)writefds, sizeof *writefds))
+        if (!lwp_user_accessable((void*)writefds, sizeof *writefds))
         {
             return -1;
         }
@@ -439,11 +439,11 @@ int sys_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, s
         {
             goto quit;
         }
-        lwp_data_get(&lwp_self()->mmu_info, kwritefds, writefds, sizeof *kwritefds);
+        lwp_get_from_user(kwritefds, writefds, sizeof *kwritefds);
     }
     if (exceptfds)
     {
-        if (!lwp_data_access_ok(&lwp_self()->mmu_info, (void*)exceptfds, sizeof *exceptfds))
+        if (!lwp_user_accessable((void*)exceptfds, sizeof *exceptfds))
         {
             return -1;
         }
@@ -452,21 +452,21 @@ int sys_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, s
         {
             goto quit;
         }
-        lwp_data_get(&lwp_self()->mmu_info, kexceptfds, exceptfds, sizeof *kexceptfds);
+        lwp_get_from_user(kexceptfds, exceptfds, sizeof *kexceptfds);
     }
 
     ret = select(nfds, kreadfds, kwritefds, kexceptfds, timeout);
     if (kreadfds)
     {
-        lwp_data_put(&lwp_self()->mmu_info, readfds, kreadfds, sizeof *kreadfds);
+        lwp_put_to_user(readfds, kreadfds, sizeof *kreadfds);
     }
     if (kwritefds)
     {
-        lwp_data_put(&lwp_self()->mmu_info, writefds, kwritefds, sizeof *kwritefds);
+        lwp_put_to_user(writefds, kwritefds, sizeof *kwritefds);
     }
     if (kexceptfds)
     {
-        lwp_data_put(&lwp_self()->mmu_info, exceptfds, kexceptfds, sizeof *kexceptfds);
+        lwp_put_to_user(exceptfds, kexceptfds, sizeof *kexceptfds);
     }
 quit:
     if (kreadfds)
@@ -494,7 +494,7 @@ int sys_unlink(const char *pathname)
     rt_size_t len;
     char *kname;
 
-    if (!lwp_data_access_ok(&lwp_self()->mmu_info, (void*)pathname, 1))
+    if (!lwp_user_accessable((void*)pathname, 1))
         return -1;
 
     len = rt_strlen(pathname);
@@ -505,7 +505,7 @@ int sys_unlink(const char *pathname)
     if (!kname)
         return -1;
 
-    lwp_data_get(&lwp_self()->mmu_info, kname, (void *)pathname, len + 1);
+    lwp_get_from_user(kname, (void *)pathname, len + 1);
     ret = unlink(kname);
 
     kmem_put(kname);
@@ -525,17 +525,17 @@ int sys_nanosleep(const struct timespec *rqtp, struct timespec *rmtp)
 
     dbg_log(DBG_LOG, "sys_nanosleep\n");
 
-    if (!lwp_data_access_ok(&lwp_self()->mmu_info, (void*)rqtp, sizeof *rqtp))
+    if (!lwp_user_accessable((void*)rqtp, sizeof *rqtp))
         return -1;
 
-    lwp_data_get(&lwp_self()->mmu_info, &rqtp_k, (void *)rqtp, sizeof rqtp_k);
+    lwp_get_from_user(&rqtp_k, (void *)rqtp, sizeof rqtp_k);
 
     tick = rqtp_k.tv_sec * RT_TICK_PER_SECOND + ((uint64_t)rqtp_k.tv_nsec * RT_TICK_PER_SECOND)/ 1000000000;
     rt_thread_delay(tick);
 
     if (rmtp)
     {
-        if (!lwp_data_access_ok(&lwp_self()->mmu_info, (void*)rmtp, sizeof *rmtp))
+        if (!lwp_user_accessable((void*)rmtp, sizeof *rmtp))
             return -1;
 
         tick = rt_tick_get() - tick;
@@ -543,7 +543,7 @@ int sys_nanosleep(const struct timespec *rqtp, struct timespec *rmtp)
         rmtp_k.tv_sec = tick/RT_TICK_PER_SECOND;
         rmtp_k.tv_nsec = (tick%RT_TICK_PER_SECOND) * (1000000000/RT_TICK_PER_SECOND);
 
-        lwp_data_put(&lwp_self()->mmu_info, rmtp, (void *)&rmtp_k, sizeof rmtp_k);
+        lwp_put_to_user(rmtp, (void *)&rmtp_k, sizeof rmtp_k);
     }
 #else
     dbg_log(DBG_LOG, "sys_nanosleep\n");
@@ -571,13 +571,13 @@ int sys_gettimeofday(struct timeval *tp, struct timezone *tzp)
 #ifdef RT_USING_USERSPACE
     if (tp)
     {
-        if (!lwp_data_access_ok(&lwp_self()->mmu_info, (void*)tp, sizeof *tp))
+        if (!lwp_user_accessable((void*)tp, sizeof *tp))
             return -1;
 
         t_k.tv_sec = rt_tick_get() / RT_TICK_PER_SECOND;
         t_k.tv_usec = (rt_tick_get() % RT_TICK_PER_SECOND) * (1000000 / RT_TICK_PER_SECOND);
 
-        lwp_data_put(&lwp_self()->mmu_info, tp, (void *)&t_k, sizeof t_k);
+        lwp_put_to_user(tp, (void *)&t_k, sizeof t_k);
     }
 #else
     if (tp)
@@ -667,7 +667,7 @@ rt_err_t sys_sem_delete(rt_sem_t sem)
 
 rt_err_t sys_sem_take(rt_sem_t sem, rt_int32_t time)
 {
-    return rt_sem_take(sem, time);
+    return rt_sem_take_interruptible(sem, time);
 }
 
 rt_err_t sys_sem_release(rt_sem_t sem)
@@ -687,7 +687,7 @@ rt_err_t sys_mutex_delete(rt_mutex_t mutex)
 
 rt_err_t sys_mutex_take(rt_mutex_t mutex, rt_int32_t time)
 {
-    return rt_mutex_take(mutex, time);
+    return rt_mutex_take_interruptible(mutex, time);
 }
 
 rt_err_t sys_mutex_release(rt_mutex_t mutex)
@@ -1069,16 +1069,54 @@ rt_size_t sys_device_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt
 /* network interfaces */
 int sys_accept(int socket, struct musl_sockaddr *addr, socklen_t *addrlen)
 {
-    struct sockaddr sa;
-    sockaddr_tolwip(addr, &sa);
+    int ret;
+    struct sockaddr ksa;
+    struct musl_sockaddr kmusladdr;
+    socklen_t uaddrlen;
+    socklen_t kaddrlen;
+
+    if (!lwp_user_accessable(addrlen, sizeof (socklen_t *)))
+    {
+        return -1;
+    }
+    lwp_get_from_user(&uaddrlen, addrlen, sizeof (socklen_t *));
+    if (!uaddrlen)
+    {
+        return -1;
+    }
+
+    if (!lwp_user_accessable(addr, uaddrlen))
+    {
+        return -1;
+    }
 
-    return accept(socket, &sa, addrlen);
+    kaddrlen = sizeof(struct sockaddr);
+    ret = accept(socket, &ksa, &kaddrlen);
+    if (ret >= 0)
+    {
+        sockaddr_tomusl(&ksa, &kmusladdr);
+        if (uaddrlen > sizeof(struct musl_sockaddr))
+        {
+            uaddrlen = sizeof(struct musl_sockaddr);
+        }
+        lwp_put_to_user(addr, &kmusladdr, uaddrlen);
+        lwp_put_to_user(addrlen, &uaddrlen, sizeof (socklen_t *));
+    }
+    return ret;
 }
 
 int sys_bind(int socket, const struct musl_sockaddr *name, socklen_t namelen)
 {
     struct sockaddr sa;
-    sockaddr_tolwip(name, &sa);
+    struct musl_sockaddr kname;
+
+    if (!lwp_user_accessable((void*)name, namelen))
+    {
+        return -1;
+    }
+    lwp_get_from_user(&kname, (void*)name, namelen);
+
+    sockaddr_tolwip(&kname, &sa);
 
     return bind(socket, &sa, namelen);
 }
@@ -1092,10 +1130,38 @@ int sys_getpeername (int socket, struct musl_sockaddr *name, socklen_t *namelen)
 {
     int ret;
     struct sockaddr sa;
-    sockaddr_tolwip(name, &sa);
+    struct musl_sockaddr kname;
+    socklen_t unamelen;
+    socklen_t knamelen;
 
-    ret = getpeername (socket, &sa, namelen);
-    if (name) sockaddr_tomusl(&sa, name);
+    if (!lwp_user_accessable(namelen, sizeof (socklen_t *)))
+    {
+        return -1;
+    }
+    lwp_get_from_user(&unamelen, namelen, sizeof (socklen_t *));
+    if (!unamelen)
+    {
+        return -1;
+    }
+
+    if (!lwp_user_accessable(name, unamelen))
+    {
+        return -1;
+    }
+
+    knamelen = sizeof(struct sockaddr);
+    ret = getpeername (socket, &sa, &knamelen);
+
+    if (ret == 0)
+    {
+        sockaddr_tomusl(&sa, &kname);
+        if (unamelen > sizeof(struct musl_sockaddr))
+        {
+            unamelen = sizeof(struct musl_sockaddr);
+        }
+        lwp_put_to_user(name, &kname, unamelen);
+        lwp_put_to_user(namelen, &unamelen, sizeof (socklen_t *));
+    }
 
     return ret;
 }
@@ -1104,11 +1170,37 @@ int sys_getsockname (int socket, struct musl_sockaddr *name, socklen_t *namelen)
 {
     int ret;
     struct sockaddr sa;
-    sockaddr_tolwip(name, &sa);
+    struct musl_sockaddr kname;
+    socklen_t unamelen;
+    socklen_t knamelen;
+
+    if (!lwp_user_accessable(namelen, sizeof (socklen_t *)))
+    {
+        return -1;
+    }
+    lwp_get_from_user(&unamelen, namelen, sizeof (socklen_t *));
+    if (!unamelen)
+    {
+        return -1;
+    }
 
-    ret = getsockname (socket, &sa, namelen);
-    if (name) sockaddr_tomusl(&sa, name);
+    if (!lwp_user_accessable(name, unamelen))
+    {
+        return -1;
+    }
 
+    knamelen = sizeof(struct sockaddr);
+    ret = getsockname (socket, &sa, &knamelen);
+    if (ret == 0)
+    {
+        sockaddr_tomusl(&sa, &kname);
+        if (unamelen > sizeof(struct musl_sockaddr))
+        {
+            unamelen = sizeof(struct musl_sockaddr);
+        }
+        lwp_put_to_user(name, &kname, unamelen);
+        lwp_put_to_user(namelen, &unamelen, sizeof (socklen_t *));
+    }
     return ret;
 }
 
@@ -1131,7 +1223,15 @@ int sys_setsockopt (int socket, int level, int optname, const void *optval, sock
 int sys_connect(int socket, const struct musl_sockaddr *name, socklen_t namelen)
 {
     struct sockaddr sa;
-    sockaddr_tolwip(name, &sa);
+    struct musl_sockaddr kname;
+
+    if (!lwp_user_accessable((void*)name, namelen))
+    {
+        return -1;
+    }
+    lwp_get_from_user(&kname, (void*)name, namelen);
+
+    sockaddr_tolwip(&kname, &sa);
 
     return connect(socket, &sa, namelen);
 }
@@ -1178,7 +1278,7 @@ int sys_recvfrom(int socket, void *mem, size_t len, int flags,
     if (!len)
         return -1;
 
-    if (!lwp_data_access_ok(&lwp_self()->mmu_info, (void*)mem, len))
+    if (!lwp_user_accessable((void*)mem, len))
         return -1;
 
     kmem = kmem_get(len);
@@ -1199,7 +1299,7 @@ int sys_recvfrom(int socket, void *mem, size_t len, int flags,
         ret = recvfrom(socket, kmem, len, flgs, NULL, NULL);
 
     if (ret > 0)
-        lwp_data_put(&lwp_self()->mmu_info, mem, kmem, len);
+        lwp_put_to_user(mem, kmem, len);
 
     kmem_put(kmem);
     return ret;
@@ -1240,14 +1340,14 @@ int sys_sendto(int socket, const void *dataptr, size_t size, int flags,
     if (!size)
         return -1;
 
-    if (!lwp_data_access_ok(&lwp_self()->mmu_info, (void*)dataptr, size))
+    if (!lwp_user_accessable((void*)dataptr, size))
         return -1;
 
     kmem = kmem_get(size);
     if (!kmem)
         return -1;
 
-    lwp_data_get(&lwp_self()->mmu_info, kmem, (void *)dataptr, size);
+    lwp_get_from_user(kmem, (void *)dataptr, size);
 
     if (to)
     {
@@ -1622,7 +1722,7 @@ int sys_access(const char *filename, int mode)
     rt_size_t len;
     char *kname;
 
-    if (!lwp_data_access_ok(&lwp_self()->mmu_info, (void*)filename, 1))
+    if (!lwp_user_accessable((void*)filename, 1))
         return -1;
 
     len = rt_strlen(filename);
@@ -1633,7 +1733,7 @@ int sys_access(const char *filename, int mode)
     if (!kname)
         return -1;
 
-    lwp_data_get(&lwp_self()->mmu_info, kname, (void *)filename, len + 1);
+    lwp_get_from_user(kname, (void *)filename, len + 1);
     ret = open(kname, mode, 0);
     kmem_put(kname);
 #else

+ 41 - 25
components/lwp/lwp_user_mm.c

@@ -39,7 +39,7 @@ void lwp_mmu_switch(struct rt_thread *thread)
     if (thread->lwp)
     {
         l = (struct rt_lwp*)thread->lwp;
-        new_mmu_table = (void*)l->mmu_info.vtable + l->mmu_info.pv_off;
+        new_mmu_table = (void*)((char*)l->mmu_info.vtable + l->mmu_info.pv_off);
 #ifdef LWP_DEBUG
         {
             int i;
@@ -93,7 +93,7 @@ static void free_area(struct rt_lwp *lwp, void *addr, size_t size, int auto_free
     void *va, *pa;
     int i;
 
-    for (va = addr, i = 0; i < size; va += ARCH_PAGE_SIZE, i += ARCH_PAGE_SIZE)
+    for (va = addr, i = 0; i < size; va = (void*)((char*)va + ARCH_PAGE_SIZE), i += ARCH_PAGE_SIZE)
     {
         pa = rt_hw_mmu_v2p(&lwp->mmu_info, va);
         if (pa)
@@ -101,7 +101,7 @@ static void free_area(struct rt_lwp *lwp, void *addr, size_t size, int auto_free
             rt_hw_mmu_unmap(&lwp->mmu_info, va, ARCH_PAGE_SIZE);
             if (auto_free)
             {
-                rt_pages_free(pa - PV_OFFSET, 0);
+                rt_pages_free((void*)((char*)pa - PV_OFFSET), 0);
             }
         }
     }
@@ -205,7 +205,7 @@ void *lwp_map_user(struct rt_lwp *lwp, void *map_va, size_t map_size)
     rt_hw_interrupt_enable(level);
     if (ret)
     {
-        ret += offset;
+        ret = (void*)((char*)ret + offset);
     }
     return ret;
 }
@@ -263,7 +263,7 @@ void *lwp_map_user_phy(struct rt_lwp *lwp, void *map_va, void *map_pa, size_t ma
     rt_hw_interrupt_enable(level);
     if (ret)
     {
-        ret += offset;
+        ret = (void*)((char*)ret + offset);
     }
     return ret;
 }
@@ -346,7 +346,7 @@ size_t lwp_get_from_user(void *dst, void *src, size_t size)
     {
         return 0;
     }
-    if (src + size > (void*)KERNEL_VADDR_START)
+    if ((void*)((char*)src + size) > (void*)KERNEL_VADDR_START)
     {
         return 0;
     }
@@ -371,7 +371,7 @@ size_t lwp_put_to_user(void *dst, void *src, size_t size)
     {
         return 0;
     }
-    if (dst + size > (void*)KERNEL_VADDR_START)
+    if ((void*)((char*)dst + size) > (void*)KERNEL_VADDR_START)
     {
         return 0;
     }
@@ -385,21 +385,37 @@ size_t lwp_put_to_user(void *dst, void *src, size_t size)
     return lwp_data_put(m_info, dst, src, size);
 }
 
-int lwp_data_access_ok(rt_mmu_info *mmu_info, void *addr, size_t size)
+int lwp_user_accessable(void *addr, size_t size)
 {
     void *addr_start, *addr_end, *next_page;
     void *tmp_addr;
+    struct rt_lwp *lwp = lwp_self();
+    rt_mmu_info *mmu_info = RT_NULL;
 
+    if (!lwp)
+    {
+        return 0;
+    }
     if (!size || !addr)
     {
         return 0;
     }
     addr_start = addr;
-    addr_end = addr + size;
+    addr_end = (void*)((char*)addr + size);
+    if (addr_start >= (void*)KERNEL_VADDR_START)
+    {
+        return 0;
+    }
+    if (addr_start > (void *)KERNEL_VADDR_START)
+    {
+        return 0;
+    }
+
+    mmu_info = &lwp->mmu_info;
     next_page = (void*)(((size_t)addr_start + ARCH_PAGE_SIZE) & ~(ARCH_PAGE_SIZE - 1));
     do
     {
-        size_t len = next_page - addr_start;
+        size_t len = (char*)next_page - (char*)addr_start;
 
         if (size < len)
         {
@@ -410,9 +426,9 @@ int lwp_data_access_ok(rt_mmu_info *mmu_info, void *addr, size_t size)
         {
             return 0;
         }
-        addr_start += len;
+        addr_start = (void*)((char*)addr_start + len);
         size -= len;
-        next_page += ARCH_PAGE_SIZE;
+        next_page = (void*)((char*)next_page + ARCH_PAGE_SIZE);
     } while (addr_start < addr_end);
     return 1;
 }
@@ -430,11 +446,11 @@ size_t lwp_data_get(rt_mmu_info *mmu_info, void *dst, void *src, size_t size)
     }
     tmp_dst = dst;
     addr_start = src;
-    addr_end = src + size;
+    addr_end = (void*)((char*)src + size);
     next_page = (void*)(((size_t)addr_start + ARCH_PAGE_SIZE) & ~(ARCH_PAGE_SIZE - 1));
     do
     {
-        size_t len = next_page - addr_start;
+        size_t len = (char*)next_page - (char*)addr_start;
 
         if (size < len)
         {
@@ -445,12 +461,12 @@ size_t lwp_data_get(rt_mmu_info *mmu_info, void *dst, void *src, size_t size)
         {
             break;
         }
-        tmp_src = rt_hw_mmu_v2p(mmu_info, addr_start) - PV_OFFSET;
+        tmp_src = (void*)((char*)rt_hw_mmu_v2p(mmu_info, addr_start) - PV_OFFSET);
         rt_memcpy(tmp_dst, tmp_src, len);
-        tmp_dst += len;
-        addr_start += len;
+        tmp_dst = (void*)((char*)tmp_dst + len);
+        addr_start = (void*)((char*)addr_start + len);
         size -= len;
-        next_page += ARCH_PAGE_SIZE;
+        next_page = (void*)((char*)next_page + ARCH_PAGE_SIZE);
         copy_len += len;
     } while (addr_start < addr_end);
     return copy_len;
@@ -469,11 +485,11 @@ size_t lwp_data_put(rt_mmu_info *mmu_info, void *dst, void *src, size_t size)
     }
     tmp_src = src;
     addr_start = dst;
-    addr_end = dst + size;
+    addr_end = (void*)((char*)dst + size);
     next_page = (void*)(((size_t)addr_start + ARCH_PAGE_SIZE) & ~(ARCH_PAGE_SIZE - 1));
     do
     {
-        size_t len = next_page - addr_start;
+        size_t len = (char*)next_page - (char*)addr_start;
 
         if (size < len)
         {
@@ -484,12 +500,12 @@ size_t lwp_data_put(rt_mmu_info *mmu_info, void *dst, void *src, size_t size)
         {
             break;
         }
-        tmp_dst = rt_hw_mmu_v2p(mmu_info, addr_start) - PV_OFFSET;
+        tmp_dst = (void*)((char*)rt_hw_mmu_v2p(mmu_info, addr_start) - PV_OFFSET);
         rt_memcpy(tmp_dst, tmp_src, len);
-        tmp_src += len;
-        addr_start += len;
+        tmp_src = (void*)((char*)tmp_src + len);
+        addr_start = (void*)((char*)addr_start + len);
         size -= len;
-        next_page += ARCH_PAGE_SIZE;
+        next_page = (void*)((char*)next_page + ARCH_PAGE_SIZE);
         copy_len += len;
     } while (addr_start < addr_end);
     return copy_len;
@@ -500,7 +516,7 @@ void lwp_data_cache_flush(rt_mmu_info *mmu_info, void *vaddr, size_t size)
     void *paddr;
 
     paddr = rt_hw_mmu_v2p(mmu_info, vaddr);
-    paddr -= PV_OFFSET;
+    paddr = (void*)((char*)paddr - PV_OFFSET);
 
     rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, paddr, size);
 }

+ 1 - 1
components/lwp/lwp_user_mm.h

@@ -36,10 +36,10 @@ int lwp_munmap(void *addr, size_t length);
 
 size_t lwp_get_from_user(void *dst, void *src, size_t size);
 size_t lwp_put_to_user(void *dst, void *src, size_t size);
+int lwp_user_accessable(void *addr, size_t size);
 
 size_t lwp_data_get(rt_mmu_info *mmu_info, void *dst, void *src, size_t size);
 size_t lwp_data_put(rt_mmu_info *mmu_info, void *dst, void *src, size_t size);
-int lwp_data_access_ok(rt_mmu_info *mmu_info, void *addr, size_t size);
 void lwp_data_cache_flush(rt_mmu_info *mmu_info, void *vaddr, size_t size);
 
 #ifdef __cplusplus

+ 1 - 1
components/net/lwip-2.0.2/src/arch/sys_arch.c

@@ -508,7 +508,7 @@ u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout)
             t = timeout / (1000/RT_TICK_PER_SECOND);
     }
 
-    ret = rt_mb_recv(*mbox, (rt_ubase_t *)msg, t);
+    ret = rt_mb_recv_interruptibale(*mbox, (rt_ubase_t *)msg, t);
     if(ret != RT_EOK)
     {
         return SYS_ARCH_TIMEOUT;

+ 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_with_flag(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_with_flag(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_with_flag(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_with_flag(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_witch_flag(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_witch_flag(tid1, RT_UNINTERRUPTIBLE);
 
     /* 延时10个OS Tick */
     rt_thread_delay(10);

+ 36 - 11
include/rtdef.h

@@ -511,13 +511,30 @@ typedef siginfo_t rt_siginfo_t;
 /*
  * thread state definitions
  */
-#define RT_THREAD_INIT                  0x00                /**< Initialized status */
-#define RT_THREAD_READY                 0x01                /**< Ready status */
-#define RT_THREAD_SUSPEND               0x02                /**< Suspend status */
-#define RT_THREAD_RUNNING               0x03                /**< Running status */
-#define RT_THREAD_BLOCK                 RT_THREAD_SUSPEND   /**< Blocked status */
-#define RT_THREAD_CLOSE                 0x04                /**< Closed status */
-#define RT_THREAD_STAT_MASK             0x07
+#define RT_THREAD_INIT                       0x00                /**< Initialized status */
+#define RT_THREAD_CLOSE                      0x01                /**< Closed status */
+#define RT_THREAD_READY                      0x02                /**< Ready status */
+#define RT_THREAD_RUNNING                    0x03                /**< Running status */
+
+/*
+ * for rt_thread_suspend_with_flag()
+ */
+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
+
+#define RT_THREAD_SUSPEND_INTERRUPTIBLE      (RT_THREAD_SUSPEND_MASK)                                                             /**< Suspend interruptable 0x4 */
+#define RT_THREAD_SUSPEND                    RT_THREAD_SUSPEND_INTERRUPTIBLE
+#define RT_THREAD_SUSPEND_KILLABLE           (RT_THREAD_SUSPEND_MASK | RT_SIGNAL_COMMON_WAKEUP_MASK)                              /**< Suspend with killable 0x6 */
+#define RT_THREAD_SUSPEND_UNINTERRUPTIBLE    (RT_THREAD_SUSPEND_MASK | RT_SIGNAL_COMMON_WAKEUP_MASK | RT_SIGNAL_KILL_WAKEUP_MASK) /**< Suspend with uninterruptable 0x7 */
+#define RT_THREAD_STAT_MASK                  0x07
 
 #define RT_THREAD_STAT_YIELD            0x08                /**< indicate whether remaining_tick has been reloaded since last schedule */
 #define RT_THREAD_STAT_YIELD_MASK       RT_THREAD_STAT_YIELD
@@ -582,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;
@@ -684,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 */

+ 41 - 0
include/rtthread.h

@@ -148,6 +148,7 @@ 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);
+rt_err_t rt_thread_suspend_with_flag(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);
@@ -314,6 +315,8 @@ rt_sem_t rt_sem_create(const char *name, rt_uint32_t value, rt_uint8_t flag);
 rt_err_t rt_sem_delete(rt_sem_t sem);
 
 rt_err_t rt_sem_take(rt_sem_t sem, rt_int32_t time);
+rt_err_t rt_sem_take_interruptible(rt_sem_t sem, rt_int32_t time);
+rt_err_t rt_sem_take_killable(rt_sem_t sem, rt_int32_t time);
 rt_err_t rt_sem_trytake(rt_sem_t sem);
 rt_err_t rt_sem_release(rt_sem_t sem);
 rt_err_t rt_sem_control(rt_sem_t sem, int cmd, void *arg);
@@ -329,6 +332,8 @@ rt_mutex_t rt_mutex_create(const char *name, rt_uint8_t flag);
 rt_err_t rt_mutex_delete(rt_mutex_t mutex);
 
 rt_err_t rt_mutex_take(rt_mutex_t mutex, rt_int32_t time);
+rt_err_t rt_mutex_take_interruptible(rt_mutex_t mutex, rt_int32_t time);
+rt_err_t rt_mutex_take_killable(rt_mutex_t mutex, rt_int32_t time);
 rt_err_t rt_mutex_release(rt_mutex_t mutex);
 rt_err_t rt_mutex_control(rt_mutex_t mutex, int cmd, void *arg);
 #endif
@@ -348,6 +353,16 @@ rt_err_t rt_event_recv(rt_event_t   event,
                        rt_uint8_t   opt,
                        rt_int32_t   timeout,
                        rt_uint32_t *recved);
+rt_err_t rt_event_recv_interruptible(rt_event_t   event,
+                       rt_uint32_t  set,
+                       rt_uint8_t   opt,
+                       rt_int32_t   timeout,
+                       rt_uint32_t *recved);
+rt_err_t rt_event_recv_killable(rt_event_t   event,
+                       rt_uint32_t  set,
+                       rt_uint8_t   opt,
+                       rt_int32_t   timeout,
+                       rt_uint32_t *recved);
 rt_err_t rt_event_control(rt_event_t event, int cmd, void *arg);
 #endif
 
@@ -368,7 +383,15 @@ rt_err_t rt_mb_send(rt_mailbox_t mb, rt_ubase_t value);
 rt_err_t rt_mb_send_wait(rt_mailbox_t mb,
                          rt_ubase_t  value,
                          rt_int32_t   timeout);
+rt_err_t rt_mb_send_wait_interruptible(rt_mailbox_t mb,
+                         rt_ubase_t  value,
+                         rt_int32_t   timeout);
+rt_err_t rt_mb_send_wait_killable(rt_mailbox_t mb,
+                         rt_ubase_t  value,
+                         rt_int32_t   timeout);
 rt_err_t rt_mb_recv(rt_mailbox_t mb, rt_ubase_t *value, rt_int32_t timeout);
+rt_err_t rt_mb_recv_interruptibale(rt_mailbox_t mb, rt_ubase_t *value, rt_int32_t timeout);
+rt_err_t rt_mb_recv_killable(rt_mailbox_t mb, rt_ubase_t *value, rt_int32_t timeout);
 rt_err_t rt_mb_control(rt_mailbox_t mb, int cmd, void *arg);
 #endif
 
@@ -390,15 +413,33 @@ rt_mq_t rt_mq_create(const char *name,
 rt_err_t rt_mq_delete(rt_mq_t mq);
 
 rt_err_t rt_mq_send(rt_mq_t mq, const void *buffer, rt_size_t size);
+rt_err_t rt_mq_send_interrupt(rt_mq_t mq, const void *buffer, rt_size_t size);
+rt_err_t rt_mq_send_killable(rt_mq_t mq, const void *buffer, rt_size_t size);
 rt_err_t rt_mq_send_wait(rt_mq_t     mq,
                          const void *buffer,
                          rt_size_t   size,
                          rt_int32_t  timeout);
+rt_err_t rt_mq_send_wait_interruptible(rt_mq_t     mq,
+                         const void *buffer,
+                         rt_size_t   size,
+                         rt_int32_t  timeout);
+rt_err_t rt_mq_send_wait_killable(rt_mq_t     mq,
+                         const void *buffer,
+                         rt_size_t   size,
+                         rt_int32_t  timeout);
 rt_err_t rt_mq_urgent(rt_mq_t mq, const void *buffer, rt_size_t size);
 rt_err_t rt_mq_recv(rt_mq_t    mq,
                     void      *buffer,
                     rt_size_t  size,
                     rt_int32_t timeout);
+rt_err_t rt_mq_recv_interruptible(rt_mq_t    mq,
+                    void      *buffer,
+                    rt_size_t  size,
+                    rt_int32_t timeout);
+rt_err_t rt_mq_recv_killable(rt_mq_t    mq,
+                    void      *buffer,
+                    rt_size_t  size,
+                    rt_int32_t timeout);
 rt_err_t rt_mq_control(rt_mq_t mq, int cmd, void *arg);
 #endif
 

+ 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_witch_flag(rt_current_thread, RT_UNINTERRUPTIBLE);
 	rt_schedule();
 
 }

+ 3 - 3
libcpu/arm/cortex-a/backtrace.c

@@ -361,11 +361,11 @@ error:
 #ifdef RT_BACKTRACE_FUNCTION_NAME
 static char *unwind_get_function_name(void *address)
 {
-    uint32_t flag_word = *(uint32_t *)(address - 4);
+    uint32_t flag_word = *(uint32_t *)((char*)address - 4);
 
     if ((flag_word & 0xff000000) == 0xff000000)
     {
-        return (char *)(address - 4 - (flag_word & 0x00ffffff));
+        return (char *)((char*)address - 4 - (flag_word & 0x00ffffff));
     }
     return RT_NULL;
 }
@@ -384,7 +384,7 @@ int unwind_frame(struct stackframe *frame, const struct unwind_idx **origin_idx,
     /* store the highest address on the stack to avoid crossing it*/
     low = frame->sp;
     rt_c_thread = rt_thread_self();
-    ctrl.sp_high = (unsigned long)(rt_c_thread->stack_addr + rt_c_thread->stack_size);
+    ctrl.sp_high = (unsigned long)((char*)rt_c_thread->stack_addr + rt_c_thread->stack_size);
 
     LOG_D("%s(pc = %08lx lr = %08lx sp = %08lx)", __func__,
             frame->pc, frame->lr, frame->sp);

+ 3 - 3
libcpu/arm/cortex-a/mmu.c

@@ -665,9 +665,9 @@ err:
         for (i = 0; i < npages; i++)
         {
             pa = rt_hw_mmu_v2p(mmu_info, va);
-            pa -= mmu_info->pv_off;
+            pa = (void*)((char*)pa - mmu_info->pv_off);
             rt_pages_free(pa, 0);
-            va += ARCH_PAGE_SIZE;
+            va = (void*)((char*)va + ARCH_PAGE_SIZE);
         }
 
         __rt_hw_mmu_unmap(mmu_info, v_addr, npages);
@@ -707,7 +707,7 @@ void *_rt_hw_mmu_map_auto(rt_mmu_info *mmu_info, void *v_addr, size_t size, size
         if (ret == 0)
         {
             rt_hw_cpu_tlb_invalidate();
-            return (void*)vaddr + offset;
+            return (void*)((char*)vaddr + offset);
         }
     }
     return 0;

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

@@ -62,7 +62,7 @@ static struct page * addr_to_page(void *addr)
     {
         return 0;
     }
-    off = addr - page_addr;
+    off = (size_t)((char*)addr - (char*)page_addr);
     off >>= ARCH_PAGE_SHIFT;
     if (off >= page_nr)
     {
@@ -77,7 +77,7 @@ static void* page_to_addr(struct page* p)
     {
         return 0;
     }
-    return page_addr + ((p - page_start) << ARCH_PAGE_SHIFT);
+    return (void*)((char*)page_addr + ((p - page_start) << ARCH_PAGE_SHIFT));
 }
 
 static inline struct page *buddy_get(struct page *p, uint32_t size_bits)

+ 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_witch_flag(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_witch_flag(thread_info.thread, RT_UNINTERRUPTIBLE);
                 rt_schedule();
             }
             return ret;

+ 278 - 49
src/ipc.c

@@ -82,10 +82,16 @@ rt_inline rt_err_t rt_ipc_object_init(struct rt_ipc_object *ipc)
  */
 rt_inline rt_err_t rt_ipc_list_suspend(rt_list_t        *list,
                                        struct rt_thread *thread,
-                                       rt_uint8_t        flag)
+                                       rt_uint8_t        flag,
+                                       int suspend_flag)
 {
+    rt_err_t ret = rt_thread_suspend_with_flag(thread, suspend_flag);
+
     /* suspend thread */
-    rt_thread_suspend(thread);
+    if (ret != RT_EOK)
+    {
+        return ret;
+    }
 
     switch (flag)
     {
@@ -144,6 +150,8 @@ rt_inline rt_err_t rt_ipc_list_resume(rt_list_t *list)
     /* get thread entry */
     thread = rt_list_entry(list->next, struct rt_thread, tlist);
 
+    thread->error = RT_EOK;
+
     RT_DEBUG_LOG(RT_DEBUG_IPC, ("resume thread:%s\n", thread->name));
 
     /* resume it */
@@ -327,10 +335,11 @@ RTM_EXPORT(rt_sem_delete);
  *
  * @return the error code
  */
-rt_err_t rt_sem_take(rt_sem_t sem, rt_int32_t time)
+static rt_err_t _rt_sem_take(rt_sem_t sem, rt_int32_t time, int suspend_flag)
 {
     register rt_base_t temp;
     struct rt_thread *thread;
+    rt_err_t ret;
 
     /* parameter check */
     RT_ASSERT(sem != RT_NULL);
@@ -373,15 +382,21 @@ rt_err_t rt_sem_take(rt_sem_t sem, rt_int32_t time)
             thread = rt_thread_self();
 
             /* reset thread error number */
-            thread->error = RT_EOK;
+            thread->error = -RT_EINTR;
 
             RT_DEBUG_LOG(RT_DEBUG_IPC, ("sem take: suspend thread - %s\n",
                                         thread->name));
 
             /* suspend thread */
-            rt_ipc_list_suspend(&(sem->parent.suspend_thread),
+            ret = rt_ipc_list_suspend(&(sem->parent.suspend_thread),
                                 thread,
-                                sem->parent.parent.flag);
+                                sem->parent.parent.flag,
+                                suspend_flag);
+            if (ret != RT_EOK)
+            {
+                rt_hw_interrupt_enable(temp);
+                return ret;
+            }
 
             /* has waiting time, start thread timer */
             if (time > 0)
@@ -413,8 +428,25 @@ rt_err_t rt_sem_take(rt_sem_t sem, rt_int32_t time)
 
     return RT_EOK;
 }
+
+rt_err_t rt_sem_take(rt_sem_t sem, rt_int32_t time)
+{
+    return _rt_sem_take(sem, time, RT_UNINTERRUPTIBLE);
+}
 RTM_EXPORT(rt_sem_take);
 
+rt_err_t rt_sem_take_interruptible(rt_sem_t sem, rt_int32_t time)
+{
+    return _rt_sem_take(sem, time, RT_INTERRUPTIBLE);
+}
+RTM_EXPORT(rt_sem_take_interruptible);
+
+rt_err_t rt_sem_take_killable(rt_sem_t sem, rt_int32_t time)
+{
+    return _rt_sem_take(sem, time, RT_KILLABLE);
+}
+RTM_EXPORT(rt_sem_take_killable);
+
 /**
  * This function will try to take a semaphore and immediately return
  *
@@ -667,10 +699,11 @@ RTM_EXPORT(rt_mutex_delete);
  *
  * @return the error code
  */
-rt_err_t rt_mutex_take(rt_mutex_t mutex, rt_int32_t time)
+static rt_err_t _rt_mutex_take(rt_mutex_t mutex, rt_int32_t time, int suspend_flag)
 {
     register rt_base_t temp;
     struct rt_thread *thread;
+    rt_err_t ret;
 
     /* this function must not be used in interrupt even if time = 0 */
     RT_DEBUG_IN_THREAD_CONTEXT;
@@ -692,7 +725,7 @@ rt_err_t rt_mutex_take(rt_mutex_t mutex, rt_int32_t time)
                   thread->name, mutex->value, mutex->hold));
 
     /* reset thread error */
-    thread->error = RT_EOK;
+    thread->error = -RT_EINTR;
 
     if (mutex->owner == thread)
     {
@@ -709,9 +742,6 @@ rt_err_t rt_mutex_take(rt_mutex_t mutex, rt_int32_t time)
     }
     else
     {
-#ifdef RT_USING_SIGNALS
-__again:
-#endif /* end of RT_USING_SIGNALS */
         /* The value of mutex is 1 in initial status. Therefore, if the
          * value is great than 0, it indicates the mutex is avaible.
          */
@@ -762,9 +792,15 @@ __again:
                 }
 
                 /* suspend current thread */
-                rt_ipc_list_suspend(&(mutex->parent.suspend_thread),
+                ret = rt_ipc_list_suspend(&(mutex->parent.suspend_thread),
                                     thread,
-                                    mutex->parent.parent.flag);
+                                    mutex->parent.parent.flag,
+                                    suspend_flag);
+                if (ret != RT_EOK)
+                {
+                    rt_hw_interrupt_enable(temp);
+                    return ret;
+                }
 
                 /* has waiting time, start thread timer */
                 if (time > 0)
@@ -788,11 +824,6 @@ __again:
 
                 if (thread->error != RT_EOK)
                 {
-#ifdef RT_USING_SIGNALS
-                    /* interrupt by signal, try it again */
-                    if (thread->error == -RT_EINTR) goto __again;
-#endif /* end of RT_USING_SIGNALS */
-
                     /* return error */
                     return thread->error;
                 }
@@ -813,8 +844,25 @@ __again:
 
     return RT_EOK;
 }
+
+rt_err_t rt_mutex_take(rt_mutex_t mutex, rt_int32_t time)
+{
+    return _rt_mutex_take(mutex, time, RT_UNINTERRUPTIBLE);
+}
 RTM_EXPORT(rt_mutex_take);
 
+rt_err_t rt_mutex_take_interruptible(rt_mutex_t mutex, rt_int32_t time)
+{
+    return _rt_mutex_take(mutex, time, RT_INTERRUPTIBLE);
+}
+RTM_EXPORT(rt_mutex_take_interruptible);
+
+rt_err_t rt_mutex_take_killable(rt_mutex_t mutex, rt_int32_t time)
+{
+    return _rt_mutex_take(mutex, time, RT_KILLABLE);
+}
+RTM_EXPORT(rt_mutex_take_killable);
+
 /**
  * This function will release a mutex, if there are threads suspended on mutex,
  * it will be waked up.
@@ -915,7 +963,7 @@ rt_err_t rt_mutex_release(rt_mutex_t mutex)
                 rt_hw_interrupt_enable(temp); /* enable interrupt */
                 return -RT_EFULL; /* value overflowed */
             }
-            
+
             /* clear owner */
             mutex->owner             = RT_NULL;
             mutex->original_priority = 0xff;
@@ -1152,6 +1200,7 @@ rt_err_t rt_event_send(rt_event_t event, rt_uint32_t set)
 
                 /* resume thread, and thread list breaks out */
                 rt_thread_resume(thread);
+                thread->error = RT_EOK;
 
                 /* need do a scheduling */
                 need_schedule = RT_TRUE;
@@ -1183,15 +1232,17 @@ RTM_EXPORT(rt_event_send);
  *
  * @return the error code
  */
-rt_err_t rt_event_recv(rt_event_t   event,
+static rt_err_t _rt_event_recv(rt_event_t   event,
                        rt_uint32_t  set,
                        rt_uint8_t   option,
                        rt_int32_t   timeout,
-                       rt_uint32_t *recved)
+                       rt_uint32_t *recved,
+                       int suspend_flag)
 {
     struct rt_thread *thread;
     register rt_ubase_t level;
     register rt_base_t status;
+    rt_err_t ret;
 
     RT_DEBUG_IN_THREAD_CONTEXT;
 
@@ -1207,7 +1258,7 @@ rt_err_t rt_event_recv(rt_event_t   event,
     /* get current thread */
     thread = rt_thread_self();
     /* reset thread error */
-    thread->error = RT_EOK;
+    thread->error = -RT_EINTR;
 
     RT_OBJECT_HOOK_CALL(rt_object_trytake_hook, (&(event->parent.parent)));
 
@@ -1236,11 +1287,11 @@ rt_err_t rt_event_recv(rt_event_t   event,
         /* set received event */
         if (recved)
             *recved = (event->set & set);
-            
-        /* fill thread event info */            
+
+        /* fill thread event info */
         thread->event_set = (event->set & set);
         thread->event_info = option;
-        
+
         /* received event */
         if (option & RT_EVENT_FLAG_CLEAR)
             event->set &= ~set;
@@ -1262,9 +1313,15 @@ rt_err_t rt_event_recv(rt_event_t   event,
         thread->event_info = option;
 
         /* put thread to suspended thread list */
-        rt_ipc_list_suspend(&(event->parent.suspend_thread),
+        ret = rt_ipc_list_suspend(&(event->parent.suspend_thread),
                             thread,
-                            event->parent.parent.flag);
+                            event->parent.parent.flag,
+                            suspend_flag);
+        if (ret != RT_EOK)
+        {
+            rt_hw_interrupt_enable(level);
+            return ret;
+        }
 
         /* if there is a waiting timeout, active thread timer */
         if (timeout > 0)
@@ -1303,8 +1360,36 @@ rt_err_t rt_event_recv(rt_event_t   event,
 
     return thread->error;
 }
+
+rt_err_t rt_event_recv(rt_event_t   event,
+                       rt_uint32_t  set,
+                       rt_uint8_t   option,
+                       rt_int32_t   timeout,
+                       rt_uint32_t *recved)
+{
+    return _rt_event_recv(event, set, option, timeout, recved, RT_UNINTERRUPTIBLE);
+}
 RTM_EXPORT(rt_event_recv);
 
+rt_err_t rt_event_recv_interruptible(rt_event_t   event,
+                       rt_uint32_t  set,
+                       rt_uint8_t   option,
+                       rt_int32_t   timeout,
+                       rt_uint32_t *recved)
+{
+    return _rt_event_recv(event, set, option, timeout, recved, RT_INTERRUPTIBLE);
+}
+RTM_EXPORT(rt_event_recv_interruptible);
+
+rt_err_t rt_event_recv_killable(rt_event_t   event,
+                       rt_uint32_t  set,
+                       rt_uint8_t   option,
+                       rt_int32_t   timeout,
+                       rt_uint32_t *recved)
+{
+    return _rt_event_recv(event, set, option, timeout, recved, RT_KILLABLE);
+}
+RTM_EXPORT(rt_event_recv_killable);
 /**
  * This function can get or set some extra attributions of an event object.
  *
@@ -1507,13 +1592,15 @@ RTM_EXPORT(rt_mb_delete);
  *
  * @return the error code
  */
-rt_err_t rt_mb_send_wait(rt_mailbox_t mb,
+static rt_err_t _rt_mb_send_wait(rt_mailbox_t mb,
                          rt_ubase_t   value,
-                         rt_int32_t   timeout)
+                         rt_int32_t   timeout,
+                         int suspend_flag)
 {
     struct rt_thread *thread;
     register rt_ubase_t temp;
     rt_uint32_t tick_delta;
+    rt_err_t ret;
 
     /* parameter check */
     RT_ASSERT(mb != RT_NULL);
@@ -1541,7 +1628,7 @@ rt_err_t rt_mb_send_wait(rt_mailbox_t mb,
     while (mb->entry == mb->size)
     {
         /* reset error number in thread */
-        thread->error = RT_EOK;
+        thread->error = -RT_EINTR;
 
         /* no waiting, return timeout */
         if (timeout == 0)
@@ -1554,9 +1641,16 @@ rt_err_t rt_mb_send_wait(rt_mailbox_t mb,
 
         RT_DEBUG_IN_THREAD_CONTEXT;
         /* suspend current thread */
-        rt_ipc_list_suspend(&(mb->suspend_sender_thread),
+        ret = rt_ipc_list_suspend(&(mb->suspend_sender_thread),
                             thread,
-                            mb->parent.parent.flag);
+                            mb->parent.parent.flag,
+                            suspend_flag);
+
+        if (ret != RT_EOK)
+        {
+            rt_hw_interrupt_enable(temp);
+            return ret;
+        }
 
         /* has waiting time, start thread timer */
         if (timeout > 0)
@@ -1606,7 +1700,7 @@ rt_err_t rt_mb_send_wait(rt_mailbox_t mb,
     ++ mb->in_offset;
     if (mb->in_offset >= mb->size)
         mb->in_offset = 0;
-    
+
     if(mb->entry < RT_MB_ENTRY_MAX)
     {
         /* increase message entry */
@@ -1617,7 +1711,7 @@ rt_err_t rt_mb_send_wait(rt_mailbox_t mb,
         rt_hw_interrupt_enable(temp); /* enable interrupt */
         return -RT_EFULL; /* value overflowed */
     }
-    
+
     /* resume suspended thread */
     if (!rt_list_isempty(&mb->parent.suspend_thread))
     {
@@ -1636,8 +1730,30 @@ rt_err_t rt_mb_send_wait(rt_mailbox_t mb,
 
     return RT_EOK;
 }
+
+rt_err_t rt_mb_send_wait(rt_mailbox_t mb,
+                         rt_ubase_t   value,
+                         rt_int32_t   timeout)
+{
+    return _rt_mb_send_wait(mb, value, timeout, RT_UNINTERRUPTIBLE);
+}
 RTM_EXPORT(rt_mb_send_wait);
 
+rt_err_t rt_mb_send_wait_interruptible(rt_mailbox_t mb,
+                         rt_ubase_t   value,
+                         rt_int32_t   timeout)
+{
+    return _rt_mb_send_wait(mb, value, timeout, RT_INTERRUPTIBLE);
+}
+RTM_EXPORT(rt_mb_send_wait_interruptible);
+
+rt_err_t rt_mb_send_wait_killable(rt_mailbox_t mb,
+                         rt_ubase_t   value,
+                         rt_int32_t   timeout)
+{
+    return _rt_mb_send_wait(mb, value, timeout, RT_KILLABLE);
+}
+RTM_EXPORT(rt_mb_send_wait_killable);
 /**
  * This function will send a mail to mailbox object, if there are threads
  * suspended on mailbox object, it will be waked up. This function will return
@@ -1654,6 +1770,18 @@ rt_err_t rt_mb_send(rt_mailbox_t mb, rt_ubase_t value)
 }
 RTM_EXPORT(rt_mb_send);
 
+rt_err_t rt_mb_send_interruptible(rt_mailbox_t mb, rt_ubase_t value)
+{
+    return rt_mb_send_wait_interruptible(mb, value, 0);
+}
+RTM_EXPORT(rt_mb_send_interruptible);
+
+rt_err_t rt_mb_send_killable(rt_mailbox_t mb, rt_ubase_t value)
+{
+    return rt_mb_send_wait_killable(mb, value, 0);
+}
+RTM_EXPORT(rt_mb_send_killable);
+
 /**
  * This function will receive a mail from mailbox object, if there is no mail
  * in mailbox object, the thread shall wait for a specified time.
@@ -1664,11 +1792,12 @@ RTM_EXPORT(rt_mb_send);
  *
  * @return the error code
  */
-rt_err_t rt_mb_recv(rt_mailbox_t mb, rt_ubase_t *value, rt_int32_t timeout)
+static rt_err_t _rt_mb_recv(rt_mailbox_t mb, rt_ubase_t *value, rt_int32_t timeout, int suspend_flag)
 {
     struct rt_thread *thread;
     register rt_ubase_t temp;
     rt_uint32_t tick_delta;
+    rt_err_t ret;
 
     /* parameter check */
     RT_ASSERT(mb != RT_NULL);
@@ -1696,7 +1825,7 @@ rt_err_t rt_mb_recv(rt_mailbox_t mb, rt_ubase_t *value, rt_int32_t timeout)
     while (mb->entry == 0)
     {
         /* reset error number in thread */
-        thread->error = RT_EOK;
+        thread->error = -RT_EINTR;
 
         /* no waiting, return timeout */
         if (timeout == 0)
@@ -1711,9 +1840,15 @@ rt_err_t rt_mb_recv(rt_mailbox_t mb, rt_ubase_t *value, rt_int32_t timeout)
 
         RT_DEBUG_IN_THREAD_CONTEXT;
         /* suspend current thread */
-        rt_ipc_list_suspend(&(mb->parent.suspend_thread),
+        ret = rt_ipc_list_suspend(&(mb->parent.suspend_thread),
                             thread,
-                            mb->parent.parent.flag);
+                            mb->parent.parent.flag,
+                            suspend_flag);
+        if (ret != RT_EOK)
+        {
+            rt_hw_interrupt_enable(temp);
+            return ret;
+        }
 
         /* has waiting time, start thread timer */
         if (timeout > 0)
@@ -1789,8 +1924,25 @@ rt_err_t rt_mb_recv(rt_mailbox_t mb, rt_ubase_t *value, rt_int32_t timeout)
 
     return RT_EOK;
 }
+
+rt_err_t rt_mb_recv(rt_mailbox_t mb, rt_ubase_t *value, rt_int32_t timeout)
+{
+    return _rt_mb_recv(mb, value, timeout, RT_UNINTERRUPTIBLE);
+}
 RTM_EXPORT(rt_mb_recv);
 
+rt_err_t rt_mb_recv_interruptibale(rt_mailbox_t mb, rt_ubase_t *value, rt_int32_t timeout)
+{
+    return _rt_mb_recv(mb, value, timeout, RT_INTERRUPTIBLE);
+}
+RTM_EXPORT(rt_mb_recv_interruptibale);
+
+rt_err_t rt_mb_recv_killable(rt_mailbox_t mb, rt_ubase_t *value, rt_int32_t timeout)
+{
+    return _rt_mb_recv(mb, value, timeout, RT_KILLABLE);
+}
+RTM_EXPORT(rt_mb_recv_killable);
+
 /**
  * This function can get or set some extra attributions of a mailbox object.
  *
@@ -2049,15 +2201,17 @@ RTM_EXPORT(rt_mq_delete);
  *
  * @return the error code
  */
-rt_err_t rt_mq_send_wait(rt_mq_t     mq,
+static rt_err_t _rt_mq_send_wait(rt_mq_t     mq,
                          const void *buffer,
                          rt_size_t   size,
-                         rt_int32_t  timeout)
+                         rt_int32_t  timeout,
+                         int suspend_flag)
 {
     register rt_ubase_t temp;
     struct rt_mq_message *msg;
     rt_uint32_t tick_delta;
     struct rt_thread *thread;
+    rt_err_t ret;
 
     /* parameter check */
     RT_ASSERT(mq != RT_NULL);
@@ -2094,7 +2248,7 @@ rt_err_t rt_mq_send_wait(rt_mq_t     mq,
     while ((msg = mq->msg_queue_free) == RT_NULL)
     {
         /* reset error number in thread */
-        thread->error = RT_EOK;
+        thread->error = -RT_EINTR;
 
         /* no waiting, return timeout */
         if (timeout == 0)
@@ -2107,9 +2261,15 @@ rt_err_t rt_mq_send_wait(rt_mq_t     mq,
 
         RT_DEBUG_IN_THREAD_CONTEXT;
         /* suspend current thread */
-        rt_ipc_list_suspend(&(mq->suspend_sender_thread),
+        ret = rt_ipc_list_suspend(&(mq->suspend_sender_thread),
                             thread,
-                            mq->parent.parent.flag);
+                            mq->parent.parent.flag,
+                            suspend_flag);
+        if (ret != RT_EOK)
+        {
+            rt_hw_interrupt_enable(temp);
+            return ret;
+        }
 
         /* has waiting time, start thread timer */
         if (timeout > 0)
@@ -2208,8 +2368,33 @@ rt_err_t rt_mq_send_wait(rt_mq_t     mq,
 
     return RT_EOK;
 }
+
+rt_err_t rt_mq_send_wait(rt_mq_t     mq,
+                         const void *buffer,
+                         rt_size_t   size,
+                         rt_int32_t  timeout)
+{
+    return _rt_mq_send_wait(mq, buffer, size, timeout, RT_UNINTERRUPTIBLE);
+}
 RTM_EXPORT(rt_mq_send_wait)
 
+rt_err_t rt_mq_send_wait_interruptible(rt_mq_t     mq,
+                         const void *buffer,
+                         rt_size_t   size,
+                         rt_int32_t  timeout)
+{
+    return _rt_mq_send_wait(mq, buffer, size, timeout, RT_INTERRUPTIBLE);
+}
+RTM_EXPORT(rt_mq_send_wait_interruptible)
+
+rt_err_t rt_mq_send_wait_killable(rt_mq_t     mq,
+                         const void *buffer,
+                         rt_size_t   size,
+                         rt_int32_t  timeout)
+{
+    return _rt_mq_send_wait(mq, buffer, size, timeout, RT_KILLABLE);
+}
+RTM_EXPORT(rt_mq_send_wait_killable)
 /**
  * This function will send a message to message queue object, if there are
  * threads suspended on message queue object, it will be waked up.
@@ -2226,6 +2411,17 @@ rt_err_t rt_mq_send(rt_mq_t mq, const void *buffer, rt_size_t size)
 }
 RTM_EXPORT(rt_mq_send);
 
+rt_err_t rt_mq_send_interrupt(rt_mq_t mq, const void *buffer, rt_size_t size)
+{
+    return rt_mq_send_wait_interruptible(mq, buffer, size, 0);
+}
+RTM_EXPORT(rt_mq_send_interrupt);
+
+rt_err_t rt_mq_send_killable(rt_mq_t mq, const void *buffer, rt_size_t size)
+{
+    return rt_mq_send_wait_killable(mq, buffer, size, 0);
+}
+RTM_EXPORT(rt_mq_send_killable);
 /**
  * This function will send an urgent message to message queue object, which
  * means the message will be inserted to the head of message queue. If there
@@ -2297,7 +2493,7 @@ rt_err_t rt_mq_urgent(rt_mq_t mq, const void *buffer, rt_size_t size)
         rt_hw_interrupt_enable(temp); /* enable interrupt */
         return -RT_EFULL; /* value overflowed */
     }
-    
+
     /* resume suspended thread */
     if (!rt_list_isempty(&mq->parent.suspend_thread))
     {
@@ -2330,15 +2526,17 @@ RTM_EXPORT(rt_mq_urgent);
  *
  * @return the error code
  */
-rt_err_t rt_mq_recv(rt_mq_t    mq,
+static rt_err_t _rt_mq_recv(rt_mq_t    mq,
                     void      *buffer,
                     rt_size_t  size,
-                    rt_int32_t timeout)
+                    rt_int32_t timeout,
+                    int suspend_flag)
 {
     struct rt_thread *thread;
     register rt_ubase_t temp;
     struct rt_mq_message *msg;
     rt_uint32_t tick_delta;
+    rt_err_t ret;
 
     /* parameter check */
     RT_ASSERT(mq != RT_NULL);
@@ -2369,7 +2567,7 @@ rt_err_t rt_mq_recv(rt_mq_t    mq,
         RT_DEBUG_IN_THREAD_CONTEXT;
 
         /* reset error number in thread */
-        thread->error = RT_EOK;
+        thread->error = -RT_EINTR;
 
         /* no waiting, return timeout */
         if (timeout == 0)
@@ -2383,9 +2581,15 @@ rt_err_t rt_mq_recv(rt_mq_t    mq,
         }
 
         /* suspend current thread */
-        rt_ipc_list_suspend(&(mq->parent.suspend_thread),
+        ret = rt_ipc_list_suspend(&(mq->parent.suspend_thread),
                             thread,
-                            mq->parent.parent.flag);
+                            mq->parent.parent.flag,
+                            suspend_flag);
+        if (ret != RT_EOK)
+        {
+            rt_hw_interrupt_enable(temp);
+            return ret;
+        }
 
         /* has waiting time, start thread timer */
         if (timeout > 0)
@@ -2475,8 +2679,33 @@ rt_err_t rt_mq_recv(rt_mq_t    mq,
 
     return RT_EOK;
 }
+
+rt_err_t rt_mq_recv(rt_mq_t    mq,
+                    void      *buffer,
+                    rt_size_t  size,
+                    rt_int32_t timeout)
+{
+    return _rt_mq_recv(mq, buffer, size, timeout, RT_UNINTERRUPTIBLE);
+}
 RTM_EXPORT(rt_mq_recv);
 
+rt_err_t rt_mq_recv_interruptible(rt_mq_t    mq,
+                    void      *buffer,
+                    rt_size_t  size,
+                    rt_int32_t timeout)
+{
+    return _rt_mq_recv(mq, buffer, size, timeout, RT_INTERRUPTIBLE);
+}
+RTM_EXPORT(rt_mq_recv_interruptible);
+
+rt_err_t rt_mq_recv_killable(rt_mq_t    mq,
+                    void      *buffer,
+                    rt_size_t  size,
+                    rt_int32_t timeout)
+{
+    return _rt_mq_recv(mq, buffer, size, timeout, RT_KILLABLE);
+}
+RTM_EXPORT(rt_mq_recv_killable);
 /**
  * This function can get or set some extra attributions of a message queue
  * object.

+ 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_with_flag(thread, RT_UNINTERRUPTIBLE);
         rt_list_insert_after(&(mp->suspend_thread), &(thread->tlist));
 
         if (time > 0)

+ 2 - 2
src/scheduler.c

@@ -315,7 +315,7 @@ void rt_schedule(void)
     }
 
 #ifdef RT_USING_SIGNALS
-    if ((current_thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_SUSPEND)
+    if ((current_thread->stat & RT_THREAD_SUSPEND_MASK) == RT_THREAD_SUSPEND_MASK)
     {
         /* if current_thread signal is in pending */
 
@@ -559,7 +559,7 @@ void rt_scheduler_do_irq_switch(void *context)
     current_thread = pcpu->current_thread;
 
 #ifdef RT_USING_SIGNALS
-    if ((current_thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_SUSPEND)
+    if ((current_thread->stat & RT_THREAD_SUSPEND_MASK) == RT_THREAD_SUSPEND_MASK)
     {
         /* if current_thread signal is in pending */
 

+ 3 - 3
src/signal.c

@@ -102,7 +102,7 @@ static void _signal_deliver(rt_thread_t tid)
         return;
     }
 
-    if ((tid->stat & RT_THREAD_STAT_MASK) == RT_THREAD_SUSPEND)
+    if ((tid->stat & RT_THREAD_SUSPEND_MASK) == RT_THREAD_SUSPEND_MASK)
     {
         /* resume thread to handle signal */
 #ifdef RT_USING_LWP
@@ -201,7 +201,7 @@ void *rt_signal_check(void* context)
 
             rt_hw_interrupt_enable(level);
             sig_context = rt_hw_stack_init((void *)_signal_entry, context,
-                    (void *)(context - 32), RT_NULL);
+                    (void*)((char*)context - 32), RT_NULL);
             return sig_context;
         }
     }
@@ -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_with_flag(tid, RT_UNINTERRUPTIBLE);
     /* set thread stat as waiting for signal */
     tid->stat |= RT_THREAD_STAT_SIGNAL_WAIT;
 

+ 51 - 8
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);
@@ -527,7 +527,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_with_flag(thread, RT_INTERRUPTIBLE);
 
     /* reset the timeout of thread timer and start it */
     rt_timer_control(&(thread->thread_timer), RT_TIMER_CTRL_SET_TIME, &tick);
@@ -586,7 +586,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_with_flag(thread, RT_UNINTERRUPTIBLE);
 
         /* reset the timeout of thread timer and start it */
         rt_timer_control(&(thread->thread_timer), RT_TIMER_CTRL_SET_TIME, tick);
@@ -738,17 +738,45 @@ rt_err_t rt_thread_control(rt_thread_t thread, int cmd, void *arg)
 }
 RTM_EXPORT(rt_thread_control);
 
+#ifdef RT_USING_LWP
+int lwp_suspend_sigcheck(rt_thread_t thread, int suspend_flag);
+#endif
+
+static 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 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_with_flag(rt_thread_t thread, int suspend_flag)
 {
     register rt_base_t stat;
     register rt_base_t temp;
@@ -774,10 +802,18 @@ rt_err_t rt_thread_suspend(rt_thread_t thread)
         /* not suspend running status thread on other core */
         RT_ASSERT(thread == rt_thread_self());
     }
+#ifdef RT_USING_LWP
+    if (lwp_suspend_sigcheck(thread, suspend_flag) == 0)
+    {
+        /* not to suspend */
+        rt_hw_interrupt_enable(temp);
+        return -RT_EINTR;
+    }
+#endif
 
     /* 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));
@@ -788,8 +824,15 @@ rt_err_t rt_thread_suspend(rt_thread_t thread)
     RT_OBJECT_HOOK_CALL(rt_thread_suspend_hook, (thread));
     return RT_EOK;
 }
+RTM_EXPORT(rt_thread_suspend_with_flag);
+
+rt_err_t rt_thread_suspend(rt_thread_t thread)
+{
+    return rt_thread_suspend_with_flag(thread, RT_UNINTERRUPTIBLE);
+}
 RTM_EXPORT(rt_thread_suspend);
 
+
 /**
  * This function will resume a thread and put it to system ready queue.
  *
@@ -807,7 +850,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_STAT_MASK) != RT_THREAD_SUSPEND)
+    if ((thread->stat & RT_THREAD_SUSPEND_MASK) != RT_THREAD_SUSPEND_MASK)
     {
         RT_DEBUG_LOG(RT_DEBUG_THREAD, ("thread resume: thread disorder, %d\n",
                                        thread->stat));
@@ -899,7 +942,7 @@ void rt_thread_timeout(void *parameter)
 
     /* thread check */
     RT_ASSERT(thread != RT_NULL);
-    RT_ASSERT((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_SUSPEND);
+    RT_ASSERT((thread->stat & RT_THREAD_SUSPEND_MASK) == RT_THREAD_SUSPEND_MASK);
     RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread);
 
     /* set error number */

+ 2 - 2
src/timer.c

@@ -415,7 +415,7 @@ rt_err_t rt_timer_start(rt_timer_t timer)
     {
         /* check whether timer thread is ready */
         if ((soft_timer_status == RT_SOFT_TIMER_IDLE) &&
-           ((timer_thread.stat & RT_THREAD_STAT_MASK) == RT_THREAD_SUSPEND))
+           ((timer_thread.stat & RT_THREAD_SUSPEND_MASK) == RT_THREAD_SUSPEND_MASK))
         {
             /* resume timer thread to check soft timer */
             rt_thread_resume(&timer_thread);
@@ -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_with_flag(rt_thread_self(), RT_UNINTERRUPTIBLE);
             rt_schedule();
         }
         else