Bladeren bron

Finally unbreak the colonel process and make it the true idle process.

Andreas Kling 6 jaren geleden
bovenliggende
commit
43f40a3050
4 gewijzigde bestanden met toevoegingen van 59 en 52 verwijderingen
  1. 7 3
      Kernel/Process.cpp
  2. 4 0
      Kernel/Process.h
  3. 40 38
      Kernel/Scheduler.cpp
  4. 8 11
      Kernel/init.cpp

+ 7 - 3
Kernel/Process.cpp

@@ -321,8 +321,12 @@ int Process::exec(const String& path, Vector<String>&& arguments, Vector<String>
     kprintf("Process %u (%s) exec'd %s @ %p\n", pid(), name().characters(), path.characters(), m_tss.eip);
 #endif
 
-    if (current == this)
-        Scheduler::yield();
+    set_state(ExecPhase1);
+
+    if (current == this) {
+        bool success = Scheduler::yield();
+        ASSERT(success);
+    }
 
     return 0;
 }
@@ -361,7 +365,7 @@ int Process::sys$execve(const char* filename, const char** argv, const char** en
     }
 
     int rc = exec(path, move(arguments), move(environment));
-    ASSERT(rc < 0);
+    ASSERT(rc < 0); // We should never continue after a successful exec!
     return rc;
 }
 

+ 4 - 0
Kernel/Process.h

@@ -43,6 +43,8 @@ public:
         Invalid = 0,
         Runnable,
         Running,
+        ExecPhase1,
+        ExecPhase2,
         Dead,
         Forgiven,
         BeingInspected,
@@ -304,6 +306,8 @@ static inline const char* toString(Process::State state)
     case Process::Runnable: return "Runnable";
     case Process::Running: return "Running";
     case Process::Dead: return "Dead";
+    case Process::ExecPhase1: return "ExecPhase1";
+    case Process::ExecPhase2: return "ExecPhase2";
     case Process::Forgiven: return "Forgiven";
     case Process::BlockedSleep: return "Sleep";
     case Process::BlockedWait: return "Wait";

+ 40 - 38
Kernel/Scheduler.cpp

@@ -10,6 +10,12 @@ static const dword time_slice = 5; // *10 = 50ms
 Process* current;
 static Process* s_colonel_process;
 
+struct TaskRedirectionData {
+    word selector;
+    TSS32 tss;
+};
+static TaskRedirectionData s_redirection;
+
 bool Scheduler::pick_next()
 {
     ASSERT_INTERRUPTS_DISABLED();
@@ -50,6 +56,16 @@ bool Scheduler::pick_next()
             return true;
         }
 
+        if (process.state() == Process::ExecPhase1) {
+            process.set_state(Process::ExecPhase2);
+            return true;
+        }
+
+        if (process.state() == Process::ExecPhase2) {
+            process.set_state(Process::Runnable);
+            return true;
+        }
+
         // Forgive dead orphans.
         if (process.state() == Process::Dead) {
             if (!Process::from_pid(process.ppid()))
@@ -57,11 +73,11 @@ bool Scheduler::pick_next()
         }
 
         // Release the forgiven.
-        Process::for_each_in_state(Process::Forgiven, [] (auto& process) {
+        if (process.state() == Process::Forgiven) {
             g_processes->remove(&process);
             g_dead_processes->append(&process);
             return true;
-        });
+        };
 
         return true;
     });
@@ -104,25 +120,13 @@ bool Scheduler::pick_next()
 
         if (process->state() == Process::Runnable || process->state() == Process::Running) {
 #ifdef SCHEDULER_DEBUG
-            dbgprintf("switch to %s(%u)\n", process->name().characters(), process->pid());
+            dbgprintf("switch to %s(%u) @ %w:%x\n", process->name().characters(), process->pid(), process->tss().cs, process->tss().eip);
 #endif
             return context_switch(*process);
         }
 
         if (process == prevHead) {
-            // Back at process_head, nothing wants to run.
-            kprintf("Nothing wants to run!\n");
-            kprintf("PID    OWNER      STATE  NSCHED  NAME\n");
-            for (auto* process = g_processes->head(); process; process = process->next()) {
-                kprintf("%w   %w:%w  %b     %w    %s\n",
-                    process->pid(),
-                    process->uid(),
-                    process->gid(),
-                    process->state(),
-                    process->timesScheduled(),
-                    process->name().characters());
-            }
-            kprintf("Switch to kernel process @ %w:%x\n", s_colonel_process->tss().cs, s_colonel_process->tss().eip);
+            // Back at process_head, nothing wants to run. Send in the colonel!
             return context_switch(*s_colonel_process);
         }
     }
@@ -214,38 +218,34 @@ int sched_yield()
     return Scheduler::yield();
 }
 
-static void redo_colonel_process_tss()
+static void initialize_redirection()
 {
-    if (!s_colonel_process->selector())
-        s_colonel_process->setSelector(gdt_alloc_entry());
-
-    auto& tssDescriptor = getGDTEntry(s_colonel_process->selector());
-
-    tssDescriptor.setBase(&s_colonel_process->tss());
-    tssDescriptor.setLimit(0xffff);
-    tssDescriptor.dpl = 0;
-    tssDescriptor.segment_present = 1;
-    tssDescriptor.granularity = 1;
-    tssDescriptor.zero = 0;
-    tssDescriptor.operation_size = 1;
-    tssDescriptor.descriptor_type = 0;
-    tssDescriptor.type = 9;
-
+    auto& descriptor = getGDTEntry(s_redirection.selector);
+    descriptor.setBase(&s_redirection.tss);
+    descriptor.setLimit(0xffff);
+    descriptor.dpl = 0;
+    descriptor.segment_present = 1;
+    descriptor.granularity = 1;
+    descriptor.zero = 0;
+    descriptor.operation_size = 1;
+    descriptor.descriptor_type = 0;
+    descriptor.type = 9;
     flushGDT();
 }
 
 void Scheduler::prepare_for_iret_to_new_process()
 {
-    redo_colonel_process_tss();
-    s_colonel_process->tss().backlink = current->selector();
-    load_task_register(s_colonel_process->selector());
+    auto& descriptor = getGDTEntry(s_redirection.selector);
+    descriptor.type = 9;
+    s_redirection.tss.backlink = current->selector();
+    load_task_register(s_redirection.selector);
 }
 
 void Scheduler::prepare_to_modify_own_tss()
 {
     // This ensures that a process modifying its own TSS in order to yield()
     // and end up somewhere else doesn't just end up right after the yield().
-    load_task_register(s_colonel_process->selector());
+    load_task_register(s_redirection.selector);
 }
 
 static void hlt_loop()
@@ -257,8 +257,10 @@ static void hlt_loop()
 
 void Scheduler::initialize()
 {
+    memset(&s_redirection, 0, sizeof(s_redirection));
+    s_redirection.selector = gdt_alloc_entry();
+    initialize_redirection();
     s_colonel_process = Process::create_kernel_process(hlt_loop, "colonel");
     current = nullptr;
-    redo_colonel_process_tss();
-    load_task_register(s_colonel_process->selector());
+    load_task_register(s_redirection.selector);
 }

+ 8 - 11
Kernel/init.cpp

@@ -168,7 +168,6 @@ static void spawn_stress()
     }
 }
 
-
 static void init_stage2() NORETURN;
 static void init_stage2()
 {
@@ -242,21 +241,19 @@ static void init_stage2()
 #endif
 
     int error;
-    auto* sh0 = Process::create_user_process("/bin/sh", (uid_t)100, (gid_t)100, (pid_t)0, error, Vector<String>(), Vector<String>(), tty0);
+    Process::create_user_process("/bin/sh", (uid_t)100, (gid_t)100, (pid_t)0, error, Vector<String>(), Vector<String>(), tty0);
 #ifdef SPAWN_MULTIPLE_SHELLS
-    auto* sh1 = Process::create_user_process("/bin/sh", (uid_t)100, (gid_t)100, (pid_t)0, error, Vector<String>(), Vector<String>(), tty1);
-    auto* sh2 = Process::create_user_process("/bin/sh", (uid_t)100, (gid_t)100, (pid_t)0, error, Vector<String>(), Vector<String>(), tty2);
-    auto* sh3 = Process::create_user_process("/bin/sh", (uid_t)100, (gid_t)100, (pid_t)0, error, Vector<String>(), Vector<String>(), tty3);
+    Process::create_user_process("/bin/sh", (uid_t)100, (gid_t)100, (pid_t)0, error, Vector<String>(), Vector<String>(), tty1);
+    Process::create_user_process("/bin/sh", (uid_t)100, (gid_t)100, (pid_t)0, error, Vector<String>(), Vector<String>(), tty2);
+    Process::create_user_process("/bin/sh", (uid_t)100, (gid_t)100, (pid_t)0, error, Vector<String>(), Vector<String>(), tty3);
 #endif
 
 #ifdef STRESS_TEST_SPAWNING
-    Process::createKernelProcess(spawn_stress, "spawn_stress");
+    Process::create_kernel_process(spawn_stress, "spawn_stress");
 #endif
 
-    for (;;) {
-        //sleep(3600 * TICKS_PER_SECOND);
-        asm("hlt");
-    }
+    current->sys$exit(0);
+    ASSERT_NOT_REACHED();
 }
 
 void init()
@@ -310,7 +307,7 @@ void init()
     Process::initialize();
 
     Process::create_kernel_process(undertaker_main, "undertaker");
-    Process::create_kernel_process(init_stage2, "init");
+    Process::create_kernel_process(init_stage2, "init_stage2");
 
     Scheduler::pick_next();