Page 1 of 1
Sleep aint no working
Posted: Tue Dec 15, 2020 2:46 pm
by verynewbienoob
Hello,
tried to figure it out by myself but I failed this I am writing here for help.
This is sleep:
Code: Select all
void sleepp(uint32_t time)
{
volatile unsigned long est_time;
est_time = timer_ticks + time;
while(timer_ticks < est_time)
asm("pause");
return;
}
timer_ticks is a global variable in timer file :
uint32_t volatile timer_ticks = 0;
My problem is that sleep is totally not working.
Code: Select all
void timer1()
{
uint32_t clock_ticks = 0;
for (;clock_ticks < 100;)
{
sleepp(100);
clock_ticks++;
terminal_display_at(clock_ticks,4, 84);
}
}
I tried to debug it by printing value inside sleep loop and it seemed like timer_ticks were constant like irq0 is not firing during sleep.
I know that it might be hard to tell what the **** is going on here.
P.S. If it is spam then I am sorry.
Re: Sleep aint no working
Posted: Tue Dec 15, 2020 2:58 pm
by carbonBased
Do you really want your sleep() function to busy spin?
I'd be inclined to context switch to the next available thread (how latency critical is this sleep() function meant to be?).
In any event, that's aside from your question; does timer_ticks increment otherwise (i.e., I don't think the 'pause' opcode is causing timer_ticks not to update).
Re: Sleep aint no working
Posted: Tue Dec 15, 2020 3:10 pm
by verynewbienoob
carbonBased wrote:Do you really want your sleep() function to busy spin?
I'd be inclined to context switch to the next available thread (how latency critical is this sleep() function meant to be?).
In any event, that's aside from your question; does timer_ticks increment otherwise (i.e., I don't think the 'pause' opcode is causing timer_ticks not to update).
Yes, I need that sleep working for context switching aswell.
About your question: Yes, it does increment when not sleeping.
Re: Sleep aint no working
Posted: Tue Dec 15, 2020 3:50 pm
by carbonBased
I would argue sleeping like that doesn't aide in context switching, since that thread is still going to be in the foreground for a period of time, even though there's likely nothing it can do but busy wait; other threads could be doing something, instead.
Regardless, though, I wonder what context you're busy looping in?
You show the sleep() function being called from a timer() function.
Is it possible that you're sleeping in an interrupt handler? As such, masking the other handler which would be updating timer_ticks?
Re: Sleep aint no working
Posted: Tue Dec 15, 2020 4:05 pm
by bloodline
verynewbienoob wrote:carbonBased wrote:Do you really want your sleep() function to busy spin?
I'd be inclined to context switch to the next available thread (how latency critical is this sleep() function meant to be?).
In any event, that's aside from your question; does timer_ticks increment otherwise (i.e., I don't think the 'pause' opcode is causing timer_ticks not to update).
Yes, I need that sleep working for context switching aswell.
About your question: Yes, it does increment when not sleeping.
I still don’t understand why you are busy waiting in the sleep function? Why not just halt the CPU?
Re: Sleep aint no working
Posted: Tue Dec 15, 2020 6:41 pm
by Schol-R-LEA
My own thought is that your
sleep() function shouldn't halt and loop at all; that's what your null process should be doing, instead. After all, the whole point of
sleep() - aside from having the process pause for a specified time - is to allow other processes to proceed while this process is waiting.
Rather, the
sleep() function ought to make a system call which yields to the scheduler, which according to most designs will
keep sleeping processes in a delta queue which counts down at each clock tick until the process is scheduled to awaken, at which point it goes back to the top of the regular scheduling queue (
not directly awakening the process, necessarily, as it still has to be handled according to priority).
For the queue itself, a simple
sleep_queue list data structure might look like this:
Code: Select all
struct sleep_node {
pid* sleeper;
uint64_t delta; // an offset in clock ticks from the preceding entries in the list
sleep_node* next;
} *sleep_queue;
This isn't a particularly good design, but it is a starting point.
Note that the kernel itself should not sleep directly at all; it makes no sense for it to, really. If it really needs to pause the system, it should schedule the null process, instead, though times when the system needs to do that are generally few and far between.
BTW, do you have an online repo (on Github, Sourceforge, wherever) where we could view your system code? It might help give us a better idea of what you are trying to do.
Re: Sleep aint no working
Posted: Wed Dec 16, 2020 4:11 am
by verynewbienoob
Yes, I do
https://github.com/verynewbienoob/FirstOs
Timer function is in timer file, and I am trying to run it from shell file by typing in keyboard. After that, system is paused forever.
P.S. dont judge my disorder
Re: Sleep aint no working
Posted: Wed Dec 16, 2020 9:26 am
by carbonBased
Right; so the issue is what I described above. You're executing the shell from within an interrupt (in this case, the keyboard interrupt) which means you're masking the timer interrupt from firing.
Also, Schol-R-LEA more clearly articulated what I was was trying to say about the busy looping; at some point you'll likely want to modify your sleep() function to put the current thread to sleep for a period of time and context switch to the next available thread.
Re: Sleep aint no working
Posted: Wed Dec 16, 2020 9:44 am
by verynewbienoob
After you said that's the problem I've checked it by initializing timer in main kernel file and it seems to work fine.
What if I want to sleep function work flawless from any point?
I keep in mind what School-ARE-LEA said, I just wondering if I can make it work in this form.
Re: Sleep aint no working
Posted: Wed Dec 16, 2020 10:01 am
by Schol-R-LEA
verynewbienoob wrote:After you said that's the problem I've checked it by initializing timer in main kernel file and it seems to work fine.
What if I want to sleep function work flawless from any point?
I keep in mind what School-ARE-LEA said, I just wondering if I can make it work in this form.
One thing I should mention is that in most OSes, things like the shell are done as user processes, or at the very least separate system processes, not as part of the kernel. That isn't to say that what you are doing isn't possible, just that it's a bit unusual and may make things harder in the long run.
As for the specific issue, the main concern is that interrupt service requests block incoming interrupts, which include the timer interrupts. As long as you aren't in an ISR, you should be able to sleep this way. The usual solution to this is to limit the time inside the ISR, by having the ISR process the incoming data and then pass it on elsewhere.
This is another case where having the process abstraction and a separation of system and user processes in place early helps, since it means that the ISRs - which run in kernel space - only do the least they need to before passing the results along to the user process which needs that result. In a conventional general purpose OS - even a monolithic one - the kernel does only the minimum necessary to keep the user processes separated and scheduled, the interrupts handled, and the drivers managing the devices.
Re: Sleep aint no working
Posted: Wed Dec 16, 2020 12:35 pm
by carbonBased
verynewbienoob wrote:After you said that's the problem I've checked it by initializing timer in main kernel file and it seems to work fine.
What if I want to sleep function work flawless from any point?
I keep in mind what School-ARE-LEA said, I just wondering if I can make it work in this form.
While I second what was already said -- you likely shouldn't sleep in an ISR; you would generally want to do as little as possible, collect what info you need and, if necessary, forward to a different thread for further processing -- in the interest of answering the question, you could use the rdtsc instruction.
You'd need to calibrate your system to know, for example, how many rdtsc "ticks" there are per microsecond, but that is one way to defer for a period of time without relying on interrupts to be firing.