diff options
Diffstat (limited to 'components/lwp/lwp_syscall.c')
| -rw-r--r-- | components/lwp/lwp_syscall.c | 220 |
1 files changed, 136 insertions, 84 deletions
diff --git a/components/lwp/lwp_syscall.c b/components/lwp/lwp_syscall.c index daa4e00480..775781afda 100644 --- a/components/lwp/lwp_syscall.c +++ b/components/lwp/lwp_syscall.c @@ -12,6 +12,7 @@ * 2021-02-20 lizhirui fix some warnings * 2023-03-13 WangXiaoyao Format & fix syscall return value * 2023-07-06 Shell adapt the signal API, and clone, fork to new implementation of lwp signal + * 2023-07-27 Shell Move tid_put() from lwp_free() to sys_exit() */ #define _GNU_SOURCE @@ -20,11 +21,12 @@ #include <rtthread.h> #include <rthw.h> #include <board.h> -#include <mm_aspace.h> + +#include <console.h> #include <string.h> #include <stdint.h> -#define DBG_TAG "SYSCALL" +#define DBG_TAG "lwp.syscall" #define DBG_LVL DBG_INFO #include <rtdbg.h> @@ -33,6 +35,7 @@ #include "libc_musl.h" #include "lwp_internal.h" #ifdef ARCH_MM_MMU +#include <mm_aspace.h> #include <lwp_user_mm.h> #include <lwp_arch.h> #endif @@ -325,16 +328,13 @@ static void _crt_thread_entry(void *parameter) /* exit group */ sysret_t sys_exit_group(int value) { - rt_base_t level; rt_thread_t tid, main_thread; struct rt_lwp *lwp; - LOG_D("process exit"); - tid = rt_thread_self(); lwp = (struct rt_lwp *)tid->lwp; + LOG_D("process(%p) exit.", lwp); - level = rt_hw_interrupt_disable(); #ifdef ARCH_MM_MMU if (tid->clear_child_tid) { @@ -351,7 +351,7 @@ sysret_t sys_exit_group(int value) if (main_thread == tid) { lwp_wait_subthread_exit(); - lwp->lwp_ret = value; + lwp->lwp_ret = LWP_CREATE_STAT(value); } #else main_thread = rt_list_entry(lwp->t_grp.prev, struct rt_thread, sibling); @@ -373,18 +373,24 @@ sysret_t sys_exit_group(int value) } #endif /* ARCH_MM_MMU */ + /** + * Note: the tid tree always hold a reference to thread, hence the tid must + * be release before cleanup of thread + */ + lwp_tid_put(tid->tid); + tid->tid = 0; + rt_list_remove(&tid->sibling); rt_thread_delete(tid); - rt_hw_interrupt_enable(level); rt_schedule(); /* never reach here */ + RT_ASSERT(0); return 0; } /* thread exit */ void sys_exit(int status) { - rt_base_t level; rt_thread_t tid, main_thread; struct rt_lwp *lwp; @@ -393,8 +399,6 @@ void sys_exit(int status) tid = rt_thread_self(); lwp = (struct rt_lwp *)tid->lwp; - level = rt_hw_interrupt_disable(); - #ifdef ARCH_MM_MMU if (tid->clear_child_tid) { @@ -411,12 +415,14 @@ void sys_exit(int status) { lwp_terminate(lwp); lwp_wait_subthread_exit(); - lwp->lwp_ret = status; + lwp->lwp_ret = LWP_CREATE_STAT(status); } #endif /* ARCH_MM_MMU */ + lwp_tid_put(tid->tid); + tid->tid = 0; + rt_list_remove(&tid->sibling); rt_thread_delete(tid); - rt_hw_interrupt_enable(level); rt_schedule(); return; @@ -1079,23 +1085,32 @@ sysret_t sys_kill(int pid, int signo) { rt_err_t kret; sysret_t sysret; - rt_base_t level; struct rt_lwp *lwp; /* handling the semantics of sys_kill */ if (pid > 0) { - /* TODO: lock the lwp strcut */ - level = rt_hw_interrupt_disable(); - lwp = lwp_from_pid(pid); - - /* lwp_signal_kill() can handle NULL lwp */ + /** + * Brief: Match the pid and send signal to the lwp if found + * Note: Critical Section + * - pid tree (READ. since the lwp is fetch from the pid tree, it must stay there) + */ + lwp_pid_lock_take(); + lwp = lwp_from_pid_locked(pid); if (lwp) + { + lwp_ref_inc(lwp); + lwp_pid_lock_release(); + kret = lwp_signal_kill(lwp, signo, SI_USER, 0); + lwp_ref_dec(lwp); + kret = 0; + } else + { + lwp_pid_lock_release(); kret = -RT_ENOENT; - - rt_hw_interrupt_enable(level); + } } else if (pid == 0) { @@ -1807,7 +1822,6 @@ sysret_t sys_timer_getoverrun(timer_t timerid) rt_thread_t sys_thread_create(void *arg[]) { - rt_base_t level = 0; void *user_stack = 0; struct rt_lwp *lwp = 0; rt_thread_t thread = RT_NULL; @@ -1887,9 +1901,9 @@ rt_thread_t sys_thread_create(void *arg[]) rt_thread_control(thread, RT_THREAD_CTRL_BIND_CPU, (void*)0); } - level = rt_hw_interrupt_disable(); + LWP_LOCK(lwp); rt_list_insert_after(&lwp->t_grp, &thread->sibling); - rt_hw_interrupt_enable(level); + LWP_UNLOCK(lwp); return thread; @@ -1903,11 +1917,9 @@ fail: } #ifdef ARCH_MM_MMU -#include "lwp_clone.h" long _sys_clone(void *arg[]) { - rt_base_t level = 0; struct rt_lwp *lwp = 0; rt_thread_t thread = RT_NULL; rt_thread_t self = RT_NULL; @@ -2001,9 +2013,9 @@ long _sys_clone(void *arg[]) rt_thread_control(thread, RT_THREAD_CTRL_BIND_CPU, (void*)0); } - level = rt_hw_interrupt_disable(); + LWP_LOCK(lwp); rt_list_insert_after(&lwp->t_grp, &thread->sibling); - rt_hw_interrupt_enable(level); + LWP_UNLOCK(lwp); /* copy origin stack */ lwp_memcpy(thread->stack_addr, self->stack_addr, thread->stack_size); @@ -2016,6 +2028,10 @@ long _sys_clone(void *arg[]) return (long)tid; fail: lwp_tid_put(tid); + if (thread) + { + rt_thread_delete(thread); + } if (lwp) { lwp_ref_dec(lwp); @@ -2091,7 +2107,6 @@ static int lwp_copy_files(struct rt_lwp *dst, struct rt_lwp *src) sysret_t _sys_fork(void) { - rt_base_t level; int tid = 0; sysret_t falival = 0; struct rt_lwp *lwp = RT_NULL; @@ -2166,34 +2181,27 @@ sysret_t _sys_fork(void) thread->lwp = (void *)lwp; thread->tid = tid; - level = rt_hw_interrupt_disable(); - + LWP_LOCK(self_lwp); /* add thread to lwp process */ rt_list_insert_after(&lwp->t_grp, &thread->sibling); + LWP_UNLOCK(self_lwp); - /* lwp add to children link */ - lwp->sibling = self_lwp->first_child; - self_lwp->first_child = lwp; - lwp->parent = self_lwp; - - rt_hw_interrupt_enable(level); + lwp_children_register(self_lwp, lwp); - /* copy origin stack */ + /* copy kernel stack context from self thread */ lwp_memcpy(thread->stack_addr, self_thread->stack_addr, self_thread->stack_size); lwp_tid_set_thread(tid, thread); /* duplicate user objects */ lwp_user_object_dup(lwp, self_lwp); - level = rt_hw_interrupt_disable(); user_stack = arch_get_user_sp(); - rt_hw_interrupt_enable(level); - arch_set_thread_context(arch_fork_exit, (void *)((char *)thread->stack_addr + thread->stack_size), user_stack, &thread->sp); + /* new thread never reach there */ - level = rt_hw_interrupt_disable(); + LWP_LOCK(lwp); if (lwp->tty != RT_NULL) { int ret; @@ -2212,7 +2220,8 @@ sysret_t _sys_fork(void) lwp->tty->foreground = lwp; } - rt_hw_interrupt_enable(level); + LWP_UNLOCK(lwp); + rt_thread_startup(thread); return lwp_to_pid(lwp); fail: @@ -2222,6 +2231,10 @@ fail: { lwp_tid_put(tid); } + if (thread) + { + rt_thread_delete(thread); + } if (lwp) { lwp_ref_dec(lwp); @@ -2576,7 +2589,6 @@ sysret_t sys_execve(const char *path, char *const argv[], char *const envp[]) char *p; struct rt_lwp *new_lwp = NULL; struct rt_lwp *lwp; - rt_base_t level; int uni_thread; rt_thread_t thread; struct process_aux *aux; @@ -2591,7 +2603,8 @@ sysret_t sys_execve(const char *path, char *const argv[], char *const envp[]) lwp = lwp_self(); thread = rt_thread_self(); uni_thread = 1; - level = rt_hw_interrupt_disable(); + + LWP_LOCK(lwp); if (lwp->t_grp.prev != &thread->sibling) { uni_thread = 0; @@ -2600,7 +2613,8 @@ sysret_t sys_execve(const char *path, char *const argv[], char *const envp[]) { uni_thread = 0; } - rt_hw_interrupt_enable(level); + LWP_UNLOCK(lwp); + if (!uni_thread) { SET_ERRNO(EINVAL); @@ -2771,10 +2785,14 @@ sysret_t sys_execve(const char *path, char *const argv[], char *const envp[]) } } - /* load ok, now set thread name and swap the data of lwp and new_lwp */ - level = rt_hw_interrupt_disable(); + /** + * Set thread name and swap the data of lwp and new_lwp. + * Since no other threads can access the lwp field, it't uneccessary to + * take a lock here + */ - rt_strncpy(thread->parent.name, run_name + last_backslash, RT_NAME_MAX); + strncpy(thread->parent.name, run_name + last_backslash, RT_NAME_MAX); + strncpy(lwp->cmd, new_lwp->cmd, RT_NAME_MAX); rt_pages_free(page, 0); @@ -2797,12 +2815,10 @@ sysret_t sys_execve(const char *path, char *const argv[], char *const envp[]) lwp_signal_detach(&lwp->signal); lwp_signal_init(&lwp->signal); - /* to do: clsoe files with flag CLOEXEC */ + /* to do: clsoe files with flag CLOEXEC, recy sub-thread */ lwp_aspace_switch(thread); - rt_hw_interrupt_enable(level); - lwp_ref_dec(new_lwp); arch_start_umode(lwp->args, lwp->text_entry, @@ -4067,14 +4083,19 @@ sysret_t sys_sigtimedwait(const sigset_t *sigset, siginfo_t *info, const struct sysret_t sys_tkill(int tid, int sig) { #ifdef ARCH_MM_MMU - rt_base_t level; rt_thread_t thread; - int ret; + sysret_t ret; - level = rt_hw_interrupt_disable(); - thread = lwp_tid_get_thread(tid); + /** + * Brief: Match a tid and do the kill + * + * Note: Critical Section + * - the thread (READ. may be released at the meantime; protected by locked) + */ + thread = lwp_tid_get_thread_and_inc_ref(tid); ret = lwp_thread_signal_kill(thread, sig, SI_USER, 0); - rt_hw_interrupt_enable(level); + lwp_tid_dec_ref(thread); + return ret; #else return lwp_thread_kill((rt_thread_t)tid, sig); @@ -4182,7 +4203,7 @@ sysret_t sys_waitpid(int32_t pid, int *status, int options) } else { - ret = waitpid(pid, status, options); + ret = lwp_waitpid(pid, status, options); } #else if (!lwp_user_accessable((void *)status, sizeof(int))) @@ -5271,11 +5292,13 @@ sysret_t sys_setaffinity(pid_t pid, size_t size, void *set) return -1; } -sysret_t sys_getaffinity(pid_t pid, size_t size, void *set) +sysret_t sys_getaffinity(const pid_t pid, size_t size, void *set) { #ifdef ARCH_MM_MMU + DEF_RETURN_CODE(rc); cpu_set_t mask; struct rt_lwp *lwp; + rt_bool_t need_release = RT_FALSE; if (size <= 0 || size > sizeof(cpu_set_t)) { @@ -5286,33 +5309,47 @@ sysret_t sys_getaffinity(pid_t pid, size_t size, void *set) return -EFAULT; } - if (pid == 0) lwp = lwp_self(); - else lwp = lwp_from_pid(pid); - if (!lwp) + if (pid == 0) { - return -ESRCH; + lwp = lwp_self(); } - -#ifdef RT_USING_SMP - if (lwp->bind_cpu == RT_CPUS_NR) /* not bind */ + else { - CPU_ZERO_S(size, &mask); + need_release = RT_TRUE; + lwp_pid_lock_take(); + lwp = lwp_from_pid_locked(pid); } - else /* set bind cpu */ + + if (!lwp) { - /* TODO: only single-core bindings are now supported of rt-smart */ - CPU_SET_S(lwp->bind_cpu, size, &mask); + rc = -ESRCH; } -#else - CPU_SET_S(0, size, &mask); -#endif - - if (lwp_put_to_user(set, &mask, size) != size) + else { - return -1; + #ifdef RT_USING_SMP + if (lwp->bind_cpu == RT_CPUS_NR) /* not bind */ + { + CPU_ZERO_S(size, &mask); + } + else /* set bind cpu */ + { + /* TODO: only single-core bindings are now supported of rt-smart */ + CPU_SET_S(lwp->bind_cpu, size, &mask); + } + #else + CPU_SET_S(0, size, &mask); + #endif + + if (lwp_put_to_user(set, &mask, size) != size) + rc = -EFAULT; + else + rc = 0; } - return 0; + if (need_release) + lwp_pid_lock_release(); + + RETURN(rc); #else return -1; #endif @@ -5369,6 +5406,7 @@ sysret_t sys_sched_setparam(pid_t pid, void *param) struct sched_param *sched_param = RT_NULL; struct rt_lwp *lwp = NULL; rt_thread_t main_thread; + rt_bool_t need_release = RT_FALSE; int ret = -1; if (!lwp_user_accessable(param, sizeof(struct sched_param))) @@ -5390,15 +5428,21 @@ sysret_t sys_sched_setparam(pid_t pid, void *param) if (pid > 0) { - lwp = lwp_from_pid(pid); + need_release = RT_TRUE; + lwp_pid_lock_take(); + lwp = lwp_from_pid_locked(pid); } else if (pid == 0) { lwp = lwp_self(); } + if (lwp) { main_thread = rt_list_entry(lwp->t_grp.prev, struct rt_thread, sibling); + if (need_release) + lwp_pid_lock_release(); + ret = rt_thread_control(main_thread, RT_THREAD_CTRL_CHANGE_PRIORITY, (void *)&sched_param->sched_priority); } @@ -5413,12 +5457,13 @@ sysret_t sys_sched_yield(void) return 0; } -sysret_t sys_sched_getparam(pid_t pid, void *param) +sysret_t sys_sched_getparam(const pid_t pid, void *param) { struct sched_param *sched_param = RT_NULL; struct rt_lwp *lwp = NULL; rt_thread_t main_thread; int ret = -1; + rt_bool_t need_release = RT_FALSE; if (!lwp_user_accessable(param, sizeof(struct sched_param))) { @@ -5433,15 +5478,21 @@ sysret_t sys_sched_getparam(pid_t pid, void *param) if (pid > 0) { - lwp = lwp_from_pid(pid); + need_release = RT_TRUE; + lwp_pid_lock_take(); + lwp = lwp_from_pid_locked(pid); } else if (pid == 0) { lwp = lwp_self(); } + if (lwp) { main_thread = rt_list_entry(lwp->t_grp.prev, struct rt_thread, sibling); + if (need_release) + lwp_pid_lock_release(); + sched_param->sched_priority = main_thread->current_priority; ret = 0; } @@ -5474,12 +5525,10 @@ sysret_t sys_sched_get_priority_min(int policy) sysret_t sys_sched_setscheduler(int tid, int policy, void *param) { - int ret = 0; + sysret_t ret; struct sched_param *sched_param = RT_NULL; rt_thread_t thread = RT_NULL; - thread = lwp_tid_get_thread(tid); - if (!lwp_user_accessable(param, sizeof(struct sched_param))) { return -EFAULT; @@ -5497,7 +5546,9 @@ sysret_t sys_sched_setscheduler(int tid, int policy, void *param) return -EINVAL; } + thread = lwp_tid_get_thread_and_inc_ref(tid); ret = rt_thread_control(thread, RT_THREAD_CTRL_CHANGE_PRIORITY, (void *)&sched_param->sched_priority); + lwp_tid_dec_ref(thread); kmem_put(sched_param); @@ -5509,7 +5560,6 @@ sysret_t sys_sched_getscheduler(int tid, int *policy, void *param) struct sched_param *sched_param = RT_NULL; rt_thread_t thread = RT_NULL; - thread = lwp_tid_get_thread(tid); if (!lwp_user_accessable(param, sizeof(struct sched_param))) { @@ -5528,7 +5578,9 @@ sysret_t sys_sched_getscheduler(int tid, int *policy, void *param) return -EINVAL; } + thread = lwp_tid_get_thread_and_inc_ref(tid); sched_param->sched_priority = thread->current_priority; + lwp_tid_dec_ref(thread); lwp_put_to_user((void *)param, sched_param, sizeof(struct sched_param)); kmem_put(sched_param); |
