Page 1 of 5

loops...

Posted: Sun Mar 09, 2008 5:00 am
by eddyb
hello, again :D
it was needed to write some functions that wait for something(such as timer_wait, get_ch, etc.).
so, i use a loop like this

Code: Select all

    unsigned long eticks;

    eticks = timer_ticks + ticks;
    while(timer_ticks < eticks);
but it seems to wont work, because irqs(in this case timer irq) never came.
I think these loops are occupying the processor and it never take attention at irqs and stuff...
I'm right?
Exists a solution for this? is there any type of loop that isn't blocking all processes?

Posted: Sun Mar 09, 2008 5:55 am
by JamesM
Your problem is elsewhere. IRQs interrupt the processor (hence INTERRUPT reQuests).

Re: loops...

Posted: Sun Mar 09, 2008 6:12 am
by Brendan
Hi,
eddyb wrote:I think these loops are occupying the processor and it never take attention at irqs and stuff...
I'm right?
I doubt it.. :)

There are/were a few CPUs with "errata", that can behave strangely in some situations involving tight loops. This includes Cyrix "6x86" CPUs (the CPU can completely lock up - see "the coma bug") and some Pentium 4 CPUs with hyper-threading (where one logical CPU doing a tight loop that includes an instruction with a LOCK prefix can hog CPU resources and prevent the other logical CPU from doing anything).

However, it's extremely unlikely that CPU errata is your problem. It's much much more likely that your IRQ isn't firing, that you've disabled IRQs (e.g. the CLI instruction), that you failed to send an EOI, that you didn't tell the compiler that "timer_ticks" is volatile, or something else.
eddyb wrote:Exists a solution for this? is there any type of loop that isn't blocking all processes?
You could find your bug (check through my "quick list of likely problems" above) and fix it. However, that only fixes the bug in your implementation, and doesn't fix the design flaw (wasting heaps of CPU time polling).

To fix the design flaw you'd want to tell the scheduler "don't give this task any CPU time until <foo> happens", and then when "<foo>" does happen you want to tell the scheduler "Hey, you can give this task CPU time again now". How you do this depends on how your scheduler works.

For example, if your scheduler has a list of running tasks, then when the task wants to delay for a while you'd remove the task from the scheduler's list of running tasks and put the task on the timer's list of tasks waiting to wake up, and then do a task switch to something else. The timer IRQ would increment the "timer_ticks" variable and then check it's list of tasks waiting to wake up. For each task that should wake up, the timer would remove it from it's list and put it back on the scheduler's list of running tasks.



Cheers,

Brendan

Posted: Sun Mar 09, 2008 7:42 am
by eddyb
yeah... maybe because i have Pentium 4 with ht :roll: :P (really)
maybe... but this function is from bran's kernel, so must be a problem at me...
looking over the code, i saw

Code: Select all

for (;;);
after initialization. and the keyboard still working

there is another mechanism at for and while?
why for doesn't block, and while does?
??? :roll:

Posted: Sun Mar 09, 2008 8:29 am
by jal
eddyb wrote:there is another mechanism at for and while?
why for doesn't block, and while does?
???
Really, these lines of thoughts don't get you anywhere. If you don't even have a basic grasp of how a processor works, and don't have a basic grasp of how C-code is translated to the processor's machine language, you have still way too much to learn before you can try something like OS developing.


JAL

Posted: Sun Mar 09, 2008 8:50 am
by eddyb
i've look on a asm file generated by compiler and i saw the loop, that's pretty simple. yeah, the processor should take attention to irqs and stuff, even in a loop, but my processor is lazy...
also i have a simple multitasking that execute another function(from a list of function) at each timer irq. i use it for my simple gui. it works well, but if i put a loop (doesn't matter where) my multitasking doesn't work...

Posted: Sun Mar 09, 2008 9:29 am
by piranha
If you think that the loop is taking too much processor (which seems unlikely) try making the loop:

Code: Select all

while([i]whatever[/i]) 
{
        asm("hlt");
}

or

for(;;)asm("hlt");
-JL

Posted: Sun Mar 09, 2008 9:46 am
by lukem95
or you could use a __asm__ __volatile__ ("nop");

Posted: Sun Mar 09, 2008 10:10 am
by jzgriffin
eddyb wrote:yeah... maybe because i have Pentium 4 with ht :roll: :P (really)
maybe... but this function is from bran's kernel, so must be a problem at me...
looking over the code, i saw

Code: Select all

for (;;);
after initialization. and the keyboard still working

there is another mechanism at for and while?
why for doesn't block, and while does?
??? :roll:
Interrupts always fire after being enabled by sti (provided that you've properly set them up ;-)) unless they've been disabled by cli.

Posted: Sun Mar 09, 2008 10:27 am
by eddyb
what i want is that i can fire a irq while i'm in a loop. at me wont work:(
I attached a floppy image(zipped). boot from it, and at this simple promt, type test
this should wait some milliseconds...

:evil: :evil: i cannot attach files bigger than 64 kb

LE i dont see the post above :roll:

LLE:

Code: Select all

void timer_handler(struct iregs *r)
{
    /* Increment our 'tick count' */
    timer_ticks++;
	int i;
	void (*task)(void);
	if(act_task>=nr_tasks-1)
		act_task=0;
	else
		act_task++;
	task = tasks[act_task];
	if (task)
	{
		task();
	}

		//puts("Tick:");
		//put_dec(timer_ticks);
		//putch('\n');
    /* Every 18 clocks (approximately 1 second), we will
    *  display a message on the screen */
    if (timer_ticks % 18 == 0)
    {
		timer_seconds = timer_ticks/18;

    }
}

/* This will continuously loop until the given time has
*  been reached */
void timer_wait(int ticks)
{
    unsigned long eticks;

    eticks = timer_ticks + ticks;
	asm("sti");
	while(timer_ticks < eticks);
}

Posted: Sun Mar 09, 2008 10:33 am
by jzgriffin
Tried bzipping it? It should remove unnecessary zeroes.

Edit: Why are you calling sti inside of the loop? It should have been called before then.

Posted: Sun Mar 09, 2008 10:37 am
by eddyb
to be sure that are enabled :D

Edit: :cry: :cry: :cry: :cry: 74.5 kb

Posted: Sun Mar 09, 2008 10:40 am
by jzgriffin
Surely the relative portions of the code aren't >= 64KB :-)

Posted: Sun Mar 09, 2008 1:03 pm
by JamesM
Where's your PIT setup code?

Re: loops...

Posted: Sun Mar 09, 2008 8:10 pm
by quok
eddyb wrote:hello, again :D
it was needed to write some functions that wait for something(such as timer_wait, get_ch, etc.).
so, i use a loop like this

Code: Select all

    unsigned long eticks;

    eticks = timer_ticks + ticks;
    while(timer_ticks < eticks);
but it seems to wont work...
This problem stinks of familiarity. Is your timer_ticks variable declared volatile? If not, change it so it is, and recompile. I'll bet that will solve your problem. I bet compiling with -O0 would fix it as well, but let's not go that route just yet. :)

Because of the way IRQs work, with happening at relatively unknown times (as far as GCC is concerned, anyway), you may need to declare some variables that are used in ISRs as volatile if they are also used outside of those ISRs. The reason for that is because GCC caches accesses to variables whenever it can as an optimization technique. Obviously this won't work in your loop function as GCC won't realize that the value of timer_ticks changed, since it's looking at a cache of that variable in your function.

So, declare timer_ticks volatile, recompile, and let us know how it goes. :)