wip: IPC and Runtime
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
#include <OS/IPC.h>
|
||||
#include <OS/Scheduler.h>
|
||||
#include <Arch/CPU.h>
|
||||
#include <Arch/Exceptions.h>
|
||||
|
||||
UInt64 IPCSend(OSTask* sender, UInt64 handleID, UInt64 data) {
|
||||
if (handleID == 0) return -1;
|
||||
OSProcess* currentProcess = sender->process;
|
||||
OSTask* targetTask = (OSTask*)SchedulerProcessGetHandle(currentProcess, handleID, kOSHandleTypeTask);
|
||||
if (!targetTask) return -1;
|
||||
|
||||
if (targetTask->state == OSTaskStateBlockedReceive) {
|
||||
ExceptionsContext* receiverContext = (ExceptionsContext*)targetTask->stackPointer;
|
||||
receiverContext->x1 = data;
|
||||
receiverContext->x0 = currentProcess->id;
|
||||
|
||||
targetTask->state = OSTaskStateRunning;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (targetTask->senderWaiting != nullptr) return -2;
|
||||
|
||||
targetTask->senderWaiting = sender;
|
||||
|
||||
SchedulerBlockCurrentTask(OSTaskStateBlockedSend);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void IPCReceive(ExceptionsContext* receiverFrame) {
|
||||
OSTask* receiver = SchedulerGetCurrentTask();
|
||||
|
||||
if (receiver->senderWaiting != nullptr) {
|
||||
OSTask* sender = receiver->senderWaiting;
|
||||
|
||||
ExceptionsContext* senderContext = (ExceptionsContext*)sender->stackPointer;
|
||||
|
||||
receiverFrame->x1 = senderContext->x1; // Data
|
||||
receiverFrame->x0 = sender->process->id; // Sender ID
|
||||
|
||||
receiver->senderWaiting = nullptr;
|
||||
sender->state = OSTaskStateRunning;
|
||||
return;
|
||||
}
|
||||
|
||||
SchedulerBlockCurrentTask(OSTaskStateBlockedReceive);
|
||||
}
|
||||
@@ -7,7 +7,7 @@
|
||||
#include <Arch/CPU.h>
|
||||
#include "../Common/bootinfo.h"
|
||||
|
||||
void ModuleLoad(BootModule* module) {
|
||||
OSTask* ModuleLoad(BootModule* module) {
|
||||
OSProcess* userProc = HeapAllocate(sizeof(OSProcess));
|
||||
MemorySet(userProc, 0, sizeof(OSProcess));
|
||||
userProc->id = SchedulerGetNextProcessID();
|
||||
@@ -56,8 +56,8 @@ void ModuleLoad(BootModule* module) {
|
||||
|
||||
if ((Address)userEntryPoint == 0x0) {
|
||||
OSLog("Skipping module %s: entry point is 0x0.\n", module->name);
|
||||
return;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SchedulerSpawn(userEntryPoint, userProc, true, userStackVirt + kVMPageSize);
|
||||
return SchedulerSpawn(userEntryPoint, userProc, true, userStackVirt + kVMPageSize);
|
||||
}
|
||||
|
||||
@@ -69,6 +69,7 @@ OSTask* SchedulerSpawn(void(*entryPoint)(), OSProcess* owner, Boolean isUser, Ad
|
||||
task->waitingForProcessId = -1;
|
||||
|
||||
task->next = gOSSchedulerCurrentTask->next;
|
||||
task->senderWaiting = nullptr;
|
||||
gOSSchedulerCurrentTask->next = task;
|
||||
|
||||
return task;
|
||||
@@ -126,3 +127,30 @@ void SchedulerYield(UInt64 ticks) {
|
||||
UInt64 SchedulerGetNextProcessID() {
|
||||
return gOSSchedulerNextProcessID++;
|
||||
}
|
||||
|
||||
void SchedulerBlockCurrentTask(UInt32 newState) {
|
||||
gOSSchedulerCurrentTask->state = newState;
|
||||
CPUException(kOSSchedulerExceptionNumber);
|
||||
}
|
||||
|
||||
OSTask* SchedulerGetCurrentTask() {
|
||||
return gOSSchedulerCurrentTask;
|
||||
}
|
||||
|
||||
Int32 SchedulerProcessAllocateHandle(OSProcess* process, OSHandleType type, Pointer object) {
|
||||
for (Int32 i = 1; i < kOSMaxHandlesPerProcess; i++) {
|
||||
if (process->handles[i].type == kOSHandleTypeNone) {
|
||||
process->handles[i].type = type;
|
||||
process->handles[i].object = object;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
Pointer SchedulerProcessGetHandle(OSProcess* process, UInt32 handleId, OSHandleType expectedType) {
|
||||
if (handleId == 0 || handleId >= kOSMaxHandlesPerProcess) return nullptr;
|
||||
OSHandle* handle = &process->handles[handleId];
|
||||
if (handle->type != expectedType) return nullptr;
|
||||
return handle->object;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
#include <OS/Syscall.h>
|
||||
#include <OS/IPC.h>
|
||||
#include <OS/Scheduler.h>
|
||||
#include <OS/Panic.h>
|
||||
#include <Arch/Exceptions.h>
|
||||
|
||||
Address SyscallDispatch(ExceptionsContext* frame) {
|
||||
UInt64 syscallNumber = frame->x8;
|
||||
OSTask* current = SchedulerGetCurrentTask();
|
||||
|
||||
switch (syscallNumber) {
|
||||
case kSyscallSend:
|
||||
frame->x0 = IPCSend(current, frame->x0, frame->x1);
|
||||
break;
|
||||
case kSyscallReceive:
|
||||
IPCReceive(frame);
|
||||
break;
|
||||
default:
|
||||
frame->x0 = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (current->state != OSTaskStateRunning) return SchedulerNext((Address)frame);
|
||||
return (Address)frame;
|
||||
}
|
||||
Reference in New Issue
Block a user