Page 1 of 1
Create timers for notification purposes
Posted: Thu Mar 15, 2007 3:37 am
by XCHG
What is the best way to create a timer that say, calls a procedure after a specific amount of time is passed. Should I be using the PIT or are there any other ways around this?
Posted: Thu Mar 15, 2007 4:46 am
by pcmattman
Note that this idea is not tested...
I think the best way is to setup a callback system. An example is like this:
Code: Select all
int Seconds = 0;
void TimerCallback()
{
printf( "Seconds passed: %d\n", Seconds++ );
}
void StartSecondCounter()
{
SetTimerCallback( TimerCallback, 1000 ); // 1000 ms = 1 s
}
Then, you have to keep a linked list of every callback function:
Code: Select all
typedef struct TimerCallbackEntry {
long timeToWait;
long myCounter;
void (*CallbackFunction)();
TimerCallbackEntry* nextEnt;
}
Whenever the timer fires, each list's counter gets incremeted. With a bit of modulus arithmetic:
Code: Select all
if( tmp->myCounter % tmp->timeToWait == 0 )
tmp->CallbackFunction();
Of course, I'll leave the initialization up to you. If you're using ASM, that's a totally different matter, I'm afraid. Either way, I hope this helps someone.
Posted: Sat Mar 17, 2007 2:18 am
by XCHG
So I should be using System's timer on IRQ0 as a scheduler right? I should be fiddling with PIT eh? I can then set the number of milliseconds between each IRQ and then put a simple scheduler in IRQ0 handler procedure.
Posted: Sat Mar 17, 2007 12:43 pm
by Brendan
Hi,
XCHG wrote:So I should be using System's timer on IRQ0 as a scheduler right? I should be fiddling with PIT eh? I can then set the number of milliseconds between each IRQ and then put a simple scheduler in IRQ0 handler procedure.
I wouldn't quite phrase it like that ("IRQ0 as a scheduler" - it makes it sound like the timer IRQ handler is the scheduler).
For most systems, most task switches are caused by the currently running task blocking or a higher priority task unblocking, and aren't caused by a task using all of the time it's given. Some tasks are "CPU bound", but not all.
When writing a scheduler, I'd recommend doing it in stages. First write a "switch to task X" function (to eventually be used when a higher priority task unblocks), then write a "find the best task to switch to and switch to it" function (to eventually be used when the currently running task blocks). The timer IRQ just calls the "find the best task to switch to" function if the time given to the task expires.
As for which timer, use some abstraction so it doesn't matter which timer - you'll be better off in the long run. In 5 years time you might decide to support SMP and want to use local APIC timers instead, or in 3 years time you might want to support
HPET timers. With some sort of abstraction layer the scheduler doesn't need to care which timer it's actually using, and you could detect which timer to use (based on what is present) instead of hard-coding it.
Cheers,
Brendan
Posted: Sun Mar 18, 2007 8:44 am
by XCHG
Okay that's great. Thank you both for answering my question. Appreciations. I fiddled around with some initialization routines of the 8254 PIT today and got a better understanding of how it should be used. Hope I can create a simple scheduler soon.