diff --git a/mkrtos_configs/STM32F205_defconfig b/mkrtos_configs/STM32F205_defconfig index a1dd7bda4..0ed7eef8d 100644 --- a/mkrtos_configs/STM32F205_defconfig +++ b/mkrtos_configs/STM32F205_defconfig @@ -115,7 +115,7 @@ CONFIG_BOARD_NAME="STM32F205" CONFIG_BUDDY_SLAB=n CONFIG_SMP=n CONFIG_CPU=1 -CONFIG_THREAD_BLOCK_SIZE=0x400 +CONFIG_THREAD_BLOCK_SIZE=0x800 CONFIG_PAGE_SHIFT=9 CONFIG_MMU=n CONFIG_KNL_TEST=n diff --git a/mkrtos_knl/arch/cortex-m3/thread_armv7m.c b/mkrtos_knl/arch/cortex-m3/thread_armv7m.c index f186ebdba..9430cb438 100644 --- a/mkrtos_knl/arch/cortex-m3/thread_armv7m.c +++ b/mkrtos_knl/arch/cortex-m3/thread_armv7m.c @@ -40,7 +40,7 @@ void thread_knl_pf_set(thread_t *cur_th, void *pc) cur_th->sp.user_sp = 0; cur_th->sp.sp_type = 0xfffffff9; } -void thread_user_pf_set(thread_t *cur_th, void *pc, void *user_sp, void *ram, umword_t stack) +void thread_user_pf_set(thread_t *cur_th, void *pc, void *user_sp, void *ram) { // assert((((umword_t)user_sp) & 0x7UL) == 0); umword_t usp = ((umword_t)(user_sp) & ~0x7UL); @@ -55,8 +55,12 @@ void thread_user_pf_set(thread_t *cur_th, void *pc, void *user_sp, void *ram, um cur_th->sp.knl_sp = ((char *)cur_th + CONFIG_THREAD_BLOCK_SIZE - 8); cur_th->sp.user_sp = cur_pf; cur_th->sp.sp_type = 0xfffffffd; - - // printk("exc_regs:%x %x %x\n", cur_pf->pf_s.pc, cur_th->sp.user_sp, ram); +} +void thread_user_pf_restore(thread_t *cur_th, void *user_sp) +{ + cur_th->sp.knl_sp = ((char *)cur_th + CONFIG_THREAD_BLOCK_SIZE - 8); + cur_th->sp.user_sp = user_sp; + cur_th->sp.sp_type = 0xfffffffd; } void task_knl_init(task_t *knl_tk) { diff --git a/mkrtos_knl/drivers/at32f437/uart/at32f437_uart.c b/mkrtos_knl/drivers/at32f437/uart/at32f437_uart.c index 46c6d849d..e8473b2a4 100755 --- a/mkrtos_knl/drivers/at32f437/uart/at32f437_uart.c +++ b/mkrtos_knl/drivers/at32f437/uart/at32f437_uart.c @@ -67,7 +67,7 @@ void uart_init(void) nvic_priority_group_config(NVIC_PRIORITY_GROUP_2); nvic_irq_enable(USART1_IRQn, 0, 0); /* configure uart param */ - usart_init(PRINT_USARTx, 115200, USART_DATA_8BITS, USART_STOP_1_BIT); + usart_init(PRINT_USARTx, 921600, USART_DATA_8BITS, USART_STOP_1_BIT); usart_transmitter_enable(PRINT_USARTx, TRUE); usart_receiver_enable(PRINT_USARTx, TRUE); diff --git a/mkrtos_knl/inc/knl/sema.h b/mkrtos_knl/inc/knl/sema.h index 10e09d330..4c101ad27 100644 --- a/mkrtos_knl/inc/knl/sema.h +++ b/mkrtos_knl/inc/knl/sema.h @@ -18,15 +18,15 @@ void sema_init(sema_t *obj, int cnt, int max); void sema_up(sema_t *obj); void sema_down(sema_t *obj); -void mutex_init(mutex_t *lock) +static inline void mutex_init(mutex_t *lock) { sema_init(lock, 1, 1); } -void mutex_lock(mutex_t *lock) +static inline void mutex_lock(mutex_t *lock) { sema_down(lock); } -void mutex_unlock(mutex_t *lock) +static inline void mutex_unlock(mutex_t *lock) { sema_up(lock); } diff --git a/mkrtos_knl/inc/knl/task.h b/mkrtos_knl/inc/knl/task.h index 6c1c4fadb..8cc6ed813 100755 --- a/mkrtos_knl/inc/knl/task.h +++ b/mkrtos_knl/inc/knl/task.h @@ -18,7 +18,7 @@ #include "obj_space.h" #include "mm_space.h" #include "ref.h" - +#include "sema.h" typedef struct task { kobject_t kobj; //!< task kernel object. @@ -28,9 +28,16 @@ typedef struct task kobject_t *exec_th; //!< execption thread. ref_counter_t ref_cn; //!< ref count. slist_head_t del_node; //!< delect list node. - void *nofity_point; //!< commint point. - addr_t nofity_stack; //!< nofity_point_stack. - pid_t pid; //!< task pid. + + void *nofity_point; //!< commint point func. + addr_t nofity_stack; //!< nofity_point_stack. + mutex_t nofity_lock; + addr_t nofity_msg_buf; //!< + umword_t *nofity_bitmap; //!< + int nofity_bitmap_len; //!< max is WORD_BITS + slist_head_t nofity_theads_head; + + pid_t pid; //!< task pid. } task_t; static inline pid_t task_pid_get(task_t *task) diff --git a/mkrtos_knl/inc/knl/thread.h b/mkrtos_knl/inc/knl/thread.h index 0c3a20cc6..3786d03ca 100755 --- a/mkrtos_knl/inc/knl/thread.h +++ b/mkrtos_knl/inc/knl/thread.h @@ -17,6 +17,7 @@ #include "ref.h" #include #include "task.h" +#include "stack.h" struct task; typedef struct task task_t; struct thread; @@ -107,16 +108,24 @@ typedef struct msg_buf #endif msg_tag_t tag; //!< 存放发送的临时标识 } msg_buf_t; + +typedef struct thread_fast_ipc_item +{ + kobject_t *task_bk; //!< 备份task,用于快速通信 + void *usp_backup; //!< 备份用户栈,用于快速通信 + void *msg_buf; +} thread_fast_ipc_item_t; +#define THREAD_FAST_IPC_ITEM_NUM 8 + #define THREAD_MAGIC 0xdeadead //!< 用于栈溢出检测 typedef struct thread { - kobject_t kobj; //!< 内核对象节点 - sched_t sche; //!< 调度节点 - kobject_t *task; //!< 绑定的task - kobject_t *task_bk; //!< 备份task,用于快速通信 - sp_info_t sp; //!< sp信息 - ram_limit_t *lim; //!< 内存限制 - ref_counter_t ref; //!< 引用计数 + kobject_t kobj; //!< 内核对象节点 + sched_t sche; //!< 调度节点 + kobject_t *task; //!< 绑定的task + sp_info_t sp; //!< sp信息 + ram_limit_t *lim; //!< 内存限制 + ref_counter_t ref; //!< 引用计数 slist_head_t futex_node; //!< futex使用 @@ -141,7 +150,9 @@ typedef struct thread enum thread_state status; //!< 线程状态 enum thread_ipc_state ipc_status; //!< ipc状态 - void *usp_backup; + thread_fast_ipc_item_t fast_ipc_stack_data[THREAD_FAST_IPC_ITEM_NUM]; //!< 栈数据,用于通信栈备份 + stack_t fast_ipc_stack; //!< fast ipc stack + slist_head_t fast_ipc_node; //!< 用于加入到task中去。 umword_t magic; //!< maigc } thread_t; @@ -207,14 +218,51 @@ static inline thread_t *thread_get_current(void) return th; } -static inline void thread_set_task_and_backup(thread_t *th, task_t *tk) +static inline int thread_fast_ipc_save(thread_t *th, task_t *tk, void *usp) { - th->task_bk = th->task; - th->task = (void*)(&(tk->kobj)); + int ret; + assert(th); + assert(tk); + assert(usp); + thread_fast_ipc_item_t item = { + .task_bk = th->task, + .usp_backup = (void *)arch_get_user_sp(), + .msg_buf = th->msg.msg, + }; + ret = stack_push(&th->fast_ipc_stack, &item); + if (ret < 0) + { + return ret; + } + th->task = &tk->kobj; + arch_set_user_sp((umword_t)usp); //!< 重新设置 + return 0; } -static inline void thread_task_restore(thread_t *th) +static inline int thread_fast_ipc_restore(thread_t *th) { - th->task = th->task_bk; + int ret; + assert(th); + thread_fast_ipc_item_t item; + + ret = stack_pop(&th->fast_ipc_stack, &item); + if (ret < 0) + { + return ret; + } + th->task = item.task_bk; + th->msg.msg = item.msg_buf; + arch_set_user_sp((umword_t)(item.usp_backup)); + return 0; +} +static inline int thread_fast_ipc_pop(thread_t *th, thread_fast_ipc_item_t *item) +{ + int ret; + assert(th); + assert(item); + + ret = stack_pop(&th->fast_ipc_stack, item); + + return ret; } task_t *thread_get_current_task(void); task_t *thread_get_task(thread_t *th); @@ -225,7 +273,7 @@ static inline pf_t *thread_get_current_pf(void) return thread_get_pf(thread_get_current()); } void thread_init(thread_t *th, ram_limit_t *lim, umword_t flags); -void thread_set_exc_regs(thread_t *th, umword_t pc, umword_t user_sp, umword_t ram, umword_t stack); +void thread_set_exc_regs(thread_t *th, umword_t pc, umword_t user_sp, umword_t ram); thread_t *thread_create(ram_limit_t *ram, umword_t flags); void thread_bind(thread_t *th, kobject_t *tk); void thread_unbind(thread_t *th); diff --git a/mkrtos_knl/inc/knl/thread_task_arch.h b/mkrtos_knl/inc/knl/thread_task_arch.h index 7a5506b04..1a1b838a5 100644 --- a/mkrtos_knl/inc/knl/thread_task_arch.h +++ b/mkrtos_knl/inc/knl/thread_task_arch.h @@ -1,4 +1,5 @@ #pragma once void thread_knl_pf_set(thread_t *cur_th, void *pc); -void thread_user_pf_set(thread_t *cur_th, void *pc, void *user_sp, void *ram, umword_t stack); +void thread_user_pf_set(thread_t *cur_th, void *pc, void *user_sp, void *ram); +void thread_user_pf_restore(thread_t *cur_th, void *user_sp); void task_knl_init(task_t *knl_tk); diff --git a/mkrtos_knl/inc/lib/stack.h b/mkrtos_knl/inc/lib/stack.h new file mode 100644 index 000000000..a008c121d --- /dev/null +++ b/mkrtos_knl/inc/lib/stack.h @@ -0,0 +1,13 @@ +#pragma once + +typedef struct +{ + void *data; + int top; + int len; + int item_size; +} stack_t; + +void stack_init(stack_t *stack, void *stack_data, int len, int item_size); +int stack_push(stack_t *stack, void *item); +int stack_pop(stack_t *stack, void *item); diff --git a/mkrtos_knl/knl/task.c b/mkrtos_knl/knl/task.c index de035e157..509e94d2c 100755 --- a/mkrtos_knl/knl/task.c +++ b/mkrtos_knl/knl/task.c @@ -22,6 +22,7 @@ #include "string.h" #include "thread.h" #include "thread_arch.h" +#include "thread_task_arch.h" #if IS_ENABLED(CONFIG_MMU) #include "arch.h" #endif @@ -41,6 +42,8 @@ enum task_op_code TASK_SET_OBJ_NAME, //!< 设置对象的名字 TASK_COPY_DATA_TO, //!< 从当前task拷贝数据到目的task TASK_SET_COM_POINT, //!< 通信点 + TASK_COM_UNLOCK, //!< 任务通信解锁 + TASK_COM_LOCK, //!< 任务通信加锁 }; static bool_t task_put(kobject_t *kobj); static void task_release_stage1(kobject_t *kobj); @@ -396,10 +399,51 @@ static void task_syscall_func(kobject_t *kobj, syscall_prot_t sys_p, msg_tag_t i tag = msg_tag_init4(0, 0, 0, ret); } break; - case TASK_SET_COM_POINT: + case TASK_SET_COM_POINT: //!< 设置通信点 { + if (!is_rw_access(tag_task, (void *)(f->regs[1]), f->regs[2], FALSE)) + { + tag = msg_tag_init4(0, 0, 0, -EPERM); + break; + } + if (f->regs[4] >= WORD_BITS) + { + tag = msg_tag_init4(0, 0, 0, -EINVAL); + break; + } + if (!is_rw_access(tag_task, (void *)(f->regs[3]), ROUND_UP(f->regs[4], 8), FALSE)) + { + tag = msg_tag_init4(0, 0, 0, -EPERM); + break; + } + if (!is_rw_access(tag_task, (void *)(f->regs[5]), THREAD_MSG_BUG_LEN, FALSE)) + { + tag = msg_tag_init4(0, 0, 0, -EPERM); + break; + } + int stack_size = f->regs[2]; + tag_task->nofity_point = (void *)(f->regs[0]); - tag_task->nofity_stack = (addr_t)(f->regs[1]); + tag_task->nofity_stack = (addr_t)(f->regs[1] + stack_size); + tag_task->nofity_bitmap = (void *)(f->regs[3]); + tag_task->nofity_bitmap_len = (f->regs[4]); + tag_task->nofity_msg_buf = (addr_t)f->regs[5]; + tag = msg_tag_init4(0, 0, 0, 0); + } + break; + case TASK_COM_UNLOCK: + { + task_t *cur_task = thread_get_current_task(); + + mutex_unlock(&cur_task->nofity_lock); + tag = msg_tag_init4(0, 0, 0, 0); + } + break; + case TASK_COM_LOCK: + { + task_t *cur_task = thread_get_current_task(); + + mutex_lock(&cur_task->nofity_lock); tag = msg_tag_init4(0, 0, 0, 0); } break; @@ -420,6 +464,8 @@ void task_init(task_t *task, ram_limit_t *ram, int is_knl) ref_counter_init(&task->ref_cn); ref_counter_inc(&task->ref_cn); slist_init(&task->del_node); + slist_init(&task->nofity_theads_head); + mutex_init(&task->nofity_lock); task->pid = -1; task->lim = ram; task->kobj.invoke_func = task_syscall_func; @@ -442,6 +488,7 @@ static bool_t task_put(kobject_t *kobj) } static void task_release_stage1(kobject_t *kobj) { + int ret; task_t *tk = container_of(kobj, task_t, kobj); kobj_del_list_t kobj_list; kobject_invalidate(kobj); @@ -449,6 +496,28 @@ static void task_release_stage1(kobject_t *kobj) obj_unmap_all(&tk->obj_space, &kobj_list); kobj_del_list_to_do(&kobj_list); + thread_t *restore_th; + thread_fast_ipc_item_t ipc_item; + + slist_foreach(restore_th, &tk->nofity_theads_head, fast_ipc_node) + { + ret = thread_fast_ipc_pop(restore_th, &ipc_item); + if (ret >= 0) + { + // 还原栈和usp + restore_th->ipc_status = THREAD_NONE; + if (restore_th->status == THREAD_SUSPEND) + { + thread_ready(restore_th, TRUE); + } + restore_th->task = ipc_item.task_bk; + thread_user_pf_restore(restore_th, ipc_item.usp_backup); + pf_t *cur_pf = ((pf_t *)((char *)restore_th + CONFIG_THREAD_BLOCK_SIZE + 8)) - 1; + cur_pf->regs[5] = (umword_t)(thread_get_bind_task(restore_th)->mm_space.mm_block); + ref_counter_dec_and_release(&tk->ref_cn, &tk->kobj); + } + } + #if IS_ENABLED(CONFIG_MMU) task_vma_clean(&tk->mm_space.mem_vma); #endif @@ -482,7 +551,7 @@ static void task_release_stage2(kobject_t *kobj) // arch_to_sche(); // } // mm_trace(); - printk("release tk %x\n", tk); + printk("release tk %x, name is:%s\n", tk, kobject_get_name(&tk->kobj)); } void task_kill(task_t *tk) { diff --git a/mkrtos_knl/knl/thread.c b/mkrtos_knl/knl/thread.c index 62a11b4b6..3e0eba363 100755 --- a/mkrtos_knl/knl/thread.c +++ b/mkrtos_knl/knl/thread.c @@ -32,6 +32,7 @@ #include "thread.h" #include "thread_task_arch.h" #include "types.h" +#include "sema.h" #if IS_ENABLED(CONFIG_SMP) #include #endif @@ -120,11 +121,15 @@ void thread_init(thread_t *th, ram_limit_t *lim, umword_t flags) sched_init(&th->sche); slist_init(&th->futex_node); slist_init(&th->wait_send_head); + slist_init(&th->fast_ipc_node); spinlock_init(&th->recv_lock); spinlock_init(&th->send_lock); ref_counter_init(&th->ref); ref_counter_inc(&th->ref); thread_arch_init(th, flags); + stack_init(&th->fast_ipc_stack, &th->fast_ipc_stack_data, + ARRARY_LEN(th->fast_ipc_stack_data), + sizeof(th->fast_ipc_stack_data[0])); th->cpu = arch_get_current_cpu_id(); th->lim = lim; th->kobj.invoke_func = thread_syscall; @@ -310,7 +315,7 @@ static void thread_release_stage2(kobject_t *kobj) #else mm_limit_free_align(th->lim, kobj, CONFIG_THREAD_BLOCK_SIZE); // mm_trace(); - // printk("release thread 0x%x\n", kobj); + printk("release thread 0x%x, name:%s\n", kobj, kobject_get_name(kobj)); #endif } @@ -322,9 +327,9 @@ static void thread_release_stage2(kobject_t *kobj) * @param ip */ void thread_set_exc_regs(thread_t *th, umword_t pc, umword_t user_sp, - umword_t ram, umword_t stack) + umword_t ram) { - thread_user_pf_set(th, (void *)pc, (void *)user_sp, (void *)ram, stack); + thread_user_pf_set(th, (void *)pc, (void *)user_sp, (void *)ram); } /** * @brief 线程绑定到task @@ -710,6 +715,41 @@ void thread_timeout_del_recv_remote(thread_t *th, bool_t is_sche) thread_ready(th, is_sche); //!< 直接唤醒接受者 #endif } +static int ipc_dat_copy_raw(obj_space_t *dst_obj, obj_space_t *src_obj, ram_limit_t *lim, + ipc_msg_t *dst_ipc, ipc_msg_t *src_ipc, msg_tag_t tag, int is_reply) +{ + if (tag.map_buf_len > 0) + { + kobj_del_list_t del; + int map_len = tag.map_buf_len; + + kobj_del_list_init(&del); + + for (int i = 0; i < map_len; i++) + { + int ret = 0; + + vpage_t dst_page = vpage_create_raw(dst_ipc->map_buf[i]); + vpage_t src_page = vpage_create_raw(src_ipc->map_buf[i]); + + if ((src_page.flags & VPAGE_FLAGS_MAP) || is_reply) + { + ret = obj_map_src_dst(dst_obj, src_obj, + vpage_get_obj_handler(dst_page), + vpage_get_obj_handler(src_page), lim, + vpage_get_attrs(src_page), &del); + } + + if (ret < 0) + { + return ret; + } + } + kobj_del_list_to_do(&del); + } + memcpy(dst_ipc->msg_buf, src_ipc->msg_buf, + MIN(tag.msg_buf_len * WORD_BYTES, IPC_MSG_SIZE)); +} /** * @brief ipc传输时的数据拷贝 * @@ -730,38 +770,9 @@ static int ipc_data_copy(thread_t *dst_th, thread_t *src_th, msg_tag_t tag, int src_ipc = src; dst_ipc = dst; - if (tag.map_buf_len > 0) - { - kobj_del_list_t del; - int map_len = tag.map_buf_len; - - kobj_del_list_init(&del); - - for (int i = 0; i < map_len; i++) - { - int ret = 0; - - vpage_t dst_page = vpage_create_raw(dst_ipc->map_buf[i]); - vpage_t src_page = vpage_create_raw(src_ipc->map_buf[i]); - - if ((src_page.flags & VPAGE_FLAGS_MAP) || is_reply) - { - ret = obj_map_src_dst(&dst_tk->obj_space, &src_tk->obj_space, - vpage_get_obj_handler(dst_page), - vpage_get_obj_handler(src_page), dst_tk->lim, - vpage_get_attrs(src_page), &del); - } - - if (ret < 0) - { - return ret; - } - } - kobj_del_list_to_do(&del); - } + ipc_dat_copy_raw(&dst_tk->obj_space, &src_tk->obj_space, dst_tk->lim, dst_ipc, src_ipc, tag, is_reply); dst_ipc->user[2] = task_pid_get(src_tk); - memcpy(dst_ipc->msg_buf, src_ipc->msg_buf, - MIN(tag.msg_buf_len * WORD_BYTES, IPC_MSG_SIZE)); + dst_th->msg.tag = tag; return 0; } @@ -918,10 +929,11 @@ again:; if (to->ipc_status == THREAD_IPC_ABORT) { ref_counter_dec_and_release(&to->ref, &to->kobj); + spinlock_set(&to->recv_lock, status_lock2); return -ECANCELED; } - spinlock_set(&to->recv_lock, status_lock2); thread_sched(TRUE); + spinlock_set(&to->recv_lock, status_lock2); preemption(); goto again; } @@ -946,7 +958,6 @@ again:; assert(to->status == THREAD_SUSPEND && to->ipc_status == THREAD_RECV); thread_timeout_del_from_send_queue_remote(to); } - // to->last_send_th = NULL; ref_counter_dec_and_release(&to->ref, &to->kobj); spinlock_set(&to->recv_lock, status_lock2); return 0; @@ -1225,55 +1236,114 @@ msg_tag_t thread_do_ipc(kobject_t *kobj, entry_frame_t *f, umword_t user_id) { case IPC_FAST_REPLAY: { - thread_task_restore(cur_th); //!< 切换task到目的task,并且进行备份 - arch_set_user_sp((umword_t)(cur_th->usp_backup)); + msg_tag_t in_tag = msg_tag_init(f->regs[0]); + task_t *old_task = thread_get_bind_task(cur_th); + //! 解锁bitmap + *(cur_task->nofity_bitmap) &= ~(1 << MIN(f->regs[2], cur_task->nofity_bitmap_len)); + slist_del(&cur_th->fast_ipc_node); + + ret = thread_fast_ipc_restore(cur_th); // 还原栈和usp + if (ret < 0) + { + mutex_unlock(&old_task->nofity_lock); + return msg_tag_init4(0, 0, 0, ret); + } + task_t *cur_task = thread_get_current_task(); + ipc_msg_t *dst_ipc = (void *)cur_th->msg.msg; + ipc_msg_t *src_ipc = (void *)old_task->nofity_msg_buf; + ret = ipc_dat_copy_raw(&cur_task->obj_space, &old_task->obj_space, cur_task->lim, + dst_ipc, src_ipc, in_tag, FALSE); + if (ret < 0) + { + mutex_unlock(&old_task->nofity_lock); + return msg_tag_init4(0, 0, 0, ret); + } + mutex_unlock(&old_task->nofity_lock); pf_t *cur_pf = ((pf_t *)((char *)cur_th + CONFIG_THREAD_BLOCK_SIZE + 8)) - 1; - cur_pf->regs[5] = (umword_t)(thread_get_current_task()->mm_space.mm_block); + cur_pf->regs[5] = (umword_t)(cur_task->mm_space.mm_block); extern void mpu_switch_to_task(struct task * tk); - mpu_switch_to_task(thread_get_current_task()); - - return msg_tag_init4(0, 0, 0, 0); + mpu_switch_to_task(cur_task); + ref_counter_dec_and_release(&old_task->ref_cn, &old_task->kobj); + return msg_tag_init4(0, 0, 0, ret); } break; case IPC_FAST_CALL: { - // 线程中的task - // 内核栈返回需要修改r9 - // 还原用户站 + msg_tag_t in_tag = msg_tag_init(f->regs[0]); + // 1.需要切换的资源有r9,task,和用户栈 + // 2.在对方进程中被杀死,需要还原当前线程的状态,并返回一个错误 + // 3.多线程访问时,服务端提供一个小的用户线程栈,然后内核到用户部分为临界区域,在服务端重新分配用户栈用,使用新的用户栈。 + // 4.fastipc嵌套访问会有问题,内核必须要提供一个软件上的调用栈。 task_t *to_task = thread_get_bind_task(to_th); if (to_task->nofity_point == NULL) { return msg_tag_init4(0, 0, 0, -EIO); } - - thread_set_task_and_backup(cur_th, to_task); //!< 切换task到目的task,并且进行备份 - + _to_unlock: + if (GET_LSB(*to_task->nofity_bitmap, to_task->nofity_bitmap_len) == GET_LSB((~0ULL), to_task->nofity_bitmap_len)) + { + thread_sched(TRUE); /*TODO:应该挂起,并在释放时唤醒*/ + preemption(); + goto _to_unlock; + } + mutex_lock(&to_task->nofity_lock); + if (GET_LSB(*to_task->nofity_bitmap, to_task->nofity_bitmap_len) == GET_LSB((~0ULL), to_task->nofity_bitmap_len)) + { + mutex_unlock(&to_task->nofity_lock); + thread_sched(TRUE); /*TODO:应该挂起,并在释放时唤醒*/ + preemption(); + goto _to_unlock; + } + ref_counter_inc((&to_task->ref_cn)); //!< 执行目标线程时用的是当前线程的资源,这里还需要备份当前线程的上下文。 - void *prev_usp = (void *)arch_get_user_sp(); + ret = thread_fast_ipc_save(cur_th, to_task, (void *)(to_task->nofity_stack - 4 * 8)); //!< 备份栈和usp + if (ret >= 0) + { + ipc_msg_t *dst_ipc = (void *)to_task->nofity_msg_buf; + ipc_msg_t *src_ipc = (void *)cur_th->msg.msg; + ret = ipc_dat_copy_raw(&to_task->obj_space, &cur_task->obj_space, to_task->lim, + dst_ipc, src_ipc, in_tag, FALSE); + if (ret >= 0) + { + dst_ipc->user[2] = task_pid_get(cur_task); // 设置pid - cur_th->usp_backup = prev_usp;//!<保存之前的用户栈 - arch_set_user_sp(to_task->nofity_stack - 32); //!<重新设置 - pf_s_t *usr_stask_point = (void *)arch_get_user_sp(); + slist_add(&to_task->nofity_theads_head, &cur_th->fast_ipc_node); - // usr_stask_point->rg0[0] = 0x1111; - // usr_stask_point->rg0[1] = 0x2222; - // usr_stask_point->rg0[2] = 0x3333; - // usr_stask_point->rg0[3] = 0x4444; - usr_stask_point->r12 = 0x12121212; - usr_stask_point->xpsr = 0x01000000L; - usr_stask_point->lr = (umword_t)NULL; //!< 线程退出时调用的函数 - usr_stask_point->pc = (umword_t)(to_task->nofity_point) | 0x1; + pf_s_t *usr_stask_point = (void *)arch_get_user_sp(); - pf_t *cur_pf = ((pf_t *)((char *)cur_th + CONFIG_THREAD_BLOCK_SIZE + 8)) - 1; //!< 获得内核栈栈顶 - cur_pf->regs[5] = (umword_t)(to_task->mm_space.mm_block); // 重新设置r9寄存器 + usr_stask_point->r12 = 0x12121212; + usr_stask_point->xpsr = 0x01000000L; + usr_stask_point->lr = (umword_t)NULL; //!< 线程退出时调用的函数 + usr_stask_point->pc = (umword_t)(to_task->nofity_point) | 0x1; - extern void mpu_switch_to_task(struct task * tk); - mpu_switch_to_task(to_task); + pf_t *cur_pf = ((pf_t *)((char *)cur_th + CONFIG_THREAD_BLOCK_SIZE + 8)) - 1; //!< 获得内核栈栈顶 + cur_pf->regs[5] = (umword_t)(to_task->mm_space.mm_block); // 重新设置r9寄存器 - return msg_tag_init4(0, 0, 0, 0); + //! 寄存器传参数 + f->regs[0] = in_tag.raw; + f->regs[1] = f->regs[2]; + f->regs[2] = f->regs[3]; + f->regs[3] = f->regs[4]; + + extern void mpu_switch_to_task(struct task * tk); + mpu_switch_to_task(to_task); + return in_tag; + } + else + { + ref_counter_dec_and_release(&to_task->ref_cn, &to_task->kobj); + mutex_unlock(&to_task->nofity_lock); + } + } + else + { + ref_counter_dec_and_release(&to_task->ref_cn, &to_task->kobj); + mutex_unlock(&to_task->nofity_lock); + } + return msg_tag_init4(0, 0, 0, ret); } break; case IPC_CALL: @@ -1376,14 +1446,7 @@ static void thread_syscall(kobject_t *kobj, syscall_prot_t sys_p, { case SET_EXEC_REGS: { - umword_t stack_bottom = 0; - - if (f->regs[4]) //!< cp_stack - { - stack_bottom = (umword_t)(thread_get_msg_buf(cur_th)); - } - thread_set_exc_regs(tag_th, f->regs[1], f->regs[2], f->regs[3], - stack_bottom); + thread_set_exc_regs(tag_th, f->regs[1], f->regs[2], f->regs[3]); tag = msg_tag_init4(0, 0, 0, 0); } break; diff --git a/mkrtos_knl/knl/thread_knl.c b/mkrtos_knl/knl/thread_knl.c index 34a5ebb0c..e7fb02fca 100755 --- a/mkrtos_knl/knl/thread_knl.c +++ b/mkrtos_knl/knl/thread_knl.c @@ -72,15 +72,23 @@ static void knl_main(void) msg_tag_t tag; umword_t user_id; ipc_msg_t *msg = (ipc_msg_t *)knl_msg_buf; - msg->msg_buf[0] = 1; /*KILL_TASK*/ - msg->msg_buf[1] = pos->pid; - msg->msg_buf[2] = 0; - int ret = thread_ipc_call(init_thread, msg_tag_init4(0, 3, 0, 0x0005 /*PM_PROT*/), - &tag, ipc_timeout_create2(3000, 3000), &user_id, TRUE); - if (ret < 0) + if (pos->pid != 0) { - printk("%s:%d ret:%d\n", __func__, __LINE__, ret); + msg->msg_buf[0] = 1; /*KILL_TASK*/ + msg->msg_buf[1] = pos->pid; + msg->msg_buf[2] = 0; + + if (thread_get_ipc_state(init_thread) != THREAD_IPC_ABORT) + { + int ret = thread_ipc_call(init_thread, msg_tag_init4(0, 3, 0, 0x0005 /*PM_PROT*/), + &tag, ipc_timeout_create2(3000, 3000), &user_id, TRUE); + + if (ret < 0) + { + printk("%s:%d ret:%d\n", __func__, __LINE__, ret); + } + } } } task_kill(pos); @@ -151,7 +159,7 @@ static void knl_init_2(void) cpio_get_size(cpio_images), (paddr_t)cpio_images, 0) >= 0); thread_set_msg_buf(init_thread, (void *)init_msg_buf, (void *)CONFIG_MSG_BUF_VADDR); thread_user_pf_set(init_thread, (void *)(entry), (void *)0xdeaddead, - NULL, 0); + NULL); #else app_info_t *app; @@ -167,7 +175,7 @@ static void knl_init_2(void) thread_set_msg_buf(init_thread, (char *)(init_task->mm_space.mm_block) + app->i.ram_size, (char *)(init_task->mm_space.mm_block) + app->i.ram_size); thread_user_pf_set(init_thread, (void *)(app), (void *)((umword_t)sp_addr_top - 8), - init_task->mm_space.mm_block, 0); + init_task->mm_space.mm_block); #endif thread_bind(init_thread, &init_task->kobj); assert(obj_map_root(&init_thread->kobj, &init_task->obj_space, &root_factory_get()->limit, vpage_create3(KOBJ_ALL_RIGHTS, 0, THREAD_PROT))); @@ -180,7 +188,7 @@ static void knl_init_2(void) assert(obj_map_root(kobj, &init_task->obj_space, &root_factory_get()->limit, vpage_create3(KOBJ_ALL_RIGHTS, 0, i))); } } - init_thread->sche.prio = 2; + init_thread->sche.prio = 15; init_task->pid = 0; thread_ready(init_thread, FALSE); #endif @@ -197,6 +205,7 @@ void task_knl_kill(thread_t *kill_thread, bool_t is_knl) status2 = spinlock_lock(&del_lock); thread_suspend(kill_thread); + kill_thread->ipc_status = THREAD_IPC_ABORT; slist_add_append(&del_task_head, &task->del_node); spinlock_set(&del_lock, status2); } diff --git a/mkrtos_knl/lib/stack.c b/mkrtos_knl/lib/stack.c new file mode 100644 index 000000000..e1c96d528 --- /dev/null +++ b/mkrtos_knl/lib/stack.c @@ -0,0 +1,37 @@ + +#include "types.h" +#include +#include +#include "stack.h" + +void stack_init(stack_t *stack, void *stack_data, int len, int item_size) +{ + assert(stack); + assert(stack_data); + memset(stack_data, 0, len * item_size); + stack->top = -1; + stack->len = len; + stack->item_size = item_size; + stack->data = stack_data; +} +int stack_push(stack_t *stack, void *item) +{ + if (stack->top < stack->len) + { + ++(stack->top); + memcpy((uint8_t *)(stack->data) + stack->top * stack->item_size, + item, stack->item_size); + return 0; + } + return -1; +} +int stack_pop(stack_t *stack, void *item) +{ + if (stack->top != -1) + { + memcpy(item, (uint8_t *)(stack->data) + stack->top * stack->item_size, stack->item_size); + stack->top--; + return 0; + } + return -1; +} diff --git a/mkrtos_user/lib/sys/inc/u_task.h b/mkrtos_user/lib/sys/inc/u_task.h index 2b2c2e2ed..38545f15b 100644 --- a/mkrtos_user/lib/sys/inc/u_task.h +++ b/mkrtos_user/lib/sys/inc/u_task.h @@ -16,4 +16,9 @@ msg_tag_t task_unmap(obj_handler_t task_han, vpage_t vpage); msg_tag_t task_alloc_ram_base(obj_handler_t task_han, umword_t size, addr_t *alloc_addr); msg_tag_t task_copy_data(obj_handler_t task_obj, void *st_addr, umword_t size); msg_tag_t task_copy_data_to(obj_handler_t task_obj, obj_handler_t dst_task_obj, void *st_addr, void *dst_addr, umword_t size); -msg_tag_t task_set_com_point(obj_handler_t task_obj, void *com_point_func, addr_t stack); +msg_tag_t task_set_com_point(obj_handler_t task_obj, void *com_point_func, + addr_t stack, umword_t stack_size, + void *bitmap, int bitmap_len, + void *msg_buf); +msg_tag_t task_com_unlock(obj_handler_t task_obj); +msg_tag_t task_com_lock(obj_handler_t task_obj); diff --git a/mkrtos_user/lib/sys/inc/u_thread.h b/mkrtos_user/lib/sys/inc/u_thread.h index 3894ad00b..480c3801d 100644 --- a/mkrtos_user/lib/sys/inc/u_thread.h +++ b/mkrtos_user/lib/sys/inc/u_thread.h @@ -7,9 +7,9 @@ #define MSG_BUF_RECV_R_FLAGS 0x02U //!< 接收上次发送数据的接收者 #define MSG_BUF_REPLY_FLAGS 0x04U //!< -#define IPC_MSG_SIZE (CONFIG_THREAD_IPC_MSG_LEN * sizeof(void*)) -#define MAP_BUF_SIZE (CONFIG_THREAD_MAP_BUF_LEN * sizeof(void*)) -#define IPC_USER_SIZE (CONFIG_THREAD_USER_BUF_LEN * sizeof(void*)) +#define IPC_MSG_SIZE (CONFIG_THREAD_IPC_MSG_LEN * sizeof(void *)) +#define MAP_BUF_SIZE (CONFIG_THREAD_MAP_BUF_LEN * sizeof(void *)) +#define IPC_USER_SIZE (CONFIG_THREAD_USER_BUF_LEN * sizeof(void *)) #if IS_ENABLED(CONFIG_VCPU) #define IPC_VPUC_MSG_OFFSET (3 * 1024) //!< vcpu 传递消息的偏移量 @@ -71,8 +71,8 @@ msg_tag_t thread_ipc_wait(ipc_timeout_t timeout, umword_t *obj, obj_handler_t ip msg_tag_t thread_ipc_reply(msg_tag_t in_tag, ipc_timeout_t timeout); msg_tag_t thread_ipc_send(msg_tag_t in_tag, obj_handler_t target_th_obj, ipc_timeout_t timeout); msg_tag_t thread_ipc_call(msg_tag_t in_tag, obj_handler_t target_th_obj, ipc_timeout_t timeout); -msg_tag_t thread_ipc_fast_call(msg_tag_t in_tag, obj_handler_t target_obj); -msg_tag_t thread_ipc_fast_replay(obj_handler_t target_obj); +msg_tag_t thread_ipc_fast_call(msg_tag_t in_tag, obj_handler_t target_obj, umword_t arg0, umword_t arg1, umword_t arg2); +msg_tag_t thread_ipc_fast_replay(msg_tag_t in_tag, obj_handler_t target_obj, int unlock_bitmap); static inline ipc_msg_t *thread_get_cur_ipc_msg(void) { diff --git a/mkrtos_user/lib/sys/src/u_task.c b/mkrtos_user/lib/sys/src/u_task.c index a4ccf88f0..23dc7ea9c 100644 --- a/mkrtos_user/lib/sys/src/u_task.c +++ b/mkrtos_user/lib/sys/src/u_task.c @@ -14,7 +14,9 @@ enum task_op_code TASK_COPY_DATA, TASK_SET_OBJ_NAME, TASK_COPY_DATA_TO, //!< 从当前task拷贝数据到目的task - TASK_SET_COM_POINT + TASK_SET_COM_POINT, + TASK_COM_UNLOCK, + TASK_COM_LOCK, }; msg_tag_t task_set_obj_name(obj_handler_t dst_task, obj_handler_t obj, const char *name) @@ -196,13 +198,50 @@ msg_tag_t task_copy_data_to(obj_handler_t task_obj, obj_handler_t dst_task_obj, return msg_tag_init(r0); } -msg_tag_t task_set_com_point(obj_handler_t task_obj, void *com_point_func, addr_t stack) +msg_tag_t task_set_com_point(obj_handler_t task_obj, void *com_point_func, addr_t stack, umword_t stack_size, void *bitmap, int bitmap_len, void *msg_buf) { register volatile umword_t r0 asm(ARCH_REG_0); mk_syscall(syscall_prot_create(TASK_SET_COM_POINT, TASK_PROT, task_obj).raw, com_point_func, stack, + stack_size, + bitmap, + bitmap_len, + msg_buf); + asm __volatile__("" + : + : + : ARCH_REG_0, ARCH_REG_1); + + return msg_tag_init(r0); +} +msg_tag_t task_com_unlock(obj_handler_t task_obj) +{ + register volatile umword_t r0 asm(ARCH_REG_0); + + mk_syscall(syscall_prot_create(TASK_COM_UNLOCK, TASK_PROT, task_obj).raw, + 0, + 0, + 0, + 0, + 0, + 0); + asm __volatile__("" + : + : + : ARCH_REG_0, ARCH_REG_1); + + return msg_tag_init(r0); +} + +msg_tag_t task_com_lock(obj_handler_t task_obj) +{ + register volatile umword_t r0 asm(ARCH_REG_0); + + mk_syscall(syscall_prot_create(TASK_COM_LOCK, TASK_PROT, task_obj).raw, + 0, + 0, 0, 0, 0, diff --git a/mkrtos_user/lib/sys/src/u_thread.c b/mkrtos_user/lib/sys/src/u_thread.c index 06f1c4509..2bbac8bf4 100644 --- a/mkrtos_user/lib/sys/src/u_thread.c +++ b/mkrtos_user/lib/sys/src/u_thread.c @@ -92,15 +92,15 @@ msg_tag_t thread_ipc_call(msg_tag_t in_tag, obj_handler_t target_th_obj, ipc_tim : ARCH_REG_0); return msg_tag_init(r0); } -msg_tag_t thread_ipc_fast_call(msg_tag_t in_tag, obj_handler_t target_obj) +msg_tag_t thread_ipc_fast_call(msg_tag_t in_tag, obj_handler_t target_obj, umword_t arg0, umword_t arg1, umword_t arg2) { register volatile umword_t r0 asm(ARCH_REG_0); mk_syscall(syscall_prot_create4(DO_IPC, THREAD_PROT, target_obj, TRUE).raw, in_tag.raw, IPC_FAST_CALL, - 0, - 0, - 0, + arg0, + arg1, + arg2, 0); asm __volatile__("" : @@ -108,13 +108,13 @@ msg_tag_t thread_ipc_fast_call(msg_tag_t in_tag, obj_handler_t target_obj) : ARCH_REG_0); return msg_tag_init(r0); } -msg_tag_t thread_ipc_fast_replay(obj_handler_t target_obj) +msg_tag_t thread_ipc_fast_replay(msg_tag_t in_tag, obj_handler_t target_obj, int unlock_bitmap) { register volatile umword_t r0 asm(ARCH_REG_0); mk_syscall(syscall_prot_create4(DO_IPC, THREAD_PROT, target_obj, TRUE).raw, - 0, + in_tag.raw, IPC_FAST_REPLAY, - 0, + unlock_bitmap, 0, 0, 0); @@ -147,7 +147,7 @@ msg_tag_t thread_msg_buf_set(obj_handler_t obj, void *msg) register volatile umword_t r1 asm(ARCH_REG_1); register volatile umword_t r2 asm(ARCH_REG_2); - mk_syscall(syscall_prot_create(MSG_BUG_SET, THREAD_PROT, obj).raw, + mk_syscall(syscall_prot_create4(MSG_BUG_SET, THREAD_PROT, obj, TRUE).raw, 0, msg, 0, diff --git a/mkrtos_user/server/init/src/init.c b/mkrtos_user/server/init/src/init.c index 26c8e3edb..789636566 100644 --- a/mkrtos_user/server/init/src/init.c +++ b/mkrtos_user/server/init/src/init.c @@ -29,26 +29,81 @@ #include "parse_cfg.h" #include #include -static ATTR_ALIGN(8) uint8_t cons_stack[2048]; +#include #define DEFAULT_INIT_CFG "init.cfg" -static void init_com_point_test_func(int r0,int r1,int r2,int r3) + +#define STACK_SIZE 2048 +#define STASCK_NUM 4 +static ATTR_ALIGN(8) uint8_t com_stack[512]; +static ATTR_ALIGN(8) uint8_t cons_stack[STASCK_NUM][STACK_SIZE]; +static uint8_t cons_msg_buf[STASCK_NUM][MSG_BUG_LEN]; +static umword_t cons_stack_bitmap; +static uint8_t cons_msg_buf_main[MSG_BUG_LEN]; +static inline umword_t arch_get_sp(void) { - printf("comm r0:%d r1:%d r2:%d r3:%d\n", r0, r1, r2, r3); - printf("comm\n"); - printf("comm\n"); - printf("comm\n"); - printf("comm\n"); - thread_ipc_fast_replay(-1); + umword_t ret; + __asm__ __volatile__( + "mov %0, sp\n" + : "=r"(ret) + : + :); + return ret; } +#define SET_SP(sp) \ + do \ + { \ + __asm__ __volatile__("mov sp, %0" ::"r"(sp)); \ + __asm__ __volatile__("" \ + : \ + : \ + : "sp"); \ + } while (0) + +int setsp(int i, void *stack, msg_tag_t tag, int arg0, int arg1); + +void last_process(int j, msg_tag_t tag, int arg0, int arg1) +{ + thread_msg_buf_set(-1, (void *)(cons_msg_buf[j])); + task_com_unlock(TASK_THIS); + + // printf("j:%d sp:0x%x\n", j, arch_get_sp()); + // printf("j:%d comm tag:%x r0:%d r1:%d\n", j, tag.raw, arg0, arg1); + // printf("%s\n", cons_msg_buf[j]); + // strcpy((void *)cons_msg_buf[j], "okay"); + + // u_sleep_ms(100); + + // *((uint8_t *)0) = 0; + task_com_lock(TASK_THIS); + memcpy(cons_msg_buf_main, cons_msg_buf[j], MSG_BUG_LEN); + tag = msg_tag_init4(0, 2, 0, 0); + thread_ipc_fast_replay(tag, -1, j); +} +static void init_com_point_test_func(msg_tag_t tag, int arg0, int arg1, int arg2) +{ + int i; + for (i = 0; i < STASCK_NUM; i++) + { + if ((cons_stack_bitmap & (1 << i)) == 0) + { + cons_stack_bitmap |= (1 << i); + break; + } + } + memcpy(cons_msg_buf[i], cons_msg_buf_main, MSG_BUG_LEN); + setsp(i, &cons_stack[i][STACK_SIZE - 8], tag, arg0, arg1); +} + int main(int argc, char *args[]) { int ret; uenv_t *env; -#if 1 +#if 0 thread_run(-1, 4); #endif - task_set_com_point(TASK_THIS,&init_com_point_test_func, (addr_t)(cons_stack + sizeof(cons_stack) - 8)); + task_set_com_point(TASK_THIS, &init_com_point_test_func, (addr_t)com_stack, + sizeof(com_stack), &cons_stack_bitmap, STASCK_NUM, cons_msg_buf_main); task_set_obj_name(TASK_THIS, TASK_THIS, "tk_init"); task_set_obj_name(TASK_THIS, THREAD_MAIN, "th_init"); diff --git a/mkrtos_user/server/init/src/setsp.S b/mkrtos_user/server/init/src/setsp.S new file mode 100644 index 000000000..565c6fc75 --- /dev/null +++ b/mkrtos_user/server/init/src/setsp.S @@ -0,0 +1,12 @@ +.syntax unified +@ .cpu cortex-m3 +.thumb +.global setsp +.global last_process +/** +* @brief syscall结束时到这儿 +*/ +.type setsp, %function +setsp: + mov sp, r1 + bl last_process \ No newline at end of file diff --git a/mkrtos_user/server/shell/src/main.c b/mkrtos_user/server/shell/src/main.c index fa07a11a8..c4fd0eb4b 100644 --- a/mkrtos_user/server/shell/src/main.c +++ b/mkrtos_user/server/shell/src/main.c @@ -9,14 +9,47 @@ #include #include #include +#include +void *test_func(void *arg) +{ + msg_tag_t tag; + ipc_msg_t *msg; + + tag = thread_msg_buf_get(-1, (void *)(&msg), NULL); + strcpy((void *)msg->msg_buf, "hello"); + + for (int i = 0; i < 10000; i++) + { + + thread_ipc_fast_call(msg_tag_init4(0, 2, 0, 0), u_get_global_env()->ns_hd, 1111, 2222, 3333); + // printf("%s\n", (void *)msg->msg_buf); + } + // while (1) + // { + // u_sleep_ms(100000); + // } + return NULL; +} +pthread_t pth1; +pthread_t pth2; +pthread_t pth3; +pthread_t pth4; +void fast_ipc_test(void) +{ + pthread_create(&pth1, NULL, test_func, NULL); + pthread_create(&pth2, NULL, test_func, NULL); + pthread_create(&pth3, NULL, test_func, NULL); + pthread_create(&pth4, NULL, test_func, NULL); +} + int main(int argc, char *args[]) { task_set_obj_name(TASK_THIS, TASK_THIS, "tk_sh"); task_set_obj_name(TASK_THIS, THREAD_MAIN, "th_sh"); -#if 1 +#if 0 thread_run(-1, 3); #endif - // thread_ipc_fast_call(msg_tag_init(0), u_get_global_env()->ns_hd); + fast_ipc_test(); for (int i = 0; i < argc; i++) { printf("args[%d]:%s\n", i, args[i]);