Spin lock

Az oldal jelenlegi verzióját még nem ellenőrizték tapasztalt közreműködők, és jelentősen eltérhet a 2022. augusztus 7-én felülvizsgált verziótól ; az ellenőrzések 3 szerkesztést igényelnek .

A spinlock vagy spinlock ( angolul  spinlock - ciklikus zár) egy alacsony szintű szinkronizációs primitív [1] , amelyet többprocesszoros rendszerekben használnak a kritikus kódszakaszok végrehajtásának kölcsönös kizárására egy aktív várakozási hurok segítségével [2] . Olyan esetekben használatos, amikor a zárolásra való várakozás várhatóan rövid lesz [2] , vagy ha a végrehajtási környezet nem teszi lehetővé a blokkolt állapotba való átmenetet [3] .

A spinlockok hasonlóak a mutexekhez , így kevesebb időt tölthet egy szál blokkolásával, mivel nem kell a szálat blokkolt állapotba vinnie. Mutexek esetén előfordulhat, hogy meg kell hívni az ütemezőt, hogy módosítsa a szál állapotát, és hozzáadja a feloldásra váró szálak listájához. A spinlockok nem használják az ütemezőt, és várakozási ciklust használnak a szál állapotának megváltoztatása nélkül, ami a CPU-időt vesztegeti arra várva, hogy egy másik szál feloldja a zárolást. A spinlock tipikus megvalósítása a spinlock változó elérhetőségének egyszerű ciklikus ellenőrzése [1] .

Fizikai megvalósítás

Fizikailag a spinlock egy változó a memóriában, és olyan atomi műveleteken valósul meg , amelyeknek jelen kell lenniük a processzor utasításkészletében . Minden processzor, amely hozzá akar férni a megosztott erőforráshoz , a swap művelet egy analógjával (x86 architektúrában - xchg) a " busy " feltételes értéket írja ebbe a változóba. Ha a változó előző (a parancs által visszaadott) értéke „ free ” volt, akkor az adott processzor hozzáfért az erőforráshoz, ellenkező esetben a processzor visszatér a swap művelethez, és a spinlockon keresztül hurkol, amíg fel nem szabadul. A megosztott erőforrással végzett munka után a processzornak - a spinlock tulajdonosának - be kell írnia a " szabad " feltételes értéket.

Példa a spinlock megvalósítására x86 assemblerben:

mov eax , spinlock_address mov ebx , SPINLOCK_BUSY várakozás_ciklus: xchg [ eax ], ebx ; Az xchg az egyetlen utasítás, amely atomikus a lock cmp ebx előtag nélkül , SPINLOCK_FREE jnz wait_cycle ; <a kritikus szakaszt ez a szál rögzíti, itt folyamatban van a megosztott erőforrással végzett munka> mov eax , spinlock_address mov ebx , SPINLOCK_FREE xchg [ eax ], ebx ; használja az xchg-t az atomi változáshoz ; az utolsó 3 utasítást le kell cserélni a mov [spinlock_address]-re, SPINLOCK_FREE - ; ez növeli a sebességet a szükségtelen buszlezárás hiánya miatt, és a mov egyébként atomosan fog végrehajtódni ; (de csak akkor, ha a spinlock_address egy dword határon van igazítva)

Egy intelligensebb megvalósítás normál műveletet használna az atomos művelet helyett a hurokban történő lekérdezéshez, és egy atomi műveletet csak a rögzítési kísérletekhez. Az a tény, hogy az atomi memóriaműveletek végrehajtása úgy történik, hogy a hardver blokkolja a rendszerbuszt a processzor által az atomi művelet (amely magában foglalja az olvasást, a módosítást és az írást) idejére. E három művelet alatt a buszon nem hajtható végre más művelet, ami csökkenti a rendszerben lévő többi processzor teljesítményét (ha közös buszon osztoznak ), még akkor sem, ha semmi közük ehhez a spinlockhoz.

Szintén használatosak az ún. sorban álló spinlockok - "sorba állított spinlockok". Ahelyett, hogy egy atomi változóhoz 0-t vagy 1-et rendelnének, egy szerkezet atomi hozzáadását használják a lista fejéhez, míg a lista feje egy "mutató" típusú atomi változó.

A sorban álló spinlockok hasznos tulajdonságai:

  • az ellátás sorrendjének garanciája a kérés sorrendjében, garancia az "éhezés" ellen
  • a lekérdezési ciklusban minden processzor lekérdezi a saját helyi változóját
  • pontosan 1 atomművelet rögzítéskor és pontosan 1 elengedéskor

A spinlockokat a kód kis szakaszainak szinkronizálására használják, ha bonyolultabb mechanizmusok használata ésszerűtlen vagy lehetetlen. A szinkronizálási primitívek és a szálkezelő megvalósítása szükségszerűen zárolást igényel a végrehajtásra kész szálak és az objektumokon várakozó szálak listájának védelmére. Egy ilyen zár nagyon alacsony szintje miatt csak spinlock lehet. Így a spinlock a legalacsonyabb szinkronizációs primitív, amelyen az összes többi megvalósítása alapul.

A Windows 7-et is magában foglaló Windows-verziói a zárolásmentes adatszerkezetek paradigmáját használják a diszpécser/ütemező megvalósításához. Így megkímélték őket az egyetlen globális spinlock KiDispatcherLocktól, amely az egyik legerősebben terhelt az operációs rendszer kernelében.

A többprocesszoros és egyprocesszoros konfigurációk sajátosságai

Széles körben elterjedt az a vélemény, hogy a többfeladatos operációs rendszer alatt futó felhasználói alkalmazásokban a spinlockok használata elfogadhatatlan, mivel a spinlock felszabadítására való várakozás aktív várakozáshoz vezet egy ciklusban, ami pazarolja a CPU számítási erőforrásait, és magas szintű primitíveket kell használni. felhasználói programok szinkronizálására szolgál, ami passzív várakozást jelent - ha egy adott szál nem tudja folytatni a végrehajtást, akkor az OS-nek adja az irányítást, és nem pörög spinlock várakozási hurokban (amely potenciálisan végtelen is lehet). Valójában ez az állítás 100%-ban csak egyprocesszoros rendszerekre igaz. Sok esetben a spinlockok használata az SMP konfigurációkban hatékonyságnövekedést eredményez, ha a lekérdezés és a spinlock beszerzése gyorsabb, mint a kernelben lévő mutex adatgyűjtés meghívása.

A fő kritérium itt a vita – az erőforrásokért folyó verseny "merevsége". Egy enyhén betöltött erőforrás, amely nem népszerű végrehajtási webhely, másképp viselkedik, mint egy erősen terhelt erőforrás, amelyet nagyon gyakran rögzítenek és felszabadítanak.

Ezenkívül ugyanabban a Windows-ban vannak különféle mutexek (például a jól ismert CRITICAL_SECTION/EnterCriticalSection/LeaveCriticalSection vagy szinonimája az operációs rendszer kernelében - FAST_MUTEX/ExAcquireFastMutex/ExReleaseFastMutex), amelyek először spinként működnek. értéklekérdezés a memóriában, és csak ezután, sok lekérdezés után lépjen a kernelhez a blokkoló várakozásra. Az ilyen objektumok a spinlockok (minimális rögzítési költség) és a mutexek (nem pazarolják a CPU-erőforrást lekérdezéshez) legjobb tulajdonságait egyesítik.

A spinlockok használata

Azok az esetek, amikor a spinlockok használata a felhasználói térben kézzelfogható hatást fejt ki:

  • A védett kód szekciójában több olyan változó is található, amelyek módosítási ideje több száz, sőt ezerszer rövidebb is lehet, mint egy processzor általi kontextusváltás , ami különösen drága művelet, különösen a modern rendszereken.
  • Nem kódrészek blokkolása , hanem adatok (minden adatszerkezethez, amelyet atomszerűen meg kell változtatni, egy spinlock van társítva, amely megvédi)
  • Kódoptimalizálás, ha csökkenteni kell a túl gyakori kontextusváltás miatt fellépő terhelést

Azonban a "gyors mutexek", mint például a Win32 CRITICAL_SECTION használata, a fentiek mindegyikét szükségtelenné teszi a felhasználói térben.

Olyan esetek, amikor a spinlockok használata nem indokolt és a processzor erőforrásainak pazarlása:

  • Hosszú blokkolási műveletek a védett kódrészen belül (a lemez és a hálózati I/O processzorszabványok szerint nagyon sokáig tarthat)
  • Egyprocesszoros konfigurációk – a processzor a hátralévő időszeletet üresjáratban tölti .

Spinlock problémák és megoldási módszerek

A modern processzorokon a csővezetékes architektúra sajátosságai miatt nagyon gyors lehet az alvási ciklus, ami a tekercses üresjárati ciklusok mellett a normál működésnél intenzívebb felfűtéshez vezethet.

A Pentium 4 és az Intel processzorok újabb modelljei bevezettek egy speciális assembler utasítást a szünet hurokba való beillesztésére ( opcode 0xf3 0x90, hasonló a rep nop-hoz a régebbi processzorokkal való kompatibilitás érdekében), amely arra utasítja a processzort, hogy ez a ciklus egy várakozási ciklus, és lehetővé teszi a processzor számára, hogy több szálat támogasson ugyanazon a magon, lépjen tovább a következő szálra.

A Windows 7 óta tartó Windows verziói úgy vannak optimalizálva, hogy „vendégként” fussanak egy virtuális gépen, és a szünet helyett olyan esetekben, amikor az operációs rendszer vendégként fut, egy speciális hívás „értesíti a hipervizort, hogy várakozási ciklusban vagyunk”. használt.

A spinlock alternatívái

  • A spinlockokat annak biztosítására használják, hogy egy szál kizárólagos hozzáféréssel rendelkezzen egy védett adatstruktúrához. Nem tesz különbséget maguk között a szálak és az elvégzett műveletek között sem. A valós alkalmazásokban azonban gyakran a szálak „olvasókra” és „írókra” oszthatók. Ebben az aszimmetrikus esetben célszerűbb az olvasási-írási zárak használata . A struktúra egyidejűleg korlátlan számú szál által használható "csak olvasható" módban, egyben adatintegritás-védelmet adva "író" szál megérkezésekor.
  • Vannak blokkolásmentes algoritmusok is, amelyek az atomütközések észlelésén alapulnak. Optimalizáltak arra az optimista esetre, amikor a teljes ütközés-ellenőrzés egyetlen atomösszeszerelő műveletre redukálódik ( Összehasonlítás és csere , x86 architektúrán - cmpxchg parancs )

A spinlockok egyéb módosításai

A spinlock automatikus növekedéssel, amíg egy teljes értékű mutex rögzítésre nem kerül bizonyos számú ciklusfordulat lejárta után, például a Windows kritikus szakaszaiban az optimalizálás érdekében, ami abból áll, hogy verseny hiányában nem hívják a mutexet. egy erőforrásért.

Jegyzetek

  1. ↑ 1 2 IEEE, The Open Group. Rendszerinterfészek indoklása , Általános információk  . Az Open Group Base Specifications 7. szám, 2018-as kiadás . The Open Group (2018). Letöltve: 2020. június 20. Az eredetiből archiválva : 2020. június 18.
  2. 1 2 Tanenbaum, 2011 , 2.3.3. Active Wait Mutual, Strict Interleaving, p. 156.
  3. Oleg Tsiljurik. Kernel programozási eszközök: 73. rész. Párhuzamosság és szinkronizálás. Zárak. 1. rész . - www.ibm.com, 2013. - augusztus 13. — Hozzáférés időpontja: 2019.12.06.

Irodalom

  • M. Russinovich , D. Solomon. 1 // Microsoft Windows belső. - 6. kiadás - Szentpétervár. : Péter, 2013. - S. 218-222. — 800 s. - ("Mesterkurzus"). — ISBN 978-5-459-01730-4 .
  • Walter Ők. A Microsoft Windows illesztőprogram-modell használata . - 2. kiadás - Szentpétervár. : Péter, 2007. - S.  173 -178. — 764 p. - ISBN 978-5-91180-057-4 .
  • Andrew S. Tanenbaum. Modern operációs rendszerek  = Modern operációs rendszerek. — 3. kiadás. - Szentpétervár: Peter: "Peter" Kiadó, 2011. - S. 165-170. — 1117 p. — (Az informatika klasszikusai). — ISBN 9785459007572 .

Lásd még