feat(core): implement spinlocks, GC and keyboard safety

* Implemented Spinlocks and applied to VM/Scheduler

* Added Garbage Collector for tasks

* Moved Getchar to IOKeyboard with locking

* Cleanup panic messages
This commit is contained in:
Karina
2026-01-31 20:50:27 +04:00
parent ee67cef4f8
commit 02dc35f0df
15 changed files with 251 additions and 51 deletions
-1
View File
@@ -29,7 +29,6 @@ IOGraphicsSize IOConsoleGetDimensions();
void IOConsoleSetForegroundColor(IOGraphicsColor color);
void IOConsoleSetDefaultForegroundColor(UInt32 color);
void IOConsoleSetCursorPosition(IOGraphicsPoint* point);
char IOConsoleGetCharacter();
void IOConsoleReadLine(char* buffer, UInt32 limit);
void IOConsolePutcharacter(char character);
void IOConsolePrint(const char *string);
+7 -4
View File
@@ -3,17 +3,20 @@
#pragma once
#include <types.h>
#include <OS/OSSpinlock.h>
enum {
kIOKeyboardBufferSize = 256,
};
typedef struct {
OSSpinlock lock;
char buffer[kIOKeyboardBufferSize];
UInt16 head;
UInt16 tail;
} IOKeyboardBuffer;
volatile UInt16 head;
volatile UInt16 tail;
} IOKeyboardController;
extern IOKeyboardBuffer gIOKeyboardInputBuffer;
extern IOKeyboardController gIOKeyboardController;
void IOKeyboardInterruptsHandler();
char IOKeyboardGetCharacter();
+1
View File
@@ -29,6 +29,7 @@ typedef struct OSTask {
UInt32 sleepTicks;
OSProcessState taskState; // reusing process_state cuz wn
UInt64 kernelStackTop;
void* kernelStackBase;
OSProcess* process;
Int32 waitingForProcess;
} OSTask;
+19
View File
@@ -0,0 +1,19 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#pragma once
#include <types.h>
typedef struct OSSpinlock {
volatile UInt32 lockValue;
} OSSpinlock;
typedef struct OSSpinlockState {
Boolean interruptsEnabled;
} OSSpinlockState;
void OSSpinlockLock(OSSpinlock* lock);
void OSSpinlockUnlock(OSSpinlock* lock);
void OSSpinlockLockIRQ(OSSpinlock* lock, OSSpinlockState* state);
void OSSpinlockUnlockIRQ(OSSpinlock *lock, OSSpinlockState* state);
+1 -10
View File
@@ -238,19 +238,10 @@ void IOConsoleSetDefaultForegroundColor(UInt32 color) {
sIOConsoleDefaultForegroundColor = color;
}
char IOConsoleGetCharacter() {
while (gIOKeyboardInputBuffer.head == gIOKeyboardInputBuffer.tail) { __asm__ volatile ("sti"); OSSchedulerYield(1); }
__asm__ volatile ("cli");
char temp = gIOKeyboardInputBuffer.buffer[gIOKeyboardInputBuffer.tail];
gIOKeyboardInputBuffer.tail = (gIOKeyboardInputBuffer.tail + 1) % kIOKeyboardBufferSize;
__asm__ volatile ("sti");
return temp;
}
void IOConsoleReadLine(char* buffer, UInt32 limit) {
UInt32 i = 0;
while (true) {
char character = IOConsoleGetCharacter();
char character = IOKeyboardGetCharacter();
switch (character) {
case '\n': {
buffer[i] = '\0';
+31 -5
View File
@@ -3,6 +3,8 @@
#include <IO/IOKeyboard.h>
#include <IO/IOConsole.h>
#include <OS/OSSpinlock.h>
#include <OS/OSScheduler.h>
#include <IO.h>
#include <types.h>
@@ -87,19 +89,20 @@ static unsigned char sIOKeyboardMapShifted[128] = {
static Boolean sIOKeyboardIsShiftPressed = false;
IOKeyboardBuffer gIOKeyboardInputBuffer = {0};
IOKeyboardController gIOKeyboardController = {0};
void IOKeyboardInterruptsHandler() {
UInt16 nextHead = (gIOKeyboardInputBuffer.head + 1) % kIOKeyboardBufferSize;
OSSpinlockLock(&gIOKeyboardController.lock);
UInt16 nextHead = (gIOKeyboardController.head + 1) % kIOKeyboardBufferSize;
UInt8 scancode = IOPortRead8(0x60);
// make code 0x00 - 0x7F; break code = make code + 0x80
if (scancode < 0x80) {
unsigned char* keyMap = sIOKeyboardIsShiftPressed ? sIOKeyboardMapShifted : sIOKeyboardMap;
char ascii = keyMap[scancode];
if (ascii && nextHead != gIOKeyboardInputBuffer.tail) {
gIOKeyboardInputBuffer.buffer[gIOKeyboardInputBuffer.head] = ascii;
gIOKeyboardInputBuffer.head = nextHead;
if (ascii && nextHead != gIOKeyboardController.tail) {
gIOKeyboardController.buffer[gIOKeyboardController.head] = ascii;
gIOKeyboardController.head = nextHead;
} else {
switch (scancode) {
case 0x2A: sIOKeyboardIsShiftPressed = true; break;
@@ -112,4 +115,27 @@ void IOKeyboardInterruptsHandler() {
default: break;
}
}
OSSpinlockUnlock(&gIOKeyboardController.lock);
}
char IOKeyboardGetCharacter() {
char ascii = 0;
OSSpinlockState state;
while (true) {
OSSpinlockLockIRQ(&gIOKeyboardController.lock, &state);
if (gIOKeyboardController.head != gIOKeyboardController.tail) {
ascii = gIOKeyboardController.buffer[gIOKeyboardController.tail];
gIOKeyboardController.tail = (gIOKeyboardController.tail + 1) % kIOKeyboardBufferSize;
OSSpinlockUnlockIRQ(&gIOKeyboardController.lock, &state);
return ascii;
}
OSSpinlockUnlockIRQ(&gIOKeyboardController.lock, &state);
__asm__ volatile ("sti");
OSSchedulerYield(1);
}
}
-2
View File
@@ -35,8 +35,6 @@ static const char* sOSPanicFunMessages[] = {
"I'll be back",
"Hastla la vista, baby",
"Ti chego mne tut nagovoril...",
"Your access has been denied because of your region.\n\t\t\t\tPlease, use Chultem VPN and try again later.",
"Fatal error has been occurred. \n\t\t\t\tYour device will be transformed into Niva in a few seconds.",
"Have you tried turning it off and on again?",
"Put it in rice maybe?",
"Just hit the monitor, it usually helps",
+63 -6
View File
@@ -1,8 +1,9 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include <OS/OSPanic.h>
#include <OS/OSScheduler.h>
#include <OS/OSSpinlock.h>
#include <OS/OSPanic.h>
#include <lib/String.h>
#include <VM/Heap.h>
#include <VM/VMM.h>
@@ -16,6 +17,7 @@ extern void irq0_handler();
extern UInt64 gVMKernelPML4Physical;
static OSProcess sOSSchedulerKernelProcess;
static OSSpinlock sOSSchedulerLock;
void idle_task() {
while (1) {
@@ -23,6 +25,39 @@ void idle_task() {
}
}
void OSSchedulerGarbadgeCollector() {
OSTask* self = gOSSchedulerCurrentTask;
while (true) {
OSTask* previousTask = self;
OSTask* nextTask = previousTask->next;
while (nextTask != self) {
if (nextTask->taskState == kOSProcessStateDead) {
OSSpinlockState lockState;
OSSpinlockLockIRQ(&sOSSchedulerLock, &lockState);
previousTask->next = nextTask->next;
OSSpinlockUnlockIRQ(&sOSSchedulerLock, &lockState);
if (nextTask->kernelStackBase) {
VMHeapFree(nextTask->kernelStackBase);
}
VMHeapFree(nextTask);
nextTask = previousTask->next;
} else {
previousTask = nextTask;
nextTask = nextTask->next;
}
}
OSSchedulerYield(200);
}
}
void OSSchedulerInitialize() {
sOSSchedulerKernelProcess.processId = 0;
sOSSchedulerKernelProcess.state = kOSProcessStateRunning;
@@ -30,7 +65,10 @@ void OSSchedulerInitialize() {
strcpy(sOSSchedulerKernelProcess.name, "kernel");
OSTask* kernelTask = (OSTask*)VMHeapAllocate(sizeof(OSTask));
if (!kernelTask) OSPanic("Failed to initialize scheduler: OOm");
memset(kernelTask, 0, sizeof(OSTask));
kernelTask->id = 0;
kernelTask->process = &sOSSchedulerKernelProcess;
kernelTask->sleepTicks = 0;
@@ -40,6 +78,8 @@ void OSSchedulerInitialize() {
gOSSchedulerCurrentTask = kernelTask;
OSSchedulerSpawn(idle_task, &sOSSchedulerKernelProcess, false, 0);
OSSchedulerSpawn(OSSchedulerGarbadgeCollector, &sOSSchedulerKernelProcess, false, 0);
return;
}
OSTask* OSSchedulerSpawn(void(*entry)(), OSProcess* owner, Boolean isUser, UInt64 fixedUserStackPointer) {
@@ -74,17 +114,27 @@ OSTask* OSSchedulerSpawn(void(*entry)(), OSProcess* owner, Boolean isUser, UInt6
task->process = owner;
task->id = owner->processId;
task->sleepTicks = 0;
task->next = gOSSchedulerCurrentTask->next;
task->kernelStackTop = (UInt64)stackBaseAddress + stackSize;
task->kernelStackBase = stackBaseAddress;
task->taskState = kOSProcessStateRunning;
task->waitingForProcess = -1;
OSSpinlockState state;
OSSpinlockLockIRQ(&sOSSchedulerLock, &state);
task->next = gOSSchedulerCurrentTask->next;
gOSSchedulerCurrentTask->next = task;
OSSpinlockUnlockIRQ(&sOSSchedulerLock, &state);
return task;
}
UInt64 OSSchedulerNext(UInt64 currentStackPointer) {
if (!gOSSchedulerCurrentTask) return currentStackPointer;
OSSpinlockLock(&sOSSchedulerLock);
gOSSchedulerCurrentTask->stackPointer = currentStackPointer;
OSTask* taskIterator = gOSSchedulerCurrentTask->next;
@@ -95,12 +145,12 @@ UInt64 OSSchedulerNext(UInt64 currentStackPointer) {
if (gOSSchedulerCurrentTask->sleepTicks > 0) gOSSchedulerCurrentTask->sleepTicks--;
OSTask* nextTask = gOSSchedulerCurrentTask;
OSTask* nextTask = gOSSchedulerCurrentTask->next;
while (1) {
// TODO: add gc here;
nextTask = nextTask->next;
if (nextTask->taskState == kOSProcessStateSleeping && nextTask->sleepTicks == 0) nextTask->taskState = kOSProcessStateRunning;
if (nextTask->taskState == kOSProcessStateRunning) break;
nextTask = nextTask->next;
if (nextTask == gOSSchedulerCurrentTask) {
if (gOSSchedulerCurrentTask->taskState == kOSProcessStateRunning) break;
OSPanic("no running tasks");
@@ -111,6 +161,8 @@ UInt64 OSSchedulerNext(UInt64 currentStackPointer) {
gOSSchedulerCurrentTask = nextTask;
gHALTaskStateSegment.rsp0 = gOSSchedulerCurrentTask->kernelStackTop;
gOSBootCPU.kernelStackPointer = gOSSchedulerCurrentTask->kernelStackTop;
OSSpinlockUnlock(&sOSSchedulerLock);
return gOSSchedulerCurrentTask->stackPointer;
}
@@ -121,6 +173,9 @@ void OSSchedulerBlock(UInt32 processID) {
}
void OSSchedulerWakeup(UInt32 processID) {
OSSpinlockState state;
OSSpinlockLockIRQ(&sOSSchedulerLock, &state);
OSTask* iteratorTask = gOSSchedulerCurrentTask;
do {
if (iteratorTask->taskState == kOSProcessStateBlocked && iteratorTask->waitingForProcess == (Int32)processID) {
@@ -129,6 +184,8 @@ void OSSchedulerWakeup(UInt32 processID) {
}
iteratorTask = iteratorTask->next;
} while (iteratorTask != gOSSchedulerCurrentTask);
OSSpinlockUnlockIRQ(&sOSSchedulerLock, &state);
}
void OSSchedulerTerminate() {
@@ -143,4 +200,4 @@ void OSSchedulerYield(UInt64 ticks) {
gOSSchedulerCurrentTask->sleepTicks = ticks;
gOSSchedulerCurrentTask->taskState = kOSProcessStateSleeping;
__asm__ volatile("hlt");
}
}
+29
View File
@@ -0,0 +1,29 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (c) 2026 0xKarinyash
#include <OS/OSSpinlock.h>
void OSSpinlockLock(OSSpinlock* lock) {
while (__atomic_exchange_n(&lock->lockValue, 1, __ATOMIC_ACQUIRE)) {
while (lock->lockValue) {
__builtin_ia32_pause();
}
}
}
void OSSpinlockUnlock(OSSpinlock *lock) {
__atomic_store_n(&lock->lockValue, 0, __ATOMIC_RELEASE);
}
void OSSpinlockLockIRQ(OSSpinlock *lock, OSSpinlockState *state) {
UInt64 rflags;
__asm__ volatile("pushfq; pop %0; cli" : "=r"(rflags) :: "memory"); // read flags and cli
state->interruptsEnabled = (rflags & (1 << 9)) != 0; // IF bit
OSSpinlockLock(lock);
}
void OSSpinlockUnlockIRQ(OSSpinlock *lock, OSSpinlockState *state) {
OSSpinlockUnlock(lock);
if (state->interruptsEnabled) __asm__ volatile("sti" ::: "memory");
}
+2 -1
View File
@@ -3,6 +3,7 @@
#include <OS/Services/OSServiceIO.h>
#include <IO/IOConsole.h>
#include <IO/IOKeyboard.h>
UInt64 OSServiceWrite(UInt64 fileDescriptor, UInt64 buffer, UInt64 length) {
if (fileDescriptor == 1 || fileDescriptor == 2) {
@@ -19,7 +20,7 @@ UInt64 OSServiceRead(UInt64 fileDescriptor, UInt64 buffer, UInt64 count) {
char* readBuffer = (char*)buffer;
if (fileDescriptor == 0) {
for (UInt64 i = 0; i < count; i++) {
readBuffer[i] = IOConsoleGetCharacter();
readBuffer[i] = IOKeyboardGetCharacter();
}
return count;
}
+39 -11
View File
@@ -6,10 +6,12 @@
#include <VM/VMM.h>
#include <lib/String.h>
#include <OS/OSPanic.h>
#include <OS/OSSpinlock.h>
#include <types.h>
extern UInt64* gVMKernelPML4;
static VMHeapBlockHeader* sVMHeapListHead = nullptr;
static OSSpinlock sVMHeapLock = {0};
static void sVMHeapCombineForward(VMHeapBlockHeader* current) {
if (!current->next || !current->next->isFree) return;
@@ -37,7 +39,7 @@ void VMHeapInitialize() {
sVMHeapListHead->previous = nullptr;
}
void* VMHeapAllocate(UInt64 size) {
static void* sVMHeapAllocateInternal(UInt64 size) {
if (size == 0) return nullptr;
UInt64 alignedSize = (size + 15) & ~15;
@@ -65,7 +67,7 @@ void* VMHeapAllocate(UInt64 size) {
return nullptr;
}
void VMHeapFree(void* pointer) {
static void sVMHeapFreeInternal(void* pointer) {
if (!pointer) return;
VMHeapBlockHeader* current = (VMHeapBlockHeader*)((UInt64)pointer - sizeof(VMHeapBlockHeader));
@@ -76,6 +78,25 @@ void VMHeapFree(void* pointer) {
if (current->previous && current->previous->isFree) sVMHeapCombineForward(current->previous);
}
void* VMHeapAllocate(UInt64 size) {
OSSpinlockState state;
OSSpinlockLockIRQ(&sVMHeapLock, &state);
void* result = sVMHeapAllocateInternal(size);
OSSpinlockUnlockIRQ(&sVMHeapLock, &state);
return result;
}
void VMHeapFree(void* pointer) {
OSSpinlockState state;
OSSpinlockLockIRQ(&sVMHeapLock, &state);
sVMHeapFreeInternal(pointer);
OSSpinlockUnlockIRQ(&sVMHeapLock, &state);
}
void* VMHeapResize(void* pointer, UInt64 newSize) {
if (!pointer) return VMHeapAllocate(newSize);
if (newSize == 0) {
@@ -83,21 +104,28 @@ void* VMHeapResize(void* pointer, UInt64 newSize) {
return nullptr;
}
VMHeapBlockHeader* current = (VMHeapBlockHeader*)((UInt64)pointer - sizeof(VMHeapBlockHeader));
if (current->size >= newSize) return pointer;
OSSpinlockState state;
OSSpinlockLockIRQ(&sVMHeapLock, &state);
if (current->next &&
current->next->isFree &&
VMHeapBlockHeader* current = (VMHeapBlockHeader*)((UInt64)pointer - sizeof(VMHeapBlockHeader));
if (current->size >= newSize) {
OSSpinlockUnlockIRQ(&sVMHeapLock, &state);
return pointer;
}
if (current->next && current->next->isFree &&
(current->size + sizeof(VMHeapBlockHeader) + current->next->size) >= newSize) { // why ts so fucking unreadable
sVMHeapCombineForward(current);
OSSpinlockUnlockIRQ(&sVMHeapLock, &state);
return pointer;
}
void* newPointer = VMHeapAllocate(newSize);
if (!newPointer) return nullptr;
memcpy(newPointer, pointer, current->size);
VMHeapFree(pointer);
void* newPointer = sVMHeapAllocateInternal(newSize);
if (newPointer) {
memcpy(newPointer, pointer, current->size);
sVMHeapFreeInternal(pointer);
}
OSSpinlockUnlockIRQ(&sVMHeapLock, &state);
return newPointer;
}
+17 -1
View File
@@ -6,7 +6,9 @@
#include <lib/String.h>
#include <lib/Math.h>
#include <OS/OSPanic.h>
#include <OS/OSPanic.h>
#include <OS/OSSpinlock.h>
#include <types.h>
#include "bootinfo.h"
@@ -16,6 +18,8 @@ UInt8* gVMPhycalMemoryBitmap = nullptr;
UInt64 gVMPhycalMemoryBitmapSize = 0;
UInt64 gVMPhycalMemoryTotalMemorySize = 0;
static OSSpinlock sVMPMMLock = {0};
extern UInt64 _kernel_start;
extern UInt64 _kernel_end;
@@ -96,6 +100,9 @@ void VMPhysicalMemoryInitialize(BIMemoryMap *memoryMap) {
}
void* VMPhysicalMemoryAllocatePage() {
OSSpinlockState state;
OSSpinlockLockIRQ(&sVMPMMLock, &state);
for (UInt64 i = 0; i < gVMPhycalMemoryBitmapSize; i++) {
if (gVMPhycalMemoryBitmap[i] == 0xFF) continue;
@@ -103,13 +110,22 @@ void* VMPhysicalMemoryAllocatePage() {
if ((gVMPhycalMemoryBitmap[i] & (1 << bit)) == 0) {
UInt64 address = (i * 8 + bit) * kVMPageSize;
BITMAP_SET(gVMPhycalMemoryBitmap, address);
OSSpinlockUnlockIRQ(&sVMPMMLock, &state);
return (void*)address;
}
}
}
OSSpinlockUnlockIRQ(&sVMPMMLock, &state);
return nullptr; // Out of memory
}
void VMPhysicalMemoryFreePage(void* address) {
OSSpinlockState state;
OSSpinlockLockIRQ(&sVMPMMLock, &state);
BITMAP_UNSET(gVMPhycalMemoryBitmap, (UInt64)address);
OSSpinlockUnlockIRQ(&sVMPMMLock, &state);
}
+33 -3
View File
@@ -4,6 +4,7 @@
#include <VM/PMM.h>
#include <OS/OSPanic.h>
#include <OS/OSSpinlock.h>
#include <GDT.h>
#include <IDT.h>
@@ -20,6 +21,7 @@ enum {
UInt64* gVMKernelPML4 = nullptr;
UInt64 gVMKernelPML4Physical = 0;
static OSSpinlock sVMVMMlock = {0};
static bool isInitialized = false;
extern UInt64 _kernel_start;
@@ -36,7 +38,7 @@ static UInt64* sVMGetVirtualTable(UInt64 phys) {
return (UInt64*)phys;
}
UInt64* VMVirtualMemoryMapPage(UInt64* pml4, UInt64 phys, UInt64 virt, UInt64 flags) {
static UInt64* sVMVirtualMemoryMapPageInternal(UInt64* pml4, UInt64 phys, UInt64 virt, UInt64 flags) {
UInt64 pt_idx = VMM_PT_INDEX(virt);
UInt64 pd_idx = VMM_PD_INDEX(virt);
UInt64 pdpt_idx = VMM_PDPT_INDEX(virt);
@@ -92,7 +94,7 @@ UInt64* VMVirtualMemoryMapPage(UInt64* pml4, UInt64 phys, UInt64 virt, UInt64 fl
return (UInt64*)virt;
}
void VMVirtualMemoryUnmapPage(UInt64* pml4, UInt64 virt) {
static void sVMVirtualMemoryUnmapPageInternal(UInt64* pml4, UInt64 virt) {
UInt64 pt_idx = VMM_PT_INDEX(virt);
UInt64 pd_idx = VMM_PD_INDEX(virt);
UInt64 pdpt_idx = VMM_PDPT_INDEX(virt);
@@ -115,6 +117,27 @@ void VMVirtualMemoryUnmapPage(UInt64* pml4, UInt64 virt) {
__asm__ volatile("invlpg (%0)" :: "r" (virt) : "memory");
}
UInt64* VMVirtualMemoryMapPage(UInt64* pml4, UInt64 phys, UInt64 virt, UInt64 flags) {
OSSpinlockState state;
OSSpinlockLockIRQ(&sVMVMMlock, &state);
UInt64* result = sVMVirtualMemoryMapPageInternal(pml4, phys, virt, flags);
OSSpinlockUnlockIRQ(&sVMVMMlock, &state);
return result;
}
void VMVirtualMemoryUnmapPage(UInt64* pml4, UInt64 virt) {
OSSpinlockState state;
OSSpinlockLockIRQ(&sVMVMMlock, &state);
sVMVirtualMemoryUnmapPageInternal(pml4, virt);
OSSpinlockUnlockIRQ(&sVMVMMlock, &state);
}
void VMLoadCR3(UInt64 pml4_addr) {
__asm__ volatile ("mov %0, %%cr3" :: "r"(pml4_addr) : "memory");
}
@@ -144,8 +167,14 @@ void VMVirtualMemoryInitialize(Bootinfo* info) {
}
UInt64 VMVirtualMemoryCreateAddressSpace() {
OSSpinlockState state;
OSSpinlockLockIRQ(&sVMVMMlock, &state);
UInt64 phys = (UInt64)VMPhysicalMemoryAllocatePage();
if (!phys) return 0;
if (!phys) {
OSSpinlockUnlockIRQ(&sVMVMMlock, &state);
return 0;
};
UInt64* virt = (UInt64*)PHYS_TO_HHDM(phys);
memset(virt, 0, kVMPageSize);
@@ -156,6 +185,7 @@ UInt64 VMVirtualMemoryCreateAddressSpace() {
virt[i] = kernel_pml4_virt[i];
}
OSSpinlockUnlockIRQ(&sVMVMMlock, &state);
return phys;
}
+8 -7
View File
@@ -11,6 +11,7 @@
#include <IO/IOSerial.h>
#include <IO/IOConsole.h>
#include <IO/IOTimer.h>
#include <IO/IOKeyboard.h>
#include <OS/OSPanic.h>
#include <OS/OSScheduler.h>
@@ -93,20 +94,20 @@ void kmain(Bootinfo* info) {
SplashShow(&sIOGraphicsContext);
bool staying_in_ksh = false;
bool rescueMode = false;
if (!info->initramfs.address) {
IOConsoleLog("^rWARNING^!: Failed to load ^yinitramfs^!! Staying in kernel rescue shell!\n\n");
staying_in_ksh = true;
IOConsoleLog("^rWARNING^!: Failed to load ^yStartupVolume^!! Staying in kernel rescue shell!\n\n");
rescueMode = true;
}
if (!staying_in_ksh) {
if (!rescueMode) {
IOConsoleLog("Press any key to continue booting. \nPress ^yq^! to stay in ^gksh^!\n");
char c = '\n';
c = IOConsoleGetCharacter();
if (c == 'q') staying_in_ksh = true;
c = IOKeyboardGetCharacter();
if (c == 'q') rescueMode = true;
}
if (staying_in_ksh) OSSchedulerSpawn(ksh, nullptr, false, 0);
if (rescueMode) OSSchedulerSpawn(ksh, nullptr, false, 0);
else OSSchedulerSpawn(init_task_entry, nullptr, false, 0);
__asm__ volatile("sti");
+1
View File
@@ -69,6 +69,7 @@ void render_list(Vector* numbers) {
}
int main() {
UInt64* bad_ptr = (UInt64*)0xDEADBEEF; *bad_ptr = 666;
Vector nums;
vector_init(&nums);
printf("Heap test\n");