loops...

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
eddyb

loops...

Post 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?
User avatar
JamesM
Member
Member
Posts: 2935
Joined: Tue Jul 10, 2007 5:27 am
Location: York, United Kingdom
Contact:

Post by JamesM »

Your problem is elsewhere. IRQs interrupt the processor (hence INTERRUPT reQuests).
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: loops...

Post 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
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
eddyb

Post 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:
jal
Member
Member
Posts: 1385
Joined: Wed Oct 31, 2007 9:09 am

Post 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
eddyb

Post 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...
User avatar
piranha
Member
Member
Posts: 1391
Joined: Thu Dec 21, 2006 7:42 pm
Location: Unknown. Momentum is pretty certain, however.
Contact:

Post 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
SeaOS: Adding VT-x, networking, and ARM support
dbittman on IRC, @danielbittman on twitter
https://dbittman.github.io
User avatar
lukem95
Member
Member
Posts: 536
Joined: Fri Aug 03, 2007 6:03 am
Location: Cambridge, UK

Post by lukem95 »

or you could use a __asm__ __volatile__ ("nop");
~ Lukem95 [ Cake ]
Release: 0.08b
Image
jzgriffin
Member
Member
Posts: 190
Joined: Tue Sep 26, 2006 1:40 pm
Libera.chat IRC: Nokurn
Location: Ontario, CA, USA
Contact:

Post 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.
eddyb

Post 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);
}
jzgriffin
Member
Member
Posts: 190
Joined: Tue Sep 26, 2006 1:40 pm
Libera.chat IRC: Nokurn
Location: Ontario, CA, USA
Contact:

Post 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.
eddyb

Post by eddyb »

to be sure that are enabled :D

Edit: :cry: :cry: :cry: :cry: 74.5 kb
jzgriffin
Member
Member
Posts: 190
Joined: Tue Sep 26, 2006 1:40 pm
Libera.chat IRC: Nokurn
Location: Ontario, CA, USA
Contact:

Post by jzgriffin »

Surely the relative portions of the code aren't >= 64KB :-)
User avatar
JamesM
Member
Member
Posts: 2935
Joined: Tue Jul 10, 2007 5:27 am
Location: York, United Kingdom
Contact:

Post by JamesM »

Where's your PIT setup code?
quok
Member
Member
Posts: 490
Joined: Wed Oct 18, 2006 10:43 pm
Location: Kansas City, KS, USA

Re: loops...

Post 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. :)
Post Reply