Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions Kernel/Core/stdint.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#define VOIDFRAME_STDINT_H

#define NULL ((void*)0)
#define INT32_MAX ((int32_t)0x7FFFFFFF)
#define INT32_MIN ((int32_t)0x80000000)

typedef unsigned char uint8_t;
_Static_assert(sizeof(uint8_t) == 1, "sizeof(uint8_t) != 1");
Expand All @@ -19,4 +21,16 @@ _Static_assert(sizeof(uint32_t) == 4, "sizeof(uint32_t) != 4");
typedef unsigned long long uint64_t;
_Static_assert(sizeof(uint64_t) == 8, "sizeof(uint64_t) != 8");

typedef unsigned char int8_t;
_Static_assert(sizeof(int8_t) == 1, "sizeof(int8_t) != 1");

typedef unsigned short int16_t;
_Static_assert(sizeof(int16_t) == 2, "sizeof(int16_t) != 2");

typedef unsigned int int32_t;
_Static_assert(sizeof(int32_t) == 4, "sizeof(int32_t) != 4");

typedef unsigned long long int64_t;
_Static_assert(sizeof(int64_t) == 8, "sizeof(int64_t) != 8");
Comment on lines +24 to +34
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Critical: Signed integer types are incorrectly defined as unsigned types

All signed integer typedefs are incorrectly using unsigned base types. This will cause serious issues with negative values, arithmetic operations, and comparisons throughout the kernel.

Apply this diff to fix the type definitions:

-typedef unsigned char int8_t;
+typedef signed char int8_t;
 _Static_assert(sizeof(int8_t) == 1, "sizeof(int8_t) != 1");

-typedef unsigned short int16_t;
+typedef short int16_t;
 _Static_assert(sizeof(int16_t) == 2, "sizeof(int16_t) != 2");

-typedef unsigned int int32_t;
+typedef int int32_t;
 _Static_assert(sizeof(int32_t) == 4, "sizeof(int32_t) != 4");

-typedef unsigned long long int64_t;
+typedef long long int64_t;
 _Static_assert(sizeof(int64_t) == 8, "sizeof(int64_t) != 8");
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
typedef unsigned char int8_t;
_Static_assert(sizeof(int8_t) == 1, "sizeof(int8_t) != 1");
typedef unsigned short int16_t;
_Static_assert(sizeof(int16_t) == 2, "sizeof(int16_t) != 2");
typedef unsigned int int32_t;
_Static_assert(sizeof(int32_t) == 4, "sizeof(int32_t) != 4");
typedef unsigned long long int64_t;
_Static_assert(sizeof(int64_t) == 8, "sizeof(int64_t) != 8");
typedef signed char int8_t;
_Static_assert(sizeof(int8_t) == 1, "sizeof(int8_t) != 1");
typedef short int16_t;
_Static_assert(sizeof(int16_t) == 2, "sizeof(int16_t) != 2");
typedef int int32_t;
_Static_assert(sizeof(int32_t) == 4, "sizeof(int32_t) != 4");
typedef long long int64_t;
_Static_assert(sizeof(int64_t) == 8, "sizeof(int64_t) != 8");
🤖 Prompt for AI Agents
In Kernel/Core/stdint.h around lines 24 to 34, the signed integer typedefs
int8_t, int16_t, int32_t, and int64_t are incorrectly defined as unsigned types.
To fix this, change the base types from unsigned char, unsigned short, unsigned
int, and unsigned long long to signed char, signed short, signed int, and signed
long long respectively, ensuring the types correctly represent signed integers.


#endif
4 changes: 2 additions & 2 deletions Kernel/Drivers/Interrupts.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,9 @@ void InterruptHandler(struct Registers* regs) {
ASSERT(regs != NULL);
if (regs->interrupt_number == 32) {
tick_count++;
// FastDisplayTicks(tick_count); // Re-enabled
// FastDisplayTicks(tick_count);
ScheduleFromInterrupt(regs); // Re-enabledc
outb(0x20, 0x20);
ScheduleFromInterrupt(regs); // Re-enabled
return;
}
if (regs->interrupt_number == 13) {
Expand Down
290 changes: 238 additions & 52 deletions Kernel/Process/Process.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,233 @@ extern void SwitchContext(ProcessContext * old, ProcessContext * new);
static uint32_t last_scheduled_slot = 0; // For round-robin optimization
static uint32_t active_process_bitmap = 0; // Bitmap for fast slot tracking (up to 32 processes)

static Scheduler MLFQscheduler;
// Fast slot allocation using bitmap
void DumpSchedulerState(void) {
PrintKernel("[SCHED] Current: ");
PrintKernelInt(MLFQscheduler.current_running);
PrintKernel(" Quantum: ");
PrintKernelInt(MLFQscheduler.quantum_remaining);
PrintKernel(" Bitmap: ");
PrintKernelInt(MLFQscheduler.active_bitmap);
PrintKernel("\n");

for (int i = 0; i < MAX_PRIORITY_LEVELS; i++) {
if (MLFQscheduler.queues[i].count > 0) {
PrintKernel(" Priority ");
PrintKernelInt(i);
PrintKernel(": ");
PrintKernelInt(MLFQscheduler.queues[i].count);
PrintKernel(" processes, quantum: ");
PrintKernelInt(MLFQscheduler.queues[i].quantum);
PrintKernel("\n");
}
}
}

static inline void EnQueue(PriorityQueue* q, uint32_t slot) {
if (q->count >= MAX_PROCESSES) return;
q->process_slots[q->tail] = slot;
q->tail = (q->tail + 1) % MAX_PROCESSES;
q->count++;
}

static inline uint32_t DeQueue(PriorityQueue* q) {
if (q->count == 0) return MAX_PROCESSES;
uint32_t slot = q->process_slots[q->head];
q->head = (q->head + 1) % MAX_PROCESSES;
q->count--;
return slot;
}

static inline int QueueEmpty(PriorityQueue* q) {
return q->count == 0;
}

void InitScheduler(void) {
FastMemset(&MLFQscheduler, 0, sizeof(Scheduler));

// Initialize priority queues with different time quantums
for (int i = 0; i < MAX_PRIORITY_LEVELS; i++) {
MLFQscheduler.queues[i].quantum = QUANTUM_BASE * (1 << i); // 10, 20, 40, 80 ticks
MLFQscheduler.queues[i].head = 0;
MLFQscheduler.queues[i].tail = 0;
MLFQscheduler.queues[i].count = 0;
}

MLFQscheduler.current_running = 0; // Start with idle
MLFQscheduler.quantum_remaining = 0;
MLFQscheduler.active_bitmap = 0;
}

// Add process to scheduler
void AddToScheduler(uint32_t slot) {
if (slot == 0) return; // Don't schedule idle process

Process* proc = &processes[slot];
if (proc->state != PROC_READY) return;

// Determine initial priority based on privilege level
uint32_t priority = 0;
if (proc->privilege_level == PROC_PRIV_SYSTEM) {
priority = 0; // Highest priority for system processes
} else {
priority = 1; // Start user processes at level 1
}

// Clamp priority
if (priority >= MAX_PRIORITY_LEVELS) {
priority = MAX_PRIORITY_LEVELS - 1;
}

proc->priority = priority;
EnQueue(&MLFQscheduler.queues[priority], slot);
MLFQscheduler.active_bitmap |= (1U << priority);
}

// Remove process from scheduler
void RemoveFromScheduler(uint32_t slot) {
// This is expensive but rarely called
for (int level = 0; level < MAX_PRIORITY_LEVELS; level++) {
PriorityQueue* q = &MLFQscheduler.queues[level];
for (uint32_t i = 0; i < q->count; i++) {
uint32_t idx = (q->head + i) % MAX_PROCESSES;
if (q->process_slots[idx] == slot) {
// Remove by shifting
for (uint32_t j = i; j < q->count - 1; j++) {
uint32_t curr_idx = (q->head + j) % MAX_PROCESSES;
uint32_t next_idx = (q->head + j + 1) % MAX_PROCESSES;
q->process_slots[curr_idx] = q->process_slots[next_idx];
}
q->count--;
if (q->tail == 0) q->tail = MAX_PROCESSES - 1;
else q->tail--;

if (q->count == 0) {
MLFQscheduler.active_bitmap &= ~(1U << level);
}
return;
}
}
}
}
static inline int FindHighestPriorityQueue(void) {
if (MLFQscheduler.active_bitmap == 0) return -1;

// Find first set bit (lowest index = highest priority)
for (int i = 0; i < MAX_PRIORITY_LEVELS; i++) {
if (MLFQscheduler.active_bitmap & (1U << i)) {
return i;
}
}
return -1;
}

// Boost all processes to prevent starvation
static void BoostAllProcesses(void) {
// Move all processes to highest priority queue
for (int level = 1; level < MAX_PRIORITY_LEVELS; level++) {
PriorityQueue* src = &MLFQscheduler.queues[level];
PriorityQueue* dst = &MLFQscheduler.queues[0];

while (!QueueEmpty(src)) {
uint32_t slot = DeQueue(src);
processes[slot].priority = 0;
EnQueue(dst, slot);
}
MLFQscheduler.active_bitmap &= ~(1U << level);
}

if (MLFQscheduler.queues[0].count > 0) {
MLFQscheduler.active_bitmap |= 1U;
}
}

// Main scheduler - called from timer interrupt
void FastSchedule(struct Registers* regs) {
MLFQscheduler.tick_counter++;

// Boost all processes periodically to prevent starvation
if (MLFQscheduler.tick_counter - MLFQscheduler.last_boost_tick >= BOOST_INTERVAL) {
BoostAllProcesses();
MLFQscheduler.last_boost_tick = MLFQscheduler.tick_counter;
}

Process* current = &processes[MLFQscheduler.current_running];

// Handle current process
if (MLFQscheduler.current_running != 0) { // Not idle
// Save context
FastMemcpy(&current->context, regs, sizeof(struct Registers));

// Update process state
if (current->state == PROC_RUNNING) {
current->state = PROC_READY;

// Check if quantum expired
if (MLFQscheduler.quantum_remaining > 0) {
MLFQscheduler.quantum_remaining--;

// If quantum not expired and no higher priority processes, keep running
int highest_priority = FindHighestPriorityQueue();
if (MLFQscheduler.quantum_remaining > 0 &&
(highest_priority == -1 || highest_priority >= (int)current->priority)) {
current->state = PROC_RUNNING;
return; // Keep current process running
}
}

// Quantum expired or higher priority process available
// Demote to lower priority (unless already at lowest)
if (current->priority < MAX_PRIORITY_LEVELS - 1) {
current->priority++;
}

// Add back to appropriate queue
AddToScheduler(MLFQscheduler.current_running);
}
}

// Find next process to run
int next_priority = FindHighestPriorityQueue();
if (next_priority == -1) {
// No processes ready, run idle
MLFQscheduler.current_running = 0;
MLFQscheduler.quantum_remaining = 0;
} else {
// Get next process from highest priority queue
uint32_t next_slot = DeQueue(&MLFQscheduler.queues[next_priority]);
if (MLFQscheduler.queues[next_priority].count == 0) {
MLFQscheduler.active_bitmap &= ~(1U << next_priority);
}

MLFQscheduler.current_running = next_slot;
MLFQscheduler.quantum_remaining = MLFQscheduler.queues[next_priority].quantum;
}

// Switch to new process
processes[MLFQscheduler.current_running].state = PROC_RUNNING;
FastMemcpy(regs, &processes[MLFQscheduler.current_running].context, sizeof(struct Registers));
}

// Called when process blocks (I/O, IPC, etc.)
void ProcessBlocked(uint32_t slot) {
if (slot == MLFQscheduler.current_running) {
// Current process blocked, trigger immediate reschedule
MLFQscheduler.quantum_remaining = 0;
RequestSchedule();
}

// When process unblocks, it goes to higher priority (I/O bound processes get priority)
Process* proc = &processes[slot];
if (proc->state == PROC_READY && proc->priority > 0) {
proc->priority--; // Boost priority
}
}

// Simple interface for your existing code


static int FindFreeSlot(void) {
// Skip slot 0 (idle process)
for (int i = 1; i < MAX_PROCESSES && i < 32; i++) {
Expand Down Expand Up @@ -70,6 +296,10 @@ void RequestSchedule(void) {
}

void Yield() {
Process* current = GetCurrentProcess();
if (current) {
current->state = PROC_BLOCKED; // Mark as blocked for scheduler to boost
}
RequestSchedule();
__asm__ __volatile__("hlt");
}
Expand Down Expand Up @@ -98,21 +328,14 @@ static void init_token(SecurityToken* token, uint32_t creator_pid, uint8_t privi

void ProcessInit(void) {
FastMemset(processes, 0, sizeof(Process) * MAX_PROCESSES);
active_process_bitmap = 0;
last_scheduled_slot = 0;

// Create idle process (PID 0)
// Initialize idle process
processes[0].pid = 0;
processes[0].state = PROC_RUNNING;
processes[0].priority = 255;
processes[0].privilege_level = PROC_PRIV_SYSTEM;
processes[0].is_user_mode = 0;

// Don't set bit 0 in bitmap - idle process is special
init_token(&processes[0].token, 0, PROC_PRIV_SYSTEM, 0);

InitScheduler(); // Initialize new scheduler
process_count = 1;
current_process = 0;
}
Comment on lines 329 to 339
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Initialize current_process variable

The current_process variable is not initialized but is still used by GetCurrentProcess(). This could lead to undefined behavior.

 void ProcessInit(void) {
     FastMemset(processes, 0, sizeof(Process) * MAX_PROCESSES);
 
     // Initialize idle process
     processes[0].pid = 0;
     processes[0].state = PROC_RUNNING;
     processes[0].privilege_level = PROC_PRIV_SYSTEM;
+    current_process = 0;  // Start with idle process
 
     InitScheduler();  // Initialize new scheduler
     process_count = 1;
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
void ProcessInit(void) {
FastMemset(processes, 0, sizeof(Process) * MAX_PROCESSES);
active_process_bitmap = 0;
last_scheduled_slot = 0;
// Create idle process (PID 0)
// Initialize idle process
processes[0].pid = 0;
processes[0].state = PROC_RUNNING;
processes[0].priority = 255;
processes[0].privilege_level = PROC_PRIV_SYSTEM;
processes[0].is_user_mode = 0;
// Don't set bit 0 in bitmap - idle process is special
init_token(&processes[0].token, 0, PROC_PRIV_SYSTEM, 0);
InitScheduler(); // Initialize new scheduler
process_count = 1;
current_process = 0;
}
void ProcessInit(void) {
FastMemset(processes, 0, sizeof(Process) * MAX_PROCESSES);
// Initialize idle process
processes[0].pid = 0;
processes[0].state = PROC_RUNNING;
processes[0].privilege_level = PROC_PRIV_SYSTEM;
current_process = 0; // Start with idle process
InitScheduler(); // Initialize new scheduler
process_count = 1;
}
🤖 Prompt for AI Agents
In Kernel/Process/Process.c around lines 329 to 339, the current_process
variable is not initialized in ProcessInit(), which can cause undefined behavior
when accessed by GetCurrentProcess(). Initialize current_process to point to the
idle process (processes[0]) after setting up the idle process and before calling
InitScheduler().


uint32_t CreateProcess(void (*entry_point)(void)) {
Expand Down Expand Up @@ -175,6 +398,9 @@ uint32_t CreateSecureProcess(void (*entry_point)(void), uint8_t privilege) {
processes[slot].privilege_level = privilege;
processes[slot].priority = (privilege == PROC_PRIV_SYSTEM) ? 10 : 100;
processes[slot].is_user_mode = (privilege != PROC_PRIV_SYSTEM);
processes[slot].weight = (privilege == PROC_PRIV_SYSTEM) ? 100 : 50;
processes[slot].cpu_time_accumulated = 0;
processes[slot].dynamic_priority_score = 0;
Comment on lines 399 to +403
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix incorrect priority initialization

The priority values (10 for system, 100 for user) exceed the valid range (0-3 for MLFQ). Also, the legacy scheduling fields are initialized but unused.

     processes[slot].stack = stack;
     processes[slot].privilege_level = privilege;
-    processes[slot].priority = (privilege == PROC_PRIV_SYSTEM) ? 10 : 100;
+    processes[slot].priority = (privilege == PROC_PRIV_SYSTEM) ? 0 : 1;
     processes[slot].is_user_mode = (privilege != PROC_PRIV_SYSTEM);
-    processes[slot].weight = (privilege == PROC_PRIV_SYSTEM) ? 100 : 50;
-    processes[slot].cpu_time_accumulated = 0;
-    processes[slot].dynamic_priority_score = 0;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
processes[slot].priority = (privilege == PROC_PRIV_SYSTEM) ? 10 : 100;
processes[slot].is_user_mode = (privilege != PROC_PRIV_SYSTEM);
processes[slot].weight = (privilege == PROC_PRIV_SYSTEM) ? 100 : 50;
processes[slot].cpu_time_accumulated = 0;
processes[slot].dynamic_priority_score = 0;
processes[slot].stack = stack;
processes[slot].privilege_level = privilege;
processes[slot].priority = (privilege == PROC_PRIV_SYSTEM) ? 0 : 1;
processes[slot].is_user_mode = (privilege != PROC_PRIV_SYSTEM);
🤖 Prompt for AI Agents
In Kernel/Process/Process.c around lines 399 to 403, the priority values
assigned (10 for system, 100 for user) exceed the valid MLFQ range of 0 to 3,
and legacy scheduling fields like weight, cpu_time_accumulated, and
dynamic_priority_score are initialized but unused. Fix this by setting priority
to valid values within 0-3, for example 0 for system and 3 for user, and remove
or comment out the initialization of the unused legacy scheduling fields to
clean up the code.


// Initialize IPC queue
processes[slot].ipc_queue.head = 0;
Expand All @@ -198,52 +424,12 @@ uint32_t CreateSecureProcess(void (*entry_point)(void), uint8_t privilege) {
processes[slot].context.ss = 0x10;

process_count++;
AddToScheduler(slot);
return new_pid;
}

void ScheduleFromInterrupt(struct Registers* regs) {
ASSERT(regs != NULL);
if (process_count <= 1) return;

// Save current context
FastMemcpy(&processes[current_process].context, regs, sizeof(struct Registers));
if (processes[current_process].state == PROC_RUNNING) {
processes[current_process].state = PROC_READY;
}

// Fast round-robin using bitmap
uint32_t next_slot = current_process;
uint32_t start_slot = (last_scheduled_slot + 1) % MAX_PROCESSES;

// Look for next ready process starting from where we left off
for (uint32_t i = 0; i < MAX_PROCESSES; i++) {
uint32_t candidate = (start_slot + i) % MAX_PROCESSES;

// Skip slot 0 unless it's our only option
if (candidate == 0 && process_count > 1) continue;

// Check if slot is active and process is ready
if (candidate < 32 && (active_process_bitmap & (1U << candidate))) {
if (processes[candidate].state == PROC_READY && processes[candidate].pid != 0) {
next_slot = candidate;
last_scheduled_slot = candidate;
break;
}
}
}

// Fallback to current process if it's still ready
if (next_slot == current_process && processes[current_process].state != PROC_READY) {
next_slot = 0; // Idle process
last_scheduled_slot = 0;
}

// Switch process
current_process = next_slot;
processes[current_process].state = PROC_RUNNING;

// Restore context
FastMemcpy(regs, &processes[current_process].context, sizeof(struct Registers));
FastSchedule(regs);
}


Expand Down Expand Up @@ -286,8 +472,8 @@ void SystemService(void) {
}
}
void SecureKernelIntegritySubsystem(void) {
PrintKernel("[SYSTEM] MLFQ scheduler initializing...\n");
PrintKernel("[SYSTEM] SecureKernelIntegritySubsystem() initializing...\n");

Process* current = GetCurrentProcess();
RegisterSecurityManager(current->pid);

Expand Down
Loading