Citat:
Ursprungligen postat av
cellplast
Elegans spelar ingen större roll - problemet är korrektheten. Dvs att inte få timing-problem med en read/modify/write.
Problemet är att:
Kod:
registerflags |= 0x0001;
i själva verket utförs som:
Kod:
load r1,[registerflags]
or r1,0x0001
store [registerflags],r1
Dvs kommer det ett interrupt efter att processorn laddat "registerflags" och interrupt-koden modifierar innehållet i registerflags, så kommer efterföljande store att skriva bort den ändring som interruptkoden införde.
Jo, man bör ju så klart att skriva interruptkoden så att interruptet bara gör det allra nödvändigaste och återställer sedan allt som det var innan interruptkoden kördes, En del mera avancerade sådana sparar undan hela register innehållet i en struct, när interruptkoden är klar så läggs detta tillbaks igen.
Man brukar också få förhindra att ett annat interrupt skulle hoppa in i ett pågående interrupt.
Ja det finns många varianter, men inte så lätt att lära ut, utan att man gör en mängd praktiska kodexempel och att programmerarna får träna på detta..
Inne i CPUn ser koden ofta sådan ut, det är bara enskilda primitiver som inte kan uppdelas mera
tex
if ( i >= 0 && i < 100) { sum = sum + i * i;}
är en enrads-if men expanderas till en mängd instruktioner (primitiver) i assembler
Men uttrycket primitiver används ibland även om datatyper som är primitiva, tex ints och unsigned ints
För multitråds programmering bör man ha semaforer,
ett annat fuskigare sätt är förstås att varje tråd har en lokal kopia av en variabel som mest bara behöver läsas, man kan sen ha en synk då och då, om den behöver uppdateras
och man kan ju rentav invalidera tex en elr fler pekare för att undvika att ngn programmerare skulle sitta och leka med en annan tråds data. Alltså Invalidera = sätta till null_ptr
En del trådar behöver ju inte omedelbar uppdatering utan den kan få snurra ganska många loopvarv innan man bryr sig om att göra en synkning
Ursäkta - är lite kass på att beskriva det här bara i text
Jag är dock inne på att
cellplast m fl beskriver problemet bra, man kan inte simulera sådant här tillförlitligt i vanliga fall med vanliga simulerade/emulerade CPU-modeller eftersom alla instruktioner förutsätts ske atomärt och omedelbart, och helt utan fördröjning.
Tex UARTs är ju en annan grej att de är asynkrona, man kan ju aldrig veta när själva operationen på UART-en görs,
det går inte heller att veta om när data kommer att bli tillgängligt på porten med bara pollning. Istället hookar man ju ett interrupt att köra koden för "data tillgängligt"
Men de flesta UARTs körs ju i buffrad mode, så man kan ju bli förvirrad ibland, bara att styra om devicen till NULL-devicen så är problemet borta igen, hehe...