Mehr Kerne, mehr Ärger – Nicht nur Steinobst kann einem den Magen verderben

Hoppla,

sonst legt der Herr von Leitner doch immer sehr präzise seine Finger in die Wunden der IT-Branche. Diesmal aber greift er daneben — und ist dabei mit Herrn Torvalds in guter Gesellschaft. Beide übersehen meiner Meinung die eigentliche Ursache und die Tragweite des Problems, das da aufgetaucht ist.

Worum geht es? – Die Entwickler des B-Baum-Dateisystems (BTRFS) und des Gnu-C-Compilers (GCC) streiten sich über einen Bug, der von einer Datenstruktur herrührt, die grob vereinfacht etwa so aussieht:

struct foo {

int a;

int b;

}

Eigentlich sollte der Integer-Datentyp ‘int’ in C einem Maschinenwort entsprechen, also der kleinsten Speichermenge, die ein Prozessor lesen oder schreiben kann. Tut er aber nicht immer. So kann es passieren, dass die Maschine a und b gleichzeitig in einem Wort lesen bzw. schreiben kann. Wenn die Maschine dann auch noch mit mehr als einem Prozessorkern auf dem Speicher unterwegs ist, kann es Probleme geben.

Warum? – Na ja. Wenn ein Prozessorkern a schreibt während ein anderer b schreibt, kommt es auf die genaue zeitliche Reihenfolge an, in der das geschieht; der zweite gewinnt und überschreibt das, was der erste zuvor geschrieben hatte. Ein so genannter Data-Race.

Gute Programmierer vermeiden solche Data-Races. Hier aber versteckt sich das Problem hinter zwei scheinbar getrennten Integer-Variablen, die auf manchen Prozessorarchitekturen vom Compiler aber eben doch in ein Maschinenwort abgebildet werden. Da liegt der Hund begraben! — Da hilft auch keine Volatile-Declaration, wie einige in dieser Diskussion vorgeschlagen haben, oder das Lamentieren über fehlende Sub-Wort-Zugriffe in der Prozessorarchitektur. Solche Sub-Wort-Zugriffe wären zwar schön, sind aber in Hardware teuer umzusetzen. Schlussendlich muss man die Wortbreite der Maschine beachten, wenn man über Data-Races nachdenkt.

Leider ist die Wortbreite in C nicht klar definiert. Moderne Sprachen machen sich da mehr Gedanken und definieren ein so genanntes Memory Modell. Aber auch das nimmt einem nicht die Aufgabe ab, sich über Data-Races Gedanken zu machen. Es vereinfacht nur das anschließende Schwarze-Peter-Spiel. Es hilft nicht dagegen, dass ein Stück Software, und sei es der Linux-Kernel, Annahmen über die Anordnung der Daten im Speicher trifft, die in der Praxis nicht gegeben sind. Hier hilft es nur, diese Annahmen im Code explizit zu machen und so den Compiler dazu zu zwingen, diese Annahmen einzuhalten.

Und warum ist das alles überhaupt so spannend? — Ich finde es höchst spannend, denn die Zahl der Prozessorkerne und die Wortbreite steigen. (Denn genau genommen muss man nicht die Registerworte sondern die Cache-Zeilen anschauen; aber das würde jetzt zu weit führen.) Es wird also immer wahrscheinlicher, dass man in der Praxis über diese Art von Problem stolpert. Herr Torvalds sagt dazu:We probably have tons of random places in the kernel that violate even the alpha rules“, wobei der Alpha-Prozessor noch vergleichsweise harmlos war. Und nein, ich glaube nicht, dass man auf Dauer die Prozessoren das Problem lösen lassen kann. Da kommt also noch einiges auf uns zu!