Verständnis Von Linux-Kernel-Ringpuffer
Gibt es einen Artikel unter: http://lwn.net/Articles/378262/, beschreibt die Linux-Kernel Ringpuffer-implementation. Ich habe einige Fragen:
Hier ist der "Produzent":
spin_lock(&producer_lock);
unsigned long head = buffer->head;
unsigned long tail = ACCESS_ONCE(buffer->tail);
if (CIRC_SPACE(head, tail, buffer->size) >= 1) {
/* insert one item into the buffer */
struct item *item = buffer[head];
produce_item(item);
smp_wmb(); /* commit the item before incrementing the head */
buffer->head = (head + 1) & (buffer->size - 1);
/* wake_up() will make sure that the head is committed before
* waking anyone up */
wake_up(consumer);
}
spin_unlock(&producer_lock);
Fragen:
- Da dieser code befasst sich explizit mit memory-Bestellung und Unteilbarkeit was ist der Punkt, der spin_lock()?
- So weit, mein Verständnis ist, dass ACCESS_ONCE Stoppt compiler umsortieren wahr?
- Hat produce_item(item) einfach alle schreibt im Zusammenhang mit dem Artikel?
- Ich glaube smp_wmb() garantiert, dass alle Schreibvorgänge in produce_item(item) abgeschlossen ist, BEVOR der "veröffentlichen" schreiben, die darauf folgt. wahr?
- Der Kommentar auf der Seite, wo ich diese code scheint zu implizieren, dass eine smp_wmb() würde
normalerweise benötigt Sie nach der Aktualisierung der Kopf-index, aber wake_up(Verbraucher) dies tut, so ist es nicht notwendig. Ist das wahr? Wenn ja, warum?
Hier ist der "Verbraucher":
spin_lock(&consumer_lock);
unsigned long head = ACCESS_ONCE(buffer->head);
unsigned long tail = buffer->tail;
if (CIRC_CNT(head, tail, buffer->size) >= 1) {
/* read index before reading contents at that index */
smp_read_barrier_depends();
/* extract one item from the buffer */
struct item *item = buffer[tail];
consume_item(item);
smp_mb(); /* finish reading descriptor before incrementing tail */
buffer->tail = (tail + 1) & (buffer->size - 1);
}
spin_unlock(&consumer_lock);
Spezifische Fragen zum "Verbraucher":
- Was bedeutet smp_read_barrier_depends() zu tun? Aus einigen Kommentaren in einem forum, es scheint, wie Sie haben könnte, hat ein smp_rmb() hier, aber auf manchen Architekturen ist dies unnötig (x86) und zu teuer, so smp_read_barrier_depends() wurde erstellt, um zu tun, diese Optional... Das heißt, ich weiß wirklich nicht verstehen, warum smp_rmb() ist immer notwendig!
- Ist die smp_mb() gibt es die Garantie, dass alle liest, bevor es abgeschlossen ist, bevor das schreiben nach es?
InformationsquelleAutor dicroce | 2013-01-17
Schreibe einen Kommentar Antworten abbrechen
Du musst angemeldet sein, um einen Kommentar abzugeben.
Für den Produzenten:
spin_lock()
hier ist, um zu verhindern, dass zwei Produzenten von versuchen, ändern Sie die Warteschlange in der gleichen Zeit.ACCESS_ONCE
verhindert Neuordnung, es verhindert auch, dass der compiler aus nachladen der Wert höher. (Es gibt ein Artikel überACCESS_ONCE
auf LWN erweitert, dass auf dieser weiter)head
Wert.Verbraucher:
smp_read_barrier_depends()
ist ein Daten-Abhängigkeit Barriere, die eine schwächere form einer schreib-Barriere (siehe Zwei). Der Effekt in diesem Fall ist zu gewährleisten, dassbuffer->tail
gelesen, bevor Sie es als ein array-index inbuffer[tail]
.smp_mb()
hier ist die komplette memory-Barriere, so dass alle lese-und Schreibvorgänge durch diesen Punkt.Zusätzliche Verweise:
(Anmerkung: ich bin mir nicht ganz sicher über meine Antworten für 5, - in den Produzenten-und 1 für den Verbraucher, aber ich glaube, Sie werden eine faire Annäherung an die Fakten. Ich empfehle das Lesen der Dokumentation Seite über memory-Barrieren, wie es ist umfassender als alles, was ich schreiben könnte hier.)