Atomműködés
Atomi ( görögül άτομος - oszthatatlan) művelet - olyan művelet, amelyet vagy teljesen végrehajtanak, vagy egyáltalán nem hajtanak végre; részben nem végrehajtható és részben nem végrehajtható művelet.
Ez a cikk a legegyszerűbb atomi műveleteket írja le (olvasás, írás stb.), bár ez a kifejezés magasabb szintű műveletekre is utalhat, mint például a DBMS -hez intézett lekérdezések sorozata egyetlen tranzakción belül .
Az atomi műveleteket többprocesszoros számítógépekben és többfeladatos operációs rendszerekben használják, hogy több folyamat és/vagy ugyanazon folyamat több szála számára biztosítsanak hozzáférést a közöttük megosztott erőforrásokhoz. Egy atomi műveletet csak egy szál hajt végre .
Osztályozás
A műveletek atomitását hardver (hardver) és szoftver (programkód) biztosíthatja. Az első esetben speciális gépi utasításokat használnak , amelyek atomitását a hardver garantálja. A második esetben speciális szinkronizáló szoftver eszközöket használnak , amelyek segítségével a megosztott erőforrást zárolják ; blokkolás után az atomosan végrehajtandó műveletet hajtják végre. A zárolás egy atomi művelet, amely vagy erőforrást ad egy szálnak , vagy közli a szálnak, hogy az erőforrást egy másik szál vagy folyamat már használja (elfoglalt).
Összeszerelési utasítások és atomitás
Gépi utasítások, amelyek végrehajtása mindig atominak tekinthető:
- gépi utasítások a memóriából egy igazított címen történő adatolvasáshoz és egy általános regiszterbe írásához;
- gépi utasítások egy általános célú regiszter adatainak kiolvasásához és a memóriába írásához igazított címen;
- kifejezetten atomi működésre tervezett gépi utasítások, amelyeket általában atomi utasításoknak neveznek.
Nem atomi utasítások:
- gépi utasítások adatok olvasásához/írásához nem igazított címen (az egyik utasítás végrehajtásával a processzor két memóriacella elérésére kényszerül. Abban a pillanatban, amikor a processzor hozzáfér az egyik cellához, a másik cellát egy másik processzor módosíthatja);
- minden gépi utasítás " olvasás-módosítás-írás " formájú (egy ilyen utasítás végrehajtása az adatok memóriából való kiolvasására, az adatok ALU -ba való cseréjére és az adatok memóriába írására redukálódik. Az adatok memóriából való kiolvasása után a memória tartalma megváltozhat);
- string gép utasítások x86 processzorokhoz ;
- push és pop gépi utasítások x86 processzorokhoz;
- gépi utasítások, amelyek speciális vezérlőregiszterekkel működnek (az ilyen utasítások több processzorcikluson belül végrehajthatók, és több tíz vagy száz memóriaelérést generálnak, csak a rendszerszoftverekben használják ).
Atomic utasítások x86 processzorokhoz
Atomic utasítások x86 architektúrájú processzorokhoz :
- A CMPXCHG, CMPXCHG8B, CMPXCHG16B az x86 processzorok fő atomutasítása, amely összehasonlítást és cserét végez . A LOCK [1] [2] előtaggal együtt használva atomosan összehasonlítja egy változó értékét a megadott értékkel, és az összehasonlítás eredményétől függően vagy beállítja a megadott értéket a változóra, vagy nem csinál semmit. Ez az alapja az összes nem blokkoló algoritmus megvalósításának, amelyet gyakran használnak a spinlockok , RWLockok és szinte minden magas szintű szinkronizáló elem, például szemaforok, mutexek, események stb. végrehajtásában;
- Az XCHG egy regiszter és memóriacella, vagy két regiszter közötti adatcserére szolgáló művelet. Ennek a műveletnek az atomitása számít, ha az utasítás operandus egy memóriacella. Az x86 -os processzorokon a LOCK [3] előtag használata nélkül is atomosan lefut (ezért kerülni kell, hogy ezt az utasítást egyszerűen egy regiszter és egy memóriahely értékeinek cseréjére használja, mert ez szükségtelen és nagyon jelentős késéseket okoz kódvégrehajtás). Gyakran használják a spinlockok végrehajtásában .
Ezen kívül számos olvasási-módosítási-írási gépi utasítás atomszerűen hajtódik végre, ha előtagja LOCK [4] ( opcode 0xF0), például a következők:
- összeadás és kivonás parancsok ADD, ADC, SUB és SBB, ha a cél operandus egy memóriacella címe;
- növelés és csökkentés parancsok INC és DEC;
- logikai parancsok ÉS, VAGY és XOR;
- egyetlen operandus utasítás NEG és NOT;
- bitműveletek BTS, BTR és BTC;
- összeadás és csere művelet XADD.
A LOCK előtag zárolja a memóriahozzáférést az utasítás időtartamára. A zár kiterjedhet az operandus hosszánál szélesebb memóriaterületre, például egy gyorsítótár -sor hosszára .
Atomic utasítások RISC processzorokban
A RISC processzorarchitektúrák egyik jellemzője az olvasási-módosítási-írási utasítások hiánya . A DEC Alpha , PowerPC , MIPS és ARM (ARMv6 és régebbi) RISC processzorok támogatják a nem blokkoló, kizárólagos memóriahozzáférést. Az atomi műveletek egy pár exkluzív LL és SC olvasási-írási utasítással valósulnak meg a következők szerint:
- betöltés jelzéssel (LL - load linked);
- adatváltozás;
- írási kísérlet (SC - feltételes tárolás).
Az első utasítás (LL) betölti az adatokat a memóriahelyről egy regiszterbe, és megjelöli a helyet a kizárólagos hozzáférés helyeként. Ezt követően megtörténik a szükséges adatmódosítások a nyilvántartásban. Az adatok a regiszterből a memóriába (SC) írása csak akkor történik meg, ha a memóriacella értéke nem változott. Ha az érték megváltozott, a három műveletet (LL, adatcsere és SC) meg kell ismételni.
Atomic utasítások és fordítók
A magas szintű nyelvek fordítói általában nem használnak atomi utasításokat a kód generálásakor, mert egyrészt az atomi műveletek sokszor erőforrásigényesebbek, mint a hagyományosak, másrészt a fordítónak nincs információja arról, hogy mikor kell hozzáférni az adatokhoz. atomosan kell végrehajtani (mert még a C/C++ változó illékony módosítója sem jelenti az atomi műveletek tényleges szükségességét). Ha szükséges, a programozó a következő módok egyikén használhatja az atomi utasításokat:
- szúrjon be atomi utasításokat a kódba a fordító által biztosított assembler segítségével , például a gcc fordító GCC Inline Assembly -jával ;
- használja a fordító által biztosított függvényeket, amelyek atomi utasításokat hívnak meg, például a gcc fordító __builtin_ vagy __sync_ családjának függvényeit ;
- használja a könyvtárak által biztosított függvényeket , amelyek atomi utasításokat hívnak, például a Glib könyvtár függvényeit ;
- használjon olyan programozási nyelveket, amelyek támogatják az atomitást, például a C11 és C++14 szabványnyelveket , amelyek támogatják az _Atomic és atomi típusokat, valamint az atomic_ család funkcióit [5] .
Lásd még
Jegyzetek
- ↑ CMPXCHG - Összehasonlítás és csere Archiválva : 2012. november 2. a Wayback Machine -nél .
- ↑ CMPXCHG8B - Hasonlítsa össze és cserélje ki 8 bájtot Archiválva : 2012. november 30. a Wayback Machine -nél .
- ↑ http://faydoc.tripod.com/cpu/xchg.htm Archiválva : 2012. november 20. a Wayback Machine -nél "Ha egy memória-operandra hivatkoznak, a processzor zárolási protokollja automatikusan megvalósul a csereművelet időtartama alatt, függetlenül a LOCK előtag vagy az IOPL értékének megléte vagy hiánya."
- ↑ Atomműveletek. A probléma története . Letöltve: 2012. november 12. Az eredetiből archiválva : 2012. november 17.. (határozatlan)
- ↑ Atomműveleti könyvtár - cppreference.com . Letöltve: 2012. november 12. Az eredetiből archiválva : 2015. augusztus 13.. (határozatlan)
Linkek