Multiuser, Capabilities and Access Controls (#54)
[lunaix-os.git] / lunaix-os / kernel / process / sched.c
index c92cde9efdb3a397042d8ed177ba09ad8f3a63b2..112741c553de299db541357d39baca3487d9f373 100644 (file)
@@ -1,8 +1,7 @@
-#include <sys/abi.h>
-#include <sys/mm/mempart.h>
+#include <asm/abi.h>
+#include <asm/mempart.h>
 
 
-#include <hal/intc.h>
-#include <sys/cpu.h>
+#include <asm/cpu.h>
 
 #include <lunaix/fs/taskfs.h>
 #include <lunaix/mm/cake.h>
 
 #include <lunaix/fs/taskfs.h>
 #include <lunaix/mm/cake.h>
 #include <lunaix/status.h>
 #include <lunaix/syscall.h>
 #include <lunaix/syslog.h>
 #include <lunaix/status.h>
 #include <lunaix/syscall.h>
 #include <lunaix/syslog.h>
-#include <lunaix/pcontext.h>
+#include <lunaix/hart_state.h>
 #include <lunaix/kpreempt.h>
 
 #include <klibc/string.h>
 
 #include <lunaix/kpreempt.h>
 
 #include <klibc/string.h>
 
-volatile struct proc_info* __current;
-volatile struct thread* current_thread;
+struct thread empty_thread_obj;
+
+volatile struct proc_info* __current = NULL;
+volatile struct thread* current_thread = &empty_thread_obj;
 
 struct scheduler sched_ctx;
 
 struct cake_pile *proc_pile ,*thread_pile;
 
 
 struct scheduler sched_ctx;
 
 struct cake_pile *proc_pile ,*thread_pile;
 
+#define root_process   (sched_ctx.procs[1])
+
 LOG_MODULE("SCHED")
 
 void
 LOG_MODULE("SCHED")
 
 void
@@ -53,9 +56,11 @@ run(struct thread* thread)
     thread->process->state = PS_RUNNING;
     thread->process->th_active = thread;
 
     thread->process->state = PS_RUNNING;
     thread->process->th_active = thread;
 
+    procvm_mount_self(vmspace(thread->process));
     set_current_executing(thread);
 
     switch_context();
     set_current_executing(thread);
 
     switch_context();
+
     fail("unexpected return from switching");
 }
 
     fail("unexpected return from switching");
 }
 
@@ -66,10 +71,9 @@ run(struct thread* thread)
     clean-up on these thread, in the preemptible kernel thread.
 */
 
     clean-up on these thread, in the preemptible kernel thread.
 */
 
-void _preemptible
-cleanup_detached_threads() {
-    ensure_preempt_caller();
-
+void
+cleanup_detached_threads() 
+{
     // XXX may be a lock on sched_context will ben the most appropriate?
     cpu_disable_interrupt();
 
     // XXX may be a lock on sched_context will ben the most appropriate?
     cpu_disable_interrupt();
 
@@ -80,9 +84,11 @@ cleanup_detached_threads() {
             continue;
         }
 
             continue;
         }
 
-        vmm_mount_pd(VMS_MOUNT_1, vmroot(pos->process));
-        destory_thread(VMS_MOUNT_1, pos);
-        vmm_unmount_pd(VMS_MOUNT_1);
+        struct proc_mm* mm = vmspace(pos->process);
+
+        procvm_mount(mm);
+        destory_thread(pos);
+        procvm_unmount(mm);
         
         i++;
     }
         
         i++;
     }
@@ -94,13 +100,22 @@ cleanup_detached_threads() {
     cpu_enable_interrupt();
 }
 
     cpu_enable_interrupt();
 }
 
-int
+bool
 can_schedule(struct thread* thread)
 {
     if (!thread) {
         return 0;
     }
 
 can_schedule(struct thread* thread)
 {
     if (!thread) {
         return 0;
     }
 
+    if (proc_terminated(thread)) {
+        return false;
+    }
+
+    if (preempt_check_stalled(thread)) {
+        thread_flags_set(thread, TH_STALLED);
+        return true;
+    }
+
     if (unlikely(kernel_process(thread->process))) {
         // a kernel process is always runnable
         return thread->state == PS_READY;
     if (unlikely(kernel_process(thread->process))) {
         // a kernel process is always runnable
         return thread->state == PS_READY;
@@ -111,6 +126,7 @@ can_schedule(struct thread* thread)
     if ((thread->state & PS_PAUSED)) {
         return !!(sh->sig_pending & ~1);
     }
     if ((thread->state & PS_PAUSED)) {
         return !!(sh->sig_pending & ~1);
     }
+
     if ((thread->state & PS_BLOCKED)) {
         return sigset_test(sh->sig_pending, _SIGINT);
     }
     if ((thread->state & PS_BLOCKED)) {
         return sigset_test(sh->sig_pending, _SIGINT);
     }
@@ -120,8 +136,9 @@ can_schedule(struct thread* thread)
         // all other threads are also SIGSTOP (as per POSIX-2008.1)
         // In which case, the entire process is stopped.
         thread->state = PS_STOPPED;
         // all other threads are also SIGSTOP (as per POSIX-2008.1)
         // In which case, the entire process is stopped.
         thread->state = PS_STOPPED;
-        return 0;
+        return false;
     }
     }
+    
     if (sigset_test(sh->sig_pending, _SIGCONT)) {
         thread->state = PS_READY;
     }
     if (sigset_test(sh->sig_pending, _SIGCONT)) {
         thread->state = PS_READY;
     }
@@ -168,13 +185,15 @@ schedule()
     assert(sched_ctx.ptable_len && sched_ctx.ttable_len);
 
     // 上下文切换相当的敏感!我们不希望任何的中断打乱栈的顺序……
     assert(sched_ctx.ptable_len && sched_ctx.ttable_len);
 
     // 上下文切换相当的敏感!我们不希望任何的中断打乱栈的顺序……
-    cpu_disable_interrupt();
+    no_preemption();
 
     if (!(current_thread->state & ~PS_RUNNING)) {
         current_thread->state = PS_READY;
         __current->state = PS_READY;
 
     if (!(current_thread->state & ~PS_RUNNING)) {
         current_thread->state = PS_READY;
         __current->state = PS_READY;
+
     }
 
     }
 
+    procvm_unmount_self(vmspace(__current));
     check_sleepers();
 
     // round-robin scheduler
     check_sleepers();
 
     // round-robin scheduler
@@ -200,19 +219,11 @@ schedule()
     sched_ctx.procs_index = to_check->process->pid;
 
 done:
     sched_ctx.procs_index = to_check->process->pid;
 
 done:
-    intc_notify_eos(0);
     run(to_check);
 
     fail("unexpected return from scheduler");
 }
 
     run(to_check);
 
     fail("unexpected return from scheduler");
 }
 
-void
-sched_pass()
-{
-    cpu_enable_interrupt();
-    cpu_trap_sched();
-}
-
 __DEFINE_LXSYSCALL1(unsigned int, sleep, unsigned int, seconds)
 {
     if (!seconds) {
 __DEFINE_LXSYSCALL1(unsigned int, sleep, unsigned int, seconds)
 {
     if (!seconds) {
@@ -248,7 +259,6 @@ __DEFINE_LXSYSCALL1(unsigned int, alarm, unsigned int, seconds)
 
     bed->alarm_time = seconds ? now + seconds : 0;
 
 
     bed->alarm_time = seconds ? now + seconds : 0;
 
-    struct proc_info* root_proc = sched_ctx.procs[0];
     if (llist_empty(&bed->sleepers)) {
         llist_append(&sched_ctx.sleepers, &bed->sleepers);
     }
     if (llist_empty(&bed->sleepers)) {
         llist_append(&sched_ctx.sleepers, &bed->sleepers);
     }
@@ -296,6 +306,7 @@ _wait(pid_t wpid, int* status, int options)
     }
 
     wpid = wpid ? wpid : -__current->pgid;
     }
 
     wpid = wpid ? wpid : -__current->pgid;
+
 repeat:
     llist_for_each(proc, n, &__current->children, siblings)
     {
 repeat:
     llist_for_each(proc, n, &__current->children, siblings)
     {
@@ -314,12 +325,12 @@ repeat:
         return 0;
     }
     // 放弃当前的运行机会
         return 0;
     }
     // 放弃当前的运行机会
-    sched_pass();
+    yield_current();
     goto repeat;
 
 done:
     if (status) {
     goto repeat;
 
 done:
     if (status) {
-        *status = proc->exit_code | status_flags;
+        *status = PEXITNUM(status_flags, proc->exit_code);
     }
     return destroy_process(proc->pid);
 }
     }
     return destroy_process(proc->pid);
 }
@@ -332,7 +343,7 @@ get_free_pid() {
         ;
     
     if (unlikely(i == MAX_PROCESS)) {
         ;
     
     if (unlikely(i == MAX_PROCESS)) {
-        panick("Panic in Ponyville shimmer!");
+        fail("Panic in Ponyville shimmer!");
     }
 
     return i;
     }
 
     return i;
@@ -382,7 +393,9 @@ alloc_process()
     proc->created = clock_systime();
     proc->pgid = proc->pid;
 
     proc->created = clock_systime();
     proc->pgid = proc->pid;
 
-    proc->sigreg = vzalloc(sizeof(struct sigregister));
+    proc->root = vfs_sysroot;
+
+    proc->sigreg = vzalloc(sizeof(struct sigregistry));
     proc->fdtable = vzalloc(sizeof(struct v_fdtable));
 
     proc->mm = procvm_create(proc);
     proc->fdtable = vzalloc(sizeof(struct v_fdtable));
 
     proc->mm = procvm_create(proc);
@@ -427,7 +440,7 @@ commit_process(struct proc_info* process)
     // every process is the child of first process (pid=1)
     if (!process->parent) {
         if (likely(!kernel_process(process))) {
     // every process is the child of first process (pid=1)
     if (!process->parent) {
         if (likely(!kernel_process(process))) {
-            process->parent = sched_ctx.procs[1];
+            process->parent = root_process;
         } else {
             process->parent = process;
         }
         } else {
             process->parent = process;
         }
@@ -447,7 +460,7 @@ commit_process(struct proc_info* process)
 }
 
 void
 }
 
 void
-destory_thread(ptr_t vm_mnt, struct thread* thread) 
+destory_thread(struct thread* thread) 
 {
     cake_ensure_valid(thread);
     
 {
     cake_ensure_valid(thread);
     
@@ -458,7 +471,7 @@ destory_thread(ptr_t vm_mnt, struct thread* thread)
     llist_delete(&thread->sleep.sleepers);
     waitq_cancel_wait(&thread->waitqueue);
 
     llist_delete(&thread->sleep.sleepers);
     waitq_cancel_wait(&thread->waitqueue);
 
-    thread_release_mem(thread, vm_mnt);
+    thread_release_mem(thread);
 
     proc->thread_count--;
     sched_ctx.ttable_len--;
 
     proc->thread_count--;
     sched_ctx.ttable_len--;
@@ -466,10 +479,25 @@ destory_thread(ptr_t vm_mnt, struct thread* thread)
     cake_release(thread_pile, thread);
 }
 
     cake_release(thread_pile, thread);
 }
 
+static void
+orphan_children(struct proc_info* proc)
+{
+    struct proc_info *root;
+    struct proc_info *pos, *n;
+
+    root = root_process;
+
+    llist_for_each(pos, n, &proc->children, siblings) {
+        pos->parent = root;
+        llist_append(&root->children, &pos->siblings);
+    }
+}
+
 void 
 delete_process(struct proc_info* proc)
 {
     pid_t pid = proc->pid;
 void 
 delete_process(struct proc_info* proc)
 {
     pid_t pid = proc->pid;
+    struct proc_mm* mm = vmspace(proc);
 
     assert(pid);    // long live the pid0 !!
 
 
     assert(pid);    // long live the pid0 !!
 
@@ -501,26 +529,26 @@ delete_process(struct proc_info* proc)
 
     vfree(proc->fdtable);
 
 
     vfree(proc->fdtable);
 
-    signal_free_registers(proc->sigreg);
+    signal_free_registry(proc->sigreg);
 
 
-    vmm_mount_pd(VMS_MOUNT_1, vmroot(proc));
+    procvm_mount(mm);
     
     struct thread *pos, *n;
     llist_for_each(pos, n, &proc->threads, proc_sibs) {
         // terminate and destory all thread unconditionally
     
     struct thread *pos, *n;
     llist_for_each(pos, n, &proc->threads, proc_sibs) {
         // terminate and destory all thread unconditionally
-        destory_thread(VMS_MOUNT_1, pos);
+        destory_thread(pos);
     }
 
     }
 
-    procvm_cleanup(VMS_MOUNT_1, proc);
+    orphan_children(proc);
 
 
-    vmm_unmount_pd(VMS_MOUNT_1);
+    procvm_unmount_release(mm);
 
     cake_release(proc_pile, proc);
 }
 
 pid_t
 destroy_process(pid_t pid)
 
     cake_release(proc_pile, proc);
 }
 
 pid_t
 destroy_process(pid_t pid)
-{
+{    
     int index = pid;
     if (index <= 0 || index > sched_ctx.ptable_len) {
         syscall_result(EINVAL);
     int index = pid;
     if (index <= 0 || index > sched_ctx.ptable_len) {
         syscall_result(EINVAL);
@@ -535,6 +563,8 @@ destroy_process(pid_t pid)
 
 static void 
 terminate_proc_only(struct proc_info* proc, int exit_code) {
 
 static void 
 terminate_proc_only(struct proc_info* proc, int exit_code) {
+    assert(proc->pid != 0);
+
     proc->state = PS_TERMNAT;
     proc->exit_code = exit_code;
 
     proc->state = PS_TERMNAT;
     proc->exit_code = exit_code;
 
@@ -562,13 +592,13 @@ terminate_proccess(struct proc_info* proc, int exit_code) {
     assert(!kernel_process(proc));
 
     if (proc->pid == 1) {
     assert(!kernel_process(proc));
 
     if (proc->pid == 1) {
-        panick("Attempt to kill init");
+        fail("Attempt to kill init");
     }
 
     terminate_proc_only(proc, exit_code);
 
     struct thread *pos, *n;
     }
 
     terminate_proc_only(proc, exit_code);
 
     struct thread *pos, *n;
-    llist_for_each(pos, n, &__current->threads, proc_sibs) {
+    llist_for_each(pos, n, &proc->threads, proc_sibs) {
         pos->state = PS_TERMNAT;
     }
 }
         pos->state = PS_TERMNAT;
     }
 }