Page 1 of 1

How could I resolve this round robin process switching?

Posted: Wed Feb 26, 2025 5:19 am
by gamingjam60
I have made three threads inside of process init_thread, thread1, thread2 by below code

Code: Select all

void init_processes() {
    // Create the init process
    process_t *process = create_process("process0", (void *) &thread0_func, NULL);
    if (!process) {
        printf("Failed to create init process\n");
        return;
    }

    thread_t* thread0 = process->threads; // Get the main thread of the init process
    if (!thread0) {
        printf("Failed to get init thread\n");
        return;
    }

    // Create a thread with an argument
    thread_t* thread1 = create_thread(process, "Thread1", (void *) &thread1_func, NULL);
    if (!thread1) {
        printf("Failed to create Thread1\n");
        return;
    }

    // Create a thread with an argument
    thread_t* thread2 = create_thread(process, "Thread2", (void *)&thread2_func, NULL);
    if (!thread2) {
        printf("Failed to create Thread2\n");
        return;
    }
   

    // Set the current process
    current_process = process;
    processes_list = process;

}
Which is giving following output

Code: Select all

Created Thread: init_thread (TID: 0) on (PID: 0) | rip : 0xFFFFFFFF8000A579 | rsp : 0xFFFFFFFF80329000
Created Thread: Thread1 (TID: 1) on (PID: 0) | rip : 0xFFFFFFFF8000A5A3 | rsp : 0xFFFFFFFF8032F000
Created Thread: Thread2 (TID: 2) on (PID: 0) | rip : 0xFFFFFFFF8000A5CD | rsp : 0xFFFFFFFF80335000
The apic_timer_handler function is calling in periodic interrupt

Code: Select all

void apic_timer_handler(registers_t *regs) {
    ticks1++;
    apic_send_eoi();

    if (!current_process || !current_process->current_thread) {
        return;
    }

    registers_t* new_regs = schedule(regs); // Saving the current thread state and selecting the next thread

    if(new_regs){
        printf("[ Switching TID: %d | rip: %x | rsp: %x ]\n", 
            current_process->current_thread->tid, 
            new_regs->iret_rip, new_regs->iret_rsp);
        restore_cpu_state(new_regs);        // Restoring the next thread's state
    }
}
The above timer interrupt is printing following output

Code: Select all

[ Switching TID: 0 | rip: 0xFFFFFFFF8000A579 | rsp: 0xFFFFFFFF80329000 ]
Init Thread is Running...
[ Switching TID: 1 | rip: 0xFFFFFFFF8000A5A3 | rsp: 0xFFFFFFFF8032F000 ]
Thread1 is Running...
[ Switching TID: 2 | rip: 0xFFFFFFFF80003B76 | rsp: 0xFFFF80007FF4FFE0 ]
[ Switching TID: 0 | rip: 0xFFFFFFFF8000952D | rsp: 0xFFFFFFFF80328FC0 ]
[ Switching TID: 1 | rip: 0xFFFFFFFF8000952D | rsp: 0xFFFFFFFF8032EFC0 ]
[ Switching TID: 2 | rip: 0xFFFFFFFF80003B76 | rsp: 0xFFFF80007FF4FFE0 ]
[ Switching TID: 0 | rip: 0xFFFFFFFF8000952D | rsp: 0xFFFFFFFF80328FC0 ]
[ Switching TID: 1 | rip: 0xFFFFFFFF8000952D | rsp: 0xFFFFFFFF8032EFC0 ]
[ Switching TID: 2 | rip: 0xFFFFFFFF80003B76 | rsp: 0xFFFF80007FF4FFE0 ]
[ Switching TID: 0 | rip: 0xFFFFFFFF8000952D | rsp: 0xFFFFFFFF80328FC0 ]
[ Switching TID: 1 | rip: 0xFFFFFFFF8000952D | rsp: 0xFFFFFFFF8032EFC0 ]
[ Switching TID: 2 | rip: 0xFFFFFFFF80003B76 | rsp: 0xFFFF80007FF4FFE0 ]
[ Switching TID: 0 | rip: 0xFFFFFFFF8000952D | rsp: 0xFFFFFFFF80328FC0 ]
[ Switching TID: 1 | rip: 0xFFFFFFFF8000952D | rsp: 0xFFFFFFFF8032EFC0 ]
[ Switching TID: 2 | rip: 0xFFFFFFFF80003B76 | rsp: 0xFFFF80007FF4FFE0 ]
The above code is showing init_thread (tid:0) and Thread(tid:1)'s registers->iret_rip value is 0xFFFFFFFF8000952D. If I commenting "printf("[ Switching TID: %d | rip: %x | rsp: %x ]\n", current_process->current_thread->tid, new_regs->iret_rip, new_regs->iret_rsp); " this line every interrupt is printing

Code: Select all

Init Thread is Running...
Thread1 is Running...
Without "Thread2 is Running..." printing.

But I am expecting below outpput

Code: Select all

...
Init Thread is Running... (interrupt: 12)
Thread1 is Running...      (interrupt: 13)
Thread2 is Running...     (interrupt: 14)
Init Thread is Running... (interrupt: 15)
Thread1 is Running...      (interrupt: 16)
Thread2 is Running...     (interrupt: 17)
....
The Schedule function is defined by following

Code: Select all

registers_t* schedule(registers_t* registers) {
    if (!current_process || !current_process->current_thread) return NULL;
    
    current_process->current_thread->status = READY;

    // Save the current thread's register state
    memcpy(current_process->current_thread->registers, registers, sizeof(registers_t));
    if (memcmp(current_process->current_thread->registers, registers, sizeof(registers_t)) != 0) {
        printf("registers assignment failed!\n");
        return NULL;
    }
    
    thread_t* start_thread = current_process->current_thread;
    thread_t* next_thread = current_process->current_thread->next;
    
    // Look for the next READY thread in a round-robin manner
    while (next_thread && next_thread->status != READY) {
        next_thread = next_thread->next;
    }
    
    // If no READY thread found, start from the first thread
    if (!next_thread) {
        next_thread = current_process->threads;
        while (next_thread && next_thread->status != READY) {
            next_thread = next_thread->next;
        }
    }
    
    // If still no READY thread, keep running the same thread
    if (!next_thread) {
        current_process->current_thread->status = RUNNING;
        return current_process->current_thread->registers;
    }
    
    // Set the next thread as RUNNING
    current_process->current_thread = next_thread;
    current_process->current_thread->status = RUNNING;
    
    return current_process->current_thread->registers;
}
The full code links :
process directory
apic_timer.c

Re: How could I resolve this round robin process switching?

Posted: Wed Feb 26, 2025 9:48 am
by techdude17
Set a breakpoint on your thread switch and watch where it jumps to for thread2. Are you sure the stack is valid for that thread?