Yksi asia, jonka olen löytänyt hyödylliseksi useille koneille, on yksinkertainen pinonvaihtaja. En ole itse kirjoittanut yhtä PIC: lle, mutta olettaa, että lähestymistapa toimisi hienosti PIC18: lla, jos molemmat / kaikki säikeet käyttävät yhteensä 31 tai vähemmän pinotasoja. 8051: n päärutiini on:
_taskswitch: xch a, SP xch a, _altSP xch a, SP ret
PIC: ssä unohdan pinon osoittimen nimen , mutta rutiini olisi jotain:
_taskswitch: movlb _altSP >> 8 movf _altSP, w, b movff _STKPTR, altSP movwf _STKPTR, c return
soita rutiini task2 (), joka lataa altSP: n vaihtoehtoisen pinon osoitteella (16 toimisi todennäköisesti PIC18Fxx: lle) ja suorittaa task2-silmukan; tätä rutiinia ei saa koskaan palata, muuten asiat kuolevat tuskallisessa kuolemassa. Sen sijaan sen tulisi kutsua _taskswitch aina, kun se haluaa ohjata ensisijaista tehtävää; ensisijaisen tehtävän tulisi sitten kutsua _taskswitch aina, kun se haluaa antaa periksi toissijaiselle tehtävälle. Usein on pieniä söpöjä rutiineja, kuten:
void delay_t1 (allekirjoittamaton lyhyt val) {do taskwitch (); while ((allekirjoittamaton lyhyt) (millisekunnin kello - val)> 0xFF00); }
Huomaa, että tehtävänvaihtajalla ei ole mitään keinoa odottaa ehtoa; kaikki se tukee on spinwait. Toisaalta tehtäväkytkin on niin nopea, että tehtäväkytkimen () yrittäminen toisen tehtävän odottaessa ajastimen päättymistä vaihtaa toiseen tehtävään, tarkistaa ajastimen ja vaihtaa takaisin nopeammin kuin tyypillinen tehtävänvaihtaja määrittäisi, että sen ei tarvitse vaihtaa tehtäviä.
Huomaa, että yhteistyöhön perustuvassa monitoiminnossa on joitain rajoituksia, mutta se välttää paljon lukitusta ja muuta mutexiin liittyvää koodia tapauksissa, joissa väliaikaisesti häiriintyneet invariantit voidaan palauttaa nopeasti.
(Muokkaa): Pari varoitusta automaattisista muuttujista ja vastaavista:
- jos tehtävänvaihtoa käyttävä rutiini kutsutaan molemmista säikeistä, on yleensä tarpeen koota kaksi rutiinin kopiota (mahdollisesti # sisällyttämällä sama lähdetiedosto kahdesti eri #define -käskyillä). Mikä tahansa annettu lähdetiedosto joko sisältää koodin vain yhdelle säikeelle tai sisältää koodin, joka käännetään kahdesti - kerran jokaiselle säikeelle - joten voin käyttää makroja, kuten "#define delay (x) delay_t1 (x)" tai #define delay (x) delay_tx (x) "riippuen siitä, mitä ketjua käytän.
- Uskon, että PIC-kääntäjät, jotka eivät" näe "kutsuttavaa toimintoa, olettavat, että tällainen funktio saattaa roskakoriin kaikki Suoritinrekisterit välttäen siten tarvetta tallentaa rekistereitä tehtävänvaihtorutiiniin [mukava etu ennalta ehkäisevään monitoimityöhön verrattuna] .Kaikkien, jotka harkitsevat samanlaista tehtäväkytkintä muille keskusyksiköille, on oltava tietoisia käytössä olevista rekisterikäytännöistä. Ennen tehtävänvaihtoa ja niiden avaamista on helppo tapa hoitaa asiat olettaen, että pinotilaa on riittävästi. yksinkertaistaa asioita huomattavasti: ennaltaehkäisevässä RTOS: ssa, jossa on tiivistävä roskakoko Esimerkiksi r on tarpeen sallia esineiden kiinnittäminen. Kun käytetään osuuskytkintä, tämä ei ole välttämätöntä, jos koodi olettaa, että GC-objektit voivat liikkua milloin tahansa tehtäväkytkintä () kutsutaan. Tiivistävä keräilijä, jonka ei tarvitse huolehtia kiinnitetyistä esineistä, voi olla paljon yksinkertaisempi kuin se.