Bladeren bron

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 jaren geleden
bovenliggende
commit
72bb80a9ae
8 gewijzigde bestanden met toevoegingen van 94 en 81 verwijderingen
  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 );
         kprintf( "%c", arg1 & 0xFF );
         break;
         break;
     case Syscall::Sleep:
     case Syscall::Sleep:
-        kprintf("syscall: sleep(%d)\n", arg1);
+        //kprintf("syscall: sleep(%d)\n", arg1);
         current->sys$sleep(arg1);
         current->sys$sleep(arg1);
         break;
         break;
     case Syscall::PosixOpen:
     case Syscall::PosixOpen:

+ 68 - 68
Kernel/Task.cpp

@@ -8,45 +8,48 @@
 #include "FileSystem.h"
 #include "FileSystem.h"
 
 
 Task* current;
 Task* current;
-static Task* kt;
-Task* Task::s_kernelTask;
+Task* s_kernelTask;
 
 
 static pid_t next_pid;
 static pid_t next_pid;
 static DoublyLinkedList<Task>* s_tasks;
 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();
     flushGDT();
 }
 }
 
 
+void Task::prepForIRETToNewTask()
+{
+    redoKernelTaskTSS();
+    s_kernelTask->tss().backlink = current->selector();
+    loadTaskRegister(s_kernelTask->selector());
+}
+
 void Task::initialize()
 void Task::initialize()
 {
 {
     current = nullptr;
     current = nullptr;
     next_pid = 0;
     next_pid = 0;
-    Task::s_kernelTask = nullptr;
     s_tasks = new DoublyLinkedList<Task>;
     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
 #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.
     // HACK: Ring2 SS in the TSS is the current PID.
     m_tss.ss2 = m_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.
     // Don't add task 0 (kernel dummy task) to task list.
     // FIXME: This doesn't belong in the constructor.
     // FIXME: This doesn't belong in the constructor.
     if (m_pid == 0)
     if (m_pid == 0)
         return;
         return;
 
 
-    if (m_pid == 1)
-        s_kernelTask = this;
-
     // Add it to head of task list (meaning it's next to run too, ATM.)
     // Add it to head of task list (meaning it's next to run too, ATM.)
     s_tasks->prepend(this);
     s_tasks->prepend(this);
 
 
@@ -178,21 +177,28 @@ void yield()
         HANG;
         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) {
     if (!current) {
         // XXX: The first ever context_switch() goes to the idle task.
         // XXX: The first ever context_switch() goes to the idle task.
         //      This to setup a reliable place we can return to.
         //      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.
     // 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) {
         if (task->state() == Task::Runnable || task->state() == Task::Running) {
             //kprintf("switch to %s\n", task->name().characters());
             //kprintf("switch to %s\n", task->name().characters());
-            context_switch(task);
-            return;
+            return contextSwitch(task);
         }
         }
 
 
         if (task == prevHead) {
         if (task == prevHead) {
             // Back at task_head, nothing wants to run.
             // Back at task_head, nothing wants to run.
-            context_switch(Task::kernelTask());
-            return;
+            return contextSwitch(Task::kernelTask());
         }
         }
     }
     }
 }
 }
 
 
 static void drawSchedulerBanner(Task& task)
 static void drawSchedulerBanner(Task& task)
 {
 {
+    // FIXME: We need a kernel lock to do stuff like this :(
+    //return;
     auto c = vga_get_cursor();
     auto c = vga_get_cursor();
     auto a = vga_get_attr();
     auto a = vga_get_attr();
     vga_set_cursor(0, 50);
     vga_set_cursor(0, 50);
@@ -257,10 +263,14 @@ static void drawSchedulerBanner(Task& task)
     vga_set_cursor(c);
     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);
     t->setTicksLeft(5);
 
 
+    if (current == t)
+        return false;
+
     // If the last task hasn't blocked (still marked as running),
     // If the last task hasn't blocked (still marked as running),
     // mark it as runnable for the next round.
     // mark it as runnable for the next round.
     if (current->state() == Task::Running)
     if (current->state() == Task::Running)
@@ -269,37 +279,27 @@ static void context_switch(Task* t)
     current = t;
     current = t;
     t->setState(Task::Running);
     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());
         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)
 Task* Task::fromPID(pid_t pid)

+ 8 - 6
Kernel/Task.h

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

+ 5 - 0
Kernel/Userspace.cpp

@@ -39,4 +39,9 @@ void sleep(DWORD ticks)
     DO_SYSCALL_A1(Syscall::Sleep, 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);
 int kill(pid_t pid, int sig);
 uid_t getuid();
 uid_t getuid();
 void sleep(DWORD ticks);
 void sleep(DWORD ticks);
+void yield();
 
 
 }
 }

+ 5 - 4
Kernel/i8253.cpp

@@ -94,6 +94,7 @@ void clock_handle()
     if (current->tick())
     if (current->tick())
         return;
         return;
 
 
+    //return;
 
 
     auto& regs = *reinterpret_cast<RegisterDump*>(state_dump);
     auto& regs = *reinterpret_cast<RegisterDump*>(state_dump);
     current->tss().gs = regs.gs;
     current->tss().gs = regs.gs;
@@ -131,12 +132,12 @@ void clock_handle()
     // Add 12 for CS, EIP, EFLAGS (interrupt mechanic)
     // Add 12 for CS, EIP, EFLAGS (interrupt mechanic)
     current->tss().esp = regs.esp + 12;
     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.
     // 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(
     asm(
         "pushf\n"
         "pushf\n"
         "orl $0x00004000, (%esp)\n"
         "orl $0x00004000, (%esp)\n"

+ 1 - 2
Kernel/init.cpp

@@ -111,12 +111,11 @@ void init()
 
 
     extern void panel_main();
     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(panel_main, "panel", IPC::Handle::PanelTask, Task::Ring0);
 
 
     //new Task(led_disco, "led-disco", IPC::Handle::Any, Task::Ring0);
     //new Task(led_disco, "led-disco", IPC::Handle::Any, Task::Ring0);
 
 
-    sched();
+    scheduleNewTask();
     enableInterrupts();
     enableInterrupts();
 
 
     banner();
     banner();

+ 5 - 0
Kernel/types.h

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