Correct Implementation of Sleep
Posted: Fri Mar 02, 2018 1:31 am
Hi all,
I have been trying to implement sleep properly in my kernel for the last few days. I have tried various mechanisms and apparently none of them seem to be working at this point. Basically, my sleep is a system call that basically runs an idle loop till the number of sleep seconds expires. I am using the PIT timer to keep decrementing a global variable that tells me if the timer has expired/not. I have declared ticks globally.
This is the PIT irq handler that I have implemented and which seems to be running correctly.
The below is my sleep system call --
Seconds is the amt of time in milliseconds for which the system should sleep.
The problem here is that the sys_sleep function does not return. It basically keeps running the while loop even after the condition has become false (when ticks > timer_ticks).
I tried using gdb to see in assembly which instruction is getting executed repeatedly. I noticed a peculiar jmp instruction.
The fourth jump instruction seems to be the culprit as it is jumping to the same address repeatedly and hence the system is going to an infinite loop.
I am quite confused as to what a proper sleep implementation would be. Is my current implementation correct ? If so, what is causing this bug ? Should I change my design in any way ?
Thanks.
I have been trying to implement sleep properly in my kernel for the last few days. I have tried various mechanisms and apparently none of them seem to be working at this point. Basically, my sleep is a system call that basically runs an idle loop till the number of sleep seconds expires. I am using the PIT timer to keep decrementing a global variable that tells me if the timer has expired/not. I have declared ticks globally.
Code: Select all
int ticks = 0;
Code: Select all
void i86_pit_irq(){
i86_set_mask(1);
// sleeping processes in queue
ticks++;
i86_pic_send_eoi_command(32);
struct pcb *process = sleeping_queue.processes;
while(process != NULL)
{
if(process->sleep_time == 0)
{
try_to_wake_up(&sleeping_queue, process);
}
else
{
process->sleep_time = process->sleep_time - 1;
}
process = process->next_in_queue;
}
struct pcb *current = get_current_process();
if(current->is_sigkill_pending) // current is current process
{
/* usually involves killing the process- signals are always handled by current process */
current->is_sigkill_pending = 0;
sys_exit(9); // signal code KILL -9
}
else if(current->is_sigsegv_pending)
{
current->is_sigsegv_pending = 0;
sys_exit(11); // signal code : 11
}
current->time_slice = current->time_slice - 1;
if(current->time_slice <= 0)
{
schedule();
}
i86_clear_mask(1);
}
Code: Select all
void sys_sleep(unsigned long seconds)
{
unsigned int timer_ticks;
timer_ticks = ticks + (seconds * 1000);
/*
kprintf("sleeping for %d seconds ", seconds);*/
while(ticks < timer_ticks);
kprintf("sleep done");
}
The problem here is that the sys_sleep function does not return. It basically keeps running the while loop even after the condition has become false (when ticks > timer_ticks).
I tried using gdb to see in assembly which instruction is getting executed repeatedly. I noticed a peculiar jmp instruction.
Code: Select all
0xffffffff80201567 <sys_sleep+13> add (%rax),%edi
0xffffffff80201569 <sys_sleep+15> cmp (%rax),%edi
0xffffffff8020156b <sys_sleep+17> jbe 0xffffffff8020156f <sys_sleep+21>
0xffffffff8020156d <sys_sleep+19> jmp 0xffffffff8020156d <sys_sleep+19>
The fourth jump instruction seems to be the culprit as it is jumping to the same address repeatedly and hence the system is going to an infinite loop.
I am quite confused as to what a proper sleep implementation would be. Is my current implementation correct ? If so, what is causing this bug ? Should I change my design in any way ?
Thanks.