X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/d1b1c8d9119229dbeed06cd252917e54a1cb77f6..34f6af4f61e0eec9c96113e07f140b609b4113c8:/lunaix-os/kernel/process/thread.c diff --git a/lunaix-os/kernel/process/thread.c b/lunaix-os/kernel/process/thread.c index 9d93566..78cce8b 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") @@ -17,14 +18,14 @@ static ptr_t __alloc_user_thread_stack(struct proc_info* proc, struct mm_region** stack_region, ptr_t vm_mnt) { - ptr_t th_stack_top = (proc->thread_count + 1) * USR_STACK_SIZE; - th_stack_top = ROUNDUP(USR_STACK_END - th_stack_top, MEM_PAGE); + ptr_t th_stack_top = (proc->thread_count + 1) * USR_STACK_SIZE_THREAD; + th_stack_top = ROUNDUP(USR_STACK_END - th_stack_top, PAGE_SIZE); struct mm_region* vmr; struct proc_mm* mm = vmspace(proc); struct mmap_param param = { .vms_mnt = vm_mnt, .pvms = mm, - .mlen = USR_STACK_SIZE, + .mlen = USR_STACK_SIZE_THREAD, .proct = PROT_READ | PROT_WRITE, .flags = MAP_ANON | MAP_PRIVATE, .type = REGION_TYPE_STACK }; @@ -37,44 +38,46 @@ __alloc_user_thread_stack(struct proc_info* proc, return 0; } - set_pte(mkptep_va(vm_mnt, vmr->start), guard_pte); + pte_t* guardp = mkptep_va(vm_mnt, vmr->start); + set_pte(guardp, guard_pte); *stack_region = vmr; - ptr_t stack_top = align_stack(th_stack_top + USR_STACK_SIZE - 1); + ptr_t stack_top = align_stack(th_stack_top + USR_STACK_SIZE_THREAD - 1); return stack_top; } 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; - // first page in the kernel stack is guardian page - pte_t pte = *(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"); return 0; found:; - // KSTACK_PAGES = 3, removal one guardian pte, give order 1 page - struct leaflet* leaflet = alloc_leaflet(1); + unsigned int po = count_order(KSTACK_PAGES); + struct leaflet* leaflet = alloc_leaflet(po); if (!leaflet) { WARN("failed to create kernel stack: nomem\n"); 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); @@ -93,7 +96,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); @@ -134,6 +137,10 @@ create_thread(struct proc_info* proc, bool with_ustack) th->kstack = kstack; th->ustack = ustack_region; + + if (ustack_region) { + th->ustack_top = align_stack(ustack_region->end - 1); + } return th; } @@ -150,11 +157,7 @@ start_thread(struct thread* th, ptr_t entry) if (!kernel_addr(entry)) { assert(th->ustack); - ptr_t ustack_top = align_stack(th->ustack->end - 1); - ustack_top -= 16; // pre_allocate a 16 byte for inject parameter - hart_user_transfer(&transition, th->kstack, ustack_top, entry); - - th->ustack_top = ustack_top; + hart_user_transfer(&transition, th->kstack, th->ustack_top, entry); } else { hart_kernel_transfer(&transition, th->kstack, entry); @@ -185,21 +188,74 @@ thread_find(struct proc_info* proc, tid_t tid) return NULL; } -__DEFINE_LXSYSCALL4(int, th_create, tid_t*, tid, struct uthread_info*, thinfo, - void*, entry, void*, param) +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; +} + +__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; } - start_thread(th, (ptr_t)entry); + ptr_t ustack_top; + + ustack_top = th->ustack_top; + ustack_top = align_stack(ustack_top - sizeof(*thparam)); - ptr_t ustack_top = th->ustack_top; - *((void**)ustack_top) = param; + memcpy((void*)ustack_top, thparam, sizeof(*thparam)); - thinfo->th_stack_sz = region_size(th->ustack); - thinfo->th_stack_top = (void*)ustack_top; + th->ustack_top = ustack_top; + start_thread(th, (ptr_t)entry); if (tid) { *tid = th->tid; @@ -230,13 +286,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;