[OSy] Nestihajici zapsani CP0 compare registru
Michal Klempa
michal.klempa at gmail.com
Wed Nov 3 12:20:37 CET 2010
Zdravim,
On Tue, 02 Nov 2010 14:00:17 +0100
Martin Decky <decky at d3s.mff.cuni.cz> wrote:
> Hezky den,
>
> priste bych prosil psat podobne dotazy prednostne do konference ..
>
> > Takze sa mi stane, ze nastavim compare na 43907 ale count uz je
> > 44010 napriklad. Tento delay v mojom kode som metodou try&fail
> > odhadol na 200 tickov a jednoduchy patch je samozrejme nastavit ten
> > compare o 200 tickov dalej v adekvatnych pripadoch.
>
> Asi nezbyva nez cely ten algoritmus udelat robustne. Stejne se musite
> probouzet periodicky z duvodu planovani, takze v planovaci muzete
> otestovat, zda od posledniho pruchodu timery nejake nahodou
> nevyprsely, aniz by se provedly, a primo je provest nebo oznacit k
> provedeni (podle toho, v jakem kontextu obsluzne rutiny casovacu
> provadite).
Mam timer, ktory si pusta priamo scheduler, takze raz cas sa aktivuje
funkcia 'schedule' volana ako handler nejakej struct timer:
schedule_init () {
timer_init(&tmr[cpuid()], 2000, &schedule_on_timer, ...)
timer_start(&tmr[cpuid()]);
}
schedule () {
....
timer_start(&tmr[cpuid()]);
// namisto write_cp0_count(read_cp0_count() + QUANTUM);
Ked handlujem timer interrupt, vytiahnem
vsetky timery, ktore uz vyprsali z listu (so zakazanymi interruptmi) a
nahadzem si ich do lokalnej premennej (povedzme ze pole). Teda si ich
nahadzem na stack threadu, na ktoreho ucet bezi obsluha timer
interruptu.Nasledne povolim interrupty a zacnem postupne vykonavat
vsetky vyprsane timery:
timer_handle_int() {
array to_procces;
query_and_disable_ints()
while ((x= pending_timers_get_nearest()).time < real_time) {
pending_timers_extract(x);
t.append(x);
}
conditionally_enable_ints();
foreach (tmr in to_process) {
tmr.handler(tmr, tmr.data);
}
}
Este napisem ako radovo vyzera timer_start:
timer_start(tmr) {
query_and_disable_ints()
tmr.scheduled_ticks= read_cp0_count() + tmr.usec * 4;
pending_timers_insert(tmr);
new_timer= pending_timers_get_nearest();
write_cp0_compare(
max(read_cp0_count() + 200, new_timer.scheduled_ticks)
);
conditionally_enable_ints();
}
Lenze ked pride niekto a napise program:
void* thread_run (void*) {
putc('1');
timer_start(&tmr)
}
kde usec = velmi malo...
Stane sa toto, nastavi sa timer -> nastavi sa compare (urcite vacsie
ako count). Vyvola sa interrupt hned ako to je mozne, pusti sa
timer_handle_int(), vytiahne si timer a povoli interrupty. Hned ako
spusti znovu tento kod
putc('1');
timer_start(&tmr)
Znova sa zaradi do pending_timers, ak je tam prvy, znova sa nastavi
compare. A znova dostanem interrupt, zavola sa timer_handle_int() a
vytiahne sa timer z fronty, zacne sa spracovavat. A znova a znova...
teoreticky stale na ucet toho isteho threadu, az dokym nepride timer
schedulera na rad. A takto mu mozem vycerpat stack, na to ze stale robi
rekurziu do timer_handle_int() v podstate.
Otazka je, maju sa spracovavat handlery timerov so zakazanym
interruptom?
Rozmyslal som, ze by timery mohol spracovavat samostatny thread, okrem
toho, ze by to bolo pomale (bud kym sa preplanuje - cely interval
schedulera, alebo natvrdo context switch- trva cely context switch) to
ani neviem naprogramovat lebo som strasny lamer:-) Napriklad nahadzem
na queue timery ktore ma specialny thread spracovat a zrazu nema na
neho kto preplanovat lebo aj scheduler je riadeny timerom:-) Takze by
som musel robit 'switch_to_thread' vzdy ked tam nejaky timer prihodim
na tu queue, a to je uz to iste ako ho spracovat rovno.
>
> > Otazka moja je (ktoru neviem z manualov vycitat), je moznost (a ako)
> > priamo nastavit IP7 bit v kode (pri zakazanych interruptoch), takze
> > by sa hned ako povolim interrupty vyvolal interrupt 7 a handlovanie
> > timerov?
>
> Ne, bit IP7 programove nastavit nelze, muze to udelat pouze procesor
> sam pri rovnosti Count a Compare registru. Uvedomte si ale, ze muzete
> nastavovat nejen hodnotu registru Compare, ale take hodnotu registru
> Count, takze vzdy, kdyz potrebujete naplanovat dalsi probuzeni, tak
> muzete zajistit, ze Count < Compare.
Myslim ze som to dokazal kodom vyssie, nejaka rozumna konstanta tam asi
vzdy bude musiet byt, lebo samotne write_cp0_compare a read_cp0_count
nieco trvaju, tak aby som tam zapisal nieco urcite vacsie, ako pocet
tickov ktore trva kym sa vykonaju tieto instrukcie.
>
> > Minimalne by som sa zbavil nejakeho 200 tick delayu, samozrejme
> > timery by tam pretekali aj tak: ked raz niekto zavola timer_start(1
> > usec) tak sa moze aj na kolomaz rozliat a nestihnem ho zobudit za
> > jednu mikrosekundu. Ale bolo by to aspon pekne.
>
> Probuzeni presne za 1 usec neni rozhodne nutne, zadani to nepozaduje
> a pochopitelne to v non-RT systemu ani nemuzete nijak garantovat.
> Obsluzna rutina timeru by se nemela zavolat drive nez po vyprseni
> timeoutu, ale pokud se zavola v rozumne dobe po vyprseni, vse je OK.
>
> Planovaci kvantum urcite odpovida definici "rozumne doby".
>
>
> M.D.
More information about the NSWI004
mailing list