diff --git a/bsp/gkipc/armv6/rtos_lib.c b/bsp/gkipc/armv6/rtos_lib.c index 7d7aec5c51d24a2e05dec33a95357ed8bdbed858..4d0a75a10d8e15f69a5048cbf5d2ba610b3d5934 100644 --- a/bsp/gkipc/armv6/rtos_lib.c +++ b/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"); diff --git a/bsp/gkipc/armv6/trap.c b/bsp/gkipc/armv6/trap.c index 602badff39211dea78e9e235a9c2e20486875f64..f3ed43ab13bd1b790fe10b2bbd9799ab57cd8e16 100644 --- a/bsp/gkipc/armv6/trap.c +++ b/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 "); diff --git a/components/dfs/src/poll.c b/components/dfs/src/poll.c index fc48eca758d9e1c1d34c58d13683582db202398c..2d948a30a3d12130ae4756f9c2a218e4bd237380 100644 --- a/components/dfs/src/poll.c +++ b/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; diff --git a/components/drivers/audio/audio_pipe.c b/components/drivers/audio/audio_pipe.c index d7c37009b6c3005aba1738ddf0f3b4a93d34f100..4fd8b0edfe776af2f3f2e0edc72018f679a6cc35 100644 --- a/components/drivers/audio/audio_pipe.c +++ b/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)); diff --git a/components/drivers/include/ipc/waitqueue.h b/components/drivers/include/ipc/waitqueue.h index e26ec1e896078620c4f1cf192b1650d035201ba2..a64b973a9e4f7572c578258763d5526a94515ebb 100644 --- a/components/drivers/include/ipc/waitqueue.h +++ b/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) \ diff --git a/components/drivers/serial/serial.c b/components/drivers/serial/serial.c index dd234f074a0a88b12f75c88dd498d8ce8fe4fe9d..dc9c7ac2cf4031cacddafaadf255edc02a04ee76 100644 --- a/components/drivers/serial/serial.c +++ b/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; } diff --git a/components/drivers/src/completion.c b/components/drivers/src/completion.c index 9e461e49ce51e31f1437f02398076f9e83e590f1..24b85e198e4bd1919509677f99fe22be654efc1c 100644 --- a/components/drivers/src/completion.c +++ b/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)); diff --git a/components/drivers/src/dataqueue.c b/components/drivers/src/dataqueue.c index bfe8e1257394da38b000e7758ecfc94c30e39f91..3f481a308ec986f85ec08a1de97fbb0470f74c49 100644 --- a/components/drivers/src/dataqueue.c +++ b/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; diff --git a/components/drivers/src/waitqueue.c b/components/drivers/src/waitqueue.c index 02240edbdfdfa79ac55c1394cc31991b9597195d..830c5bed9ca5e265336172019d6806af916c9b5d 100644 --- a/components/drivers/src/waitqueue.c +++ b/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); +} diff --git a/components/drivers/src/workqueue.c b/components/drivers/src/workqueue.c index 2e0280df3a747ca4c09950676781527dc6f29295..564dde78f29d5d243281512e0642d72b250cb02a 100644 --- a/components/drivers/src/workqueue.c +++ b/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(); } diff --git a/components/finsh/cmd.c b/components/finsh/cmd.c index d53e30ceaaf2a3cab1526db4ea7b80226e836118..3c2a0b74c8eced868bf8609782b47894e2435c11 100644 --- a/components/finsh/cmd.c +++ b/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"); diff --git a/components/libc/compilers/newlib/syscalls.c b/components/libc/compilers/newlib/syscalls.c index 228fa0d140e0ce39dbc7968b974123313a11fdc3..aac6ff1d0b8aecc50920786f830ef9a0d98b4092 100644 --- a/components/libc/compilers/newlib/syscalls.c +++ b/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(); } diff --git a/components/libc/libdl/dlmodule.c b/components/libc/libdl/dlmodule.c index 314cf52709f691e68f3d8f83dfab8612e64b36ea..3c513acc277eee58c54d17d7c31047d5d829267d 100644 --- a/components/libc/libdl/dlmodule.c +++ b/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); } } } diff --git a/components/lwp/arch/arm/common/reloc.c b/components/lwp/arch/arm/common/reloc.c index 80b05e5d1c57cbe7c479266d7d0dffcfd8e61c2a..cab0b76fd793eca96c1a1fefa6feaa0506c81904 100644 --- a/components/lwp/arch/arm/common/reloc.c +++ b/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); } } } diff --git a/components/lwp/arch/arm/cortex-a/arch_user_stack.c b/components/lwp/arch/arm/cortex-a/arch_user_stack.c index e90ed650f3f7d5db63da0995183990e4350caefc..8911da82096b81ec8b28459d14bd5b4fdcecf46c 100644 --- a/components/lwp/arch/arm/cortex-a/arch_user_stack.c +++ b/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; } diff --git a/components/lwp/arch/arm/cortex-a/lwp_arch.h b/components/lwp/arch/arm/cortex-a/lwp_arch.h index 716e2ce26f4f3f38bd5720635e5989a2de4aba30..22a0f1fc6cabb04035e47dc544269faa70c17ce0 100644 --- a/components/lwp/arch/arm/cortex-a/lwp_arch.h +++ b/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 diff --git a/components/lwp/lwp.c b/components/lwp/lwp.c index 6486e621d5ff4f9811154a49186ea8f0e0aa7ec2..7d7cd3db89f01945bdfacb189abb50f2e6dc3ecd 100644 --- a/components/lwp/lwp.c +++ b/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)); diff --git a/components/lwp/lwp.h b/components/lwp/lwp.h index 1667df5c9ecb2c4c62ef6295a81fabf49f5a2d3a..c4a279673d72534a7712b0985103809a1ac6d5a4 100644 --- a/components/lwp/lwp.h +++ b/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; diff --git a/components/lwp/lwp_console.c b/components/lwp/lwp_console.c index ce7893782213c2dcf0397ac30e90db1b5704d17a..f964d6a0559fb6bdda82900b949abf4b9f8f69a2 100644 --- a/components/lwp/lwp_console.c +++ b/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; } diff --git a/components/lwp/lwp_ipc.c b/components/lwp/lwp_ipc.c index 3b6f5627e38d8c63c82bf6ab7175ccd196305187..40126229bc3ff9fc2e79f7ad9aa0f9eeac40d959 100644 --- a/components/lwp/lwp_ipc.c +++ b/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) diff --git a/components/lwp/lwp_pid.c b/components/lwp/lwp_pid.c index 700f347007fbabec57a1b5a2cb9cd8b6c1c3ca56..e13c6f33aa651ba0f013952b85eebb7b95eecfc3 100644 --- a/components/lwp/lwp_pid.c +++ b/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(); diff --git a/components/lwp/lwp_shm.c b/components/lwp/lwp_shm.c index 5c6754664f73ecbcc388dfe02d0ad214d93fc9b7..022b665877ca92e0e3848a73c60203d96caefd32 100644 --- a/components/lwp/lwp_shm.c +++ b/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. */ diff --git a/components/lwp/lwp_signal.c b/components/lwp/lwp_signal.c index e0e0c24ff1739d11a79d8fc90f18440d4dde8162..3c7f0d0195b938a5e841d5b329b9fe205a0e2e7e 100644 --- a/components/lwp/lwp_signal.c +++ b/components/lwp/lwp_signal.c @@ -12,13 +12,155 @@ #include #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; diff --git a/components/lwp/lwp_signal.h b/components/lwp/lwp_signal.h index fe07a4e1739a2c85852a65842f7b67fdad154694..7e3118bb0e4aaa65e5a1716205448f6a27c67d57 100644 --- a/components/lwp/lwp_signal.h +++ b/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); diff --git a/components/lwp/lwp_syscall.c b/components/lwp/lwp_syscall.c index 3513aafacbdd84c365238a93dbb146e95c5d492c..a3926983671a88daa31e8735292d1d0b283567a3 100644 --- a/components/lwp/lwp_syscall.c +++ b/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 diff --git a/components/lwp/lwp_user_mm.c b/components/lwp/lwp_user_mm.c index c2631b9f4d7108099a1f5dfb433df9061dca8cf2..c5ebe96bf4d8c5176b66c429cbe4c4a8c21fbbe3 100644 --- a/components/lwp/lwp_user_mm.c +++ b/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); } diff --git a/components/lwp/lwp_user_mm.h b/components/lwp/lwp_user_mm.h index 47f5fb604ceacf15feca02117dc76b2a52c1b302..d72a1ff30080c4779e73c89eed13069393bc2e15 100644 --- a/components/lwp/lwp_user_mm.h +++ b/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 diff --git a/components/net/lwip-2.0.2/src/arch/sys_arch.c b/components/net/lwip-2.0.2/src/arch/sys_arch.c index 40c79011ec612e762276212c16ae7aed10fe859d..827dcd154bfe4ba24447bccd0545cf0b3b48f285 100644 --- a/components/net/lwip-2.0.2/src/arch/sys_arch.c +++ b/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; diff --git a/components/vbus/prio_queue.c b/components/vbus/prio_queue.c index bca3cdcd9a698095226b0fa8e80326f128c7ecf1..0d15da5ab86d0933873117aa2c2fc2e52d536b9c 100644 --- a/components/vbus/prio_queue.c +++ b/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)); diff --git a/components/vbus/vbus.c b/components/vbus/vbus.c index 8add15d9dbacede318dbbb2374490b6a1c7e23a6..d471a9d21b274cefc66e14228b57332921337551 100644 --- a/components/vbus/vbus.c +++ b/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) diff --git a/components/vbus/watermark_queue.h b/components/vbus/watermark_queue.h index 0ecc52d8ff7710650ccef31108b1c6cca79cc914..8828ceb1ac44935d5c90ca3ca91ca93952c9c9b6 100644 --- a/components/vbus/watermark_queue.h +++ b/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) { diff --git a/examples/kernel/thread_resume.c b/examples/kernel/thread_resume.c index cea814616f92047339f38ddb2631e0fb516df045..26bebe91603f4288ad73872947f9686b83ce6821 100644 --- a/examples/kernel/thread_resume.c +++ b/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(); diff --git a/examples/kernel/thread_suspend.c b/examples/kernel/thread_suspend.c index 947cc3cbf61a6f605bc1043f231ccec6efc0910c..a6cf11b08910e9c13eb3505c3bc413dc06675ba5 100644 --- a/examples/kernel/thread_suspend.c +++ b/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); diff --git a/include/rtdef.h b/include/rtdef.h index 7f39ec35c352543a90275cf98ab7cf81ccd5ac35..efc8634e8c6996dc2dca6b8873bc3e74a00bb461 100644 --- a/include/rtdef.h +++ b/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 */ diff --git a/include/rtthread.h b/include/rtthread.h index ce0505e9ed99a03a688c6772301a187210139953..f6e08898897559e6d58d2ca17afbe8e5cb45f68d 100644 --- a/include/rtthread.h +++ b/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 diff --git a/libcpu/arm/AT91SAM7X/trap.c b/libcpu/arm/AT91SAM7X/trap.c index 1c1c351ff81b63ac1c80f1586cd2a0d4db0ca9e8..dbbe2a1684a8ea00229ae0cce6c86e995e20f948 100644 --- a/libcpu/arm/AT91SAM7X/trap.c +++ b/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(); } diff --git a/libcpu/arm/cortex-a/backtrace.c b/libcpu/arm/cortex-a/backtrace.c index 37a04e90aff547b7886ef4d61ae8c3eecb9695d3..695e31ca5a69d275742986bbb0884cfd84ca96ac 100644 --- a/libcpu/arm/cortex-a/backtrace.c +++ b/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); diff --git a/libcpu/arm/cortex-a/mmu.c b/libcpu/arm/cortex-a/mmu.c index eb9ba0fd8e22037f959c509193edce9307f1ce55..b50d7ab92edecaaee00fe722b343275e4c47fad9 100644 --- a/libcpu/arm/cortex-a/mmu.c +++ b/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; diff --git a/libcpu/arm/cortex-a/page.c b/libcpu/arm/cortex-a/page.c index 24c105cc3d824b0dcf028f48a40518c4e7a0ecf6..716e4f1aaf7a93a62103d08a0ee1b651b83b5831 100644 --- a/libcpu/arm/cortex-a/page.c +++ b/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) diff --git a/libcpu/arm/cortex-a/trap.c b/libcpu/arm/cortex-a/trap.c index 7bdf5a846ec4024d8043cd778c2aad890f34b597..bc4cf36a8cbddee3cd75e59b41991e51cb12af1c 100644 --- a/libcpu/arm/cortex-a/trap.c +++ b/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; diff --git a/src/ipc.c b/src/ipc.c index 454fcb5439bd26ae3534d4e6c7c66b22e31b1f89..7e64496e55d85c62c03d25adf7402b16fbb7b8e6 100644 --- a/src/ipc.c +++ b/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. diff --git a/src/mempool.c b/src/mempool.c index db614032aa67ac7d357408b9521192c39555adbe..5be9520c94454d2f0c4dbb208c522d303f316d2c 100644 --- a/src/mempool.c +++ b/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) diff --git a/src/scheduler.c b/src/scheduler.c index 2daf9aae9e50c577b3b6c2ee477c1b26f6a3025d..385d800b482c265627a906424fba6ae8052bd429 100644 --- a/src/scheduler.c +++ b/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 */ diff --git a/src/signal.c b/src/signal.c index 8745c18e47bb58e51cb311980f14994e015bdbd1..cef7e853352f0062929f8688f59233b792af582b 100644 --- a/src/signal.c +++ b/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; diff --git a/src/thread.c b/src/thread.c index 0290f330f8fade13c8a78871a1661314e6bb02de..863bf6259a3dee7bd323e399aa0c943da9661270 100644 --- a/src/thread.c +++ b/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 */ diff --git a/src/timer.c b/src/timer.c index b5c978991ca4c8eac9c07b5f62b83cfe8ccf4267..38c17687ad08a5feada2b7af9011cf5c6c1dbf7f 100644 --- a/src/timer.c +++ b/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