mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-22 20:45:14 +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:
parent
87d41bdca4
commit
72bb80a9ae
Notes:
sideshowbarker
2024-07-19 18:47:40 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/72bb80a9ae3
8 changed files with 94 additions and 81 deletions
|
@ -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:
|
||||
|
|
136
Kernel/Task.cpp
136
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());
|
||||
|
||||
// HACK: To avoid ridiculous clock skew, decrement the system uptime
|
||||
// counter. It's incremented by int 0x50...
|
||||
--system.uptime;
|
||||
asm("int $0x50");
|
||||
if (!scheduleNewTask())
|
||||
return;
|
||||
|
||||
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"(¤t->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);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
redo_kt_td();
|
||||
kt->tss().backlink = t->selector();
|
||||
loadTaskRegister(kt->selector());
|
||||
return true;
|
||||
}
|
||||
|
||||
Task* Task::fromPID(pid_t pid)
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -39,4 +39,9 @@ void sleep(DWORD ticks)
|
|||
DO_SYSCALL_A1(Syscall::Sleep, ticks);
|
||||
}
|
||||
|
||||
void yield()
|
||||
{
|
||||
DO_SYSCALL_A0(Syscall::Yield);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue