Sfoglia il codice sorgente

These changes were lying around uncommitted in the old repo.

I'm just gonna commit them without too much thinking and then take
it from there.
Andreas Kling 6 anni fa
parent
commit
72bb80a9ae
8 ha cambiato i file con 94 aggiunte e 81 eliminazioni
  1. 1 1
      Kernel/Syscall.cpp
  2. 68 68
      Kernel/Task.cpp
  3. 8 6
      Kernel/Task.h
  4. 5 0
      Kernel/Userspace.cpp
  5. 1 0
      Kernel/Userspace.h
  6. 5 4
      Kernel/i8253.cpp
  7. 1 2
      Kernel/init.cpp
  8. 5 0
      Kernel/types.h

+ 1 - 1
Kernel/Syscall.cpp

@@ -102,7 +102,7 @@ DWORD handle(DWORD function, DWORD arg1, DWORD arg2, DWORD arg3)
         kprintf( "%c", arg1 & 0xFF );
         break;
     case Syscall::Sleep:
-        kprintf("syscall: sleep(%d)\n", arg1);
+        //kprintf("syscall: sleep(%d)\n", arg1);
         current->sys$sleep(arg1);
         break;
     case Syscall::PosixOpen:

+ 68 - 68
Kernel/Task.cpp

@@ -8,45 +8,48 @@
 #include "FileSystem.h"
 
 Task* current;
-static Task* kt;
-Task* Task::s_kernelTask;
+Task* s_kernelTask;
 
 static pid_t next_pid;
 static DoublyLinkedList<Task>* s_tasks;
 
-PRIVATE void context_switch(Task*);
+static bool contextSwitch(Task*);
 
-static void redo_kt_td()
+static void redoKernelTaskTSS()
 {
-    Descriptor td;
+    if (!s_kernelTask->selector())
+        s_kernelTask->setSelector(allocateGDTEntry());
 
-    td.setBase(&kt->tss());
-    td.setLimit(0xffff);
-    td.dpl = 0;
-    td.segment_present = 1;
-    td.granularity = 1;
-    td.zero = 0;
-    td.operation_size = 1;
-    td.descriptor_type = 0;
-    td.type = 9;
+    auto& tssDescriptor = getGDTEntry(s_kernelTask->selector());
 
-    if (!kt->selector())
-        kt->setSelector(allocateGDTEntry());
+    tssDescriptor.setBase(&s_kernelTask->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;
 
-    writeGDTEntry(kt->selector(), td);
     flushGDT();
 }
 
+void Task::prepForIRETToNewTask()
+{
+    redoKernelTaskTSS();
+    s_kernelTask->tss().backlink = current->selector();
+    loadTaskRegister(s_kernelTask->selector());
+}
+
 void Task::initialize()
 {
     current = nullptr;
     next_pid = 0;
-    Task::s_kernelTask = nullptr;
     s_tasks = new DoublyLinkedList<Task>;
-
-    kt = new Task(0, "dummy", IPC::Handle::Any, Task::Ring0);
-
-    redo_kt_td();
+    s_kernelTask = new Task(0, "idle", IPC::Handle::Any, Task::Ring0);
+    redoKernelTaskTSS();
+    loadTaskRegister(s_kernelTask->selector());
 }
 
 #ifdef TASK_SANITY_CHECKS
@@ -146,17 +149,13 @@ Task::Task(void (*e)(), const char* n, IPC::Handle h, RingLevel ring)
     // HACK: Ring2 SS in the TSS is the current PID.
     m_tss.ss2 = m_pid;
 
-    // Get a nice GDT entry @ next context switch.
-    m_selector = 0;
+    m_farPtr.offset = 0x12345678;
 
     // Don't add task 0 (kernel dummy task) to task list.
     // FIXME: This doesn't belong in the constructor.
     if (m_pid == 0)
         return;
 
-    if (m_pid == 1)
-        s_kernelTask = this;
-
     // Add it to head of task list (meaning it's next to run too, ATM.)
     s_tasks->prepend(this);
 
@@ -178,21 +177,28 @@ void yield()
         HANG;
     }
 
-    current->setTicksLeft(1);
+    //kprintf("%s<%u> yield()\n", current->name().characters(), current->pid());
+
+    if (!scheduleNewTask())
+        return;
 
-    // HACK: To avoid ridiculous clock skew, decrement the system uptime
-    //       counter. It's incremented by int 0x50...
-    --system.uptime;
-    asm("int $0x50");
+    Descriptor& descriptor = getGDTEntry(current->selector());
+    descriptor.type = 9;
+    flushGDT();
+
+    //kprintf("yield() jumping to new task: %x (%s)\n", current->farPtr().selector, current->name().characters());
+    asm(
+        "ljmp *(%%eax)\n"
+        ::"a"(&current->farPtr())
+    );
 }
 
-void sched()
+bool scheduleNewTask()
 {
     if (!current) {
         // XXX: The first ever context_switch() goes to the idle task.
         //      This to setup a reliable place we can return to.
-        context_switch(Task::kernelTask());
-        return;
+        return contextSwitch(Task::kernelTask());
     }
 
     // Check and unblock tasks whose wait conditions have been met.
@@ -226,20 +232,20 @@ void sched()
 
         if (task->state() == Task::Runnable || task->state() == Task::Running) {
             //kprintf("switch to %s\n", task->name().characters());
-            context_switch(task);
-            return;
+            return contextSwitch(task);
         }
 
         if (task == prevHead) {
             // Back at task_head, nothing wants to run.
-            context_switch(Task::kernelTask());
-            return;
+            return contextSwitch(Task::kernelTask());
         }
     }
 }
 
 static void drawSchedulerBanner(Task& task)
 {
+    // FIXME: We need a kernel lock to do stuff like this :(
+    //return;
     auto c = vga_get_cursor();
     auto a = vga_get_attr();
     vga_set_cursor(0, 50);
@@ -257,10 +263,14 @@ static void drawSchedulerBanner(Task& task)
     vga_set_cursor(c);
 }
 
-static void context_switch(Task* t)
+static bool contextSwitch(Task* t)
 {
+    //kprintf("c_s to %s (same:%u)\n", t->name().characters(), current == t);
     t->setTicksLeft(5);
 
+    if (current == t)
+        return false;
+
     // If the last task hasn't blocked (still marked as running),
     // mark it as runnable for the next round.
     if (current->state() == Task::Running)
@@ -269,37 +279,27 @@ static void context_switch(Task* t)
     current = t;
     t->setState(Task::Running);
 
-    // You might be looking at the slowest i386 context switcher ever made.
-    // (But I don't think so.)
-
-    Descriptor td;
-
-    td.limit_hi = 0;
-    td.limit_lo = 0xFFFF;
-    td.base_lo = (DWORD)(&t->tss()) & 0xFFFF;
-    td.base_hi = ((DWORD)(&t->tss()) >> 16) & 0xFF;
-    td.base_hi2 = ((DWORD)(&t->tss()) >> 24) & 0xFF;
-    td.dpl = 0;
-    td.segment_present = 1;
-    td.granularity = 1;
-    td.zero = 0;
-    td.operation_size = 1;
-    td.descriptor_type = 0;
-    td.type = 11;
-
-    if (!t->selector()) {
+    if (!t->selector())
         t->setSelector(allocateGDTEntry());
-        writeGDTEntry(t->selector(), td);
-        flushGDT();
-    } else {
-        writeGDTEntry(t->selector(), td);
-    }
 
-    drawSchedulerBanner(*t);
+    auto& tssDescriptor = getGDTEntry(t->selector());
+
+    tssDescriptor.limit_hi = 0;
+    tssDescriptor.limit_lo = 0xFFFF;
+    tssDescriptor.base_lo = (DWORD)(&t->tss()) & 0xFFFF;
+    tssDescriptor.base_hi = ((DWORD)(&t->tss()) >> 16) & 0xFF;
+    tssDescriptor.base_hi2 = ((DWORD)(&t->tss()) >> 24) & 0xFF;
+    tssDescriptor.dpl = 0;
+    tssDescriptor.segment_present = 1;
+    tssDescriptor.granularity = 1;
+    tssDescriptor.zero = 0;
+    tssDescriptor.operation_size = 1;
+    tssDescriptor.descriptor_type = 0;
+    tssDescriptor.type = 11; // Busy TSS
 
-    redo_kt_td();
-    kt->tss().backlink = t->selector();
-    loadTaskRegister(kt->selector());
+    flushGDT();
+    drawSchedulerBanner(*t);
+    return true;
 }
 
 Task* Task::fromPID(pid_t pid)

+ 8 - 6
Kernel/Task.h

@@ -46,11 +46,13 @@ public:
     const String& name() const { return m_name; }
     pid_t pid() const { return m_pid; }
     DWORD ticks() const { return m_ticks; }
-    WORD selector() const { return m_selector; }
+    WORD selector() const { return m_farPtr.selector; }
     TSS32& tss() { return m_tss; }
     State state() const { return m_state; }
     IPC::Handle handle() const { return m_handle; }
 
+    const FarPtr& farPtr() const { return m_farPtr; }
+
     FileHandle* fileHandleIfExists(int fd);
     FileHandle* createFileHandle();
 
@@ -62,10 +64,12 @@ public:
     void setWakeupTime(DWORD t) { m_wakeupTime = t; }
     DWORD wakeupTime() const { return m_wakeupTime; }
 
+    static void prepForIRETToNewTask();
+
     bool tick() { ++m_ticks; return --m_ticksLeft; }
     void setTicksLeft(DWORD t) { m_ticksLeft = t; }
 
-    void setSelector(WORD s) { m_selector = s; }
+    void setSelector(WORD s) { m_farPtr.selector = s; }
     void setState(State s) { m_state = s; }
 
     uid_t sys$getuid();
@@ -104,7 +108,7 @@ private:
     DWORD m_ticksLeft { 0 };
     IPC::Handle m_handle { 0 };
     DWORD m_stackTop { 0 };
-    WORD m_selector { 0 };
+    FarPtr m_farPtr;
     State m_state { Invalid };
     DWORD m_wakeupTime { 0 };
     TSS32 m_tss;
@@ -112,13 +116,11 @@ private:
     Vector<FileHandle*> m_fileHandles;
     RingLevel m_ring { Ring0 };
     int m_error { 0 };
-
-    static Task* s_kernelTask;
 };
 
 extern void task_init();
 extern void yield();
-extern void sched();
+extern bool scheduleNewTask();
 extern void block(Task::State);
 extern void sleep(DWORD ticks);
 

+ 5 - 0
Kernel/Userspace.cpp

@@ -39,4 +39,9 @@ void sleep(DWORD ticks)
     DO_SYSCALL_A1(Syscall::Sleep, ticks);
 }
 
+void yield()
+{
+    DO_SYSCALL_A0(Syscall::Yield);
+}
+
 }

+ 1 - 0
Kernel/Userspace.h

@@ -11,5 +11,6 @@ int seek(int fd, int offset);
 int kill(pid_t pid, int sig);
 uid_t getuid();
 void sleep(DWORD ticks);
+void yield();
 
 }

+ 5 - 4
Kernel/i8253.cpp

@@ -94,6 +94,7 @@ void clock_handle()
     if (current->tick())
         return;
 
+    //return;
 
     auto& regs = *reinterpret_cast<RegisterDump*>(state_dump);
     current->tss().gs = regs.gs;
@@ -131,12 +132,12 @@ void clock_handle()
     // Add 12 for CS, EIP, EFLAGS (interrupt mechanic)
     current->tss().esp = regs.esp + 12;
 
-    // Prepare a new task to run.
-    sched();
+    // Prepare a new task to run;
+    if (!scheduleNewTask())
+        return;
+    Task::prepForIRETToNewTask();
 
     // Set the NT (nested task) flag.
-    // sched() has LTRed a dummy task with a backlink to the next task.
-    // This is probably super slow/stupid, but I'm just learning...
     asm(
         "pushf\n"
         "orl $0x00004000, (%esp)\n"

+ 1 - 2
Kernel/init.cpp

@@ -111,12 +111,11 @@ void init()
 
     extern void panel_main();
 
-    new Task(0, "KernelTask", IPC::Handle::Any, Task::Ring0);
     new Task(panel_main, "panel", IPC::Handle::PanelTask, Task::Ring0);
 
     //new Task(led_disco, "led-disco", IPC::Handle::Any, Task::Ring0);
 
-    sched();
+    scheduleNewTask();
     enableInterrupts();
 
     banner();

+ 5 - 0
Kernel/types.h

@@ -63,3 +63,8 @@ typedef DWORD gid_t;
 typedef int pid_t;
 typedef DWORD time_t;
 typedef DWORD size_t;
+
+struct FarPtr {
+    DWORD offset { 0 };
+    WORD selector { 0 };
+} PACKED;