wo SPINLOCK_SHARED = 0x80000000 ist eine vordefinierte Konstante.
Ich frage mich, wozu wir brauchen (SPINLOCK_SHARED | 1) - 1 – für Typkonvertierungszwecke? das Ergebnis des Ausdrucks wäre 80000000 – dasselbe wie 0x80000000, nicht wahr? aber warum ist ORing 1 und Subtracting 1 wichtig?
Habe das Gefühl, dass mir etwas fehlt..
#define SPINLOCK_SHARED 0x80000000
– RaGa__M
19. Dezember 2019 um 12:35 Uhr
Ich vermute, es gibt keinen Grund. Möglicherweise eine Copy-Paste-Sache. Könnten Sie hinzufügen, wo genau Sie das gefunden haben (welche Version von welchem Kernel, welche Datei usw.).
Wenn es keinen Wettbewerb gibt, dann count (der vorherige Wert) sein sollte 0, ist es aber nicht. Dies count value wird als Parameter an übergeben _spin_lock_contested als die value Parameter. Dies value wird dann mit überprüft if aus dem OP:
/*
* WARNING! Caller has already incremented the lock. We must
* increment the count value (from the inline's fetch-add)
* to match.
*
* Handle the degenerate case where the spinlock is flagged SHARED
* with only our reference. We can convert it to EXCLUSIVE.
*/
if (value == (SPINLOCK_SHARED | 1) - 1) {
if (atomic_cmpset_int(&spin->counta, SPINLOCK_SHARED | 1, 1))
return;
}
Das im Hinterkopf behalten value ist der vorherige Wert von spin->countaund letzteres wurde bereits um 1 erhöht, erwarten wir spin->counta gleich value + 1 (sofern sich zwischenzeitlich nichts geändert hat).
Also prüfen ob spin->counta == SPINLOCK_SHARED | 1 (Voraussetzung für die atomic_cmpset_int) entspricht der Überprüfung von if value + 1 == SPINLOCK_SHARED | 1die umgeschrieben werden kann als value == (SPINLOCK_SHARED | 1) - 1 (auch wenn sich zwischenzeitlich nichts geändert hat).
Während value == (SPINLOCK_SHARED | 1) - 1 könnte umgeschrieben werden als value == SPINLOCK_SHAREDwird unverändert gelassen, um die Absicht des Vergleichs zu verdeutlichen (d. h. den inkrementierten vorherigen Wert mit dem Testwert zu vergleichen).
Oder iow. Die Antwort scheint zu sein: für Klarheit und Codekonsistenz.
Danke für deine Antwort, alles außer (SPINLOCK_SHARED | 1) - 1 Teil ist verständlich und value == SPINLOCK_SHARED ist auch mein Gedanke, weil wir prüfen, ob der vorherige Wert das Shared-Flag gesetzt hat. Wenn ja, schalten Sie die Sperre auf exklusiv………
– RaGa__M
19. Dezember 2019 um 13:19 Uhr
@RaGa__M : die Absicht der if prüfen ist zu prüfen, ob value + 1 (was der gleiche Wert sein sollte wie spin->counta wenn sich zwischenzeitlich nichts geändert hat) gleich SPINLOCK_SHARED | 1. Wenn du das schreibst if prüfen als value == SPINLOCK_SHARED, diese Absicht ist nicht klar, und es wäre viel schwieriger herauszufinden, was die Überprüfung bedeutet. Beides behalten SPINLOCK_SHARED | 1 und - 1 ausdrücklich in der if Überprüfung ist beabsichtigt.
– Sander DeDycker
19. Dezember 2019 um 13:26 Uhr
Aber es sorgt tatsächlich für Verwirrung.
– RaGa__M
20. Dezember 2019 um 5:30 Uhr
Warum nicht if (value + 1 == (SPINLOCK_SHARED | 1) )?
– Paul H
20. Dezember 2019 um 20:09 Uhr
Nun …. es könnte einfach sein value & SPINLOCK_SHARED was besser lesbar ist.
– RaGa__M
21. Dezember 2019 um 7:09 Uhr
Ich denke, das Ziel ist wahrscheinlich, das niedrigstwertige Bit zu ignorieren:
Wenn SPINLOCK_SHARED binär ausgedrückt xxx0 ist -> Ergebnis ist xxx0
Wenn SPINLOCK_SHARED = xxx1 -> Ergebnis ist auch xxx0
wäre vielleicht klarer gewesen, einen Bitmaskenausdruck zu verwenden?
Das ist, was der Code tut, aber die Frage ist warum Würden Sie das für eine definierte Konstante tun, bei der das niederwertigste Bit nicht gesetzt ist?
– Sander DeDycker
19. Dezember 2019 um 12:37 Uhr
@SanderDeDycker Weil Linux-Kernel?
– Ludin
19. Dezember 2019 um 12:39 Uhr
@Lundin Der Linux-Kernel ist nicht von verständlichen Codierungspraktiken ausgenommen. Ganz im Gegenteil.
– Qix – MONICA WURDE MISSHANDELT
19. Dezember 2019 um 12:40 Uhr
@ Qix Ich bin absolut anderer Meinung. Lesen Sie das Dokument zum Programmierstil des Linux-Kernels. Es ist ein Qualitätsdokument zum “Garagenhacken”, das völlig frei von Begründungen ist.
– Ludin
19. Dezember 2019 um 12:41 Uhr
@ Qix Wenn du das sagst. Ich war ein großer Linux-Fan, bis ich einen Blick auf den Code geworfen und das Kernel-Coding-Style-Dokument gelesen habe. Heute halte ich 10 Meter Sicherheitsabstand zu Linux-Rechnern ein.
– Ludin
19. Dezember 2019 um 12:53 Uhr
Der Effekt von
(SPINLOCK_SHARED | 1) - 1
soll sicherstellen, dass das niederwertige Bit des Ergebnisses vor dem Vergleich mit gelöscht wird value. Ich stimme zu, dass es ziemlich sinnlos erscheint, aber anscheinend hat das niederwertige Bit eine bestimmte Verwendung oder Bedeutung, die in diesem Code nicht offensichtlich ist, und ich denke, wir müssen davon ausgehen, dass die Entwickler einen guten Grund dafür hatten. Eine interessante Frage wäre – ist das gleiche Muster (| 1) -1) in der gesamten Codebasis verwendet, die Sie sich ansehen?
Es ist eine verschleierte Art, eine Bitmaske zu schreiben. Lesbare Version: value == (SPINLOCK_SHARED & ~1u).
Es wurde nur aus Gründen der Klarheit so gemacht, das ist alles. Das liegt daran, dass atomic_fetchadd_int() (in zB sys/spinlock2.h) den Wert VOR der Addition/Subtraktion zurückgibt und dieser Wert an _spin_lock_contested() übergeben wird.
Beachten Sie, dass der C-Compiler alle konstanten Ausdrücke vollständig vorberechnet. Tatsächlich kann der Compiler sogar Inline-Code basierend auf Bedingungen optimieren, die übergebene Prozedurargumente verwenden, wenn den Prozeduren Konstanten in diesen Argumenten übergeben werden. Aus diesem Grund hat lockmgr() inline in sys/lock.h eine case-Anweisung …. weil diese gesamte case-Anweisung optimiert wird und in einen direkten Aufruf der entsprechenden Funktion übergeht.
Außerdem stellt bei all diesen Verriegelungsfunktionen der Overhead der atomaren Operationen alle anderen Berechnungen um zwei oder drei Größenordnungen in den Schatten.
-Matt
Diese Antwort stammt vom Autor.
– RaGa__M
2. September 2020 um 11:01 Uhr
Meistens wird dies getan, um mehrere zusätzliche Fälle zu behandeln. In diesem Fall sagen wir das zum Beispiel SPINLOCK_SHARED kann nicht 1 sein:
int SPINLOCK_SHARED = 0x01
int res = (SPINLOCK_SHARED | 1) - 1 // 0
Diese Antwort stammt vom Autor.
– RaGa__M
2. September 2020 um 11:01 Uhr
14077600cookie-check(x | y) – y warum kann es nicht einfach x oder gar `x | sein 0`yes
#define SPINLOCK_SHARED 0x80000000
– RaGa__M
19. Dezember 2019 um 12:35 Uhr
Ich vermute, es gibt keinen Grund. Möglicherweise eine Copy-Paste-Sache. Könnten Sie hinzufügen, wo genau Sie das gefunden haben (welche Version von welchem Kernel, welche Datei usw.).
– Sander DeDycker
19. Dezember 2019 um 12:39 Uhr
Hier, github.com/DragonFlyBSD/DragonFlyBSD/blob/master/sys/kern/…
– RaGa__M
19. Dezember 2019 um 12:42 Uhr
Dieselbe Quellcodedatei enthält auch
if (atomic_cmpset_int(&spin->counta, SPINLOCK_SHARED|0, 1))
.– Eric Postpischil
19. Dezember 2019 um 12:58 Uhr
Dann denke ich, müssen wir den Autor fragen, warum es geändert wurde.
– komischer Mann
19. Dezember 2019 um 13:01 Uhr