X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/28c176b668c841a3b7fb093faccf0efa39257603..refs/heads/cor/lrud:/lunaix-os/kernel/process/thread.c diff --git a/lunaix-os/kernel/process/thread.c b/lunaix-os/kernel/process/thread.c index ef207aa..f4bbac0 100644 --- a/lunaix-os/kernel/process/thread.c +++ b/lunaix-os/kernel/process/thread.c @@ -5,11 +5,12 @@ #include #include #include +#include #include -#include -#include +#include +#include LOG_MODULE("THREAD") @@ -49,16 +50,18 @@ __alloc_user_thread_stack(struct proc_info* proc, static ptr_t __alloc_kernel_thread_stack(struct proc_info* proc, ptr_t vm_mnt) { - pfn_t kstack_top = leaf_count(KSTACK_AREA_END); + pfn_t kstack_top = pfn(KSTACK_AREA_END); pfn_t kstack_end = pfn(KSTACK_AREA); pte_t* ptep = mkptep_pn(vm_mnt, kstack_top); while (ptep_pfn(ptep) > kstack_end) { - ptep -= KSTACK_PAGES + 1; + ptep -= KSTACK_PAGES; - pte_t pte = pte_at(ptep + 1); + pte_t pte = pte_at(ptep); if (pte_isnull(pte)) { goto found; } + + ptep--; } WARN("failed to create kernel stack: max stack num reach\n"); @@ -73,13 +76,42 @@ found:; return 0; } - set_pte(ptep, guard_pte); - ptep_map_leaflet(ptep + 1, mkpte_prot(KERNEL_DATA), leaflet); + set_pte(ptep++, guard_pte); + ptep_map_leaflet(ptep, mkpte_prot(KERNEL_DATA), leaflet); ptep += KSTACK_PAGES; return align_stack(ptep_va(ptep, LFT_SIZE) - 1); } +static int +__thread_putsleep(int seconds) +{ + if (!seconds) { + return 0; + } + + struct scheduler* sched; + time_t systime; + struct haybed* bed; + + sched = scheduler(); + systime = clock_systime() / 1000; + bed = ¤t_thread->sleep; + + if (bed->wakeup_time) { + return (bed->wakeup_time - systime); + } + + bed->wakeup_time = systime + seconds; + + if (llist_empty(&bed->sleepers)) { + llist_append(&sched->sleepers, &bed->sleepers); + } + + block_current_thread(); + return seconds; +} + void thread_release_mem(struct thread* thread) { @@ -93,7 +125,7 @@ thread_release_mem(struct thread* thread) pte_t* ptep = mkptep_va(vm_mnt, thread->kstack); leaflet = pte_leaflet(*ptep); - ptep -= KSTACK_PAGES - 1; + ptep -= KSTACK_PAGES; set_pte(ptep, null_pte); ptep_unmap_leaflet(ptep + 1, leaflet); @@ -185,9 +217,79 @@ thread_find(struct proc_info* proc, tid_t tid) return NULL; } +void +thread_stats_update(bool inbound, bool voluntary) +{ + struct thread_stats* stats; + time_t now; + + now = clock_systime(); + stats = ¤t_thread->stats; + + stats->at_user = !kernel_context(current_thread->hstate); + + if (!inbound) { + if (kernel_process(current_thread->process) || + stats->at_user) + { + // exiting to user or kernel (kernel thread only), how graceful + stats->last_leave = now; + } + else { + // exiting to kernel, effectively reentry + stats->last_reentry = now; + } + + stats->last_resume = now; + return; + } + + stats->last_reentry = now; + + if (!stats->at_user) + { + // entering from kernel, it is a kernel preempt + thread_stats_update_kpreempt(); + return; + } + + // entering from user space, a clean entrance. + + if (!voluntary) { + stats->entry_count_invol++; + } + else { + stats->entry_count_vol++; + } + + thread_stats_reset_kpreempt(); + stats->last_entry = now; +} + +void +kthread_spawn(ptr_t entry) +{ + assert(kernel_process(__current)); + + struct thread* th = create_thread(__current, false); + + assert(th); + start_thread(th, entry); + detach_thread(th); +} + +void +kthread_sleep(int seconds) +{ + if (__thread_putsleep(seconds)) + yield_current(); +} + __DEFINE_LXSYSCALL3(int, th_create, tid_t*, tid, struct uthread_param*, thparam, void*, entry) { + no_preemption(); + struct thread* th = create_thread(__current, true); if (!th) { return EAGAIN; @@ -232,13 +334,14 @@ __DEFINE_LXSYSCALL2(int, th_join, tid_t, tid, void**, val_ptr) } while (!proc_terminated(th)) { - sched_pass(); + yield_current(); } if (val_ptr) { *val_ptr = (void*)th->exit_val; } + no_preemption(); destory_thread(th); return 0; @@ -277,3 +380,16 @@ __DEFINE_LXSYSCALL2(int, th_kill, tid_t, tid, int, signum) return 0; } + +__DEFINE_LXSYSCALL1(unsigned int, sleep, unsigned int, seconds) +{ + int sec; + + sec = __thread_putsleep(seconds); + store_retval(seconds); + + if (sec) + schedule(); + + return 0; +} \ No newline at end of file