1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-30 23:28:12 +00:00

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.
This commit is contained in:
Andreas Kling 2018-10-16 11:06:35 +02:00
parent 87d41bdca4
commit 72bb80a9ae
8 changed files with 94 additions and 81 deletions

View file

@ -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:

View file

@ -8,45 +8,48 @@
#include "FileSystem.h" #include "FileSystem.h"
Task* current; Task* current;
static Task* kt; Task* s_kernelTask;
Task* 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()); auto& tssDescriptor = getGDTEntry(s_kernelTask->selector());
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;
if (!kt->selector()) tssDescriptor.setBase(&s_kernelTask->tss());
kt->setSelector(allocateGDTEntry()); 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>;
s_kernelTask = new Task(0, "idle", IPC::Handle::Any, Task::Ring0);
kt = new Task(0, "dummy", IPC::Handle::Any, Task::Ring0); redoKernelTaskTSS();
loadTaskRegister(s_kernelTask->selector());
redo_kt_td();
} }
#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_farPtr.offset = 0x12345678;
m_selector = 0;
// 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());
// HACK: To avoid ridiculous clock skew, decrement the system uptime if (!scheduleNewTask())
// counter. It's incremented by int 0x50... return;
--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 contextSwitch(Task::kernelTask());
return;
} }
// 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 contextSwitch(task);
return;
} }
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 contextSwitch(Task::kernelTask());
return;
} }
} }
} }
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. if (!t->selector())
// (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()) {
t->setSelector(allocateGDTEntry()); t->setSelector(allocateGDTEntry());
writeGDTEntry(t->selector(), td);
flushGDT();
} else {
writeGDTEntry(t->selector(), td);
}
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
flushGDT();
drawSchedulerBanner(*t); drawSchedulerBanner(*t);
return true;
redo_kt_td();
kt->tss().backlink = t->selector();
loadTaskRegister(kt->selector());
} }
Task* Task::fromPID(pid_t pid) Task* Task::fromPID(pid_t pid)

View file

@ -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);

View file

@ -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);
}
} }

View file

@ -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();
} }

View file

@ -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. // Prepare a new task to run;
sched(); 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"

View file

@ -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();

View file

@ -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;