syscalls: fix nanosleep, thanks to gemini, sorry for that

This commit is contained in:
2025-09-03 16:35:07 +03:00
parent 5b922ea773
commit 63938e1acd
2 changed files with 55 additions and 27 deletions
+4 -3
View File
@@ -315,10 +315,11 @@ uint32_t sys_nanosleep(TrapFrame *tf)
//debug_log("waiting for 0x%X ms\n", ms); //debug_log("waiting for 0x%X ms\n", ms);
size_t start_time = timer_ticks; size_t start_time = timer_ticks;
scheduler_lock();
current->wake_up_time = timer_ticks + ms; current->wake_up_time = timer_ticks + ms;
//debug_log("setting wake up time to %X (current time is %X)\n", current->wake_up_time, timer_ticks); current->state = Waiting;
schedule();
//TODO: find a way to call the scheduler from here without fucking shit up scheduler_unlock();
return 0; return 0;
} }
+50 -23
View File
@@ -103,23 +103,33 @@ void scheduler_unlock()
void schedule() { void schedule() {
scheduler_lock(); scheduler_lock();
Process* prev = NULL; // Step 1: Iterate through all processes to wake up any that are due.
Process* p = queue; Process* p = queue;
while (p) {
if (p->state == Waiting && timer_ticks >= p->wake_up_time) {
p->state = Ready;
}
p = p->next;
}
// Step 2: Clean up any terminated processes.
Process* prev = NULL;
p = queue;
while (p) { while (p) {
if (p->state == Terminated) { if (p->state == Terminated) {
Process* next_proc = p->next; Process* next_proc = p->next;
// Unlink from the queue
if (prev) { if (prev) {
prev->next = next_proc; prev->next = next_proc;
} else { } else {
queue = next_proc; queue = next_proc;
} }
// If the terminated process is the current one, we must not switch to it. // If we are terminating the currently running process, we must find a new one.
if (p == current) { if (p == current) {
current = NULL; current = NULL;
} }
// Free the terminated process's resources.
destroy_page_dir(p->pagedir); destroy_page_dir(p->pagedir);
free_page((void*)virt_to_phys(p->kstack)); free_page((void*)virt_to_phys(p->kstack));
free_page((void*)virt_to_phys(p)); free_page((void*)virt_to_phys(p));
@@ -131,36 +141,53 @@ void schedule() {
} }
} }
// If 'current' was terminated or this is the first run, find a new process. // If there are no processes left, we have a problem.
if (!current || current->state != Ready) { if (!queue) {
current = queue; // Start search from the beginning scheduler_unlock();
// Ideally, you would panic the kernel here.
// For now, we just return and hope an interrupt happens.
return;
} }
if(current->wake_up_time > timer_ticks) // Step 3: Find the next process to run using a round-robin algorithm.
{ Process* start_search = NULL;
current = queue; if (current && current->state == Ready) {
// If the current process is still ready, start searching from the next one.
start_search = current->next;
} else {
// If the current process is not ready (e.g., it's Waiting or was Terminated),
// start the search from the beginning of the queue.
start_search = queue;
} }
// Find the next ready process to run // Ensure start_search is not NULL (handles wrapping around).
Process* next = current ? current->next : NULL; if (!start_search) {
if (!next) next = queue; start_search = queue;
}
// Iterate through the list to find a process that is ready to run // Find the first available 'Ready' process.
Process* start_node = next; Process* next = start_search;
while (next && next->state != Ready) { do {
next = next->next; if (next->state == Ready) {
if (!next) next = queue; // Wrap around // We found a process to run.
if (next == start_node) { // Full circle, no ready process // If it's not the same one we're already running, switch to it.
if (next != current) {
tss.esp0 = next->kstack_top;
switchProcess(next); // This will update 'current' and switch contexts.
}
// If next == current, we don't need to switch. Just continue execution.
scheduler_unlock(); scheduler_unlock();
return; return;
} }
next = next->next;
if (!next) {
next = queue; // Wrap around to the beginning of the list.
} }
} while (next != start_search);
if (next && next != current) { // If we get here, it means no process is in the 'Ready' state.
tss.esp0 = next->kstack_top; // This can happen if all tasks are waiting for I/O or sleeping.
switchProcess(next); // We just unlock and wait for the next interrupt to change a process's state.
}
scheduler_unlock(); scheduler_unlock();
} }