Handbuch zur dynamischen Ablaufverfolgung in Solaris

Kapitel 18 Der Provider lockstat

Der Provider lockstat stellt Prüfpunkte zur Verfügung, die zur Unterscheidung von statistischen Daten über Lock-Contentions oder zur Untersuchung nahezu jedes Aspekts des Sperrverhaltens eingesetzt werden können. Der Befehl lockstat(1M) ist eigentlich ein DTrace-Verbraucher, der den Provider lockstat zum Abrufen der Rohdaten benutzt.

Überblick

Der Provider lockstat stellt zwei Arten von Prüfpunkten zur Verfügung: „contention-event-Prüfpunkte“ und „hold-event-Prüfpunkte“.

Contention-event-Prüfpunkte sprechen auf Konkurrenzsituationen (Contentions oder Kollisionen) an einer Synchronisierungsgrundeinheit an und werden ausgelöst, wenn ein Thread gezwungen ist, zu warten, bis eine Ressource verfügbar wird. Solaris ist allgemein für den konkurrenzfreien Betrieb (also ohne Contentions) optimiert. Länger andauernde Konkurrenzsituationen sind folglich nicht zu erwarten. Diese Prüfpunkte helfen Ihnen, Fälle zu verstehen, in welchen es trotzdem zu Konkurrenz kommt. Da Konkurrenzsituationen relativ selten sind, beeinträchtigt die Aktivierung von contention-event-Prüfpunkten die Leistung in der Regel kaum.

Hold-event-Prüfpunkte sprechen auf das Erhalten, Freigeben oder eine andere Art der Manipulation von Synchronisierungsgrundeinheiten an. Diese Prüfpunkte können helfen, beliebige Fragen über die Art und Weise der Manipulation von Synchronisierungsgrundeinheiten zu beantworten. Da in Solaris sehr häufig Synchronisierungsgrundeinheiten erhalten und freigegeben werden (auf belasteten Systemen bewegen wir uns hier in einem Größenbereich von mehreren Millionen Mal pro Sekunde und CPU), bewirkt die Aktivierung von hold-event-Prüfpunkten eine wesentlich höheren Prüfaktivität als die Aktivierung von contention-event-Prüfpunkten. Die Aktivität kann zwar beträchtlich ausfallen, ist aber nicht schädlich. Diese Prüfpunkte können trotzdem gefahrlos auf Produktionssystemen aktiviert werden.

Der Provider lockstat stellt Prüfpunkte zur Verfügung, die auf die verschiedenen Synchronisierungsgrundeinheiten in Solaris ansprechen. Der Rest dieses Kapitels befasst sich mit diesen Grundeinheiten und den auf sie ansprechenden Prüfpunkten.

Prüfpunkte für adaptive Sperren

Adaptive Sperren (adaptive locks) schützen einen kritischen Abschnitt durch Mutex (gegenseitiger Ausschluss) und können in den meisten Kontexten im Kernel erworben werden. Da für adaptive Sperren nur wenige Kontextbeschränkungen gelten, stellen sie die große Mehrheit der Synchronisierungsgrundeinheiten im Solaris-Kernel dar. Diese Sperren weisen ein in Bezug auf Konkurrenzsituationen adaptives (dynamisches) Verhalten auf: Wenn ein Thread eine belegte adaptive Sperre fordert, stellt er fest, ob der besitzende Thread derzeit auf einer CPU läuft. Wenn der Besitzer auf einer anderen CPU läuft, wird der fordernde Thread in den Wartezustand versetzt. Wenn der Besitzer nicht läuft, wird der fordernde Thread blockiert.

Die vier lockstat-Prüfpunkte für adaptive Sperren sind in Tabelle 18–1 aufgeführt. arg0 enthält für jeden Prüfpunkt einen Zeiger auf die kmutex_t-Struktur, die den adaptiven Lock darstellt.

Tabelle 18–1 Prüfpunkte für adaptive Sperren

adaptive-acquire

Hold-event-Prüfpunkt, der unmittelbar nach dem Erlangen einer adaptiven Sperre ausgelöst wird. 

adaptive-block

Contention-event-Prüfpunkt, der ausgelöst wird, nachdem ein durch einen belegten, adaptiven Mutex blockierter Thread „aufgewacht“ ist und den Mutex erlangt hat. Wenn beide Prüfpunkte aktiviert sind, wird adaptive-block vor adaptive-acquire ausgelöst. Für das Erlangen einer einzigen Sperre können die Prüfpunkte adaptive-block und adaptive-spin ausgelöst werden. arg1 für adaptive-block enthält die Schlafzeit in Nanosekunden.

adaptive-spin

Contention-event-Prüfpunkt, der ausgelöst wird, nachdem ein durch einen belegten, adaptiven Mutex in den Wartezustand versetzter Thread den Mutex erfolgreich erlangt hat. Wenn beide Prüfpunkte aktiviert sind, wird adaptive-spin vor adaptive-acquire ausgelöst. Für das Erlangen einer einzigen Sperre können die Prüfpunkte adaptive-block und adaptive-spin ausgelöst werden. arg1 für adaptive-spin enthält die Spin-Anzahl: die Zeit in Nanosekunden, die in der Warteschleife vor dem Erlangen der Sperre verbracht wurde.

adaptive-release

Hold-event-Prüfpunkt, der unmittelbar nach der Freigabe einer adaptiven Sperre ausgelöst wird. 

Spinlock-Prüfpunkte

In einigen Kernel-Kontexten wie beispielsweise Interrupts auf hoher Ebene oder in jedem den Dispatcher-Zustand manipulierenden Kontext können Threads nicht blockiert werden. In diesen Kontexten wird die Verwendung von adaptiven Sperren durch diese Einschränkung verhindert. Stattdessen wird der Mutex in diesen Kontexten anhand von Spinlocks ausgesprochen. Das Verhalten dieser Sperren bei Konkurrenz besteht im Durchlaufen einer Warteschleife, bis die Sperre vom Besitzer-Thread freigegeben wird. Die drei Prüfpunkte im Zusammenhang mit Spinlocks sind in Tabelle 18–2 beschrieben.

Tabelle 18–2 Spinlock-Prüfpunkte

spin-acquire

Hold-event-Prüfpunkt, der unmittelbar nach dem Erlangen eines Spinlocks ausgelöst wird. 

spin-spin

Contention-event-Prüfpunkt, der ausgelöst wird, nachdem ein Thread, der durch einen belegten Spinlock in eine Warteschleife gestellt wurde, den Spinlock erfolgreich erlangt hat. Wenn beide Prüfpunkte aktiviert sind, wird spin-spin vor spin-acquire ausgelöst. arg1 für spin-spin enthält die Spin-Zeit: die Zeit in Nanosekunden, die im Spin-Status vor dem Erlangen der Sperre verbracht wurde. Die Spin-Anzahl an sich ist nicht sehr bedeutungsvoll, kann aber zum Vergleich von Wartezeiten genutzt werden.

spin-release

Hold-event-Prüfpunkt, der unmittelbar nach der Freigabe eines Spinlocks ausgelöst wird. 

Adaptive Sperren sind sehr viel häufiger als Spinlocks. Um diese Beobachtung auf Daten zu stützen, greifen wir auf das folgende Skript zurück, das die Gesamtzahl beider Lock-Typen anzeigt.

lockstat:::adaptive-acquire
/execname == "date"/
{
	@locks["adaptive"] = count();
}

lockstat:::spin-acquire
/execname == "date"/
{
	@locks["spin"] = count();
}

Führen Sie dieses Skript in einem Fenster aus und den Befehl date(1) in einem anderen. Wenn Sie das DTrace-Skript beenden, erhalten Sie eine Ausgabe wie im nächsten Beispiel:


# dtrace -s ./whatlock.d
dtrace: script './whatlock.d' matched 5 probes 
^C
spin                                                             26
adaptive                                                       2981

Wie diese Ausgabe zeigt, sind über 99 Prozent der bei der Ausführung des Befehls date erlangten Sperren adaptive Sperren. Es überrascht Sie vielleicht, dass bei einer einfachen Aktion wie date so viele Sperren erlangt werden. Die große Anzahl der Sperren ist ein natürlicher Nebeneffekt der in einem so extrem skalierbaren System wie dem Solaris-Kernel erforderlichen feinkörnigen Sperrstrukturen.

Threadsperren

Threadsperren sind eine spezielle Form des Spinlocks, die dazu dienen, einen Thread zu sperren, damit sein Status geändert werden kann. Während Hold-Ereignisse von Threadsperren als hold-event-Prüfpunkte für Spinlocks zur Verfügung stehen (d. h. als spin-acquire und spin-release), gibt es für spezifisch auf Threadsperren bezogene Konkurrenzereignisse einen eigenen Prüfpunkt. Der Prüfpunkt für Threadsperren-Hold-Ereignisse ist in Tabelle 18–3 beschrieben.

Tabelle 18–3 Threadsperren-Prüfpunkt

thread-spin

Contention-event-Prüfpunkt, der ausgelöst wird, nachdem ein Thread in einer Warteschleife an einer Threadsperre gewartet hat. Wie auch bei anderen contention-event-Prüfpunkten, wird thread-spin vor spin-acquire ausgelöst, wenn sowohl der contention-event-Prüfpunkt als auch der hold-event-Prüfpunkt aktiviert sind. Im Gegensatz zu anderen contention-event-Prüfpunkten wird thread-spin jedoch vor dem tatsächlichen Erlangen der Sperre ausgelöst. So können auf eine spin-acquire- mehrere thread-spin-Prüfpunktauslösungen kommen.

Prüfpunkte für Leser/Schreiber-Sperren

Leser/Schreiber-Sperren setzen eine Richtlinie um, die entweder mehrere Leser (reader) oder einen einzigen Schreiber (writer) in einem kritischen Abschnitt zulässt - nicht aber beides. Diese Sperren kommen in der Regel in Strukturen vor, die häufiger durchsucht als geändert werden und für die im kritischen Abschnitt viel Zeit vorgesehen ist. Wenn nicht viel Zeit im kritischen Abschnitt zur Verfügung steht, werden Leser/Schreiber-Sperren implizit über den für die Implementierung der Sperre genutzten gemeinsamen Speicher serialisiert. Dabei wird ihnen kein Vorrang gegenüber adaptiven Sperren eingeräumt. Unter rwlock(9F) finden Sie weitere Informationen zu Leser/Schreiber-Sperren.

Tabelle 18–4 zeigt die Prüfpunkte für Leser/Schreiber-Sperren. arg0 enthält für jeden Prüfpunkt einen Zeiger auf die krwlock_t-Struktur, die den adaptiven Lock darstellt.

Tabelle 18–4 Prüfpunkte für Leser/Schreiber-Sperren

rw-acquire

Hold-event-Prüfpunkt, der unmittelbar nach dem Erlangen einer Leser/Schreiber-Sperre ausgelöst wird. arg1 enthält die Konstante RW_READER, wenn die Sperre als Leser erlangt wurde und RW_WRITER, wenn sie als Schreiber erlangt wurde.

rw-block

Contention-event-Prüfpunkt, der ausgelöst wird, nachdem ein an einer belegten Leser/Schreiber-Sperre blockierter Thread aufgewacht ist und die Sperre erlangt hat. arg1 enthält die Dauer (in Nanosekunden), die der aktuelle Thread schlafen gelegt wurde, bis er die Sperre erlangen konnte. arg2 enthält die Konstante RW_READER, wenn die Sperre als Leser erlangt wurde und RW_WRITER, wenn sie als Schreiber erlangt wurde. arg3 und arg4 enthalten weitere Informationen zu den Gründen für die Blockierung. arg3 ist nicht Null, wenn - und nur dann - die Sperre beim Blockieren des aktuellen Threads als Schreiber belegt war. arg4 enthält die Anzahl der Leser zum Zeitpunkt der Blockierung des aktuellen Threads. Wenn sowohl der Prüfpunkt rw-block als auch rw-acquire angegeben sind, wird rw-block vor rw-acquire ausgelöst.

rw-upgrade

Hold-event-Prüfpunkt, der ausgelöst wird, nachdem ein Thread eine Leser/Schreiber-Sperre erfolgreich vom Leser- auf den Schreiberstatus heraufgestuft hat. Für diese Upgrades gibt es kein Konkurrenzereignis, da sie nur über eine nicht-blockierende Schnittstelle, rw_tryupgrade(9F), möglich sind.

rw-downgrade

Hold-event-Prüfpunkt, der ausgelöst wird, nachdem ein Thread seinen Besitzerstatus für eine Leser/Schreiber-Sperre von Schreiber auf Leser herabgestuft hat. Für diese Downgrades gibt es keine Konkurrenzereignisse, da sie stets ohne Kollision erfolgen. 

rw-release

Hold-event-Prüfpunkt, der unmittelbar nach der Freigabe einer Leser/Schreiber-Sperre ausgelöst wird. arg1 enthält die Konstante RW_READER, wenn die freigegebene Sperre als Leser belegt wurde und RW_WRITER, wenn sie als Schreiber belegt wurde. Aufgrund von Up- und Downgrades wird die Sperre möglicherweise nicht in der Form freigegeben, in der sie erhalten wurde.

Stabilität

Der Provider lockstat beschreibt die verschiedenen Stabilitäten anhand des DTrace-Stabilitätsmechanismus gemäß der folgenden Tabelle. Weitere Informationen zum Stabilitätsmechanismus finden Sie in Kapitel 39Stabilität.

Element 

Namensstabilität 

Datenstabilität 

Abhängigkeitsklasse 

Provider 

Evolving 

Evolving 

Common

Modul 

Private 

Private 

Unknown 

Funktion 

Private 

Private 

Unknown 

Name 

Evolving 

Evolving 

Common

Argumente 

Evolving 

Evolving 

Common