[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