Spin lås

Den aktuelle version af siden er endnu ikke blevet gennemgået af erfarne bidragydere og kan afvige væsentligt fra den version , der blev gennemgået den 7. august 2022; checks kræver 3 redigeringer .

En spin-lås eller spinlock ( engelsk  spinlock - cyclic lock) er en lav-niveau synkronisering primitiv [1] brugt i multiprocessor systemer til at implementere gensidig udelukkelse af udførelsen af ​​kritiske kode sektioner ved hjælp af en aktiv ventesløjfe [2] . Det bruges i tilfælde, hvor ventetiden på en lås forventes at være kort [2] eller hvis udførelseskonteksten ikke tillader overgangen til en blokeret tilstand [3] .

Spinlocks ligner mutexes , hvilket giver dig mulighed for at bruge mindre tid på at blokere en tråd, da du ikke behøver at overføre tråden til den blokerede tilstand. I tilfælde af mutexes kan det være nødvendigt at kalde skemalæggeren for at ændre trådens tilstand og tilføje den til listen over tråde, der venter på at blive låst op. Spinlocks bruger ikke skemalæggeren og bruger en venteløkke uden at ændre trådens tilstand, hvilket spilder CPU-tid på at vente på, at en anden tråd frigiver låsen. En typisk implementering af en spinlock er en simpel cyklisk kontrol af spinlock-variablen for tilgængelighed [1] .

Fysisk implementering

Fysisk er en spinlock en variabel i hukommelsen og implementeres på atomoperationer, der skal være til stede i processorens instruktionssæt . Hver processor, der ønsker at få adgang til den delte ressource, skriver atomisk den betingede værdi " optaget " til denne variabel ved at bruge en analog af swap-operationen (i x86-arkitekturen - xchg). Hvis den tidligere værdi af variablen (returneret af kommandoen) var " fri ", anses den givne processor for at have adgang til ressourcen, ellers vender processoren tilbage til swap-operationen og går gennem spinlocken, indtil den frigøres. Efter at have arbejdet med en delt ressource, skal processoren - ejeren af ​​spinlocken skrive den betingede værdi " gratis " ind i den.

Et eksempel på implementering af en spinlock i x86 assembler:

mov eax , spinlock_address mov ebx , SPINLOCK_BUSY wait_cycle: xchg [ eax ], ebx ; xchg er den eneste instruktion, der er atomisk uden præfikset lås cmp ebx , SPINLOCK_FREE jnz wait_cycle ; <kritisk sektion er fanget af denne tråd, arbejde med delt ressource er i gang her> mov eax , spinlock_address mov ebx , SPINLOCK_FREE xchg [ eax ], ebx ; brug xchg til atomændring ; sidste 3 instruktioner skal erstattes med mov [spinlock_address], SPINLOCK_FREE - ; dette vil øge hastigheden på grund af fraværet af unødvendig busblokering, og mov vil alligevel blive udført atomisk ; (men kun hvis spinlock_address er justeret på en dword-grænse)

En smartere implementering ville bruge en almindelig operation i stedet for en atomoperation til polling i en løkke og en atomoperation kun til fangstforsøg. Faktum er, at implementeringen af ​​atomare hukommelsesoperationer sker ved, at hardware blokerer systembussen af ​​processoren i varigheden af ​​atomoperationen (som inkluderer læsning, ændring og skrivning). Under disse tre operationer kan der ikke udføres andre operationer på bussen, hvilket reducerer ydeevnen af ​​andre processorer i systemet (hvis de deler en fælles bus ), selvom de ikke har noget at gøre med denne spinlock.

Også brugt er de såkaldte. queued spinlocks - "køede spinlocks". I stedet for at tildele 0 eller 1 til en atomvariabel, bruger de en atomisk tilføjelse af en struktur til listens hoved, mens listens hoved er en atomvariabel af typen "pointer".

Nyttige egenskaber ved spinlocks i kø:

  • garanti for leveringsrækkefølgen i anmodningsrækkefølgen, garanti mod "sult"
  • i afstemningssløjfen poller hver processor sin lokale variabel
  • præcis 1 atomoperation ved indfangning og præcis 1 ved frigivelse

Spinlocks bruges til at synkronisere små sektioner af kode, når brugen af ​​mere komplekse mekanismer er urimelig eller umulig. Implementeringen af ​​synkroniseringsprimitiverne og trådhåndteringen kræver nødvendigvis låse for at beskytte listerne over tråde, der er klar til at udføre, og listerne over tråde, der venter på objekter. En sådan lås kan kun være en spinlock på grund af dens meget lave niveau. Således er spinlock den laveste synkroniseringsprimitiv, som implementeringen af ​​alle de andre er baseret på.

Versioner af Windows fra inklusive Windows 7 bruger det låsefri datastrukturparadigme til at implementere afsenderen/planlæggeren. Dermed er de skånet for den eneste globale spinlock KiDispatcherLock, en af ​​de mest belastede i OS-kernen.

Specifikationer for multiprocessor- og uniprocessor-konfigurationer

Der er en udbredt opfattelse af, at i brugerapplikationer, der kører under multitasking OS, er brugen af ​​spinlocks uacceptabel, da at vente på, at en spinlock frigives fører til en aktiv ventetid i en loop, der spilder CPU-computerressourcer, og primitiver på højt niveau skal bruges til at synkronisere brugerprogrammer, som indebærer passiv venting - hvis en given tråd ikke kan fortsætte eksekveringen, så giver den kontrol til OS og spinder ikke i en spinlock-venteløkke (som potentielt kan være uendelig). Faktisk er denne erklæring kun 100 % sand for uniprocessor-systemer. I mange tilfælde fører brug af spinlocks i SMP - konfigurationer til effektivitetsgevinster, hvis polling og erhvervelse af en spinlock er hurtigere end at kalde en mutex-acquisition i kernen.

Hovedkriteriet her er påstand - "rigiditeten" af konkurrencen om ressourcen. En let indlæst ressource, der ikke er et populært eksekveringssted, opfører sig anderledes end en tungt indlæst ressource, der fanges og deallokeres meget ofte.

Derudover er der i de samme Windows varianter af mutexes (f.eks. den velkendte CRITICAL_SECTION/EnterCriticalSection/LeaveCriticalSection, eller dets synonym i OS-kernen - FAST_MUTEX/ExAcquireFastMutex/ExReleaseFastMutex), som først fungerer som en spinlock, vha. en værdiafstemning i hukommelsen, og først derefter, efter et stort antal afstemninger, gå til kernen for at blokere vente. Sådanne objekter kombinerer de bedste kvaliteter af spinlocks (minimumsomkostninger ved optagelse) og mutexes (intet spild af CPU-ressourcer til polling).

Brugen af ​​spinlocks

Tilfælde, hvor brugen af ​​spinlocks i brugerrummet giver en håndgribelig effekt:

  • Inde i sektionen af ​​den beskyttede kode er der flere tilknyttede variabler, hvis modifikationstid kan være hundredvis og endda tusindvis af gange mindre end en kontekstskift fra processoren, hvilket er en særlig dyr operation, især på moderne systemer.
  • Blokering ikke kodesektioner , men data (med hver datastruktur, der skal ændres atomisk som en helhed, er der tilknyttet en spinlock, der beskytter den)
  • Kodeoptimering, når det er nødvendigt at reducere den belastning, der opstår på grund af for hyppig kontekstskift

Men brugen af ​​"hurtige mutexes" såsom Win32's CRITICAL_SECTION gør alt ovenstående unødvendigt i brugerrummet.

Tilfælde, hvor brugen af ​​spinlocks ikke er berettiget og er spild af processorressourcer:

  • Lange blokeringsoperationer inde i den beskyttede kodesektion (disk og netværks-I/O kan tage meget lang tid ifølge processorstandarder)
  • Enkeltprocessorkonfigurationer - processoren bruger resten af ​​tiden på en inaktiv cyklus .

Spinlock-problemer og metoder til at løse dem

På moderne processorer kan dvalecyklussen være meget hurtig på grund af de særlige kendetegn ved pipeline-arkitekturen, som ud over at vikle tomgangscyklusser kan føre til mere intens opvarmning end under normal drift.

Pentium 4 og senere modeller af Intel - processorer introducerede en speciel assembler-instruktion om at indsætte i en pause-loop ( opcode 0xf3 0x90, svarende til rep nop for kompatibilitet med ældre processorer), som har til formål at instruere processoren om, at denne cyklus er en vente-løkke, og giver processoren mulighed for at understøtte flere tråde på den samme kerne, gå videre til næste tråd.

Versioner af Windows siden Windows 7 er optimeret til at køre som "gæst" i en virtuel maskine, og i stedet for at holde pause i tilfælde, hvor operativsystemet kører som gæst, vil et særligt opkald "underrette hypervisoren om, at vi er i en venteløkke" anvendes.

Alternativer til spinlocks

  • Spinlocks bruges til at sikre, at en tråd har eksklusiv adgang til en beskyttet datastruktur. Den skelner ikke mellem selve trådene og heller ikke mellem de udførte operationer. Men ofte i rigtige applikationer kan tråde opdeles i "læsere" og "skribenter". Til dette asymmetriske tilfælde er det mere hensigtsmæssigt at bruge læse-skrive-låse . Strukturen kan samtidig bruges af et ubegrænset antal tråde i "skrivebeskyttet"-tilstand, samtidig med at det giver dataintegritetsbeskyttelse, når der kommer en "skrivende" tråd.
  • Der er også blokeringsfrie algoritmer baseret på atomart kollisionsdetektion. De er optimeret til det optimistiske tilfælde, hvor hele kollisionskontrollen reduceres til én atomsamleroperation ( Sammenlign og swap , på x86 -arkitektur - kommandoen cmpxchg )

Andre ændringer af spinlocks

Spinlock med automatisk vækst, indtil en fuldgyldig mutex er fanget efter et vist antal cyklusomdrejninger er udløbet, bruges for eksempel i kritiske dele af Windows til optimering, som består i fravær af kald til mutex'en i mangel af konkurrence for en ressource.

Noter

  1. ↑ 1 2 IEEE, Den åbne gruppe. Begrundelse for systemgrænseflader , generel information  . Open Group Base Specifications Issue 7, 2018-udgave . Den åbne gruppe (2018). Hentet 20. juni 2020. Arkiveret fra originalen 18. juni 2020.
  2. 1 2 Tanenbaum, 2011 , 2.3.3. Active Wait Mutual, Strict Interleaving, s. 156.
  3. Oleg Tsilyurik. Kernelprogrammeringsværktøjer: Del 73. Parallelisme og synkronisering. Låse. Del 1 . - www.ibm.com, 2013. - 13. august. — Dato for adgang: 06/12/2019.

Litteratur

  • M. Russinovich , D. Solomon. 1 // Microsoft Windows internt. - 6. udgave - Sankt Petersborg. : Peter, 2013. - S. 218-222. - 800 sek. - ("Master Class"). — ISBN 978-5-459-01730-4 .
  • Walter De. Brug af Microsoft Windows-drivermodellen . - 2. udg. - Sankt Petersborg. : Peter, 2007. - S.  173 -178. — 764 s. - ISBN 978-5-91180-057-4 .
  • Andrew S. Tanenbaum. Moderne operativsystemer  = Moderne operativsystemer. — 3. udgave. - Skt. Petersborg: Peter: Forlaget "Peter", 2011. - S. 165-170. — 1117 s. — (Klassikere inden for datalogi). — ISBN 9785459007572 .

Se også