userspace fun: maze game and a new device to support it
[lunaix-os.git] / lunaix-os / kernel / process / thread.c
index 4ad4653f9dde7b89763d72de126a53ef8988c973..ef207aa0be82ccc9404f60210ebb58675d6aa768 100644 (file)
 LOG_MODULE("THREAD")
 
 static ptr_t
 LOG_MODULE("THREAD")
 
 static ptr_t
-__alloc_user_thread_stack(struct proc_info* proc, struct mm_region** stack_region, ptr_t vm_mnt)
+__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,
 
     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 };
 
                                 .proct = PROT_READ | PROT_WRITE,
                                 .flags = MAP_ANON | MAP_PRIVATE,
                                 .type = REGION_TYPE_STACK };
 
-    int errno = mmap_user((void**)&th_stack_top, &vmr, th_stack_top, NULL, &param);
-
+    int errno;
+    
+    errno = mmap_user((void**)&th_stack_top, &vmr, th_stack_top, NULL, &param);
     if (errno) {
         WARN("failed to create user thread stack: %d", errno);
         return 0;
     }
 
     if (errno) {
         WARN("failed to create user thread stack: %d", errno);
         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;
 
 
     *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;
 }
 
     return stack_top;
 }
 
@@ -50,10 +53,9 @@ __alloc_kernel_thread_stack(struct proc_info* proc, ptr_t vm_mnt)
     pfn_t kstack_end = pfn(KSTACK_AREA);
     pte_t* ptep      = mkptep_pn(vm_mnt, kstack_top);
     while (ptep_pfn(ptep) > kstack_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;
+        ptep -= KSTACK_PAGES + 1;
 
 
-        // first page in the kernel stack is guardian page
-        pte_t pte = *(ptep + 1);
+        pte_t pte = pte_at(ptep + 1);
         if (pte_isnull(pte)) {
             goto found;
         }
         if (pte_isnull(pte)) {
             goto found;
         }
@@ -63,8 +65,8 @@ __alloc_kernel_thread_stack(struct proc_info* proc, ptr_t vm_mnt)
     return 0;
 
 found:;
     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");
 
     if (!leaflet) {
         WARN("failed to create kernel stack: nomem\n");
@@ -132,6 +134,10 @@ create_thread(struct proc_info* proc, bool with_ustack)
     
     th->kstack = kstack;
     th->ustack = ustack_region;
     
     th->kstack = kstack;
     th->ustack = ustack_region;
+    
+    if (ustack_region) {
+        th->ustack_top = align_stack(ustack_region->end - 1);
+    }
 
     return th;
 }
 
     return th;
 }
@@ -144,22 +150,18 @@ start_thread(struct thread* th, ptr_t entry)
 
     assert(mm->vm_mnt);
     
 
     assert(mm->vm_mnt);
     
-    struct transfer_context transfer;
+    struct hart_transition transition;
     if (!kernel_addr(entry)) {
         assert(th->ustack);
 
     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
-        thread_create_user_transfer(&transfer, th->kstack, ustack_top, entry);
-
-        th->ustack_top = ustack_top;
+        hart_user_transfer(&transition, th->kstack, th->ustack_top, entry);
     } 
     else {
     } 
     else {
-        thread_create_kernel_transfer(&transfer, th->kstack, entry);
+        hart_kernel_transfer(&transition, th->kstack, entry);
     }
 
     }
 
-    inject_transfer_context(mm->vm_mnt, &transfer);
-    th->intr_ctx = (isr_param*)transfer.inject;
+    install_hart_transition(mm->vm_mnt, &transition);
+    th->hstate = (struct hart_state*)transition.inject;
 
     commit_thread(th);
 }
 
     commit_thread(th);
 }
@@ -183,21 +185,23 @@ thread_find(struct proc_info* proc, tid_t tid)
     return NULL;
 }
 
     return NULL;
 }
 
-__DEFINE_LXSYSCALL4(int, th_create, tid_t*, tid, struct uthread_info*, thinfo
-                                    void*, entry, void*, param)
+__DEFINE_LXSYSCALL3(int, th_create, tid_t*, tid
+                        struct uthread_param*, thparam, void*, entry)
 {
     struct thread* th = create_thread(__current, true);
     if (!th) {
         return EAGAIN;
     }
 
 {
     struct thread* th = create_thread(__current, true);
     if (!th) {
         return EAGAIN;
     }
 
-    start_thread(th, (ptr_t)entry);
+    ptr_t ustack_top;
 
 
-    ptr_t ustack_top = th->ustack_top;
-    *((void**)ustack_top) = param;
+    ustack_top = th->ustack_top;
+    ustack_top = align_stack(ustack_top - sizeof(*thparam));
 
 
-    thinfo->th_stack_sz = region_size(th->ustack);
-    thinfo->th_stack_top = (void*)ustack_top;
+    memcpy((void*)ustack_top, thparam, sizeof(*thparam));
+
+    th->ustack_top = ustack_top;
+    start_thread(th, (ptr_t)entry);
     
     if (tid) {
         *tid = th->tid;
     
     if (tid) {
         *tid = th->tid;