Planet FAUi2k9

December 09, 2017

Christian DietrichEntwicklungsziele der Menschheit

Ich trage diesen Artikel schon mehrere Monate in meinem Kopf herum; wälze einzelne Punkte hin und her und überlege was ich eigentlich schreiben möchte. Es geht mir darum zu beleuchten, wie es mit der Evolution des Menschen eigentlich weiter gehen könnte. Wo sind Punkte an denen Gehirn und Körper des Menschen an eine Welt angepasst sind, die es nicht mehr gibt?

Evolution ist ein Prozess, der nicht stillsteht. Es ist der Prozess mit dem sich das Leben durch Zufallsexperimente an neue Gegebenheiten anpasst. Millionen von zufälligen Mutationen; viele davon Schlecht und manche davon mit evolutionärem Vorteil behaftet. Mit Glück propagieren sich die hilfreichen fort.

Nun ist der Mensch in den meisten Dingen kein Spezialist, sondern ein Generalist. Oder anders gesagt: wir sind nicht besonders gut, aber von allem ein bischen. Die einzige Sache in der wir wirklich brillieren ist das Denken. Es stellt sich da die Frage, ob das überhaupt eine Spezialisierung ist oder eher eine spezialisierte Plattform für eine generalisierte Methode Probleme durch denken zu lösen.

Der Mensch hat sich an seine Umgebung über viele hunderttausend Jahre angepasst. Handlungsweisen und Instinkte haben sich entwickelt, die ein Leben in kleinen Gruppen in der "Wildnis" bei ständiger Nahrungsmittelknappheit erleichtern.

Nun hat sich aber die menschliche Gesellschaft schnell entwickelt und hat in wenigen hundert Jahren massiv an Komplexität gewonnen. Es stellt sich die Frage, was Mechanismen sind, die in der vorherigen Gesellschaft sinnvoll waren und funktioniert haben, aber uns jetzt behindern.

Ich will drei Punkte aufzählen, von denen ich mir vorstellen kann, dass der Mensch sich evolutionär anpasst. Diese Veränderungen könnten stattfinden, wenn weiterhin komplexe Gesellschaftsformationen bestehen und viele Milliarden Menschen den Planeten bevölkern. Die Zeiträume werden allerdings sehr groß sein. Aber eins ist sicher: Wieso sollte uns das unbeeinflusst lassen?

Gier

In der feindlichen Natur macht es Sinn Nahrung dann aufzunehmen, wenn sie vorhanden ist. Wenn wir irgendwo Beeren gefunden haben, und sie gerade reif sind, sollten wir am besten alle zu uns nehmen. Wer mehr Nahrung zu sich nimmt und dabei fett wird, hat eine bessere Chance den nächsten Winter zu überleben. Gier nach Nahrung macht Sinn. Umso mehr ich habe, umso besser sind meine Chancen zu überleben und ich kann meine Gene weiter geben.

Was ist nun anders in der stark arbeitsteiligen Gesellschaft, in der wir Leben? Nahrung ist immer verfügbar. Kalorienreiche Nahrung ist sogar billiger, als kalorienarme Nahrung. Wir sind zudem vor dem Winter um ein vielfaches besser geschützt, als dies früher der Fall war. Es gibt also keinen Grund mehr, mehr Nahrung aufzunehmen, als wir bis zur nächsten Mahlzeit verstoffwechseln. Aber wir befinden uns weiterhin in einem andauernden Exzess; und dafür ist unsere Gier nicht ausgelegt.

Unsere Gier hat, in der Situation eines endlosen Nahrungsstroms, aber erhebliche Nachteile. Unsere Körper werden Übergewichtig und in folge davon krank. Diabetis und Adipositas werden epidemisch und belasten sowohl den einzelnen, als auch die sozialen Strukturen.

Aber unsere Gier beschränkt sich nicht nur auf Nahrung, sondern auch auf andere Konsumgüter. Ich bin mir nicht sicher inwiefern der Drang nach mehr "haben wollen" eine Übertragung der Gier nach Nahrung auf andere Güter ist. Aber man kann es sicherlich als Gier beschreiben. Dadurch betreiben wir eine systematische Ausbeutung der Ressourcen der Erde auf Kosten nachfolgender Generationen. Und wir tun dies entgegen besseren Wissens! Evolutionär völliger Käse. Jedenfalls in komplexen menschengefüllten Systemen.

Angst

Angst macht Sinn. Angst bewahrt uns vor gefährlichen Situationen. Angst bewahrt uns davor es für eine gute Idee zu halten in ein Rudel von Löwen zu gehen und sich dazukuscheln zu wollen. Angst schüttet Adrenalin aus und bereitet den Körper auf Flucht oder Kampf vor. Meistens sitzt man eh unter einem Baum und schnitzt einen Stock zu. Fliehen war die Ausnahme. Macht auch alles Sinn; jedenfalls, wenn es etwas gibt vor dem man flüchten oder gegen das man Kämpfen kann.

Aber wir werden nicht mehr von dem großen Teil der Flora und Fauna tyranisiert, sondern das Blatt hat sich gewendet. Solange wir in Gemeinschaft sind müssen wir keine Angst mehr vor den meisten Dingen der Umgebung haben.

Der Mechanismus allerdings, der ist noch da. Und er springt an. Auf viele Dinge. Angst vor Dingen die unsere Existenz garnicht in Frage stellen. Angst vor der Präsentation. Angst den Job zu verlieren. Angst verlassen zu werden. Angst das Studium nicht zu schaffen. Das sind, ohne Frage, alles unangenehme Dinge die man gerne Vermeiden möchte, aber sie werden einen in den seltensten Fällen direkt, oder auch nur indirekt, umbringen.

Stress wird häufig als andauernder Angstzustand, als ständiges angespannt sein, beschrieben. Und Stress belastet die Gesundheit. Cortisol unterdruckt das Immunsystem. Wer unter Stress stand, zeigt häufig erst dann Symptome, wenn der Stress abgeklungen ist. Und wer einmal mit Menschen, die unter einer Angststörung leiden, zu tun hatte, der weiss auch wie schlimm die Angst das Leben belasten kann.

In einer Welt, die komplex ist und die sich ständig verändert, in der ständig tausend Reize auf uns einfluten, ist es evolutionär eine dumme Idee einen ständigen Angstzustand auszulößen. Vor allem, wenn unsere Existenz von den "Gefahren" garnicht wirklich bedroht ist. Evolutionär könnten wir daher eine erhöhte Angstschwelle entwickeln.

Tod und Lebensdauer

Tod ist der evolutionäre Motor. Wer wengier angepasst ist, der hat eine höhere Mortalitätsrate. Keinen Tod mehr zu haben würde den Stillstand der Entwicklung bedeuten. Jedenfalls wenn wir von Individuuen ausgehen, die ihre Gensequenz nicht maßgeblich während ihrer Lebenszeit ändern.

Im Vergleich zu den meisten Tieren ist unsere Lebensspanne schon relativ lange. Außerdem sterben menschliche Individuen nicht kurz nach ihrer Zeugungsunfähigkeit (Grossmutter-Hypothese). Find ich persöhnlich ja auch eine gute Sache, dass das so ist.

Aber unsere Lebensspanne ist nur relativ lange im Vergleich zum Zyklus der Jahre auf der Erde. In dem Moment in dem wir die Erde verlassen wollen, ist sie unsere größte Beschränkung. Das Universum lässt es nicht zu, dass wir mit mehr als Lichtgeschwindigkeit reisen. Daher ist eigentlich unsere einzige andere Stellschraube, wie wir interstellare Reisen bei realistischen Geschwindigkeiten durchführen können, lange zu leben.

Auf lange Sicht wird es ein evolutionärer Vorteil sein sich an die Zeitskalen des Universums anzupassen. Dies mag dann sogar den Nachteil des langsameren Evolutionsmechanismus ausgleichen. Außerdem zeigt sich dann vielleicht auch ein höhreres Maß an Binnen-Evolution, bei der sich einzelne mutierte Zellen innerhalb eines Organismus als Vorteilhaft erweisen und sich durchsetzen.

Christian DietrichVernunft- und Tatsachenwahrheiten

Dieser Beitrag ist eine Erwiderung auf den Blogbeitrag von Maxfragg vom 5. Oktober 2015. Er hat dort beleuchtet, dass wir bisher einen "Major Consensus Narrative" (MCN) hatten, der durch die Medien vermittelt wurde. Dieser MCN behauptet von sich die "Wahrheit" zu sein; die "Tagesschauwahrheit".

Maxfragg stellte sich nun die Frage, was mit diesem MCN passiert, wenn wir eine vielfältigere Berichterstattung haben. Jeder kann sich dann seine ganz persöhnliche Wahrheit aus verschiedenen Quellen zusammenstellen, die seine Realität beschreibt. Der eine ließt SPON und schaut die Tagesschau, der andere ließt PI und glaubt an die "Lügenpresse". Brauchen wir dann noch eine Wahrheit? Darauf will ich einige Gedanken verwenden.

Zunächst will ich seinem Aufruf nachgehen, zu zeigen, dass es eine "echte" Wahrheit geben muss. Danach will ich darauf eingehen, wie Vernunft- und Tatsachenwahrheiten sich unterscheiden und die "wissenschaftliche" Wahrheit sich von der "historischen" Wahrheit unterscheiden. Das Ergebnis der Untersuchung wird sein, dass wir zwischen Wahrheiten und Hypothesenräumen unterscheiden müssen und der MCN ein Hypothesenraum ist, der die Wahrheit beinhalten kann.

Gibt es Wahrheit? Ist das überhaupt die richtige Frage? Wir tun uns schwer damit, die Frage zu beantworten, daher beantworte ich zunächst eine andere (in guter Sonnebornscher Manier): Gibt es das Gegenteil von Wahrheit? Und da müssen wir doch sagen: ja, gibt es. Bei manchen Dingen können wir uns sicher sein, dass sie nicht wahr sind, dass die Welt so nicht beschaffen ist. Ein Beispiel: Der Satz "jeder Mensch kann ohne Kopf Leben mehrere Jahre leben" ist nicht wahr. Es gibt mindestens ein Gegenbeispiel. Der Satz kann nicht wahr sein.

Zwei Hypothesenraeume

Es gibt also einen Bereich von Sätzen/Hypothesen/Aussagen die nicht wahr sind. Wir haben über die letzten 2500 Jahre die wissenschaftliche Methode entwickelt, um Hypothesen zu falsifizieren. Das Ergebnis dieser Methode ist allerdings nicht die Wahrheit an sich, sondern ein Kreis der sich immer Enger zieht. Außerhalb des Kreises sind all die falsifizierten Aussagen, innen die bisher nicht bewiesenen aber noch nicht wiederlegten Hypothesen. Die Menge innerhalb des Kreises ist ein Hypothesenraum.

Das kleine Bildchen soll das Verhältnis von Wahrheit und Hypothesenraum verdeutlichen. Die wissenschaftliche Methode ist nun ein Druck der von Aussen der auf den Hypothesenraum drückt, und versucht den Kreis enger zu ziehen. Innerhalb des Kreises nehmen wir mal einen Punkt an, der beschreibt wie die Welt wirklich ist, wie sich das Universum verhält. Also was denn tatsächlich passiert. Wir nennen diesen Punkt mal "Wahrheit", auch wenn wir ihn nicht an sich ausmachen können; wir können nur sagen wo er nicht ist.

Was sich daraus nicht direkt ergibt ist, ob es nur einen solchen Punkt gibt, oder mehrere (rechte Bildhälfte). Aber geben muss es mindestens einen, da das Universum sich ja irgendwie verhält. Bisher haben wir keine Annahme zu glauben, dass das Universum sich gleichzeitig so und so verhält. Es kann sich in jeder Situation anders verhalten, aber zu einem Zeitpunkt verhält sich das Universum auf jeden Fall irgendwie. Daher ist "eine Wahrheit" eine Hypothese, die sich bisher recht gut macht.

Gut, soweit so kompliziert. Jetzt dieses MCN Konzept. Bei Hannah Arendt habe ich die Unterscheidung zwischen Vernunftwahrheiten und Tatsachenwahrheiten gelernt (Wahrheit und Politik, H. Arendt, 1964, Tonmitschnitt von Arendt).

Vernunftwahrheiten können durch Experiment und Nachdenken jederzeit erkannt werden. In diesen Bereich fallen alle physikalischen Gesetze. Würden wir heute die Relativitätstheorie verlieren, so könnte sie in 10.000 Jahren von eine Lebenwesen auf einem anderen Planeten wieder entdeckt werden. Eine Vernunftwahrheit kann wiederholt untersucht werden, denn sie gehören zur Stuktur des Universums. Man kann sie auch "objektive Wahrheiten" nennen.

Tatsachenwahrheiten beziehen sich auf singuläre Ereignisse. So ist die Aussage, dass Konrad Adenauer Bundeskanzler war, eine Tatsachenwahrheit. Diese Klasse von Wahrheiten, sind viel leichter zu manipulieren. Arendt bringt hier das Beispiel von der Rolle Trotzkis in der Russischen Revolution. Dort hat sich Stalin an der Tatsachenwahrheit vergangen und Trotzki aus den Geschichtsbüchern getilgt. Dieses Manipulation ist besonders schändlich, da sie Wahrheiten für immer tilgt. Ein historisches Ereignis kann nur einmal "gemessen" werden. Kein Mensch kann eine Tatsachenwahrheit wiederbeleben, wenn erst einmal die perfekte Lüge von allen Menschen geglaubt wird und alle Beweise gefälscht wurden. Man könnte Tatsachenwahrheiten also auch "historische Wahrheiten" nennen.

Der Verlust des MCNs ist nun das Vorhandensein mehrerer solcher Räume die sich teilweise überlappen und unter Umständen die Tatsachenwahrheit beinhalten. Das heisst aber nicht, dass es für eine Sache keine Tatsachenwahrheit mehr gibt. Man ist nur leichter Bereit zu sagen: "ach, ist doch eh alles egal, hat doch jeder seine Wahrheit". Aber dem ist nicht so, nicht jeder hat seine Wahrheit, sondern jeder hat einen anderen Hypothesenraum. Der Wahrheit tut das keinen Abbruch, den für eine historische Wahrheit ist sicher: für den Zeitpunkt um den es geht hat sich das Universum irgendwie verhalten.

Wenn Maxfragg also jetzt über den MCN schreibt, dann bezieht sich dieser MCN meist auf historische Wahrheiten und ist ein Hypothesenraum. Dieser MCN kann nun aktiv Aussagen vertreten, die Ausserhalb des aktuellen Hypothesenraumes liegen; lügen wider besseren wissens. Der MCN übt dadurch Druck aus und verschiebt den Hypothesenraum. Mittels der perfekten Lüge verschiebt man den Raum soweit, dass die Tatsachenwahrheit sich nicht mehr innerhalb befindet. Die Tatsachenwahrheit ist für immer verloren, weil wir nicht nochmal messen können.

Wir dürfen nicht zulassen, dass wir die Tatsachenwahrheiten verlieren, denn einmal verloren, sind sie für immer vergangen.

Christian DietrichTechnik die begeistert

Dieser Post ist das Ergebnis mehrerer Begegnungen mit meinen Kollegen und es ist mein Ziel darzulegen, welche meine Beweggründe in einem ganz speziellen, eng abgesteckten Bereich sind und wie ich hier zu meinen Überzeugungen gekommen bin. Ziel ist es nicht meine Ansicht anderen überzuhelfen, sondern nur sie verständlich zu machen.

An meiner Arbeitsstelle bekommen alle Mitarbeiter die Chance einen Dienstlaptop zu kaufen. In den meisten Fällen fällt die Entscheidung auf einen Apple Laptop. Und so stand auch ich am Beginn meiner Anstellung als wissenschaftlicher Mitarbeiter vor der Frage, ob und welchen mobilen Rechner ich mir zulegen will.

Allerdings habe ich mich aktiv gegen das Kaufen entschieden. Stattdessen verwende ich seit geraumer Zeit ein mehrere Jahre altes Gerät, dass einer meiner Kollegen durch ein Neues ersetzt hat. Es funktioniert noch hervorragend, ist nur nicht mehr auf dem "aktuellen Stand der Technik". Was ich mir habe leisten lassen war ein Hardwareupgrade (RAM, Festplatte) für einige hundert Euro.

Meine bewusste Entscheidung gegen die Neuanschaffung hat mehrere Gründe. Zum einen, ist der Stand der Technik von vor 5 Jahren für die allermeisten meiner Anforderungen völlig ausreichend. Es hat seitdem einfach nur in sehr begrenztem Maße bahnbrechende Verbesserungen gegeben. Nur in einigen Bereichen (Retina-Displays, Akkulaufzeit) ist eine wirkliche Verbesserung spürbar geworden. Brauche ich doch einmal mehr Rechenleistung muss ich diese eh auf größere Infrastruktur ausweichen.

Zum anderen sehe ich es nicht ein, ein völlig funktionsfähiges Gerät auszumustern oder in den Schrank zu legen, nur weil es einige Jahre alt ist. Alter ist kein Problem an sich. Selbstverständlich erhöht sich das Ausfallrisiko einiger Komponenten mit den Jahren, was durch vergangene Komponententauschungen bei diesem Gerät in geringerem Maße zutrifft. Eine Neuanschaffung hingegen ist immer auch Ressourcenverbrauch. Bei der Produktion wird sowohl Energie, als auch andere endliche Ressourcen unseres Planeten verbraucht. Konkret diese Ressourcen werden unsere Nachkommen nicht mehr haben. Und Menschen müssen dafür Arbeiten, damit ich ein neues Gerät in Händen halten kann.

Unser ständiger Wunsch nach den neusten Geräten ist mit einem enormen Ressourcenverbrauch verbunden. Jedes neue technische Spielzeug, von denen wir ja sehr viele haben und haben wollen, bindet Ressourcen. Umso häufiger wir diese wechseln, umso höher wird der Verbrauch. Und solange keine Not besteht, solange will ich diesen Verbrauch hinauszögern soweit es geht.

Außerdem ist Konsum anstregend. Ich will mich nicht ständig mit den neuesten Laptops, Handys, E-Book Readern, Smartwatches und Bildschirmen auseinander setzen. Ich weiss besseres mit meiner Zeit anzufangen. Für mich wiegt das kurzfristige Belohnungsgefühl beim Kauf eines neuen Gerätes nicht mehr den Zeitaufwand der Anschaffung auf.

Ein anderer Grund der speziell für die Informatik ist und der über dieses eine konkrete Gerät hinaus geht ist ein eher Ideelles. Mit unendlichen Ressourcen kann ich in der Informatik das allermeiste bewältigen. Probleme können häufig durch teurere Hardware erschlagen werden. Aber wir wissen auch, dass alle Rechner prinzipiell gleich mächtig sind, wenn wir sie einmal als angenäherte Turing-Maschine begreifen. Die Kunst eines guten Programmiers ist es aus wenigen Ressourcen alles rauszuholen was geht. Das ist Kunst: aus (fast) nichts (fast) alles machen.

Und dies trifft auch gerade in dem Bereich der Informatik mit dem ich mich beschäftige zu. Betriebssysteme will niemand haben; niemand will seine kostbaren Rechenzyklen dafür hergeben, dass das Betriebssystem irgendwelchen Quatsch berechnet. Am besten das Betriebssystem wäre garnicht da. Hier, und noch viel mehr im Bereich der eingebetten Systeme, kommt es im Besonderen darauf an Ressourceneffizient zu arbeiten. Ich sehe allerdings, dass dieser Geist und diese Freude am Minimalismus nicht mehr so populär ist.

Ich jedenfalls werde die Benutzung dieses Laptops solange ausdehen, wie das nur überhaupt möglich ist.

Christian DietrichLund in Schweden

Zur Zeit befinde ich mich wiedereinmal in schönen Schweden. Letztes Jahr was ich mit zwei Freunden einige Zeit mit dem Wohnmobil von Västerås nach Göteborg unterwegs. Ich habe in der Zeit den schönsten See der Welt gesehen und die Gegend sehr genossen. Ich kann die Strecke wirklich empfehlen, wenn man mit Wohnmobil oder Zelt unterwegs ist.

Dieses Jahr hatte ich glücklicherweise, dank einer Konferenz in Lund, wieder die Chance nach Schweden zu kommen. Diesmal deutlich weiter südlich als letztes Jahr. Lund befindet sich in der Provinz Skåne und etwa 20 Kilometer nördlich von Malmö. Mit seinen 100.000 Einwohnern ist es ungefähr so gross wie Erlangen, hat aber tatsächlich eine noch grössere Universität. 46.000 Studenten absolvieren an der Universität von Lund ihr Studium. Meine Gastgeberin hier meinte auch, dass alle Studenten irgendwie auf dem Stadtgebiet Leben, was zu einer enormen Platznot führt. Aktuell sind gerade Ferien, daher bekomme ich nicht so besonders viel von diesen Studentenmassen mit.

Das Universitätshuset Die Unibibliothek Ein weiteres Universitätsgebäude, dessen Namen ich nicht weiss

Während der Woche hatte ich nicht besonders viel Zeit mir die Stadt anzuschauen, da ja nebenbei auch noch Konferenz war. Aber Lund ist schon ein wirklich schönes Städtchen, und von grad der niedlichkeit mit Rothenburg o.d.T. vergleichbar, was nahe meines Heimatortes liegt. Die Gebäude sind hier zu einem sehr grossen Teil in Backstein gehalten und es gibt wirklich viele alte Gebäude. Es hat wirklich eine erstaunliche Wirkung auf das Stadtbild, wenn eine Stadt nie wirklich zerstört wurde. Allerding hat man hier auch sehr schnell das allermeiste gesehen. Wie es meine Gastgeberin gesagt hat: "Alles ist 20 Minuten entfernt, alles".

Am Samstag, meinem ersten freien Tag, hab ich mir dann ein Fahrrad gemietet um die Gegend ein bischen zu erkunden. Allerdings dafür, dass Lund von sich behauptet eine Fahrrad Stadt zu sein, ist es ausserordentlich schwierig ein Fahrrad zu leihen. Weil scheinbar alle Läden die Fahrräder verleihen in den letzten Jahren das Angebot eingestellt haben. Ende vom Lied: Ich konnte mir am Samstag um 11 Uhr ein klappriges Damenrad mit einer 3 Gang Nabenschaltung für 25 EUR leihen. Naja, aber immerhin: fahrbarer Untersatz. Was man dann als Gegend zu sehen bekommt ist auch durchaus ansprechend. Ich möchte ausserdem vermelden, dass ich mich 65 km auf diesem Drahtesel, GEGEN den Wind, gekämpft habe.

Kyrka in Dalby Eine Windmühle Der Öresund

Am Sonntag hab ich mich dann mittels "Fahrrad" Richtung Malmö begeben. Ich muss sagen: Minder begeistert. Es ist eine ganz nette Stadt, hat ein paar schöne Ecken, aber so wirklich vom Hocher gerissen hat es mich nicht. Mag auch daran liegen, dass das Wetter nicht ganz so grossartig war wie gestern. Aber Malmö, was direkt am Öresund liegt, ist halt doch nur eine Industriehafenstadt. Von Malmö aus geht auch die Öresundbrücke Richtung Kopenhagen, welche ich auch am Dienstag wieder nehmen werde um zurück zum Flughafen zu kommen. Es ist nämlich so, dass man nach Lund am besten kommt, wenn man nach Kopenhagen (Dänemark!) fliegt und dann mit dem Zug über die Brücke gondelt.

Die Öresundbrücke

Christian DietrichWaiting in dOSEK

In my current research, I'm working on the dOSEK operating system. dOSEK is dependable operating system that implements the OSEK standard for embedded real-time systems. dOSEK is designed to be resilient against soft-errors (transient hardware faults, bit flipts) in memory and the registers (A paper on RTAS'15 will be published soon). In this blog post, I will describe how we implemented a branchless version of OSEK events, and integrated it in our system. First, I will give a short overview about the scheduling primitive used in dOSEK.

Scheduling in dOSEK

The core of dOSEK is the priority-driven scheduler. OSEK is a static operating-system standard; for a specific system, we know exactly how many threads exists. This number will never change, it is configured at compile time. The scheduler selects always the thread with the highest priority that is runnable and executes it. In dOSEK, a thread is runnable, if its priority is larger than the priority of the idle thread. In pseudocode, the scheduler/dispatcher looks like this:

schedule() {
   current_thread = idle_id;
   current_prio   = idle_prio;

   updateMax((current_thread, current_prio),
             (thread_1_id, thread_1_prio));

   updateMax((current_thread, current_prio),
             (thread_2_id, thread_2_prio));

   updateMax((current_thread, current_prio),
             (thread_3_id, thread_3_prio));

   switch_to_thread(current_thread);
}

The scheduler is generated for the specific system (in this case, for a system with 3 threads), and contains a updateMax() cascade. updateMax() is a hardened operation, that updates the first input tuple with the second one, iff the priority of the second argument-tuple (second tuple, second item) is higher than the priority of the first tuple. In the first cascade element, current_thread is set to thread_1_id, if current_prio \< thread_1_prio. In pseudocode:

updateMax((a, b), (c, d)) {
  if (b < d) {
    (a, b) = (c, d);
  }
}

Events in OSEK

In OSEK, events are the only possibility for a thread to wait on something. Each thread can receive a number of event signals. With the system call WaitEvent(), a thread can wait for one or more events to happen. If any of the events from the list got signaled by another thread with SetEvent, the waiting thread unblocks. Signals are not automatically cleared, but must be cleared explicitly by ClearEvent.

A version with branches can be implemented by two bitmasks:

 struct Thread {
  ...
  event_mask_t events_waiting;
  event_mask_t events_set;
  ...
};

SetEvent(Thread t, event_mask_t m) {
   t.event_set |= m;
}
WaitEvent(Thread t, event_mask_t m) {
   t.event_waiting = m;
}
ClearEvent(Thread t, event_mask_t m) {
   // Remove the event mask bitwise
   t.event_waiting &= ~m;
   t.event_set     &= ~m;
}

Schedule() {
   ...
   if (thread_1.event_waiting != 0
       || (thread_1.event_waiting & thread_1.event_set) != 0) {
      updateMax((current_thread, current_prio),
                (thread_1_id, thread_1_prio));
   }

In this simple variant, we maintain a event_waiting mask, which maintains a bitmask of events a specific thread is waiting for. The event_set bitmask holds a bitmask of signaled events. If a thread is waiting, and none of the waited signals is set, we exclude the thread from the updateMax() cascade. It is get blocked.

But there is one problem here, with dependability: we have branches. Branches are evil; makeing them resilent against soft-errors is hard. Therefore, we want to have a branchless version of it.

Events in dOSEK

Shortly explained, in the branchless version, we let the priority of a thread drop below the idle~priority~, if it currently blocks. Therefore, we calculate a blocking term for every thread that is either zero or the highest priority in the system. This blocking term is substracted from the thread priority, when calling updateMax():

updateMax((current_thread, current_prio),
          (thread_1_id,    thread_1_prio - blocking_term));

For each event, a thread can receive, we have two integer variables W (for waiting) and S (for set). Both variables can have two values: either 0 or High (for highest priority in the system).

In this diagram, we see all four states a event can have. A event is a tuple of (W, S). The set() and clear() operations set override the tuple. If we want to wait for an event mask, we set the W flag accordingly for all events a thread can wait for:

struct Event {
   int W;
   int S;
};

Event thread_1_event_a;
Event thread_1_event_b;

...
WaitEvent(Thread t, event_mask_t m) {
   // t is always known at compile time, and this cascade is generated for the system.
   if (t == thread_1) {
      if (m & 1)
         thread_1_event_a.W = High;
      else
         thread_1_event_a.W = 0;

      if (m & 2)
         thread_1_event_b.W = High;
      else
         thread_1_event_b.W = 0;
   }
}

But how can we now deduce the blocking_term from the event states? First we calculate the blocking_term for a single event. We use a matrix notation that captures all four states from the diagram shown before.

By the blocking term function, we generate a term for each event that is only 0, if the event was used for blocking and is set. In all other cases, the blocking term is High. We achieved this by using only bitwise XOR an OR operation. We're still branchless! :-)

We combine now all blocking terms of all events a specific task can wait for with AND. So the result is only then zero if at least single event, which is on the waiting list, is set. Furthermore, we determine whether we can block in the first place, by combining all W states with OR. The should_wait variable is either High, if we're waiting, or 0 if we're not waiting.

does_block  = blocking_term(thread_1_event_a) & blocking_term(thread_1_event_b);
should_wait = thread_1_event_a.W | thread_1_event_b.W;
blocking_term = should_wait & blocking_term;

Combining both variables with AND, we achieve our blocking term. Branchless. And we can subtract it, before we call the updateMax(), from the threads priority.

Christian DietrichAlles voller Idioten!

Immer, wenn ich in die Verlegenheit komme Auto zu fahren, habe ich das Gefühl nur Idioten zu treffen. Also stellt sich die Frage, sind wirklich alle anderen Autofahrer Idioten oder Treffe ich die Idioten die es gibt mit besonderer Häufigkeit. Wenn wir das ganze Mal auf den einfachen Fall Autobahn runterbrechen, dann merken wir dass wir diejenigen, die genauso schnell fahren wie wir, niemals treffen. Wir treffen nur die, die schneller bzw. langsamer fahren als wir, und das mit zunehmender Häufigkeit. Und um das plausibel zu machen, hab ich ein bisschen simuliert und Graphen gemalt.

Zunächst wollen wir uns mal die Geschwindigkeitsverteilung anschauen, wie sie auf einer deutschen, unbeschränkten Autobahn herrscht. Ich hab da mal die Verteilung der MAWES Forschungsgruppe genommen (Studie zur Reduzierung der CO2-Emissionen durch eine Geschwindigkeitsbegrenzung auf BAB). Die Verteilung für PKWs sieht man in Bild 1.

Geschwindigkeitsverteilung auf einer unbeschränkten BAB

Bild 1: Geschwindigkeitsverteilung auf einer unbeschränkten Bundesautobahn für PKWs

Es stellt sich nun die Frage, was ist ein Idiot in diesem Zusammenhang? Als unangehmen werden wir es finden, wenn jemand sehr schnell an uns vorbei zieht bzw. wenn jemand sehr viel langsamer fährt als wir selbst. In dem einem Fall ist er ein Idiot, weil der Fahrer viel zu schnell fährt. In dem anderen Fall ist er ein Idiot, weil er schnarch langsam fährt. Als willkürliche Festlegung nehme ich an, dass 40 km/h Geschwindigkeitsunterschied einen anderen Fahrer als Idiot für einen selbst markiert. Natürlich ist die Markierung eines anderen Fahrers als einen Idioten eine völlig subjektive Aktion.

Und jetzt das System in der Simulation. Diese Simulation ist höchstens ein plausibel machen meiner These, kein wirklich aussagekräftiges Ergebnis. In meiner Simulation sind Autos punktförmig; der Betrachtete Autobahnabschnitt ist 10 Kilometer lang; es befinden sich zu jedem Zeitpunkt eine konstante Anzahl Fahrzeuge auf der Strecke. Es wird simuliert, bis eine gewisse Anzahl an Fahrzeugen den Autbahnabschnitt durchfahren haben. Bei der Simulation 100 gleichzeitig fahrenden Autos zählen wir nun die Überholvorgänge, und welcher Anteil der Überholvorgänge ein mulmiges Gefühl erzeugt hat bzw. eine Idiotiezuschreibung vorgenommen wurde von den beteiligten Fahrern. Das Ergebnis der Simulation ist in Bild 2 abgebildet.

Anteil der Überholvorgänge mit Idiotiezuschreibung seitens eines Fahrers

Bild 2:Anteil der Überholvorgänge mit Idiotiezuschreibung seitens eines Fahrers.

Wir sehen hier, dass ungefähr ein Drittel der Überholvorgänge unangenehm ist. Jemand der ungefähr eine Geschwindigkeit fährt, die dem Erwartungswert der Verteilung fährt führt zu weniger unangenehmen Überholvorgängen. Jemand, der 200 km/h fährt, wird viele Mitmenschen viel zu schnell überholen und hat daher einen großen Impact. Für Autofahrer, die sehr langsam fahren, gilt dies übrigens in einem ähnlichen Maße.

Wie sieht die Situation nun aus, wenn wir die Geschwindigkeit hart auf maximal 140 km/h deckeln. Alle die bisher schneller gefahren sind, werden nun auf dieses Maximum gestuzt. Wir erhalten die Verteilung aus Bild 3. Ein weiteres Ergebnis ist auch, dass man sich schon nur von Idioten umgeben fühlt, wenn man nur leicht vom Erwartungswert abweicht. Allerdings zeigen andere Studien, dass der Erwartungswert auf deutschen Autobahnen bei Geschwindigkeitsbeschränkten Strecken über der Beschränkung liegen. Kurz: Wer so schnell fährt wie er maximal darf, fühlt sich nur von Deppen umgeben.

Geschwindigkeitsverteilung auf einer beschränkten BAB

Bild 3:Geschwindigkeitsverteilung bei einem CutOff von 140 km/h.

Bei einer gleichen Simulation erhalten wir nun einen Anteil von idiotischen Überholvorgängen von unter 10 Prozent (Bild 4). Und das, obwohl die Zahl der Überholvorgänge in der gleichen Größenordnung ist wie ohne Beschränkung.

Anteil der Überholvorgänge mit Idiotiezuschreibung seitens eines Fahrers

Bild 4:Auswirkungen auf den Anteil der unangenehmen Überholvorgängen bei Geschwindigkeitsbeschränkung.

Ich nehme aus dieser groben Abschätzung, denn mehr ist diese Simulation nicht, weil sie viele Faktoren (mehrere Spuren, bremsen -- beschleunigen) nicht beachtet, mit, dass eine Geschwindigkeitsbeschränkung auf der Autobahn das Leben für alle angenehmer Gestalten würde.

Das Simulationsskript gibt es hier.

Christian DietrichDas Ende der Scheinkausalitäten

Ich habe in den letzten Jahren viel über soziale Mechanismen nachgedacht, die auf mich wirken und die dazu führen, dass ich mich auf eine gewisse Art und Weise verhalte. Ich werde hier ein wenig meine Gedanken niederschreiben.

Zunächst möchte ich die Kräfte, die normierend auf mich einwirken, in drei grobe Kategorien einteilen: Werte, Normen und Gesetze. Werte sind die Dinge von denen ich überzeugt bin, dass sie richtig sind und nach denen es sich lohnt zu handeln. Ob diese Werte rational begründet sind, oder beispielsweise aus einer religiösen Ansicht hervorgehen, ist dabei unerheblich. Werte sind die Kräfte, denen ich gerne nachkomme.

Dem gegenüber stehen die Gesetze. Gesetze wirken auf mich, aber ich muss nicht an sie glauben, ich muss sie nur befolgen, weil mir sonst Strafe droht. Allerdings befreien mich Gesetze davon, mich damit zu beschäftigen ob es moralisch gut ist über die Rote Ampel zu gehen oder nicht. Gesetze, vor allem verschriftlichte Gesetze, sind eine Errungenschaft, die es Menschen unterschiedlicher Wertvorstellungen erlaubt miteinander auszukommen. Kriege, die mit religiöser Begründung geführt werden, sind Konflikte von Wertesystemen. "Der andere Christ ist des Tötens wert, weil er an eine andere Interpretation der Dreifaltigkeit Gottes glaubt". Unter diesem Aspekt ist die Juristifizierung der Gesellschaft eine Befreiung und eine Befriedung. Für mehr Details zu diesem Gedankengang, den nicht ich mir ausgedacht habe, empfehle ich SWR2 Aula: Normen für Manager.

Zwischen diesen beiden Polen der Werte und der Gesetze, stehen, in meiner Aufteilung, die Normen. Normen sind Kräfte die auf meine sozialen Interaktionen wirken, die allerdings nicht von Außen kontrolliert werden, wie dies bei den Gesetzen der Fall ist. An Normen muss ich auch nicht zwangsläufig glauben, ich kann sogar meine internalisierten Normen verabscheuen und mich ihnen dennoch beugen. Das perfide an Normen ist, dass der Wächter des Normengefängnisses mein eigener Geist ist. Und ich selbst bekomme natürlich alles mit was ich denke. Mein Geist hat die wirkliche Fähigkeit zur Gedankenpolizei.

Normen sind immer internalisierte Regeln des Zusammenlebens. Das macht sie allerdings nicht unbedingt verabscheuenswert. Ich bin beispielsweise der Meinung, dass es nicht nur ein Gesetz geben muss, dass Mord verbietet, sondern dass auch jeder die Norm internalisiert haben sollte, Mord sei böse. Am liebsten ist es mir sogar, wenn alle den Wert vertreten, Mord sei unmöglich. Normen erfüllen also auch eine wichtige gesellschaftliche Funktion. Allerdings tragen Normen auch maßgeblich zur Trägheit einer Gesellschaft bei. Diesen Punkt möchte ich weiter ausführen und ziehe dabei das Beispiel der Homosexualität heran.

Inzwischen sind wir gesellschaftlich so weit, dass wir Gesetze haben, die Homosexualität nicht mehr verbieten (jedenfalls in sehr vielen Ländern, über die anderen mag ich gerade gar nicht sprechen). Wir haben vielleicht sogar eine große Wertakzeptanz von Homosexualität erreicht. Allerdings heißt dies nicht, dass es nicht viele Menschen gibt die eine internalisierte Homophobie in sich tragen. Diese internalisierte Homophobie erlaubt es ihnen unter Umständen nichtden eigenen Gelüsten nachzugehen ohne sich schuldig zu fühlen. Gesetze lassen sich in einer Parlamentsabstimmung ändern, Werte können durch eine einzige Diskussion verändert werden, aber Normen, die wir gelernt haben, bleiben häufig ein Leben lang. Die eigenen Normen zu hinterfragen ist eine schwierige Angelegenheit.

Und wieso ist das so? Wieso ist es so schwer die eigenen Normen zu hinterfragen. Ich glaube, dies liegt daran, dass durch den Prozess der Internalisierung der Norm (dem Erlernen der Norm), wir vermittelt bekommen haben, dass der Inhalt dieser Norm kausal ist. "Mädchen können kein Mathe", "Frauen können nicht einparken", "Männer weinen nicht, und tun sie es doch sind sie schwach", "Homosexualität ist abnormal". Und wir haben diese Normen so oft gehört und so oft gelesen, dass Menschen scheinbar kausale Erklärungen für diese Normen gefunden zu haben scheinen (die Wissenschaft hat sich die Hände sehr schmutzig gemacht), dass wir daran glauben, dass es die rationale Wahrheit ist.

Aber etwas anderes ist häufig der Fall: Normen beinhalten häufig nur Scheinkausalitäten. Weil wir die Normen internalisiert haben, glauben wir, dass der Inhalt der Norm kausal ist und wir nehmen jeden Strohhalm um dies zu untermauern. Aber hat der Platz zwischen meinen Beinen wirklich etwas damit zu tun, wie ich einparke? Oder hat ein Mann wirklich andere biologische Anlagen Tränen zu produzieren?

Das Hinterfragen und Ablegen von Normen geht damit einher, dass wir diese Scheinkausalitäten aufbrechen. Wir fangen an zu hinterfragen, ob mein Penis wirklich etwas mit meinem räumlichen Vorstellungsvermögen zu tun hat und wie zum Teufel ich damit das Lenkrad bedienen soll; besteht da wirklich ein kausaler Zusammenhang. Oder handelt es sich nur um eine Scheinkausalität, die wir erlernt haben und die sozial konstruiert ist und wir durch beständiges wiederholen in den Köpfen sedimentieren.

Christian DietrichMasterarbeit: The Global Control Flow Graph

In den letzten Monaten habe ich viel Zeit damit verbracht meiner Masterarbeit zu schreiben. Abgegeben habe ich sie schon im September, aber ich bin erst letzten Freitag dazu gekommen meinen Abschlussvortrag zu halten. Aber das Ergebnis von allem ist, dass ich jetzt einen Masterabschluss habe und mein Informatikstudium nach 5 Jahren beendet habe.

In meiner Arbeit habe ich mich damit beschäftigt wie man in einem eingebetten Echtzeitsystem Wissen über die Interaktion von Betriebssystem und Anwendung extrahieren kann. In der Automobilbranche kommt häufig OSEK als Betriebssystemstandard zu Einsatz. OSEK definiert einen relativ übersichtlichen Satz an Betriebsystemaufrufen.

Um jetzt dieses Interaktionswissen einzufangen, konstruiere ich den Globalen Kontrollflussgraphen für eine einzelne Anwendung. In dem globalen Kontrollflussgraphen sind alle Übergänge von Basisblöcken verzeichnet, wie sie hintereinander auf der realen CPU ausgeführt werden können.

In dem Bild sieht man, dass Task 1, der eine mittlere Priorität hat, einen höher Prioren aktiviert. Nachdem Task 3 an dieser Stelle läuffähig wird, wird er auch auf der Stelle ausgeführt und erst nachdem er sich wieder beendet hat geht es wieder zu Task 1 zurück.

Der Unterschied zum lokalen Kontrollflussgraphen sieht man, an dem ausgegrauten Pfad der direkt vom ActivateTask zum TerminateTask geht. Dieser ist im Task-lokalen Kontrollflussgraphen vorhanden, aber im System-globale Kontrollflussgraphen nicht.

Für weitere Details gibt es:

Christian DietrichEx Libris

Ein Exlibris ist eine Buchmarke, die man vorne in ein Buch einkleben kann, um den Besitzer anzuzeigen. Diese Tradition der kunstvollen Buchmarke stammt aus dem 15. Jahrhundert, kurz nachdem der Buchdruck mit beweglichen Lettern von Gutenberg erfunden wurde. Da ich diese Trandition recht schön fand, habe ich mir auch ein solches Exlibris entworfen.

Die Hauptgraphik zeigt den Namen des Planeten Galifrey aus der Science-Fiction Serie Dr. Who. Dort haben die Timelords, denen auch der Doktor angehört, ihren Ursprung. Ich mag nicht nur die Serie, sondern finde auch den Namen in galifreyan sehr hübsch. Ausserdem habe ich nehmen meinem Namen und meiner Mail-Adresse als QR-Code noch den Schriftzug "Pignus Amoris Habes!". Dieser lateinische Schriftzug heisst "Du hast meiner Liebe Pfand", was häufig in römischen Eheringen graviert war.

Christian DietrichSymposium - Leben im Überfluss

Gestern habe ich über die reichlich deprimierenden Veranstaltung "10 Jahre Elitenetzwerk Bayern" geschrieben. Heute will ich über eine Veranstaltung reden, die nur dem Inhalt nach deprimierend war, aber ansonsten eine gute Erfahrung. Es geht um ein Symposium zum Thema "Leben im Überfluss" das in Regensburg stattgefunden hat. Nachhaltigkeit war das Thema das dort um die 40 Leute versammelt hat. Es wurde 4 Tage lang über Strukturen und Mechanismen des Konsums geredet und verschiedene Lösungsansätze diskutiert. Ich werde die Veranstaltung nicht dem Ablauf, aber dem Inhalt nach zusammenfassen, es wird also eher ein "Meine Sicht der Dinge" mit besonderer Berücksichtigung des Symposiums sein.

Die Grundlage aller Betrachtungen zum Thema Nachhaltigkeit ist die Erkenntnis der Endlichkeit aller Ressourcen auf unserem Planeten. Dabei geht es nicht nur um den Klimawandel und den CO2-Ausstoß, den wir verursachen. Es geht auch nicht nur um den Verbrauch von Öl. Wir stoßen mit unserem Verbrauch an sehr viele Grenzen. Wir verbrauchen zu viel Öl (das nicht wirklich nach wächst), zu viel Wasser, zu viel Land, versäuern die Meere zu sehr, vernichten die Artenvielfalt, emitieren zu viele Schadstoffe, etc.. Wir müssen uns vor Augen halten, dass sogar die, von der Sonne eingestrahlte, Energiemenge begrenzt ist. Um ein bisschen zu verdeutlichen wie groß unser Einfluss ist, ist dieser XKCD zu empfehlen, der zeigt wie viel Biomasse unsere Nutztiere im Vergleich zum Rest aller wild lebenden Tiere ausmachen.

Wir haben keine wirkliche unberührte Natur vor uns. Alles ist berührt vom Menschen. Die Natur auf dem Land, die gerne romantisiert wird, ist Kulturland. Geschaffen vom Menschen für sein eigenes Überleben und seine Bequemlichkeit. Es gibt keine unberührte Natur mehr. Nur noch uns und wie wir mit der Menschenspähre (Anthroposphäre) interagieren.

Wenn man sich jetzt die Zahlen anschaut, wie viele Erden man bräuchte um alle Menschen auf einem Gewissen Niveau Leben zu lassen, kommt man zu relativ unangenehmen Zahlen: Leben alle wie in der EU brauchen wir 2.6 Erden; Leben alle wie in den USA brauchen wir 4 Erden. Diese Zahlen berechnen sich aus dem ökologischen Fussabdruck. Die Zahl des ökologischen Fussabdruckes ist selbst umstritten, aber wenn wir konservativ annehmen, dass die Zahlen um 50% zu pessimistisch sind, sieht es ziemlich schlecht aus. Aber es ist natürlich politisch nicht gewollt, dass alle Menschen so Leben wie in den USA oder der EU. Die Grenzpolitik der EU manifestiert eine Festung Europa. Wir schließen uns in Europa ein und hoffen das 938 Millionen Afrikaner nicht auf blöde Ideen kommen bzw. Frontex sie ausreichend in Angst versetzt. Es geht also um die Verteilung unserer Ressourcen auf dem Planeten. Alle Kriege des 21. Jahrhunderts werden Verteilungskriege um begrenzte Ressourcen sein.

Es gibt viele Eckpunkte in dieser Geschichte an der man merkt, dass diese Welt ein ernsthafteres Problem hat, als wir uns das eingestehen wollen. Ich habe meinen Workshopleiter, der im Wissenschaftsbeirat der Bundesregierung war, am Symposium gefragt, ob er eine, nur eine, Studie kennt bei der es für uns nicht düster aussieht. Er sagte nein. Also die Ausgangslage ist nicht gerade rosig.

Jetzt gibt es verschiedene Stoßrichtungen, wie man unsere Gesellschaft(en) Nachhaltiger gestalten kann. Die am leichtesten zu akzeptierende, weil bequem, ist die technokratische Lösung: Wir schrauben die Effizienz unserer Prozesse so weit in die Höhe und machen uns so unabhängig von fossilen Ressourcen, dass wir innerhalb der Grenzen unseres Wachstums bleiben. Wir entkoppeln das Wachstum von begrenzten Ressourcen, eine decarbonisierung der Wirtschat. Das ist sicherlich ein Standbein nachhaltiger Entwicklung, aber ich glaube nicht, dass es ausreichend ist. Zum einen sind wir sehr weit weg von unseren Wachstumsgrenzen und zum anderen löst es nicht die Verteilungs- und Entwicklungsprobleme. Können wir wirklich alle Menschen mit einem I-Phone ausstatten, das es ihnen erlaubt die eigenen globalen Energieströme zu jonglieren. Die Frage die man sich bei jeder Maßnahme stellen muss ist doch: Wie skaliere ich das auf 7 Milliarden (oder später 9 Milliarden) Menschen? Und ich denke, dass bei Elektroautos und Flugzeugen die Antwort sein wird: Ich kann es nicht skalieren.

Die andere Stoßrichtung ist die der Suffizienz. Sie geht von der psychologischen Beobachtung aus, dass wir ab einer gewissen Maß an materiellem Wohlstand nicht mehr zufriedener werden. Das heißt, das jeder Konsum über dieser Grenze, wo auch immer die genau liegen mag, vielleicht kurzfristig das Glück steigert, aber nicht das allgemeine Wohlbefinden einer Person. Die Konsumausgaben über dieser Grenze sind demnach nicht wirklich effektiv, wenn man Konsum als Mittel zur Steigerung des Wohlbefindens sieht. Die Idee der Suffizienz ist eigentlich eine sehr marktwirtschaftliche, weil sie sagt, dass man diese uneffektiven Ausgaben reduzieren muss. Suffizienz ist also die Frage nach den Dingen, die man wirklich braucht. Hauptredner dieser Idee und der Idee der Postwachstumsökonomie in Deutschland ist Niko Paech, bei dem es sich wirklich lohnt zuzuhören (25 Min; mp3).

Um sich den Wahnsinn unseres Wirtschaftssystems vor Augen zu führen, möchte ich nur kurz folgendes zu bedenken geben. Wenn wir jedes Jahr eine konstante Wachstumsrate haben, haben wir im Endeffekt exponentielles Wachstum (man denke an Zineszins). Und das in einer Welt mit begrenzten Ressourcen. Guter Plan!

Eins der wohl leicht verständlichsten Themen, wo diese Suffizienz anwendbar, aber unbequem, ist, ist der Fleischkonsum. Es ist Wahnsinn Nahrungsmittel, die wir schon selbst verstoffwechseln könnten, zuerst noch durch ein Nutztier zu schieben (mit einer Effizienz von ca. 10 %) um dann das Ergebnis zu essen. Es ist eine andere Geschichte Nutztiere Flächen bewirtschaften zu lassen, die nicht für Ackerbau geeignet sind. Aber dieser Fall macht nicht den Hauptteil der Fleischproduktion aus. Nun könnte man in der westlichen Welt auf einen großen Teil seines Fleischkonsumes verzichten, aber man will halt nicht, weil es ist unbequem, weil es eine Aufgabe von Privilegien ist. Es wird einen Punkt in der Geschichte geben, an der hungernde Menschen einsehen, dass Rinder und Schweine ihre Fressfeinde sind. Nachdem ich den Ausführungen der Tierethik nicht folge, kann man daraus nur folgern, dass ich lieber Menschen ernähre als Tiere.

Im Symposium wurden viele Themen angesprochen, aber ich habe mich in meinem Workshop hauptsächlich mit den ganz großen Strukturen auseinander gesetzt. Deswegen möchte ich zum Abschluss noch unser Ergebnis in dieser Hinsicht darlegen. Wir haben die größten Strukturen mit ihrer Motivation, ihren Potentialen und Hemmnissen erarbeitet.

  • Politik -- Die Poltik hat als grundlegende Motivation den Erhalte der Macht. Sie hat die Möglichkeit alle Rahmenbedingungen zu schaffen, in denen der Rest der Gesellschaft handeln muss. Allerdings ist diese Entscheidungsmacht eingeschränkt vom Gedanken an die eigene Wiederwahl und durchsetzt von Lobbyismus. Als Instrumente hat die Politik Sanktionen und Subventionen in der Hand.
  • Wirtschaft -- Die Wirtschaft hat als primäres Ziel Gewinn zu erwirtschaften. Sie tut dies im Rahmen der gesetzlichen Rahmenbedingungen (ansonsten ist es organisierte Kriminalität), füllt hier aber diesen Rahmen gänzlich aus, inklusive aller Schlupflöcher. Eigentlich ist die Wirtschaft wenn sie sich bewegt flexibel im Anpassen an neue Gegebenheiten. Was aber nicht heißt, dass alle Firmen einen Wandel überstehen. Allerdings ist jedes Umlenken und jede Änderung ein Risiko. Und solange es eine weniger risikoreiche Möglichkeit gibt Profite zu machen gibt es keinen Grund sich zu bewegen. Von einer Suffizienzgesellschaft hätte die aktuelle Wirtschaftsordnung am wenigsten. Als effektivstes Instrumente hat sie Lobbyismus, Werbung und die Hoheit über die Arbeitsplätze. Die meiste Finanzkraft ist hier versammelt.
  • Individuum -- Der einzelne ist eigentlich die Struktur die alles durchdringt. Jeder ist ein Verbraucher, jeder Politiker und jeder Manager. Die grundlegende Motivation des Individuums ist es die eigenen Bedürfnisse zu befriedigen und Glück und Wohlbefinden zu erreichen. Allerdings steht die eigene Bequemlichkeit der unbeschränkten Macht des bewussten Konsums im Wege. Im amerikanischen gibt den Ausspruch "Every Dollar is a VOTE", jede Ausgabe ist eine Entscheidung für etwas und gegen etwas anderes..
  • Wissenschaft -- Sie steht eigentlich querschneidend zu allen anderen Strukturen. Als Struktur sucht sie nach der Wahrheit. Sie hat die steigende Zahl der Wissenschaftler, sowie rigorose Forschungsmethoden auf der Haben-Seite. Sie ist es auch, die den technischen Wandel der Technokraten voran bringen soll. Allerdings ist ihre Unabhängigkeit durch Industrieforschung und Ergebnisbindung von Drittmitteln gefährdet. Ihr Grundprinzip (im Gegensatz zum aktuellen Modus Operandi) wird von den Ideen der Nachhaltigkeit nicht berührt, sondern eher bestärkt. Zum Thema der gekauften Forschungsergebnisse ist vielleicht noch anzumerken, dass sich eine große Firma vielleicht Ergebnisse kaufen kann. Jedoch kann sie sich keine neue Wirklichkeit kaufen. Widerspricht das Ergebnis der Wirklichkeit wird diese das falsche Ergebnis irgendwann überholen.

Eigentlich sollte die Wirtschaft vom Individuum und der Politik in "die Ecke gedrückt werden, bis sie quietscht" (Hat schon bei Franz von Papen und Hitler nicht funktioniert). Sie sollte die Bedürfnisse befriedigen, die in der Gesellschaft da sind, und keine neuen schaffen. Die Realität sieht aber so aus, dass die Wirtschaft die Politik mit Arbeitsplätzen erpresst und Staaten gegeneinander ausspielt (outsourcing). Und auf der anderen Seite die Bedürfnisse des Individuums mit Werbung steuert. Allein die Idee von Werbung, die in einer Welt mit begrenzten Ressourcen neue Bedürfnisse schafft, ist pervers.

Mein erstes persönliches Fazit aus dem Symposium ist es nur noch einmal die Woche Fleisch zu mir zu nehmen. Und ansonsten auch darauf zu achten, was die materiellen Güter sind, die ich wirklich brauche und auch brauchen will. Denn auf die Frage "Brauche ich das?" wird der eigene Geist immer eine gute Antwort finden, die das Bedürfnis rationalisiert. Die Frage "Will ich das? Will ich das wollen?" ist eine viel selbstbestimmtere und autonomere.

October 13, 2017

Andreas RuprechtSchweden 2017

Wieder Urlaub, wieder Schweden! Ein paar Eindrücke aus zwei Wochen Småland.

October 03, 2017

Christoph EggerObservations on Catalunya

Some things I don't really understand reading in German media

  • Suddenly the electoral system becomes a legitimacy problem. While it has never been a problem for any of the previous decisions of the Catalunyan regional government suddenly a "only 48% of people voted for the government" results in the decisions being illegitimate? This is also a property of many governments (Greece and the US president being obvious examples but also the German Bundestag can have a majority government without the majority of votes). Is this just the media trying to find something they can blame on "the other side"?

  • How can you ever possibly excuse violence against people peacefully and non-violently doing whatever they're doing. Sure this referendum was considered illegal (and it may be legitimate to ignore the result, or legal prosecution of the initiators) but how can that ever possibly be an excuse for half a population peacefully doing whatever they are about to do? How can you possibly claim that "both sides are to blame" for the violence? "Die Zeit" seems to be the only one with an somewhat convincing argument ("Deciding to press on despite the obviously happening violence") while "Welt", "Spiegel" and "SĂźddeutsche" all trying to blame the regional government for the violence with as much of an argument as asking people to do something illegal in a totally peaceful way. Possibly an argument for legal consequences, sure -- but for violence?

Too bad I didn't keep the links / articles from Sunday night.

Christoph EggerAnother Xor (CSAW 2017)

A short while ago, FAUST participated in this year's CSAW qualification and -- as usual -- I was working on the Crypto challenges again. The first puzzle I worked on was called "Another Xor" -- and, while there are quite some write ups already our solution was somewhat different (maybe even the intended solution given how nice things worked out) and certainly interesting.

The challenge provides a cipher-text. It's essentially a stream cipher with key repeated to generate the key stream. The plain-text was plain + key + checksum.

p = this is a plaintextThis is the keyfa5d46a2a2dcdeb83e0241ee2c0437f7
k = This is the keyThis is the keyThis is the keyThis is the keyThis i

Key length

Our first step was figuring out the key length. Let's assume for now the key was This is the key. Notice that the key is also part of the plain-text and we know something about its location -- it ends at 32 characters from the back. If we only take a look at the encrypted key it should have the following structure:

p' = This is the key
k' = he keyThis is t

The thing to notice here is that every character in the Key appears both in the plain-text and key stream sequence. And the cipher-text is the XOR (⊕) of both. Therefore XOR over the cipher-text sequence encrypting the key should equal 0 (⊕(p') ⊕ ⊕(k') = 0). So remove the last 32 characters and find all suffixes that result in a XOR of 0. Fortunately there is exactly one such suffix (there could be multiple) and therefore we know the key size: 67.

To put it in code, this basically is the function we implemented for this:

def calculate(ciphertextcandidate):
    accumulator = 0
    for char in ciphertextcandidate:
        accumulator = accumulator ^ char

Which, for the matching plain-text and key-stream fragments is equal (due to the XOR encryption) to

def calculate(plainfragment, keyfragment):
    accumulator = 0
    for i in range(len(plainfragment):
        accumulator = accumulator ^ (plainfragment[i] ^ keyfragment[i])

Now XOR lets us nicely reorder this to

def calculate(plainfragment, keyfragment):
    accumulator = 0
    for i in range(len(plainfragment):
        accumulator = accumulator ^ (plainfragment[i] ^
                                     keyfragment[(i + 6) % len(plainfragment)])

And, as plainfragment[i] and keyfragment[(i + 6) % len(plainfragment)] are equal for the plain-text range encoding the key this becomes

def calculate(plainfragment, keyfragment):
    accumulator = 0
    for i in range(len(plainfragment):
        accumulator = accumulator ^ 0

Or simply 0 if the guess of the cipher-text range is correct.

Key recovery

Now the nice thing to notice is that the length of the key (67) is a prime (and 38, the plain-text length, is a generator). As a result, we only need to guess one byte of the key:

Assume you know one byte of the key (and the position). Now you can use that one byte of the key to decrypt the next byte of the key (using the area where the key is part of the plain-text). Due to the primeness of the key length this allows recovery of the full key.

Finally you can either print all 256 options and look for the one that looks reasonable or you can verify the md5sum which will give you the one valid solution, flag{sti11_us3_da_x0r_for_my_s3cratz}.

Code


cipher = b"'L\x10\x12\x1a\x01\x00I[P-U\x1cU\x7f\x0b\x083X]\x1b'\x03\x0bR(\x04\r7SI\n\x1c\x02T\x15\x05\x15%EQ\x18\x00\x19\x11SJ\x00RV\n\x14YO\x0b\x1eI\n\x01\x0cE\x14A\x1e\x07\x00\x14aZ\x18\x1b\x02R\x1bX\x03\x05\x17\x00\x02\x07K\n\x1aLAM\x1f\x1d\x17\x1d\x00\x15\x1b\x1d\x0fH\x0eI\x1e\x02I\x01\x0c\x15\x00P\x11\\PXPCB\x03B\x13TBL\x11PC\x0b^\tM\x14IW\x08\rDD%FC"

def keycover(guess):
    key = dict()
    pos = 38
    key[38] = guess

    for i in range(67):
        newpos = (pos % 67) + 38
        key[newpos] = xor(cipher[pos:], key[pos])
        pos = newpos

    try:
        return b''.join([ key[i] for i in range(38, 105, 1) ])
    except:
        return b'test'

for guess in range(256):
    keycand = keycover(bytes([guess]))

    plaincand = xor(cipher, repeat(keycand, len(cipher)))

    if md5(plaincand[:-32]).hexdigest().encode() == plaincand[-32:]:
        print(keycand, plaincand)

Christoph EggerLooking for a mail program + desktop environment

Seems it is now almost a decade since I migrated from Thunderbird to GNUS. And GNUS is an awesome mail program that I still rather like. However GNUS is also heavily quirky. It's essentially single-threaded and synchronous which means you either have to wait for the "IMAP check for new mails" to finish or you have to C-g abort it if you want the user interface to work; You have to wait for the "Move mail" to complete (which can take a while -- especially with dovecot-antispam training the filter) before you can continue working. It has it's funny way around TLS and certificate validation. And it seems to hang from time to time until it is C-g interrupted.

So when I set up my new desktop machine I decided to try something else. My first try was claws-mail which seems OK but totally fails in the asynchronous area. While the GUI stays reactive, all actions that require IMAP interactions become incredibly slow when a background IMAP refresh is running. I do have quite some mailboxes and waiting the 5+ minutes after opening claws or whenever it decides to do a refresh is just to much.

Now my last try has been Kmail -- also driven by the idea of having a more integrated setup with CalDAV and CardDAV around and similar goodies. And Kmail really compares nicely to claws in many ways. After all, I can use it while it's doing its things in the background. However the KDE folks seem to have dropped all support for the \recent IMAP flag which I heavily rely on. I do -- after all -- keep a GNUS like workflow where all unread mail (ref \seen) needs to still be acted upon which means there can easily be quite a few unread messages when I'm busy at the moment and just having a quick look at the new (ref \recent) mail to see if there's something super-urgent is essential.

So I'm now looking for useful suggestions for a mail program (ideally with desktop integration) with the following essential features:

  • It stays usable at all times -- which means smarter queuing than claws -- so foreground actions are not delayed by any background task the mail program might be up to and tasks like moving mail are handled in the background.
  • Decent support for filtering. Apart from some basic stuff I need shortcut filtering for \recent mail.
  • Option to hide \seen mail (and ideally hide all folders that only contain \seen mail). Hopefully toggle-able by some hotkey. "Age in days" would be an acceptable approximation, but Kmail doesn't seem to allow that in search (it's available as a filter though).

September 28, 2017

Florian SchmausHow to add a REPL to your Project, using Ammonite and Gradle

Posted on September 28, 2017
Tags: gradle

Introduction

A REPL (Read-Eval-Print Loop) is a great way to use, explore and test your software. Imagine “browsing” the API of the code you have just written with tab completion.

After researching the existing REPL implementations, I decided for the Ammonite REPL. It’s an active project with an responsive maintainer, very feature rich and yet easy to use. I can only recommend looking into the other Ammonite projects.

The Ammonite REPL features tab completion, syntax highlighting and more. It can also be used for scripting purposes or as a system shell. Even though I will use it here as REPL, I can only recommend looking at its other features too.

How to add the REPL

The following will show you how to add a REPL to your project by the example of MiniDNS. The approach consists of a new Gradle subproject, whose name is post-fixed with -repl, and a two scripts: One written in Bash the other in Scala.

Creating the ‘-repl’ Gradle subproject

The -repl subproject is used to collect the classpath and thus, should declare dependencies on all other subprojects. It also comes with a custom task called printClasspath which prints the classpath to stdout for later use in the Bash script.

The build.gradle of MiniDNS looks as follows:

ext {
  scalaVersion = '2.11.7'
}

dependencies {
  // Delcare all dependencies that should be available in the REPL.
  compile project(':minidns-core')
  compile project(':minidns-iterative-resolver')
  compile project(':minidns-dnssec')
  compile project(':minidns-integration-test')
  compile project(':minidns-hla')

  // Also pull in Ammonite.
  compile "com.lihaoyi:ammonite_$scalaVersion:0.8.0"

  // The dependencies for the -repl tests.
  testCompile project(path: ":minidns-core", configuration: "testRuntime")
  testCompile project(path: ":minidns-core", configuration: "archives")
}

// The printClasspath task is used by the Bash script to kickoff the
// repl with a properly configured classhpath.
task printClasspath(dependsOn: assemble) << {
  println sourceSets.main.runtimeClasspath.asPath
}

The Bash script to kickoff the REPL

The repl Bash script will kickoff the REPL by using gradle to collect the Maven artifacts of the required dependencies and to prepare the classpath. After that is done, the java binary is used to start the REPL.

#!/usr/bin/env bash
set -e
set -u
set -o pipefail

while getopts d OPTION "$@"; do
case $OPTION in
d)
set -x
;;
esac
done

PROJECT_ROOT=$(dirname "${BASH_SOURCE[0]}")
cd "${PROJECT_ROOT}"

echo "Compiling and computing classpath (May take a while)"
# Sadly even with the --quiet option Gradle (or some component of)
# will print the number of warnings/errors to stdout if there are
# any.
GRADLE_CLASSPATH="$(gradle :minidns-repl:printClasspath --quiet |\
  tail -n1)"

echo "Classpath computed, starting REPL"

java \
  -ea \
  -Dscala.usejavacp=true \
  -classpath "${GRADLE_CLASSPATH}" \
  ammonite.Main \
  -f minidns-repl/scala.repl

You may have noticed the -f minidns-repl/scala.repl argument given to Ammonite. The scala.repl is basically file containing Scala code which is used to setup the environment of the REPL. It is where you want to declare often used and important parts of the API, that you want to make easily accessible in the REPL.

For MiniDNS, the scala.repl file looks like this:

de.measite.minidns.minidnsrepl.MiniDnsRepl.init()

import de.measite.minidns._
import de.measite.minidns.record._
import de.measite.minidns.Record.TYPE

import de.measite.minidns.dnssec.DNSSECClient

import de.measite.minidns.minidnsrepl.MiniDnsRepl.clearCache

import de.measite.minidns.minidnsrepl.MiniDNSStats._

import de.measite.minidns.jul.MiniDnsJul._

// Some standard values
Predef.println("Set value 'c' to DNSClient")
val c = de.measite.minidns.minidnsrepl.MiniDnsRepl.DNSCLIENT
Predef.println("Set value 'ic' to IterativeDNSClient")
val ic = de.measite.minidns.minidnsrepl.MiniDnsRepl.ITERATIVEDNSCLIENT
Predef.println("Set value 'dc' to DNSSECClient")
val dc = de.measite.minidns.minidnsrepl.MiniDnsRepl.DNSSECCLIENT
// A normal resolver
Predef.println("Set value 'r' to ResolverApi")
val r = de.measite.minidns.hla.ResolverApi.INSTANCE
// A DNSSEC resolver
Predef.println("Set value 'dr' to DnssecResolverApi")
val dr = de.measite.minidns.hla.DnssecResolverApi.INSTANCE

Predef.println("Enjoy MiniDNS. Go ahead and try a query. For example:")
Predef.println("c query (\"geekplace.eu\", TYPE.A)")
Predef.println("dr resolveDnssecReliable (\"verteiltesysteme.net\", classOf[A])")

Conclusion

I use this technique in multiple FOSS projects I’m involved. Most notably:

Having a such a powerful and nice REPL as provided by Ammonite at hand when developing makes it easy to test and evaluate new features. While using the API via the REPL I often discovered rough edges that made the API unnecessarily hard to use, which I’ve fixed afterwards.

Furthermore the REPL allows new user to explore the API. Feel free to try for yourself. Always wondered what is happening when MiniDNS performs a DNSSEC-enabled lookup? Lets try it out:

$ git clone https://github.com/rtreffer/minidns
$ cd minidns
$ ./repl
Compiling and computing classpath (May take a while)
Classpath computed, starting REPL
Loading...
MiniDNS REPL
Set value 'c' to DNSClient
Set value 'ic' to IterativeDNSClient
Set value 'dc' to DNSSECClient
Set value 'r' to ResolverApi
Set value 'dr' to DnssecResolverApi
Enjoy MiniDNS. Go ahead and try a query. For example:
c query ("geekplace.eu", TYPE.A)
dr resolveDnssecReliable ("verteiltesysteme.net", classOf[A])
Welcome to the Ammonite Repl 0.8.0
(Scala 2.11.8 Java 1.8.0_144)
@ enableMiniDnsTrace
@ dc queryDnssec ("uni-erlangen.de", TYPE.A)

April 09, 2017

Christoph EggerSecured OTP Server (ASIS CTF 2017)

This weekend was ASIS Quals weekend again. And just like last year they have quite a lot of nice crypto-related puzzles which are fun to solve (and not "the same as every ctf").

Actually Secured OTP Server is pretty much the same as the First OTP Server (actually it's a "fixed" version to enforce the intended attack). However the template phrase now starts with enough stars to prevent simple root.:

def gen_otps():
    template_phrase = '*************** Welcome, dear customer, the secret passphrase for today is: '

    OTP_1 = template_phrase + gen_passphrase(18)
    OTP_2 = template_phrase + gen_passphrase(18)

    otp_1 = bytes_to_long(OTP_1)
    otp_2 = bytes_to_long(OTP_2)

    nbit, e = 2048, 3
    privkey = RSA.generate(nbit, e = e)
    pubkey  = privkey.publickey().exportKey()
    n = getattr(privkey.key, 'n')

    r = otp_2 - otp_1
    if r < 0:
        r = -r
    IMP = n - r**(e**2)
    if IMP > 0:
        c_1 = pow(otp_1, e, n)
        c_2 = pow(otp_2, e, n)
    return pubkey, OTP_1[-18:], OTP_2[-18:], c_1, c_2

Now let A = template * 2^(18*8), B = passphrase. This results in OTP = A + B. c therefore is (A+B)^3 mod n == A^3 + 3A^2b + 3AB^2 + B^3. Notice that only B^3 is larger than N and is statically known. Therefore we can calculate A^3 // N and add that to c to "undo" the modulo operation. With that it's only iroot and long_to_bytes to the solution. Note that we're talking about OTP and C here. The code actually produced two OTP and C values but you can use either one just fine.

#!/usr/bin/python3

import sys
from util import bytes_to_long
from gmpy2 import iroot

PREFIX = b'*************** Welcome, dear customer, the secret passphrase for today is: '
OTPbase = bytes_to_long(PREFIX + b'\x00' * 18)

N = 27990886688403106156886965929373472780889297823794580465068327683395428917362065615739951108259750066435069668684573174325731274170995250924795407965212988361462373732974161447634230854196410219114860784487233470335168426228481911440564783725621653286383831270780196463991259147093068328414348781344702123357674899863389442417020336086993549312395661361400479571900883022046732515264355119081391467082453786314312161949246102368333523674765325492285740191982756488086280405915565444751334123879989607088707099191056578977164106743480580290273650405587226976754077483115441525080890390557890622557458363028198676980513

WRAPPINGS = (OTPbase ** 3) // N

C = 13094996712007124344470117620331768168185106904388859938604066108465461324834973803666594501350900379061600358157727804618756203188081640756273094533547432660678049428176040512041763322083599542634138737945137753879630587019478835634179440093707008313841275705670232461560481682247853853414820158909864021171009368832781090330881410994954019971742796971725232022238997115648269445491368963695366241477101714073751712571563044945769609486276590337268791325927670563621008906770405196742606813034486998852494456372962791608053890663313231907163444106882221102735242733933067370757085585830451536661157788688695854436646

x = N * WRAPPINGS + C

val, _ = iroot(x, 3)
bstr = "%x" % int(val)

for i in range(0, len(bstr) // 2):
    sys.stdout.write(chr(int(bstr[2*i:2*i+2], 16)))

print()

November 03, 2016

Maximilian HenryAqbanking Error -57

Wer schon länger Gnucash oder andere auf Aqbanking setzende Lösungen für sein Onlinebanking bei der Sparkasse verwendet, wird feststellen, dass dies nicht mehr funktioniert und die einzige Meldung im Log sagt wenig hilfreich error -57.
Nachdem die Antwort auf dieses Problem nirgends ordentlich beschrieben ist, will ich dieses Lücke hier füllen.

Lösung:
Die Sparkasse versucht euch seit geraumer zeit mitzuteilen, dass ihr von HBCI 2.2 auf HBCI 3.0 umstellen müsst, leider habt ihr die Nachricht nie gesehen.
unter ~/.aqbanking/backends/aqhbci/data/banks/de/[BLZ]/users/[UID]/[KN]/messages/in findet ihr Nachrichten von eurer Bank, die euch sagen, dass ihr auf HBCI 3.0
umstellen sollt, inklusive des neuen Servers.
Also öffnen wir ~/.aqbanking/settings/*.conf und setzen das Feld
int hbciVersion ="300" und passen noch char server=banking-by1.s-fints-pt-by.de%3A3000%2F entsprechend an. Nicht wundern, dass die Kodierung etwas seltsam ist, das ist bestimmt der beste weg den Port 3000 zu speichern. Nach diesen beiden Änderungen sollte wieder alles wie gewohnt funktionieren.

October 26, 2016

Christoph EggerInstalling a python systemd service?

As web search engines and IRC seems to be of no help, maybe someone here has a helpful idea. I have some service written in python that comes with a .service file for systemd. I now want to build&install a working service file from the software's setup.py. I can override the build/build_py commands of setuptools, however that way I still lack knowledge wrt. the bindir/prefix where my service script will be installed.

Solution

Turns out, if you override the install command (not the install_data!), you will have self.root and self.install_scripts (and lots of other self.install_*). As a result, you can read the template and write the desired output file after calling super's run method. The fix was inspired by GateOne (which, however doesn't get the --root parameter right, you need to strip self.root from the beginning of the path to actually make that work as intended).

As suggested on IRC, the snippet (and my software) no use pkg-config to get at the systemd path as well. This is a nice improvement orthogonal to the original problem. The implementation here follows bley.


def systemd_unit_path():
    try:
        command = ["pkg-config", "--variable=systemdsystemunitdir", "systemd"]
        path = subprocess.check_output(command, stderr=subprocess.STDOUT)
        return path.decode().replace('\n', '')
    except (subprocess.CalledProcessError, OSError):
        return "/lib/systemd/system"


class my_install(install):
    _servicefiles = [
        'foo/bar.service',
        ]

    def run(self):
        install.run(self)

        if not self.dry_run:
            bindir = self.install_scripts
            if bindir.startswith(self.root):
                bindir = bindir[len(self.root):]

            systemddir = "%s%s" % (self.root, systemd_unit_path())

            for servicefile in self._servicefiles:
                service = os.path.split(servicefile)[1]
                self.announce("Creating %s" % os.path.join(systemddir, service),
                              level=2)
                with open(servicefile) as servicefd:
                    servicedata = servicefd.read()

                with open(os.path.join(systemddir, service), "w") as servicefd:
                    servicefd.write(servicedata.replace("%BINDIR%", bindir))

Comments, suggestions and improvements, of course, welcome!

Florian SchmausDesigning a DNSSEC application API

Posted on October 26, 2016
Tags: dnssec, xmpp

I’m intending to apply a patch adding DNSSEC support to Smack, a XMPP client library, in the near feature. And since DNSSEC support in application protocol libraries is still uncommon, I thought it might be a good idea to share the principles how the API was designed.

DNSSEC

DNSSEC authenticates DNS answers, positive and negative ones. This means that if a DNS response secured by DNSSEC turns out to be authentic, then you can be sure that the domain either exists, and that the returned resource records (RRs) are the ones the domain owner authorized, or that the domain does not exists and that nobody tried to fake its non existence.

The tricky part is that an application using DNSSEC can not determine whether a domain uses DNSSEC, does not use DNSSEC or if someone downgraded your DNS query using DNSSEC to a response without DNSSEC.

Smack’s DNSSEC API

I like to keep APIs I design as simple as possible to use for the user. Thus Smack’s DNSSEC API simply extends the already existing ConnectionConfiguration used to – you guessed it – configure XMPP connections by a single method:

ConnectionConfiguration.setDnssecMode(DnssecMode dnssecMode);

where DnssecMode is an enum defined as follows:

enum DnssecMode {
  disabled,
  needsDnssec,
  needsDnssecAndDane,
}

The user simply calls config.setDnssecMode(DnssecMode.needsDnssec) and Smack will only connect to an XMPP service if all involved DNS resource recordes could be verified using DNSSEC.

You may noticed the ...AndDane variant of the enum. If this mode is used, then Smack will not only require DNSSEC, but also require DANE (RFC 6598) in order to verify the service’s TLS certificate.

Desiging for a good UI and UX

The Issue

The issue with the DnssecMode API exposed by Smack is that an application should never have to ask the end-user if it’s XMPP account is secured by DNSSEC. There should be no questionare, checkbox or whatever about this feature. The best UI regarding a option is if there is none, i.e., if it just works out of the box.

A possible solution

So what should applications do? The answer is simple and similar to “HTTP Strict Transport Security” (HSTS, RFC 6797) used for HTTP(S) connections. Instead of asking the user if DNSSEC is available, they should check for DNSSEC support on every connection attempt. Once DNSSEC support has been discovered, the application uses the needsDnssec mode for all future connection attempts.

An analysis

Of course this scheme is not without drawbacks. First, it is possible that an attacker downgrades the DNS responses to non-DNSSEC. Depending on where the attacker sits in the path between the user and its service, this may always be possible for the attacker or only if the user’s device uses a certain network. The downgrade attack also becomes impossible with this scheme after the application was at least once able to connect to the service using DNSSEC.

Furthermore, if the user’s service needs to drop DNSSEC support for whatever reason (technical, political, …), then the user possible gets a message that the connection failed because something named “DNSSEC” was not avaialble. As with most security concepts, it is hard for the average user to asses situation and take the approbiate action. Of course, the application could ask the user to contact the service provider and ask if DNSSEC was indeed disabled before continuing the connection attempt.

But ideally, service providers would never drop DNSSEC support and the application would simply start a new connection attempt after a failed one caused by the lack of DNSSEC. This is similar to how most applications would (or should) treat a STARTTLS downgrade attack: Simply retry until the demanded security gurantees are fullfiled. Then the user doesn’t have to deal with technical error messages.

Note that the exact same scheme can be used with the needsDnssecAndDane mode. Once DNSSEC and a TLSA RR has been discovered for the service and was successfully used to verify the TLS connection, the application should always use the needsDnssecAndDane mode.

Why not in Smack?

The attentive reader may wonder why I did not implement the described mechanism in Smack, instead of having the application deal with it. I’d really love to do so, but Smack has no API and mechanism for saving a connection state to persistent storage. This would be required for the described scheme. Such a mechanism planned to come with Smack 4.3 though.

October 22, 2016

Christoph EggerRunning Debian on the ClearFog

Back in August, I was looking for a Homeserver replacement. During FrOSCon I was then reminded of the Turris Omnia project by NIC.cz. The basic SoC (Marvel Armada 38x) seemed to be nice hand have decent mainline support (and, with the turris, users interested in keeping it working). Only I don't want any WIFI and I wasn't sure the standard case would be all that usefully. Fortunately, there's also a simple board available with the same SoC called ClearFog and so I got one of these (the Base version). With shipping and the SSD (the only 2242 M.2 SSD with 250 GiB I could find, a ADATA SP600) it slightly exceeds the budget but well.

ClearFog with SSD

When installing the machine, the obvious goal was to use mainline FOSS components only if possible. Fortunately there's mainline kernel support for the device as well as mainline U-Boot. First attempts to boot from a micro SD card did not work out at all, both with mainline U-Boot and the vendor version though. Turns out the eMMC version of the board does not support any micro SD cards at all, a fact that is documented but others failed to notice as well.

U-Boot

As the board does not come with any loader on eMMC and booting directly from M.2 requires removing some resistors from the board, the easiest way is using UART for booting. The vendor wiki has some shell script wrapping an included C fragment to feed U-Boot to the device but all that is really needed is U-Boot's kwboot utility. For some reason the SPL didn't properly detect UART booting on my device (wrong magic number) but patching the if (in arch-mvebu's spl.c) and always assume UART boot is an easy way around.

The plan then was to boot a Debian armhf rootfs with a defconfig kernel from USB stick. and install U-Boot and the rootfs to eMMC from within that system. Unfortunately U-Boot seems to be unable to talk to the USB3 port so no kernel loading from there. One could probably make UART loading work but switching between screen for serial console and xmodem seemed somewhat fragile and I never got it working. However ethernet can be made to work, though you need to set eth1addr to eth3addr (or just the right one of these) in U-Boot, saveenv and reboot. After that TFTP works (but is somewhat slow).

eMMC

There's one last step required to allow U-Boot and Linux to access the eMMC. eMMC is wired to the same PINs as the SD card would be. However the SD card has an additional indicator pin showing whether a card is present. You might be lucky inserting a dummy card into the slot or go the clean route and remove the pin specification from the device tree.

--- a/arch/arm/dts/armada-388-clearfog.dts
+++ b/arch/arm/dts/armada-388-clearfog.dts
@@ -306,7 +307,6 @@

                        sdhci@d8000 {
                                bus-width = <4>;
-                               cd-gpios = <&gpio0 20 GPIO_ACTIVE_LOW>;
                                no-1-8-v;
                                pinctrl-0 = <&clearfog_sdhci_pins
                                             &clearfog_sdhci_cd_pins>;

Next Up is flashing the U-Boot to eMMC. This seems to work with the vendor U-Boot but proves to be tricky with mainline. The fun part boils down to the fact that the boot firmware reads the first block from eMMC, but the second from SD card. If you write the mainline U-Boot, which was written and tested for SD card, to eMMC the SPL will try to load the main U-Boot starting from it's second sector from flash -- obviously resulting in garbage. This one took me several tries to figure out and made me read most of the SPL code for the device. The fix however is trivial (apart from the question on how to support all different variants from one codebase, which I'll leave to the U-Boot developers):

--- a/include/configs/clearfog.h
+++ b/include/configs/clearfog.h
@@ -143,8 +143,7 @@
 #define CONFIG_SPL_LIBDISK_SUPPORT
 #define CONFIG_SYS_MMC_U_BOOT_OFFS             (160 << 10)
 #define CONFIG_SYS_U_BOOT_OFFS                 CONFIG_SYS_MMC_U_BOOT_OFFS
-#define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR        ((CONFIG_SYS_U_BOOT_OFFS / 512)\
-                                                + 1)
+#define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR        (CONFIG_SYS_U_BOOT_OFFS / 512)
 #define CONFIG_SYS_U_BOOT_MAX_SIZE_SECTORS     ((512 << 10) / 512) /* 512KiB */
 #ifdef CONFIG_SPL_BUILD
 #define CONFIG_FIXED_SDHCI_ALIGNED_BUFFER      0x00180000      /* in SDRAM */

Linux

Now we have a System booting from eMMC with mainline U-Boot (which is a most welcome speedup compared to the UART and TFTP combination from the beginning). Getting to fine-tune linux on the device -- we want to install the armmp Debian kernel and have it work. As all the drivers are build as modules for that kernel this also means initrd support. Funnily U-Boots bootz allows booting a plain vmlinux kernel but I couldn't get it to boot a plain initrd. Passing a uImage initrd and a normal kernel however works pretty well. Back when I first tried there were some modules missing and ethernet didn't work with the PHY driver built as a module. In the meantime the PHY problem was fixed in the Debian kernel and almost all modules already added. Ben then only added the USB3 module on my suggestion and as a result, unstable's armhf armmp kernel should work perfectly well on the device (you still need to patch the device tree similar to the patch above). Still missing is an updated flash-kernel to automatically generate the initrd uImage which is work in progress but got stalled until I fixed the U-Boot on eMMC problem and everything should be fine -- maybe get debian u-boot builds for that board.

Pro versus Base

The main difference so far between the Pro and the Base version of the ClearFog is the switch chip which is included on the Pro. The Base instead "just" has two gigabit ethernet ports and a SFP. Both, linux' and U-Boot's device tree are intended for the Pro version which makes on of the ethernet ports unusable (it tries to find the switch behind the ethernet port which isn't there). To get both ports working (or the one you settled on earlier) there's a second patch to the device tree (my version might be sub-optimal but works), U-Boot -- the linux-kernel version is a trivial adaption:

--- a/arch/arm/dts/armada-388-clearfog.dts
+++ b/arch/arm/dts/armada-388-clearfog.dts
@@ -89,13 +89,10 @@
                internal-regs {
                        ethernet@30000 {
                                mac-address = [00 50 43 02 02 02];
+                               managed = "in-band-status";
+                               phy = <&phy1>;
                                phy-mode = "sgmii";
                                status = "okay";
-
-                               fixed-link {
-                                       speed = <1000>;
-                                       full-duplex;
-                               };
                        };

                        ethernet@34000 {
@@ -227,6 +224,10 @@
                                pinctrl-0 = <&mdio_pins>;
                                pinctrl-names = "default";

+                               phy1: ethernet-phy@1 { /* Marvell 88E1512 */
+                                    reg = <1>;
+                               };
+
                                phy_dedicated: ethernet-phy@0 {
                                        /*
                                         * Annoyingly, the marvell phy driver
@@ -386,62 +386,6 @@
                tx-fault-gpio = <&expander0 13 GPIO_ACTIVE_HIGH>;
        };

-       dsa@0 {
-               compatible = "marvell,dsa";
-               dsa,ethernet = <&eth1>;
-               dsa,mii-bus = <&mdio>;
-               pinctrl-0 = <&clearfog_dsa0_clk_pins &clearfog_dsa0_pins>;
-               pinctrl-names = "default";
-               #address-cells = <2>;
-               #size-cells = <0>;
-
-               switch@0 {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       reg = <4 0>;
-
-                       port@0 {
-                               reg = <0>;
-                               label = "lan1";
-                       };
-
-                       port@1 {
-                               reg = <1>;
-                               label = "lan2";
-                       };
-
-                       port@2 {
-                               reg = <2>;
-                               label = "lan3";
-                       };
-
-                       port@3 {
-                               reg = <3>;
-                               label = "lan4";
-                       };
-
-                       port@4 {
-                               reg = <4>;
-                               label = "lan5";
-                       };
-
-                       port@5 {
-                               reg = <5>;
-                               label = "cpu";
-                       };
-
-                       port@6 {
-                               /* 88E1512 external phy */
-                               reg = <6>;
-                               label = "lan6";
-                               fixed-link {
-                                       speed = <1000>;
-                                       full-duplex;
-                               };
-                       };
-               };
-       };
-
        gpio-keys {
                compatible = "gpio-keys";
                pinctrl-0 = <&rear_button_pins>;

Conclusion

Apart from the mess with eMMC this seems to be a pretty nice device. It's now happily running with a M.2 SSD providing enough storage for now and still has a mSATA/mPCIe plug left for future journeys. It seems to be drawing around 5.5 Watts with SSD and one Ethernet connected while mostly idle and can feed around 500 Mb/s from disk over an encrypted ethernet connection which is, I guess, not too bad. My plans now include helping to finish flash-kernel support, creating a nice case and probably get it deployed. I might bring it to FOSDEM first though.

Working on it was really quite some fun (apart from the frustrating parts finding the one-block-offset ..) and people were really helpful. Big thanks here to Debian's arm folks, Ben Hutchings the kernel maintainer and U-Boot upstream (especially Tom Rini and Stefan Roese)

August 30, 2016

Maximilian HenryDateien mit Linux-Anwendungen unter Windows 10 öffnen

Windows 10 bietet seit Anfang August eine Linux Umgebung, welche in der Lage ist, viele übliche Linux-Anwendungen auszuführen. Während es von Haus aus keine Unterstützung für GUI-Anwendungen gibt, dauerte es nicht lange, bis Leute herausfanden, dass dies mit Hilfe des X-Servers XMing in der Windows-Umgebung kein Problem ist. Doch wie kann man nun diese Anwendungen direkt als Filehandler starten?
2 kleine Skripte, und schon können wir zum Beispiel den PDF-Betrachter Katarakt unter Windows 10 nutzen:
Skript 1 plazieren wir als katarakt.cmd irgendwo in unserem Windows

pushd && bash.exe -c "~/bin/winrun katarakt '"%1"'"  

Skript 2 ist ein bash-skript und gehört in die Linux-Umgebung, wenn es nicht unter ~/bin/winrun liegen soll, muss der Pfad in Skript 1 angepasst werden.

#!/bin/bash

winpath="$2"  
prog="$1"  
driveletter=$(echo "$winpath" | head -c1 | tr '[:upper:]' '[:lower:]')  
localpath=$(echo "$winpath" | cut -f2- -d"\\" | sed 's#\\#\/#g')  
fullpath="/mnt/$driveletter/$localpath"  
DISPLAY=:0 "$prog" "$fullpath"  

Das 2. Skript dient nun dazu, den absoluten Windows-Pfad, welcher übergeben wurde, in einen in der Linux-Umgebung gültigen zu verwandeln und dann die Anwendung zu starten. Nicht vergessen, vorher den XMing zu starten und das 2. Skript ausführbar zu machen und ihr könnt eure Lieblingsanwendung, die es nicht für Windows gibt, quasi-nativ verwenden.

Christoph EggerDANE and DNSSEC Monitoring

At this year's FrOSCon I repeted my presentation on DNSSEC. In the audience, there was the suggestion of a lack of proper monitoring plugins for a DANE and DNSSEC infrastructure that was easily available. As I already had some personal tools around and some spare time to burn I've just started a repository with some useful tools. It's available on my website and has mirrors on Gitlab and Github. I intent to keep this repository up-to-date with my personal requirements (which also means adding a xmpp check soon) and am happy to take any contributions (either by mail or as "pull requests" on one of the two mirrors). It currently has smtp (both ssmtp and starttls) and https support as well as support for checking valid DNSSEC configuration of a zone.

While working on it it turned out some things can be complicated. My language of choice was python3 (if only because the ssl library has improved since 2.7 a lot), however ldns and unbound in Debian lack python3 support in their bindings. This seems fixable as the source in Debian is buildable and useable with python3 so it just needs packaging adjustments. Funnily the ldns module, which is only needed for check_dnssec, in debian is currently buggy for python2 and python3 and ldns' python3 support is somewhat lacking so I spent several hours hunting SWIG problems.

August 11, 2016

Christoph EggerLooking for a replacement Homeserver

Almost exactly six years ago I bought one of these Fuloong 6064 mini PCs. The machine has been working great ever since both collecting my mail and acting as an IMAP server as well as providing public services -- it's also keyserver.siccegge.de. However jessie is supposed to be the last Debian release supporting the hardware and the system's rather slow and lacks memory. This is especially noticeable with IMAP spam filter training and mail indexing. Therefore I'm looking for some nice replacement -- preferably non-x86 again (no technical reasons). My requirements are pretty simple:

  • Works with vanilla stretch (and stretch kernel)
  • Still works with Debian stable six years from now
  • Faster (single-core performance, 2-4 cores would be nice as well), currently it's a 900MHz super-scalar, out-of-order MIPS64 CPU
  • Consumes less power
  • SATA port
  • Preferably fanless
  • Maximum same price range, around 200 EUR including case and shipping

Now I'd consider one of these ARM boards and get it a nice case but they seem all to either fail in terms of SATA or not being faster at all (and one needs to go for outdated hardware to stand a chance of mainline kernel support). If anyone knows something nice and non-x86 I'll happily take suggestions.

July 04, 2016

Florian SchmausXMPP IoT Anti-Patterns

Posted on July 4, 2016
Tags: xmpp

The recent issue (2016-14 page 78 ff.) of the German computer magazine c’t has an interesting article about security issues in alarm systems. I was a bit surprised that in 2016 we still have systems online which are vulnerable because of a default password or passwords like ‘1234’. The c’t had articles about similar issues before. Obviously the industry has much to learn about securing the Internet of Things (IoT).

What caught my attention was an XMPP message that is, according to the article, used by the alarm system to confirm the user PIN with a central server in order to disarm the system. The article describes a security flaw where sending the same message without the PIN would erroneously disarm the system. The message stanza looks like this

<message
  id="n0000-000000"
  to="<unique-id-of-alarm-system-central>@climax-home-portal"
  type="chat"
  from="security_ admin@climax-home-portal/Smack">
    <body> 4150795OqiESNX2RCHC/ :;MODA:1,0, 1234 </body>
</message>

This demonstrates nicely a few XMPP-for-IoT Anti-Patterns I’d like to discuss.

The Anti-Patterns

  1. Using XMPP without properly secured TLS. What made it easy to have a direct look at the used XMPP stanzas, was that the alarm system used an unencrypted connection. This revealed the PIN position and made it possible to inject spoofed stanzas.

  2. Abusing <body/> to carry machine data. RFC 6121 § 5.2.3 defines the <body/> content as “human-readable XML character data”. I guess this contributed a bit to the security flaw, where a message stanza without the PIN would disarm the system, because parsing that particular body content format doesn’t seem easy. But even if my guess is wrong, abusing the <body/> element in such a way will eventually snap back to you once your IoT environment grows.

  3. Allowing the client to determine the resource. Depending on the services policy on resource conflicts, this could lead to reconnect loops until the old connection using the same resource finally timeouts. Hardcoded resource strings also make it easy for an attacker to guess a resource. If the client does not protect itself against unsolicited stanzas send, e.g. by using XEP-0016 Privacy Lists, then this could at least allow an attacker to drain a mobile clients battery or allow him to access unprotected IQ interfaces.

  4. Using ‘chat’ type messages. Often done because “we don’t know better”. OK, I’m just guessing that ‘chat’ was used because of this reason. But I see it often that people just use ‘chat’ for no obvious reason, ‘normal’ would be the better choice in this case. And since it is the default type, you can omit it, saving a few bytes over the wire.

The Correct Patterns

  1. Use proper TLS for god’s sake. But “enabling” TLS is not enough. There is an intolerably large amount of implementations using TLS with an “accept all certificates” policy in order to be able to connect to hosts with self-signed certificates. That is a very bad approach in every aspect. Instead, use Certificate Pinning. With Java Pinning and Smack, TLS Certificate Pinning is as easy as:

    SSLContext sc = Java7Pinning
      .forPin("SHA256:e3b1812d945da1a2a2c5fa28029d2fe34c7c...");
    XMPPTCPConnectionConfiguration conf = XMPPTCPConnectionConfiguration
      .builder()
      .setUsernameAndPassword("user", "pass")
      .setXmppDomain("example.org")
      .setCustomSSLContext(sc)
      .build();
  2. Use a custom extension element for your data. After all, extensibility is one of the strong arguments for XMPP. All XMPP libraries provide APIs to handle (create, process, serialize, deserialize) custom extension elements. The message above could for example look like this if they had used a custom <disarm xmlns='namespace:of:vendor'/> extension element:

    <message
      id="n0000-000000"
      to="<unique-id-of-alarm-system-central>@climax-home-portal"
      from="security_ admin@climax-home-portal/ba7971ca-a887-404b-8c48">
    <disarm xmlns='namespace:of:vendor'>
      <data>4150795OqiESNX2RCHC/</data>
      <mode foo='true' bare='false'>MODA</mode>
      <pin>1234</pin>
    </disarm>
    </message>
  3. Let the server assign a resource. You usually want to do this independently of your use-case for XMPP (e.g. also when using XMPP for Instant Messaging). Since this is not IoT specific, but true for general XMPP usage, the XMPP Wiki also mentions this as guideline for IM developers also providing a rationale.

  4. Use a fitting message type. XMPP provides a variety of message types, each with different semantics. Sadly those types are named after their common use-case and not after their semantic, so people assume that they are just useful for that. For example ‘chat’ for chatting purposes and ‘headline’ for headlines. But in the end, you should choose the message type depending on your use-case. Primarily the message type affects the routing rules of the message stanzas. There is no reason you would want to use ‘chat’ in IoT. Use ‘normal’ and omit the ‘type’ attribute completely, since ‘normal’ is the default. Messages of type ‘headline’ also provide some nice properties for the IoT use-case (fan-out to all available resources of the recipient).

Remark

Note that this list of patterns is not comprehensive. Also some points are not exclusive to XMPP-for-IoT, but apply to XMPP usage in general.

Get in touch with the XMPP Community

I really encourage vendors to discuss their ideas, designs and approaches build upon XMPP with the XMPP community. I have encountered a lot of IoT specifications and implementations using XMPP which had, not only minor, but also serious design flaws. Fixing the ones which are already in production is an enormous effort. Thus I can only strongly recommend to get a peer review for your design early.

The XMPP community is very friendly, especially when it comes to supporting open standards and potentially subsequent open-source implementations. Usually you will find people willing to help you design and review your XMPP usage. Just join the xsf@muc.xmpp.org chat or post your XMPP related questions to the standards@mail.jabber.org mailing list.

April 22, 2016

Florian SchmausAlpha release of MiniDNS DNSSEC

Posted on April 22, 2016
Tags: dns, xmpp

Introduction

Rene just tagged MiniDNS 0.2.0-alpha3 and pushed it to Maven Central. This release includes experimental support for DNSSEC.

About MiniDNS

MiniDNS is an open-source and highly portable DNS resolver written in Java for Android and Java SE runtimes. MiniDNS aims to be lightweight and modular, which makes it different from similar projects like dnsjava.

It is triple licensed. Users can choose the license terms they like from: Apache License 2.0, LGPL 2.1 and WTFPL.

The fastest way to get familiar with MiniDNS is by playing around with its built-in Read-Evaluate-Print-Loop (REPL). Pleaes note that proper support for CNAME / DNAME is not yet implemented.

DNSSEC

The new DNSSEC (DNS Security Extensions) support was added through a Google Summer of Code (GSOC) project in 2015 under the umbrella of the XMPP Standards Foundation (XSF). We would like to thank our skilled student Marvin and Google for making this possible.

DNSSEC has multiple benefits, it not only allows the verification of DNS responses (data origin authentication), but also helps making protocols like HTTP, SMTP, IMAP and XMPP more secure by using DANE.

Multiple open source projects already expressed interested in MiniDNS’s DNSSEC feature: Also Smack, the XMPP client library for Android and Java SE I maintain, will provide experimental support for DANE using MiniDNS soon. Daniel, the author of the popular Android XMPP client Conversations, already a MiniDNS user, also expressed interest in adding support for DANE. And last but not least, Vincent and Dominik of OpenKeychain fame are looking forward to adding support for the OPENPGPKEY record as defined in draft-ietf-dane-openpgpkey.

Other projects are of course welcome as well. But please contact me before using the DNSSEC features of MiniDNS: Again, this is highly experimental code. I will keep you updated about the current state of MiniDNS in this very blog.

Help Wanted

The MiniDNS code has not yet received an extensive security review. As an understaffed open source project without any funding, we don’t have the necessary resources to pay for such a review.

But even if we had the funds, we first need to find someone capable of actually performing such a review. Maybe you know someone or how to help?

Feel free to contact me if you want to help.

Future Release Highlight: Support for the Kitchen Sink RR

With DNSSEC support in the ‘master’ branch, the only killer feature missing is support for the Kitchen Sink Resource Record (KS RR). The KS RR allows “to put complex, bulky, and/or obscurely structured data into the Domain Name System (DNS)”. Combined with DNSSEC this allows signing arbitrary data of any size, allowing for a broad range of possible use cases. Unlike most other pending features in open source projects, we are able to give an exact date when this feature will arrive: 2017-04-01. Stay tuned.

March 19, 2016

Maximilian HenryEine neue Vision

Es ist kein Geheimnis, dass Deutschland nach Schröder und Merkel ohne eine Volkspartei mit einer wirkliche Vision oder Ideologie da steht, während viele das gar nicht so schlecht finden mögen, ist es doch diese Ideenlosigkeit, welche auch einer der Gründe für den Aufstieg der AfD ist. Dort wo Merkel all jene, die wirklich eine konservative Politik wollten verloren hat, schöpft die AfD, abseits des braunen Sumpfes, aus dem die NPD nie herauskam und in welchen die Medien und die etablierten Parteien sie gerne einsortieren würden. Doch die alten Ideologien sind nicht nur an Schröder und Merkel gestorben, ihnen fehlt es auch heute an dem Bezug zur gesellschaftlichen Realität.
Wie soll denn heute eine sozialdemokratische Politik aussehen, ganz ohne die Arbeiter, welche einst das Kernklientel bildeten und deren Jobs fast vollständig verschwunden sind.
Ich glaube, dass uns durchaus eine Partei, welche für eine soziale und faire Behandlung der Unterschicht und unteren Mittelschicht, aller Abhängig-Beschäftigen und Arbeitslosen braucht, aber die SPD erfüllt diese Rolle nicht und kann sie, ohne eine neue Idee auch nicht mehr erfüllen, selbst wenn sie wollte und die Linke ist einfach zu intellektuell und außerdem gerade in Westdeutschland noch immer nicht wählbar.
Die Partei, die wir bräuchten, müsste ganz oben Arbeit psychologisch entwerten. Es gibt keinen Grund, warum in unserer Welt arbeit, gerade für die schlechter gestellten, identitätsstiftend sein sollte, nutzlose neoliberale Begriffe wie Leistungsträger gehören entwertet! Gleichzeitig, muss die eine Botschaft verbreitet werden, die wirklich weiten Teilen der Gesellschaft eine Beschäftigung verschaffen kann, wir müssen die Regelarbeitszeit schrittweise in die Richtung 30-32h senken und eine Obergrenze der Wochenarbeitszeit einführen!
Die Automatisierung weiter Geschäftsfelder kann nur so ein Gewinn für die Gesellschaft sein und man muss sich klar machen, dass wer heute 60h arbeitet, einer zweiten Person ihre Beschäftigung klaut und keine neoliberale Bewunderung verdient. Wie eine Entsprechung dazu im konservativen Spektrum aussehen könnte, um der AfD auch dort etwas anderes, als Ideenlosigkeit entgegen zu setzen, fällt mir schwer zu beurteilen, da dies zu weit von meiner eigenen politischen Identität entfernt ist.

February 24, 2016

Christoph Eggerdoveadm deduplicate

Without further words:

% for i in $(seq 1 90) ; do doveadm mailbox status messages debian.buildd.archive.2011.05 | column -t ;  doveadm deduplicate mailbox debian.buildd.archive.2011.05 ; done
debian.buildd.archive.2011.05  messages=8094
debian.buildd.archive.2011.05  messages=7939
debian.buildd.archive.2011.05  messages=7816
debian.buildd.archive.2011.05  messages=7698
debian.buildd.archive.2011.05  messages=7610
debian.buildd.archive.2011.05  messages=7529
debian.buildd.archive.2011.05  messages=7455
debian.buildd.archive.2011.05  messages=7375
debian.buildd.archive.2011.05  messages=7294
debian.buildd.archive.2011.05  messages=7215
debian.buildd.archive.2011.05  messages=7136
debian.buildd.archive.2011.05  messages=7032
debian.buildd.archive.2011.05  messages=6941
debian.buildd.archive.2011.05  messages=6839
debian.buildd.archive.2011.05  messages=6721
debian.buildd.archive.2011.05  messages=6631
debian.buildd.archive.2011.05  messages=6553
debian.buildd.archive.2011.05  messages=6476
debian.buildd.archive.2011.05  messages=6388
debian.buildd.archive.2011.05  messages=6301
debian.buildd.archive.2011.05  messages=6211
debian.buildd.archive.2011.05  messages=6140
debian.buildd.archive.2011.05  messages=6056
debian.buildd.archive.2011.05  messages=6007
debian.buildd.archive.2011.05  messages=5955
debian.buildd.archive.2011.05  messages=5887
debian.buildd.archive.2011.05  messages=5826
debian.buildd.archive.2011.05  messages=5752
debian.buildd.archive.2011.05  messages=5706
debian.buildd.archive.2011.05  messages=5657
debian.buildd.archive.2011.05  messages=5612
debian.buildd.archive.2011.05  messages=5570
debian.buildd.archive.2011.05  messages=5523
debian.buildd.archive.2011.05  messages=5474
debian.buildd.archive.2011.05  messages=5422
debian.buildd.archive.2011.05  messages=5382
debian.buildd.archive.2011.05  messages=5343
debian.buildd.archive.2011.05  messages=5308
debian.buildd.archive.2011.05  messages=5256
debian.buildd.archive.2011.05  messages=5221
debian.buildd.archive.2011.05  messages=5168
debian.buildd.archive.2011.05  messages=5133
debian.buildd.archive.2011.05  messages=5092
debian.buildd.archive.2011.05  messages=5058
debian.buildd.archive.2011.05  messages=5030
debian.buildd.archive.2011.05  messages=4994
debian.buildd.archive.2011.05  messages=4964
debian.buildd.archive.2011.05  messages=4935
debian.buildd.archive.2011.05  messages=4900
debian.buildd.archive.2011.05  messages=4868
debian.buildd.archive.2011.05  messages=4838
debian.buildd.archive.2011.05  messages=4811
debian.buildd.archive.2011.05  messages=4778
debian.buildd.archive.2011.05  messages=4748
debian.buildd.archive.2011.05  messages=4722
debian.buildd.archive.2011.05  messages=4686
debian.buildd.archive.2011.05  messages=4661
debian.buildd.archive.2011.05  messages=4637
debian.buildd.archive.2011.05  messages=4613
debian.buildd.archive.2011.05  messages=4593
debian.buildd.archive.2011.05  messages=4570
debian.buildd.archive.2011.05  messages=4554
debian.buildd.archive.2011.05  messages=4536
debian.buildd.archive.2011.05  messages=4520
debian.buildd.archive.2011.05  messages=4500
debian.buildd.archive.2011.05  messages=4481
debian.buildd.archive.2011.05  messages=4466
debian.buildd.archive.2011.05  messages=4445
debian.buildd.archive.2011.05  messages=4430
debian.buildd.archive.2011.05  messages=4417
debian.buildd.archive.2011.05  messages=4405
debian.buildd.archive.2011.05  messages=4390
debian.buildd.archive.2011.05  messages=4376
debian.buildd.archive.2011.05  messages=4366
debian.buildd.archive.2011.05  messages=4360
debian.buildd.archive.2011.05  messages=4350
debian.buildd.archive.2011.05  messages=4336
debian.buildd.archive.2011.05  messages=4329
debian.buildd.archive.2011.05  messages=4320
debian.buildd.archive.2011.05  messages=4315
debian.buildd.archive.2011.05  messages=4312
debian.buildd.archive.2011.05  messages=4311
debian.buildd.archive.2011.05  messages=4309
debian.buildd.archive.2011.05  messages=4308
debian.buildd.archive.2011.05  messages=4308
debian.buildd.archive.2011.05  messages=4308
debian.buildd.archive.2011.05  messages=4308
debian.buildd.archive.2011.05  messages=4308
debian.buildd.archive.2011.05  messages=4308
debian.buildd.archive.2011.05  messages=4308

February 10, 2016

Maximilian HenryPodcast Empfehlungen 2016

In diesem Blog gab es vor langer Zeit schon Podcast Empfehlungen und ich möchte diese Tradition nun hier wieder aufleben lassen. Dieses mal ist die Empfehlungsliste sehr englisch-lastig.

  • Radio War Nerd ist sicherlich eine seltsame Nische, zumal es den Podcast ohne zu bezahlen nicht als rss-Feed gibt, sondern ihr ihn von Hand von Patreon pulen müsst. Als Inhalt gibt es Gespräche über aktuelle und vergangene Kriege, mit Fokus auf Strategie und Motivation. Wer verstehen will, was der eigentlich Sinn des Syrien Kriegs ist, dem sei dieser Podcast sehr empfohlen.
  • Arms Control Wonk handelt schon wieder von Waffen. Aber mehr von ihrer Entwicklung und Verbreitung als von ihrem Einsatz. Es geht um Waffenkontrollen und international kontrollierte und beschränkte Waffen, wie Atombomben, ballistische Raketen und Marschflugkörper und das komplexe System aus Kontrollen dahinter.
  • Very Bad Wizards ist ein Philosophie und Soziologie Podcast aus den USA, der sich sehr unakademisch gibt, in dem geflucht wird und die beiden Gastgeber auch nicht vor schwierigen Themen von Sodomie bis zu dem Political Correctness Wahn an amerikanischen Universitäten. Daneben geht es gerne auch um die Moralaspekte von Filmen oder Serien, wie der großartigen Serie Mr. Robot.
  • Common Sense with Dan Carlin ist ein streitbarer Kommentar zur aktuellen Politik in den USA. Wenn ihr Donald Trump gut findet, einfach dafür, dass er das System vorführt und kein Fan plumper politischer Kategorien seid, hört rein. Wem seine typisch linken Ansichten heilig sind, wird vermutlich zu oft herausgefordert.
  • Bowery Boys erzählt anekdotenreich wechselnde Kapitel aus der der Geschichte New Yorks. Mal geht es um Stadtviertel, mal um einzelne Ereignisse oder Personen, aber immer ist es lebendige Geschichte. Tipp: Während des hörens lassen sich viele Orte in GTA 4 besuchen.
  • Omega Tau ist einer dieser Maratonpodcasts, die guten Episonen brechen gerne mal die 3 Stunden Marke. Themen sind wild gestreut, aber die besonders guten sind meiner Meinung nach die Luft und Raumfahrt Episoden. Die Sprache der einzelnen Episoden wechselt semi-regelmäßig zwischen Deutsch und Englisch.

January 15, 2016

Maximilian HenryThe Future of Tolerance

Ich höre in letzter Zeit viele Podcasts von Sam Harris, schon allein, weil er ein verflucht guter Redner ist und ich stimme ihm in vielen Dingen zu. So stimme ich auch der Einschätzung zu, dass es unehrlich ist, Islamischen Terrorismus von der Religion losgelöst zu betrachten. Über ISIS zu sprechen und zu behaupten, eine Gruppe, welche alles aus heiligen Schriften ableitet, von dieser Religon zu trennen ist absurd. Aber warum sind wir überhaupt an diesem Punkt? Warum akzeptieren wir diesen Schritt?
Ich glaube, dass dies in weiten Teilen eine Folge des westlichen Verständnisses von Religionsfreiheit ist und es höchste Zeit wird, dies zu überwinden. Denn dieses Verständnis, Islamischer Terrorismus hätte nichts mit dem Islam zu tun, genau so, wie all die verbrechen, welche im Namen des Christentums nichts mit der Religion zu tun hätten, rühren von unserer religiösen Toleranz her.

Damit habe ich zwei Probleme:

  1. Religionsfreiheit und die Toleranz gegenüber Religionen mag in der Zeit der Aufklärung ein großer Schritt gewesen sein, aber langfristig ist diese Idee Gift. Alle Religionen sind Quatsch und Menschen können wunderbar auch ohne Religion leben, dass religion ein besonderer Schutz angedeihen soll, mag in Zeiten einer allgegenwärtigen Religion und religiöser Führer in Europa ein Fortschritt gewesen sein. Diesen Standpunkt als weitgehend säkulare Gesellschaft weiter aufrecht zuhalten, ist nicht nur an sich unlogisch, es führt zu vielen widersprüchlichen Positionen. So gibt es in unserer pluralistischen Gesellschaft viele sich widersprechende Religionen und doch scheint es Konsensfähig zu sein, dass es innerhalb dieser Religonen eine richtige und eine falsche Auslegung gibt. So ist die Auslegung des Christentums richtig, wenn sie von Papst, evangelischer Landessynode oder ähnlichen Einrichtungen geteilt wird und offensichtlich falsch, wenn damit Gewalt in der Ehe, gegenüber den eigenen Kindern, Homosexuellen oder Andersgläubigen begründet wird. Wohlgemerkt lässt sich alles, genau wie vermutlich jede politische Postion, mit Bibelzitaten belegen, je nach aktuellem Bedarf mal wörtlich und mal im übertragenen Sinne. Das kann doch nicht sein! Entweder wir sehen Religion als gerechtfertigt an, dann müssen wir aber auch jeden Käse, den irgendjemand sich aus seinen Heiligen Schriften pflückt akzeptieren oder aber, wir überkommen den Stand des 17. Jahrhunderts und einigen uns endlich mal darauf, dass Menschen glauben können, was sie wollen, es aber keinerlei Anspruch darauf gibt, dass wir als Gesellschaft dies ernst nehmen oder besonders beachten.

  2. Es bedarf außerdem einer Diskussion, ob Toleranz überhaupt ein hilfreiches Konzept ist. Ich zitiere aus Wikipedia:
    "Toleranz, auch Duldsamkeit, ist allgemein ein Geltenlassen und Gewährenlassen fremder Überzeugungen, Handlungsweisen und Sitten. Umgangssprachlich ist damit heute häufig auch die Anerkennung einer Gleichberechtigung gemeint, die jedoch über den eigentlichen Begriff („Duldung“) hinausgeht." Demnach hat sich die Bedeutung dieses Begriffs zwar schon weg von Duldung bewegt, aber dennoch glaube ich, dass es Hilfreich wäre, sich darüber klar zu werden, was das eigentliche Ziel ist, denn im Bereich von Religion mag Duldung genau das sein, was mir in den Sinn kommt, dulden im Sinne von ertragen, obwohl man die feste Überzeugung hat, dass es falsch ist. Aber ich möchte nicht, dass die Zukunft unseres zusammen Lebens in einer zwangsläufig immer heterogener werdenden Gesellschaft aus einem ertragen besteht.

Daneben ist mein eigentliches Problem mit Sam Harris, dass ich wirklich nicht glaube, dass für uns in der westlichen Welt der islamische Terrorismus gerade unser größtes und dringendstes Problem ist.

December 30, 2015

Christoph EggerFinally moving the Weblog

As of a few minutes ago, the old weblog on christoph-egger.org is past. I've added redirects for all the entries to the new one at weblog.siccegge.de.if you find any dead links please contact me so I can fix it up.

Note that comments are gone. I'll try to include the already present comments on the new blog some time in the future. Not sure if I will ever add a comment function again (though chronicle seems to have some support for that)

December 22, 2015

Christian DietrichA templated System-Call Interface for OO/MPStuBS

We use OOStuBS/MPStuBS in our operating system course. In the first part of our two part lecture, the students implement basic IRQ handling, coroutine switching, and synchronisation primitives. We have no spatial or privilege isolation in place, since this is topic of the second lecture part.

Still, we want to differentiate between a user space and the kernel space. On a technical level, the kernel space or system level is defined by a big kernel lock; the so called guard. If a control flow enters the guard, it transitions to the kernel and leaves the kernel, when the guard is left. The guard concept is heavily coupled with our idea of IRQ handling in epilogues (similar to bottom-halves or deferred interrupt handlers).

Our proposed implementation of the system call interface uses facade pattern to expose some of the system functionality as "Guarded Services".

class Guarded_Scheduler {
     static void resume() {
          Secure section; // does guard.enter() in constructor
          scheduler.resume();
          // guard.leave() is called on Secure destructor
     }
}

The used Secure class uses a Resource Acquisition Is Initialisation pattern to enter the guard on construction, and to leave it upon destruction of the secure object. But, as you see, coding down this pattern is cumbersome and involves a lot of boilerplate. Nobody, especially interested students, want to write boilerplate. But, our OS is implemented in C++, so we have powerful abstractions to implement a usable abstraction. In the following, I will explain, how we can implement an easily extensible system-call interface for a library operating system (everything is linked together, and we have no spatial isolation).

A First Attempt

First, we start with a "simple" templated function that can wrap every member function of an object and call with the guard taken. The actual API usage looks like this:

 syscall(&Scheduler::resume, scheduler);
 syscall(&Scheduler::kill,   scheduler, &other_thread);

The first argument to syscall() might surprise some readers, since it is a seldom used C++ feature. It is a "Pointer to Member" that captures how we can access or call a member when having the corresponding object at hand. The datatype of &Scheduler::resume is void (Scheduler::*)(), which is similar to a function pointer returning nothing and taking no arguments. &Scheduler::kill has the datatype void (Scheduler::*)(Thread *); it is a pointer to a member function, which returns nothing but takes an Thread pointer as argument. Both pointers only make sense with a Scheduler object at hand. When we have a scheduler object at hand, we can use the rarely used .* operator:

 ((scheduler).*(&Scheduler.kill))(thread)

We now can combine this concept with C++11 templates to get the described syscall function:

template<typename Func, typename Class, typename ...Args>
inline auto syscall(Func func,  Class &obj, Args&&... args) -> decltype((obj.*func)(args...)){
    Secure secure;
    return (obj.*func)(args...);
};

Huh, what happens here? Let's take this monster apart to understand its working. So, it is a function template, it generates functions depending on the types it is specialized for. You can think of this specialization process like this: the compiler has a Schablone (german word for template, but with the notion of scissors and paper) at hand. When it sees a function call to syscall() it fills the missing parts in the Schablone with the argument types and compiles the result a new function.

syscall(Func arg0, Class arg1, Args... args2_till_9001)

So, our syscall function takes at least two arguments, but can consume arbitrarily many arguments in its variadic part at the end (the Args...). The type of the first argument is bound to the type "Func", the second argument type is bound to the type "Class", all others are collected in the variadic type "Args". The func argument, which type Func, is pointer-to-member object, the obj argument the actual system object. So, now we can call the function with the other arguments.

 (obj.*func)(args...)

But, our function, still has no return type. What to do? Here comes C++ auto and decltype to the rescue. When using auto as a return type, the compiler excepts -> Type after the closing parenthesis of the function. The decltype() built-in gives the type of the enclosed expresion. So decltype((obj.*func)(args...)) is exactly the return type of the given pointer-to-member-function argument.

Furthermore, we just have to allocate a Secure object to make the guard.enter() and guard.leave() calls. Voila, a system call interface. But it still has some problems. We can call every method on every object in the whole system. We have no notion of "allowed" system calls and forbidden ones. Of course, in a library operating system with no protection this is ok. Furthermore, we always have to give the system object (e.g., scheduler) on each system call. I think, we can do better here. So let's revisit our implementation.

A second Attempt

In our second attempt, we want to restrict the system-call interface to certain classes. This gives coarse-grained control about the methods that can be called via the syscall interface. As a side-effect, we can omit the actual system-object argument such that we can write:

syscall(&Scheduler::resume)
syscall(&Scheduler::kill, that)

We implement a system_object function that returns the system-object singleton instance when called for a given type. We implement this function only for those classes, we want to allow access via syscall. This gives us some control about the possible syscall targets.

template<typename Class>
Class& system_object();

// Get the scheduler singleton
Scheduler &scheduler = system_object<Scheduler>();

The template specialization can be done in the source file and does not have to be put into the header. This allows us to hide the actual system-object symbol from the rest of the system. For example, this could be located in the thread/scheduler.cc file:

static Scheduler instance;

template<>
Scheduler &system_object() {
    return instance;
}

We still have to call this function from our system call implementation. For this, we need to have the class type of the underlying system object at hand. The only thing we have is the pointer-to-member object that identifies the desired system-call (&Scheduler::resume). But, as you remember, the class type is part of the type of such pointer-to-member types (Func). We only have to extract that information from the given type.

The concept of accessing information about types is called type traits. This is grandiloquent word for "a template that takes a type and provides several types and constants". So let's look at our type trait:

// Fail for all cases...
template<typename> struct syscall_traits;

// ..., except for deconstructing a pointer to member type
template<typename ReturnType, typename ClassType, typename ...Args>
struct syscall_traits<ReturnType(ClassType::*)(Args...)> {
    typedef ReturnType result_type;
    typedef ClassType class_type;
};

This syscall_traits is only specialized for pointer-to-member types and destructs the type of our &Scheduler::resume argument (void (Scheduler::*)()) with the pattern ReturnType (ClassType::*)(Args...). As you see, the templates does only pattern matching on types and binds types to template parameters. This can generally said for templates: The <>-line after the template keyword defines type variables, which can be bound later on or have to be supplied by the user. With our type trait we can simply access the instance class of our pointer-to-member argument and can call system_object():

template<typename Func, typename ...Args>
inline auto syscall(Func func, Args&&... args) -> typename syscall_traits<Func>::result_type {
      // We do everything with a taken guard
      Secure secure;

      // Get traits of systemcall
      typedef typename syscall_traits<Func>::class_type system_object_type;

     // Get a singleton instance for the given base type.
     system_object_type &obj = system_object<system_object_type>();

     return (obj.*func)(args...);
};

The first thing we see is that the deduced return type has changed. It no has to use our type trait, since we have no system object at hand we can use with decltype (-> decltype((obj.*func)(args...)). Within the body of the syscall function, we use the trait to extract the system-object's class type from the Func type and call system_object to gain access to the singleton instance.

If we use syscall on a class that is not exposed via specializing system_object<>, we get an linker error and the developer is informed that he wants to do bullshit.

So, what have we achieved in the second attempt? We have a cleaner system-call interface and do not have to supply the system object directly, but it is deduced from the supplied arguments. Furthermore, only annotated classes are suitable for being called via this interface. Nevertheless, we can still call all functions on these classes. In the third attempt we want to solve this as well.

The third and final Attempt

How can we annotate functions as being system calls? The only real thing we have at hand in static C++ land are types. So we have to annotate the function type of our system call somehow. The type of a method is defined by only a few pieces of information: The argument types, the class type, and the return type. The one thing that is always there, and that is not shared among several functions is the return type. We use the return type for our annotation by wrapping it into an marker struct:

template <typename T=void> struct syscall_return;
template<> struct syscall_return<void> { void get() {}; };

template <typename T>
class syscall_return {
    T value;
public:
    syscall_return(T&& x) : value(x) {}
    operator T() { return value; }
    T get() { return value; }
};

The syscall_return wraps a type and contains a copy of it. Furthermore, it implements a get() method to access this inner object and has the cast operator for T overloaded for easier handling. The void type is special here, and has to be handled special, since it is a no-object type and cannot be instantiated.

We can no annotate functions in our Scheduler class:

struct Scheduler {
    syscall_return<void> resume() {
        printf("resume %d\n", (int)barfoo(23));
        return syscall_return<>();
    }

    virtual syscall_return<int> increment(int i) {
        return i+1;
    }
}

As you see, we have to special case for void again ("Damn you void, you and your voidness!"). But, the implicit cast via the constructor makes it easy to return all other types. But we also have to adapt the rest of our implementation. In the syscall_traits template, the matched pattern strips the syscall_return wrapper from the type. This will also cause all unwrapped return types to fail.

// ..., except for deconstructing a pointer to member type
template<typename ReturnType, typename ClassType, typename ...Args>
struct syscall_traits<syscall_return<ReturnType>(ClassType::*)(Args...)> {
    typedef ReturnType result_type;
    typedef ClassType class_type;
};

In the syscall template, we only have to additionally call .get() on the result:

template<typename Func, typename ...Args>
inline auto syscall(Func func, Args&&... args) -> typename syscall_traits<Func>::result_type {
      // We do everything with a taken guard
      Secure secure;

      // Get traits of systemcall
      typedef typename syscall_traits<Func>::class_type system_object_type;

      // Get a singleton instance for the given base type.
      system_object_type &obj = system_object<system_object_type>();

      return (obj.*func)(args...).get();
};

And voila, we have a system call interface with annotations that prevents the user to call unmarked functions via syscall. All abstractions from above come at zero run-time cost.

The only downside is that the user is still able to call the functions directly. But, this can never be solved in a library operating system.

I hope I could give you an impression what is possible with C++ templates in the context of a bare-metal operating system.

December 15, 2015

Christian DietrichTesting Three-Valued Vectors for Compatibility

For a colleagues project, we encountered the problem to check vectors of values for compatibility. The values are either set or undefined. An undefined value is compatible to everything; a set value is compatible to the same value. An example instance of this problem might look like this, when the possible values are 'a', 'b', and 'c'; undefined is indicated by 'U':

Vector 1 Vector 2
a a |
b U |
U U |
a c |

These two vectors are compatible in their first three lines, since undefined is compatible to everything. How can be test these vectors for compatibility in a fast fashion? The first simple idea is to use an char array and compare it character by character and to encode undefined as 0:

char A[] = {'a', 'b', 0, 'a'};
char B[] = {'a',  0,  0, 'c'};

bool compatible = true;
for (unsigned i = 0; i < 4; i++) {
    if (A[i] != 0 && B[i] != 0 && A[i] != B[i]) {
        compatible = false; break;
    }
}

This would do the job and is already quite fast. Nevertheless, we can do it faster. We can avoid checking three different conditions (&&) by using multiplication and the zero element property of the number zero:

if (A[i] * B[i] * (A[i] - B[i]) != 0) {
    compatible = false; break;
}

This expression is exactly then non-zero, if both elements are non-zero and their difference is non-zero, a trait that is also known as inequality. But, as we learned from our processor design lecture, multiplications are expensive. So let's search for a way to do the same without multiplication. Our advantage is, that we are not interested in the result of the multiplication, but only in its property of not-being-zero. Perhaps we can do something with bit shifts. First, we encode our three elements in a more dense way, using two bits at most:

char A[] = {1, 2, 0, 1};
char B[] = {1, 0, 0, 3};

After fiddling around at the whiteboard I can up with the following solution for 3 possible values plus the undefined vector, which works quite well for our use case:

if (((A[i] << 1) & B[i]) ^ ((B[i] << 1) & A[i]) != 0) {
    compatible = false; break;
}

This expression implements, although it is not easily visible, the required behavior. We can see this easily by looking at the truth table of the function f(a, b)=(((a << 1) & b) ^ ((b << 1) & a)) == 0

 | a | b | f(a, b)|         | a | b | f(a, b)|
 |:-:|:-:|:------:|         |:-:|:-:|:------:|
 | 0 | 0 | 1      |         | 2 | 0 | 1      |
 | 0 | 1 | 1      |         | 2 | 1 | 0      |
 | 0 | 2 | 1      |         | 2 | 2 | 1      |
 | 0 | 3 | 1      |         | 2 | 3 | 0      |
 | 1 | 0 | 1      |         | 3 | 0 | 1      |
 | 1 | 1 | 1      |         | 3 | 1 | 0      |
 | 1 | 2 | 0      |         | 3 | 2 | 0      |
 | 1 | 3 | 0      |         | 3 | 3 | 1      |

So, this is a very limited Boolean function, since it works only for 2 bit wide A/B's. But, it is fast. And the best part is that it consists only of bit operations. This means, we can put many vector values into a single machine word and compare many of them in one step. Unfortunately we have to insert padding bits between the value bits to have zeroes that can be shifted in and out. So when we encode our example from above, we get the following bit vectors:

         [0]  [1]  [2]  [3]  | int
      A  001  010  000  001  | 641
      B  001  000  000  011  | 515
 ---------------------------------
 f(A, B) 000  000  000  010  |   2

As you see, the difference occurs in the [3] columns, where our values are both set, but different. With this neat trick, we can put 21(!) values in a single 64 bit word and compare them all at once. With this optimization, I could improve the runtime of our problem from 5 minutes to 1 minute; just to give you a qualitative idea of the improvement for our (unspecified) problem. This stems as well from the more densed coding (transferring less memory) and the faster operations (bit operations are cheap).

October 19, 2015

johnLateSimple local catch-all mail server

You don’t need “real” mail delivery on your machine?

But you want to receive e.g. status mails from cron?

You want to get all mails originating from localhost, regardless of the recipient, so you can detect services and programs gone rogue?

Try OpenSMTPD. There’s a package for Arch Linux, here’s the manual and here’s my config (/etc/smtpd/smtpd.conf):

# To accept external mail, replace with: listen on all
listen on localhost
 
# map any recipient to my user account
table catchall { "@"="johnlate" }
 
# "listen on localhost" should already take care of this
reject from ! local
 
# apply catchall mapping
accept for any virtual <catchall> deliver to mbox
 
# default rule, if I ever change the catch all mapping
reject for any

October 17, 2015

Christian Dietrich10 Jahre Elitenetzwerk Bayern

Vor zwei Wochen hatte ich die Möglichkeit an der Jubiläumsfeier des Bayrischen Elitenetzwerkes teilzunehmen. Das bayrische Elitenetzwerk (ENB) ist der größere Rahmen des Max-Weber Programms (MWP), in dem ich gefördert werde. Ich gehöre demnach dieser "Elite" an unabhängig davon, wie ich den Begriff verstehe. Aus diesem Grund werde ich meine Beobachtungen und meine Einschätzungen zu diesem Ereignis kundtun.

Das Publikum bei der Veranstaltung war sehr gemischt. Es waren neben Stipendiaten und Promotionsstudenten in den Doktorandenkollegs viele Professoren und einige politische Würdenträger anwesend. Darunter auch der Bayerische Wissenschaftsminister Dr. Ludwig Spaenle. In der gesamten Veranstaltung hatte ich das Gefühl als Statist einer politischen Inszenierung aufzutreten. Das hätte ich mir zwar denken können, aber es hat mich dann doch stärker getroffen, als ich das vorher gedacht hatte.

Die Veranstaltung bestand zu großen Teilen aus Reden, in denen sich die Professoren und Würdenträger gegenseitig auf die Schulter geklopft haben, was für einen großen Wurf sie mit dem Elitenetzwerk Bayern geschaffen haben. Der Begriff "Elite", der im Namen auftaucht und der in Deutschland aufgrund Nationalsozialistischer Vergangenheit verbrannt ist, wurde mit dem ENB wieder salonfähig gemacht. Davon ist meiner Erfahrung nach bei den Stipendiaten nichts zu spüren. Man spottet häufig zur Elite zu gehören, man schmückt sich nicht mit dem Namen und viele Stipendiaten mit denen ich geredet habe, fühlen sich mit den Begriff der Elite unwohl.

Besonderer Höhepunkt war die Festrede des Wissenschaftsministers, der aus meiner Sicht völlig desinteressiert war und schnell wieder verschwand. Zu Schade dass er der erste Festredner war und für die zweite Festrede, die deutlich substantieller war, noch bleiben musste. Auch ist in keiner Weise auf die Probleme von Universität, die wir vorher lang und ausführlich diskutiert hatten, eingegangen worden.

Angenehm und produktiv war in meinen Augen die Forumsdiskussion in der ich war. Es ging darum wie sich das Humboldtsches Bildungsideal, also die Einheit von Forschung und Lehre, mit der aktuellen Situation der Massenuniversität vereinbaren lässt. Die Idee bei diesem Ideal ist der Wissenschaftler, der sich zurückzieht und mit einem kleinen Kreis von Studierenden Forschung betreibt. Das war zu der Zeit als dies erdacht wurde ebenso unfinanzierbar, wie es das heute ist. Dennoch fand ich die Diskussion höchst spannend, weil es die Frage aufwirft, wie man mit den unterschiedlichen Herangehensweisen von Studierenden an Universität umgeht. Der eine möchte "nur" eine gute Ausbildung machen und später in der Industrie arbeiten, der andere interessiert sich über sein Fach hinaus, möchte Wissenschaft machen und um der Erkenntnis Willen lernen.

Ein Konzept, was ich in der Hinsicht sehr attraktiv finde, ist neben einem "normalen" Studiengang noch einen forschungsintensiven Bachelor/Master zu haben, der parallel läuft. Der Studierende kann sich nach einigen Semestern bewerben und in den Forschungsstudiengang wechseln. In dem gibt es dann, neben der normalen Grundausbildung, viele Forschungspraktika, interdisziplinäre Arbeitswochen und eine eingebettete Promotion. Dies bringt die Studierenden frühzeitig mit Forschung in Berührung. Eine Schwierigkeit, die es dabei zu vermeiden gilt, und die ich auch als kritisch sehe ist, dass man die "normalen" Studierenden deswegen nicht vernachlässigen darf. Man darf sich nicht auf die Argumentation einlassen: "Die werden später keine Forschung machen, deswegen bekommen sie weniger Aufmerksamkeit und weniger Betreuung". In Bayern gibt es bisher eine solche Konstruktion, einen zweigleisigen Physikstudiengang in Erlangen. Alle anderen forschungsorientierten Studiengänge sind in Bayern spezialisierte Masterstudiengänge. Dabei sehe ich das Problem der geringeren Durchlässigkeit. Es ist eine größere Hürde zu wechseln und wieder zurück zu wechseln. Außerdem ist damit unter Umständen ein Umzug verbunden, was die Hemmschwelle noch nach oben setzt. Das ganze läuft unter dem großen Oberbegriff der Binnendifferenzierung.

Mein persönliches "Highlight" der Veranstaltung war der Vertreter der Bayrischen Metall- und Elektroindustrie (VBM). Da wurde von den Stipendiaten in der Rede als Ressource gesprochen, die man veredeln muss und die man später abbauen und für die Industrie verwenden kann. Es ging nicht um die Bildung der Stipendiaten oder um gute Wissenschaftler, sondern ganz eindeutig um den Stipendiaten als Quelle neuer Profite. Der VBM hat 2004 das ENB mit 7 Millionen Euro anfinanziert. Ich als Mensch fühle mich richtig wert geschätzt.

Alles in allem war es die Veranstaltung nicht wert besucht zu haben. Aber ein Gedanke, den ich bei einer anderen MWP Veranstaltung gehört habe und der mich wieder etwas versöhnt mit dem Elitegedanken ist dieser:

Wir als Elite sind die Speerspitze der Gesellschaft. Aber vielleicht ist der Speer ein anderer als der gedachte.

October 05, 2015

Maximilian HenryMajor Consensus Narrative

Was bedeutet schon Wahrheit? Ist Wahrheit, was in der 20 Uhr Tagesschau berichtet wird? War das jemals die Wahrheit? Es gibt Anhaltspunkte, die nahelegen, dass das zumindest das war, was viele von uns heute für die Wahrheit halten. Ich glaube, dass es durchaus wichtig für eine Gesellschaft ist, dass sie eine gewisse Einigkeit darüber hat, was denn nun wahr ist, und was nicht.
In manchen Details diese Einordnung noch nie einfach. Haben sich Andreas Baader, Gudrun Ensslin und Jan-Carl Raspe selbst getötet? War Gundolf Köhler ein Einzeltäter? Was hat Lee Harvey Oswald am November 22, 1963 getan? Es gibt diese einzelnen Punkte, an denen der Strang der kollektiven Wahrheit sind trennt und in viele einzelne Fäden auftrennt, aber im großen und ganzen gibt es ihn noch bis in die relativ junge Vergangenheit. Der 11. September 2001, der darauf Folgende Afghanistan- und Irak-Krieg mögen umstritten sein, aber was die Wahrheit dieser Ereignisse betrifft, gibt es noch eine gewisse Einigkeit. Danach löst sich dieser Faden jedoch auf und ich glaube, dies ist nicht nur der Nähe zum jetzt geschuldet, sondern Teil eines größeren Phänomens.

Teil dieser Theorie ist, dass man Wahrheit besser durch Major Consensus Narrative ersetzen sollte. Denn, ist es nicht eigentlich völlig egal, was wirklich war, solange wir uns darin einig sind, was passiert ist? Oder, ist es nicht viel mehr so, dass Wahrheit sowieso nie etwas anderes bedeutet hat, da, eine "echte" Wahrheit, wenn sie denn existiert, sowieso nie als solche erkannt werden kann? Viele Anhänger harter Wissenschaft mögen drauf beharren, dass es eine "echte" Wahrheit geben muss, aber davon konnte mich noch niemand überzeugen. Ihr seid dazu aufgerufen!

Viel spannender finde ich jedoch die Frage, wenn wir die Existenz eines Major Consensus Narrative akzeptieren und eingestehen, dass durch den Bedeutungsverlust der Massenmedien dieser leidet, was bedeutet dies für unsere Gesellschaft? Gibt es einen Weg zu verhindern, dass unsere Gesellschaft in Teile zerfällt, in denen jeder sein eigenes Weltbild mit seinem eigenen Narrativ hat, welche alle, völlig adäquat unsere Realität beschreiben? Oder wäre das überhaupt nicht schlimm? Spielt es eine Rolle, ob eines dieser Narrative die tatsächliche Kausalität beschreibt oder ist das nicht eigentlich völlig egal, da Politik und Wirtschaft schon immer nur auf Scheinkausalitäten beruhen und nähert ein weiter Baum an Narrativen nicht die "echte" Kausalität am Ende viel besser an?

Ich glaube, am Ende haben wir wenig zu verlieren, wenn wir den Begriff der Wahrheit beerdigen.

September 25, 2015

Maximilian HenryChili!

Nachdem der Konsens in der WG auf fleischlos steht, gab es heute Chili sin Carne in der WG und es ist mir mMn richtig gut gelungen. Die Mengenangaben sind zum größten Teil nur Schätzung außerdem mag euer Geschmack variieren.

Zutaten:

  • Sojagranulat
  • Gemüsebrühe
  • 1 Espresso
  • 2 Getrocknete Habanero-Chilies
  • 3 Esslöffel Zucker
  • 1 Zimtstange
  • 1 Schuss Rum
  • 3 Zwiebeln
  • 6 Zehen Knoblauch
  • Geräucherte Chiliflocken
  • Geräuchertes Paprikapulver
  • 3 EL Kreuzkümmelsamen
  • 1 EL Koriandersamen
  • 1 TL Zimt
  • Salz
  • Tomatenmark
  • 5 Dosen Kidneybohnen
  • 2 Dosen Mais
  • 2 Dosen Kichererbsen
  • 3 Packen Passierte Tomaten
  • 5 TL Kakaopulver
  • 50g geraspelte Zartbitter-Schokolade
  • Olivenöl

Vorbereitung

Als erstes sollten wir das Sojagranulat in kochendem Wasser einweichen, vorzugsweise ein paar Stunden lang, und damit es nach etwas mehr schmeckt, kommt noch etwas Gemüsebrühe dazu. Wie viel Soja ihr wollt ist etwas Geschmackssache, erfahrungsgemäß will man weniger verwenden, als man von Hackfleisch nehmen würde, da es sonst etwas hervor schmecken kann.
Dann kümmern wir uns um ein grundlegendes Würzmittel, den Chili-Kaffee-Extrakt. Dafür hacken wir die Habaneros fein (Tipp: Zieht euch dafür Einweghandschuhe an!) und bereiten einen starken Espresso vor. Dann erhitzen wir etwas Öl in einem kleinen Topf und rösten die gehackten Chilis darin. Wenn die Schärfe im Hals kratzt, ist der richtige Moment um Kaffee, Rum, Zucker und eine Zimtstange dazu zu geben und anschließende das ganze einreduzieren lassen, bis noch die Hälfte übrig ist.

Kochen

Das kann nun erstmal zur Seite und wir können richtig anfangen. Dafür schneiden wir die Zwiebeln und den Knoblauch und waschen das Sojagranulat in einem Sieb aus, solange bis die Flüssigkeit nicht mehr bräunlich ist, dann schmeckt es auch nicht so hervor.
Jetzt brauchen wir unseren großen Chilitopf und braten dort zuerst nur die Zwiebeln an, geben dann Soja und Knoblauch dazu, wenn das Soja anfängt anzuhängen, mischen wir etwas Tomatenmark und 2 Esslöffel von unserem Chili-Kaffee darunter. Anschließend können Tomaten, Bohnen, Kichererbsen und Mais dazu und alles darf vor sich hin köcheln, es wird dadurch nur besser.
Jetzt haben wir zeit uns um die Gewürze zu kümmern, während wir gelegentlich umrühren. Dazu kommen Koriander, Kreuzkümmel und Salz in einen Mörser und werden dort zerkleinert. Das Salz erleichtert den Prozess und wir wollten ja eh Salzen. Anschließende noch die Pulvergewürze dazu und ab in den Topf. Jetzt noch das Kakaopulver und die Schokolade dazu geben, so dass die rote Farbe der Tomaten sich ins bräunliche verfärbt.
Wie viel von dem Chili-Kaffee ihr noch rein schütten wollt und wie viel ihr euren Gästen zum Nachschärfen lasst, überlasse ich mal euch. Jetzt ist das Chili im Prinzip fertig, will aber noch mindestens eine halbe Stunde köcheln, eher länger.
Dazu empfehle ich selbst gemachte Guacamole, damit lässt sich auch übermäßige Schärfe wieder etwas mildern

August 14, 2015

Andreas RuprechtDänemark, Schweden und Hamburg – Sommer 2015

Hier eine Sammlung von Bildern aus dem Sommerurlaub – diesmal im Norden, um der Wüstenhitze zu entkommen, was auch richtig gut funktioniert hat 🙂

August 07, 2015

Christian Dietrichorg-mode: Literature Handlling

At the moment I'm working on my master's thesis. For this i have to manage the notes on the related work. For this purpose i use Emacs and org-mode. I wrote two snippets that are extremely useful when working with related work in org-mode. First of all, I attach the discussed paper to the subtree. This is done normally with C-c C-a a, but most of the time the to be attached file is available on the web. So i wrote a function that downloads an URL and attaches the file to the current subtree.

(require 'url)
(require 'org-attach

(defun org-attach-download-file (&optional url download-dir download-name)
  (let* ((selection (x-selection))
         (initial-input (if (string-match "^http:" selection)
                            selection
                          ""))
         (url (or url
                 (read-string "Enter download URL: " initial-input))))
    (let ((download-buffer (url-retrieve-synchronously url)))
      (save-excursion
        (set-buffer download-buffer)
        ;; we may have to trim the http response
        (goto-char (point-min))
        (re-search-forward "^$" nil 'move)
        (forward-char)
        (delete-region (point-min) (point))

        (let ((filename 
               (concat (or download-dir
                           "/tmp/")
                       (or download-name
                           (car (last (split-string url "/" t)))))))
          (write-file filename)
          filename)))))

(defun org-attach-url ()
  (interactive)
  (let ((filename (org-attach-download-file)))
    (message filename)
    (let ((org-attach-method 'mv)) 
      (org-attach-attach filename))))

The snippet preselects asks for a URL, but uses the current X selection as default value. Another quite common task is, that i want to share my notes with a colleague. This snippet exports the current subtree as ASCII and inserts into a notmuch mail buffer. All files attached to the subtree are added as an attachment to the mail.

(defun org-subtree-as-mail ()
  "Send current subtree as mail with notmuch and attach subtree
   attachments"
  (interactive)
  (let* ((subject (org-get-heading t t))
        (attach-dir (org-attach-dir))
        (files  (and attach-dir
                     (org-attach-file-list attach-dir))))
    (org-export-to-buffer 'ascii " *org-subtree-as-mail*" nil t nil t)
    ;; Fix this if you don't use notmuch.
    (notmuch-mua-mail nil subject)
    (goto-char (point-max))
    (insert-buffer (get-buffer " *org-subtree-as-mail*"))
    (kill-buffer " *org-subtree-as-mail*")
    ;; Attach files
    (mapc (lambda (file)
            (mml-attach-file (concat attach-dir "/" file)))
          files)
    ;; Set Cursor to To:
    (goto-char (point-min))
    (search-forward "To:")))

Christian DietrichDataref

In den letzten Jahren bin ich häufiger in die Verlegenheit gekommen wissenschaftliche Texte zu schreiben. Diese haben die Eigenschaft, dass sie ein Narrativ sind, die (hoffentlich) auf Zahlen und der Interpretation dieser bestehen. Nun hat man also diesen Text, der einen Haufen von Zahlen referenziert und Aussagen auf diesen Zahlen aufbaut. Aber was, wenn man merkt, dass das Experiment, das man gemacht hat, leicht (bis schwer) fehlerhaft war? Man muss das Experiment natürlich wiederholen und neue Zahlen produzieren. Und man muss natürlich alle Zahlen im Text updaten, eine mühsame und unnötige Arbeit, vor allem wenn noch abgeleitete Zahlenwerte, wie Prozentzahlen, darin auftauchen.

Da ich dieses Problem eigentlich regelmäßig hatte, habe ich eine Lösung für LaTeX gesucht. Gefunden habe ich irgendwie nichts, aber ich habe dann dataref gebaut. Das dataref Packet erlaubt es symbolische Namen für Datenpunkte zu vergeben, diese im Text zu verwenden und abgeleitete Werte davon zu berechnen.

% Definieren
\drefset{/count}{42}
\drefset{/abc}{23}

% Referenzieren
\dref{/count} :: \dref{/abc}

% Ableiten/Berechnen
\drefcalc{data("/abc")/data("/count")}

% Annahmen über die Zahlen machen
\drefassert{data("/abc") < data("/count")}

Besonders interessant finde ich die Idee, asserts in den Text einzubauen, die prüfen, ob der Prosatext mit den abgeleiteten Aussagen noch zu den jetzt geänderten Daten passt. Dataref ist übrigens nicht nur praktisch, wenn sich die Datenpunkte ändern, sondern auch gut um den Überblick zu behalten, welche Prozentzahl aus welchen Datenpunkten berechnet wird.

June 19, 2015

Christian DietrichC++ Template Metaprogramming

Wie ich ja schon bei meinem Semestervorrausblick geschrieben habe, bin ich dieses Semester in einem Seminar "Advanced C++ Programming". Dort hatte ich gestern auch meinen ersten Vortrag über C++ Template Programmierung.

C++ Templates sind eine eigene Programmiersprache, die von Compiler ausgeführt wird. Man kann mit dieser Programmiersprache alles berechnen, was man mit einem Computer berechnen kann.

Die Folien, die ich für den Vortrag sind nicht sehr Textlastig, weil ich Vortragsfolien immer nur als Optischen Hintergrundtrack zu der Tonspur sehe die ich dazu sage. Wenn sich jemand mehr dafür interessiert kann ich gern in einem Gespräch (für Menschen vor Ort) Dinge erzählen.

June 17, 2015

Maximilian HenryInformatik in der Schule?

Durch die Diskussion auf Twitter um den Lehrplan an Gymnasien in Baden-Württemberg, Gespräche mit Kommilitonen und auch durch meine Eindrücke von dem, was Erstsemester-Studenten bei unseren Einführungsveranstaltungen berichten, habe ich mich immer wieder damit auseinander gesetzt, wie ich finde, dass Informatik an Schulen aussehen sollte und warum ich den bayerischen Status Quo nicht gut finde.
Für alle, die nicht aus Bayern kommen, ein kurzer Abriss, was derzeit an Gymnasien im besten Fall gelehrt wird. Sprich auf dem technischen Zweig und wenn entsprechende Lehrer vorhanden sind. In diesem Fall haben Schüler bis zur 12. Klasse Informatik und behandleln dort Objekt Orientierung, UML, SQL, Programmieren Java und machen Algorithmik bis hin zu den typischen Pfadalgorithmen wie Prim, Kruskal und Dijkstra. Damit haben sie, im Grunde alles behandelt, was im ersten Semester in Algorithmen und Datenstrukturen besprochen wird! Und dieses Fach ist ein Drittel des ersten Semesters. Das ist doch super! Mehr Zeit für anderen spannenden Stoff im Studium, oder?
Well, no.

Das ist das "Optimum". Das Minimum, selbst bei Studenten, die ihr Abitur auf einem bayerischen Gymnasium gemacht haben, sieht völlig anders aus. Abseits vom technischen Zweig ist Informatik in der Oberstufe kein Pflichtfach mehr und was in der Mittelstufe gemacht wurde, kann auch gerne mal eine Mischung aus Office-Klicken und Robot-Karol sein.
Ist also die Streuung das einzige Problem? Nein. Für die Streuung gäbe es naheliegende Optionen, dieses Problem zu verringern, zum Beispiel könnte das Informatik Studium mit Haskell als erste Programmiersprache starten, worin der überwiegende Teil der Studenten das gleiche Erfahrungslevel, keines, hat.
Bleibt aber die Frage: Muss Informatik an Gymnasien überhaupt auf das Studium vorbereiten und wenn nein, warum sollte es wichtig sein, Menschen programmieren beizubringen.
Ich glaube, auf dem Weg in eine immer weiter technisierte Welt gibt es viel wichtiger Dinge, welche Schulen vermitteln sollten, als programmieren! Ich habe die Argumente gehört, dass Programmieren ja zur Ermächtigung der Nutzer, weg vom reinen Konsumenten helfe und auch, dass Programmieren ja bei einem Verständnis von Computern helfen könne, ein Lernziel, welches mir selbst sehr am Herzen liegt. Aber ich bin nicht davon überzeugt. Meine 2,5 Jahre als Tutor in einer Informatik Vorlesung für andere Ingenieure spricht ein anderes Bild. Hier ist eine Auswahl von Menschen, welche die Schule schon hinter sich gelassen haben und sich für ein technisches Studium entschieden haben und noch nicht mal für diese führt programmieren zu lernen zu einem Verständnis von Computern. Wie soll das dann Jahre eher in der Schule klappen? Den gedanklichen Sprung von "Der doofe Computer macht nicht, was ich will" zu "Ich hab dem Computer das falsche gesagt und das hat er dann auch gemacht" schafft nicht mal die Hälfte dort.
Außerdem sollte der Informatikunterricht den Folgen von iPads und Co. entgegenwirken. Denn während ich zu meiner Schulzeit noch die Hoffnung hatte, dass technische Verständnis nachfolgender Generationen könnte besser werden, habe ich inzwischen den gegenteiligen Eindruck. Die Digital Natives sind am Ende doch nur iPad und Facebook Natives, weil die Computer, mit denen sie aufwachsen, ihre Technik viel zu gut verstecken und immer mehr zu schwarzen Boxen werden.
Um nicht nur Negatives und Probleme aufzuzählen, was würde ich nun in einen modernen Informatik Lehrplan packen? Also von mir aus, etwas Programmieren kann man ja machen, aber bitte mit der niedrigst möglichen Einstiegshürde und ohne diesen albernen Fokus auf Objektorientierung, die derzeit in Bayern schon irgendwo in der 7. Klasse eingeführt wird. Stattdessen eher Irgendeine Skriptsprache, mit der man auch interaktiv spielen kann beibringen. Viel wichtiger fände ich aber ein Verständnis von abstrakten Konzepten wie Berechenbarkeit und Verschlüsselung zu vermitteln. Bringt Leuten bei, dass ein Computer eben nicht alles kann! Und, macht Schülern klar, was die gesellschaftlichen Konsequenzen der Digitalen Welt sind, warum es so gut wie unmöglich ist, Dinge wieder aus dem Internet raus zu bekommen, selbst wenn es die Nacktfotos der 16. Jährigen Klassenkameradin sind, die sich doch nur für ihren Freund gemacht hat. Gute und richtige Schritte in diese Richtung gibt es, aber sie kommen aus keinem Kultusministerium, sondern aus der Aktion Chaos macht Schule des Chaos Computer Clubs.

June 14, 2015

Christian DietrichOn Conference: PLDI and LCTES

Currently, I'm attending the FCRC Multi-Conference in Portland, Oregon. I want to write a few paragraphs about contributions I found especially interesting, and this post is more a journal for myself, than written for wider audience. But, perhaps this is interesting to others as well.

Panchekha et al. introduced Herbie, which is an heuristic optimizer for floating-point expressions to increase precision. In computing floating-point expression, the ordering and selectiong of instructions is essential for the precision of the calculation. Herbie takes an actual Rn->R function and emits a partially defined function with a minimized imprecision introduced by the selected operations.

Lopes et al presented Alive, which is an verifier for peephole optimizations in compilers. A peephole optimizations looks at the immediate representation or the machine code and replaces templates of code with faster templates of code. Alive does use the C3 theorem prover to prove the correctness of such optimizations in LLVM and found 8 bugs.

Furthermore, I learned about the existence of Vickery auctions, which is a form of auction, where the highest bid wins, but the winner does pay the price of the second highest bid. In constrast to a normal auction, this auction type does maximize the social welfare instead of the revenue. Social wellfare is defined in this setting as: the bidder with the highest need to get the item will win.

Kanev et al. presented a hardware profiling of whole datacenters. And the results are rather amazing. They profiles a bunch of Google servers for a few weeks and examined the results. It is surprising that about 30 percent of all instructions are spent in the "datacenter tax" (allocation, memmove, rpc, protobuf, hash, compression). This is really a huge number. Furthermore, they could show that pipeline stalls due to instruction cache misses contribute largely to the waiting time in those large datacenter applications. The i-cache working sets are often larger than the L2 cache; the instructions have to compete with data cache lines. Perhaps we will see computers with split L2 cache in the future.

In the DCC keynote, John Wilkes talked about cluster management at the Google datacenters. And their approach is fascinating. The basic assumption is: a machine that is not running has a speed of 0. Therefore, we optimize for availability and we assume failure to be the normal operation mode. In an EuroSys'15 paper, Verma et al talk about the Borg cluster management software, Google uses internally for its management.

During the LCTES conference, Bardizbanyan et al. presented a processor modification to adapt the memory-fetch stage so it takes the need of the current memory operation into account. Not all memory operations need all features the addressing mode provides. For example, mov 4(%eax), %ebx doesn't need an offset from a register with scaling (in contrast to niv 4(%eax, %ecx, 4)). Therefore, they propsed to gate these addressing features within the memory fetch stage and do speculative address calculation to improve energy consumption and latency of the stage.

Baird et al. presented a method to optimize programs for static-pipeline processors. A static pipeline is similar to a horizontal-micro instruction CPU. For a static-pipeline CPU, the compiler doesn't emit a stream of instructions, where each token is one instruction, but it splits the effects upon several commands. Each command describes what all stages of the pipeline should do in the current instruction cycle. Statically pipelined processors, are hard to program, but reveal a high energy efficiency. Baird proposed methods to optimize transfer-of-control instructions for these command-packets.

From Ghosh et al., I learned that processors that do dynamic binary translation (e.g., Transmeta Crusoe) can to speculative alias analysis. For this, the processor has some alias registers and every instructions is marked to either update of check a specific alias register. If two instructions then have an aliased pointer, the CPU faults, and the program is translated without the optimization that lead to that fault.

With Clover, Liu et al. presented an hybrid approach to mitigate soft-errors. As a hardware plattform, they used a processor with sonic micro-detectors that can detect the impact of a cosmic particle. In software, they implemented checkpointing for code-regions. Since the detector has a delay due to the physical limiation of a sonic detector, they proposed a compiler-based approach to execute the last N instructions of each code region twice in order to cover the worst-case detection delay. Although they claimed to be free of SDCs, they have strong assumptions, about their fault-model (fault occur on chip and the memory is ECC protected) and control-flow errors (there is a working software-based control-flow error detection).

May 22, 2015

Maximilian Henrygogs auf uberspace

gogs ist ein git-Webdienst ähnlich zu dem was github, oder als Konkurent gitlab, welches man sich ebenfalls zum selbst hosten installieren kann, bietet. Gitlab ist zwar das bekanntere Projekt und hat vielleicht auch mehr Features, ist allerdings typische Ruby-Software und entsprechend lustig zum aufsetzen. Wer es unkomplizierter mag und außerdem vielleicht auch ohne eine gitshell aus kommt, weil es eigentlich nur um ein Webinterface geht, mit der Möglichkeit geht, eigene Projekte mit einer http(s)-url verfügbar zu machen, für den ist gogs auf jeden Fall eine einfache und schicke Lösung.

Die Installation geht relativ einfach von statten und folgt im großen der offiziellen Anleitung. Wichtig war bei mir, nicht das Go zu benutzen, welches installiert ist, auch wenn es eigentlich aktuell genug sein sollte, sondern auch hier, eine neue Version lokal zu installieren.

Die aus den Quellen gebaute Version braucht außerdem MySQL oder PostgreSQL, SQLite funktionierte bei mir nicht. Also erst einmal in den Adminer gehen, und eine neue Datenbank für gogs anlegen.
Dann nach dem wir die Installation abgeschlossen haben, wollen wir vor dem ausführen noch die Config anpassen.

Mein Ansatz ist, gogs in einem Unterordner meiner Domain laufen zu lassen, also wollen wir das in die Konfiguration schreiben und außerdem brauchen wir noch eine freie Port Nummer.
Also sollte unser app.ini nun so aussehen:

   DOMAIN = $EUREURL
   HTTP_PORT = $EUERPORT
   ROOT_URL = https://$EUREURL/git/
   DISABLE_SSH = true
   [database]
   DB_TYPE = mysql
   HOST = 127.0.0.1:3306
   NAME = $UBERSPACEUSER_gogs
   USER = $UBERSPACEUSER
   PASSWD = $MYSQLPW

und für den port brauchen wir noch in dem Webroot euer Domain im Ordner /git/ eine .htaccess Datei, welche so aussehen sollte:

   RewriteRule ^(.*) http://localhost:$EUERPORT/$1 [P]

Damit passt jetzt alles, und ihr solltet, nachdem ihr gogs mit ./gogs web gestartet hab, euch euren Nutzer anlegen können.

April 22, 2015

fauiwgMitbewohner

Mitbewohner, wobei eigentlich sollte ich hier ja den neutralen Standpunkt einnehmen! Lasst uns also Bewohner sagen. Bewohner gehören zu einer WG notwendigerweise dazu und werden darum meist als gegeben hingenommen. Für die Letzten 2,5 Jahre, war das auch, abgesehen von kurzzeitigen Schwankungen in der konkreten Verfügbarkeit, nie ein Problem. Doch nun zeichnet sich eine größere Veränderung ab. Ein Bewohner wird diese WG Ende Juli verlassen. Das bedeutet eine große Veränderung, die Herausforderung jemand neuen in einen über 2,5 Jahre gewachsenen Sauhaufen zu integrieren, stellte sich bei Lebensabschnittspartnern zwar auch immer, war dort aber auch nie so fix, man war nie so auf ein funktionierendes Zusammenleben angewiesen wie in diesem Fall. Jemanden zu suchen, mit welcher wir als als Mitbewohnerin glücklich werden und welche zu gleich auch mit uns als Mitbewohnern glücklich werden kann, ist eine ungewohnte Herausforderung und spannend, aber auch wirklich anstrengend und ich glaube, wir sind alle Froh, wenn die diese Herausforderung gemeistert haben. Lasst uns hoffen, dass es noch diese Woche soweit sein wird.

April 07, 2015

Maximilian HenryDie alte Dame

Ich habe eine Obszession, es ist nicht meine erste und es wird nicht meine letzte sein. Dieses mal geht es um eine alte Dame, welcher ein 2. nein vielmehr ein 3. Leben geschenkt wurde. Die Rede ist natürlich von der Erlanger Zuse Z23.

Aber was macht diesen alten Computer nun so spannend? Das spannende ist einen Rechner zu haben, welcher erstens groß genug ist, dass alle Funktionalen Bauteile bis hin zu einzelnen Transistoren und Bits im Schnellspeicher sichtbar sind. Zum anderen, ist dieser Rechner so anders, als alles was man gewohnt ist, anders als alles, was man im Studium über die Konstruktion von Prozessoren und ganzen Computern lernt, dass auch das eine Faszination ausübt. Mit all meinem Wissen, wäre ich nie auf die Idee gekommen, einen 40 bit Bitseriellen Prozessor zu konstruieren, welcher einen vollständig orthogonaler Befehlssatz besitzt und ohne einen Instruktionszeiger auskommt, zu konstruieren. Dieses Desgin macht für die Zeit und die Kosten eines einzelnen Transistors absolut Sinn, entspricht aber eben überhaupt nicht der amerikanischen Tradition des CPU-Designs, welcher heute alle aktuellen Prozessoren folgen.

Eurokarten mit der Prozessorlogik

Dieser Computer ist so modern! Er verfügt über Speichereingeblendete Eingabe und Ausgabe, er hat einen riesigen Registersatz, es ist ein RISC-Prozessor!

Bedienpanel

Dieser Computer ist so archaisch! Er hat eigentlich garkeine Register, sondern nur einen kleinen Hauptspeicher (genannt Schnellspeicher). 40 Bit sind nichts halbes und nichts ganzes! Die Ausgabe passiert auf einem Fernschreiber, die Eingabe auf einem Lochstreifen.

Klassische Kathegorien scheitern hier. Was bleibt, ist ein Rechner, welcher dank der Arbeit zweier Männer nun, nach seinem Wissenschaftlichen Einsatz im IMMD der Uni-Erlangen und seinem Dienst im Christian-Ernst-Gymnasium nun in der Informatiksammlung Erlangen ein drittes Leben geschenkt bekam. Danke dafür an Volkmar Sieh und Edwin Aures.
Eine ausführliche technische Beschreibung wird an dieser Stelle hoffentlich bald folgen, denn eine solche findet sich derzeit nicht einmal in der Wikipedia.

March 31, 2015

Christian DietrichdOSEK Version 1.1

The DanceOS team is proud to announce the release of dOSEK version 1.1. With the latest release, we added support for OSEK events and an improved ARM support.

OSEK events are a synchronization primitive provided by the kernel. Events are system objects, which are declared in the OIL configuration file. Each event belongs to exactly one task in the system. Only the owning task can clear the event or wait for its arrival. Events can be signaled by any other task in the system. Additionally an alarm can be configured to send an signal to a specific task.

The ARM support was improved and dOSEK runs now on a real hardware platform; the ZedBoard. This architecture port supports all dependability features of dOSEK besides the memory protection.

The additional dependability features of dOSEK include: an concurrent checker for data objects, replication of OS state, and retry of encoded schedule operations.

The source code can be obtained from github. For more details on the changes, have a look at the Changelog.

February 23, 2015

Christian DietrichWaiting in dOSEK

In operating systems, waiting states are an essential feature to keep up the illusion that every thread is alone on the machine. In general-purpose operating systems, waiting states occur when data is read from the hard drive or when data is written from a network socket. A thread can also wait for the completion of work executed in another thread. Here, one thread waits for a signal the other thread provides. Waiting states are also part of real-time operating systems, like the OSEK standard. We've now implemented this feature, which is required for the OSEK ECC1 conformance class.

Scheduling in dOSEK

The core of dOSEK is the priority-driven scheduler. Since OSEK is a static operating-system standard, we know, for a specific system, exactly how many threads exists. This number will never change, it is configured at compile time. The scheduler selects always the thread with the highest priority that is runnable and executes it. In dOSEK, a thread is runnable, if its priority is larger than the priority of the idle thread. In pseudo code, the scheduler/dispatcher looks like this:

schedule() {
   current_thread = idle_id;
   current_prio   = idle_prio;

   updateMax((current_thread, current_prio),
             (thread_1_id, thread_1_prio));

   updateMax((current_thread, current_prio),
             (thread_2_id, thread_2_prio));

   updateMax((current_thread, current_prio),
             (thread_3_id, thread_3_prio));

   switch_to_thread(current_thread);
}

The scheduler is generated for the specific system (in this case, for a system with 3 threads), and contains a updateMax() cascade. updateMax() is a hardened operation, that updates the first input tuple with the second one, iff the priority of the second argument-tuple (second tuple, second item) is higher than the priority of the first tuple. In the first cascade element, current_thread is set to thread_1_id, if current_prio < thread_1_prio. In pseudo code:

updateMax((a, b), (c, d)) {
  if (b < d) {
    (a, b) = (c, d);
  }
}

Events in OSEK

In OSEK, events are the only possibility for a thread to wait on something. Each thread can receive a number of event signals. With the system call WaitEvent(), a thread can wait for one or more events to happen. If any of the events from the list got signaled by another thread with SetEvent, the waiting thread unblocks. Signals are not automatically cleared, but must be cleared explicitly by ClearEvent.

A version with branches can be implemented by two bit masks:

 struct Thread {
  ...
  event_mask_t events_waiting;
  event_mask_t events_set;
  ...
};

SetEvent(Thread t, event_mask_t m) {
   t.event_set |= m;
}
WaitEvent(Thread t, event_mask_t m) {
   t.event_waiting = m;
}
ClearEvent(Thread t, event_mask_t m) {
   // Remove the event mask bitwise
   t.event_waiting &= ~m;
   t.event_set     &= ~m;
}

Schedule() {
   ...
   if (thread_1.event_waiting != 0
       || (thread_1.event_waiting & thread_1.event_set) != 0) {
      updateMax((current_thread, current_prio),
                (thread_1_id, thread_1_prio));
   }

In this simple variant, we maintain a event_waiting mask containing a bit mask of events a the thread is waiting for. The event_set bit mask holds a bit mask of signaled events. If a thread is waiting, and none of the waited signals is set, we exclude the thread from the updateMax() cascade. It is blocked.

But there is one problem with dependability: we have branches. Branches are evil; making them resilient against soft-errors is hard. Therefore, we want to have a branchless version.

Events in dOSEK

Shortly explained, in the branchless version, we let the priority of a thread drop below the idle priority, if it currently blocks. Therefore, we calculate a blocking term for every thread that is either zero or the highest priority in the system. This blocking term is subtracted from the thread priority, when calling updateMax():

updateMax((current_thread, current_prio),
          (thread_1_id,    thread_1_prio - blocking_term));

For each event, a thread can receive, we have two integer variables W (for waiting) and S (for set). Both variables can have two values: either 0 or High (for highest priority in the system).

In this diagram, we see all four states a event can have. A event is a tuple of (W, S). The set() and clear() operations set override the tuple. If we want to wait for an event mask, we set the W flag accordingly for all events a thread can wait for:

struct Event {
   int W;
   int S;
};

Event thread_1_event_a;
Event thread_1_event_b;

...
WaitEvent(Thread t, event_mask_t m) {
   // t is always known at compile time, and this cascade is generated for the system.
   if (t == thread_1) {
      if (m & 1)
         thread_1_event_a.W = High;
      else
         thread_1_event_a.W = 0;

      if (m & 2)
         thread_1_event_b.W = High;
      else
         thread_1_event_b.W = 0;
   }
}

But how can we now deduce the blocking_term from the event states? First we calculate the blocking_term for a single event. We use a matrix notation that captures all four states from the diagram shown before.

By the blocking term, we generate a term for each event that is only 0, if the event was used for blocking and is set. In all other cases, the blocking term is High. We achieved this by using only bit wise XOR and OR operation. We're still branchless! :-)

We combine now all blocking terms of all events a specific task can wait for with AND. The result is only zero if at least single event, which is on the waiting list, is set. Furthermore, we determine whether we can block in the first place, by combining all W states with OR. The should_wait variable is either High, if we're waiting; or 0 if we're not waiting.

does_block  = blocking_term(thread_1_event_a) & blocking_term(thread_1_event_b);
should_wait = thread_1_event_a.W | thread_1_event_b.W;
blocking_term = should_wait & blocking_term;

Combining both variables with AND, we achieve our blocking term. Branchless. And we can subtract it, before we call the updateMax(), from the threads priority.

February 07, 2015

Thorsten WißmannAm Strand

Zwei mal wurde ich von meinem Betreuer und seiner Familie zum Strand mitgenommen. Canberra liegt jedoch fast schon im Landesinneren: bis zur Küste sind es ca. 2 Stunden mit dem Auto über die Landstraße — eine Autobahn gibt es nicht.

Damals bei meiner Busreise von Melbourne nach Sydney fuhr der Bus angeblich auf einem Highway. Interessanterweise hatte dieser keine Autobahnauf- oder -abfahrten sondern war einfach über gewöhnliche Kreuzungen (ohne Ampeln) an das restliche Straßennetz und an Tankstellen angebunden.

Aber zurück zum Strand: am 27. Dezember badeten wir am Maloneys Beach und am 7. Februar zusammen mit einem Arbeitskollegen mit dessen Familie am North Broulee Beach.

Die Anfahrt

Bei beiden Fahrten machten wir im historischen Braidwood Pause. Die Kleinstadt scheint wohl eine der älteren in Australien zu sein und deren Archtektur erinnert stark an den Wilden Westen — besonders in Kombination mit trockenem Wetter.

Die Strecke von Braidwood zur Küste führt durch gebirgiges Waldgebiet. Die Straße schlängelt sich mit unzähligen Serpentienen den einen nach dem anderen Berg hoch und runter. Leider war es nicht möglich, die Aussicht von der hinter den Bäumen versteckten Straße per Kamera festzuhalten. Eine Besonderheit war in einer 180°-Kurve zu finden: in einer kleinen Höhle — dem Pooh Bear’s Corner — hatten sich etliche Plüschtiere angesammelt.

Maloneys Beach

Auch wenn die Sonne den Tag ganz schön aufheizte, war das Wasser der ruhigen Bucht deutlich kälter als erwartet. Für Aufregung neben dem Badespaß sorgte ein Mäusebaby, welches auf einmal unter meinem Rucksack auftauchte und scheinbar von Ameisen gejagt wurde, welche sich überall an dessen Körper festbissen. Da keine Mutter oder Höhle zu finden war befreiten wir das Mäusschen von den Ameisen und versuchten vergeblich es zu füttern. Im Laufe des Tages tauchten noch zwei weitere Mäusschen auf, eines davon raste über den Sand auf der Flucht von den Ameisen. Nachdem die drei nicht überlebensfähig schienen, nahmen wir sie mit nach Canberra, wo sie dann trotzdem in der darauffolgenden Nacht verstarben.

North Broulee Beach

Hier war die Situation gewissermaßen umgekehrt: das Wetter zwar warm aber durch den Wind gefühlt sehr kalt, das wilde Wasser jedoch schön warm. Außergewöhnliches ist nichts passiert, die Bilder sagen alles.

Die Heimfahrt

Erschöpft vom Tag konnte ich nocheinmal die Landschaft und besonders diesen schönen Sonnenuntergang hinter den Wolken bewundern:

Alle Bilder in chronologischer Reihenfolge

February 06, 2015

Maximilian HenryPanorama Schummelei

Für das Erstellen von Panoramabildern gibt es mehr als einen Weg und der häufige Kompromiss liegt zwischen Qualität und Bedienbarkeit. Auf dieser Skala immer relativ gut schneidet meiner Meinung nach Microsoft ICE ab, welches jetzt in einer 2. Version erschienen ist, die alles verändert. So lassen sich jetzt Panoramen aus Videos erstellen, es gibt mehr Einflussmöglichkeiten und, der Titel deutet es schon an, Es gibt einen Schummelmodus nahmens "auto completion" der Fehlende Bildteile versucht zu erraten, ähnlich dem Smartfill aus Photoshop und auf diesem Weg das Beschneiden von Bildern sparen soll. Auf den ersten Blick liefert diese Funktion durchwachsene Ergebnisse und ich werde in Zukunft wohl doch weiter die Panoramen zurecht stutzen, statt Dinge dazu zu erfinden.

Thorsten WißmannZwei Tage Sydney

Mit einer 12-stündigen Busfahrt ging es über Nacht von Melbourne ins 900 km entfernte Sydney. Die Stadt empfing mich um 7 Uhr früh, am 28. Februar, mit heftigen Regen, welcher bis in den Nachmittag anhielt.

Der erste Tag

Netterweise hat mich Caity, die ich im Dezember bei der Logic Summer School in Canberra kennenlernte, etwas durch Sydney herumgeführt und eine Übernachtungsmöglichkeit angeboten. Mit der Fähre sind wir vom südlichen Stadtteil Cronulla über den Bundeena Bay zum Royal National Park gefahren. Da es relativ stark regnete, haben wir leider vom Nationalpark nicht viel gesehen und sind recht bald wieder zurück. Bevor es nach Hause ging, schauten wir noch kurz zum verregneten Strand von Cronulla, der bei schönerem Wetter sicherlich ein Bade- und Surf-Paradies ist. Leider gibt es keine Bilder von von diesem Tag — ich hab einfach nicht daran gedacht.

Der Zweite Tag

Bei Sonnenschein machte ich mich dann alleine auf die Socken, ein paar Standard-Attraktionen in Sydney abzuklappern. Los ging es mit Darling Harbour und Cockle Bay. In der Mall vor Ort ist auch das Hard Rock Cafe Sydney zu finden. Für die Pop-Freunde waren dort sogar original Bühenoutfits von Rock-Legenden wie Pink, Cher oder Beyoncé ausgestellt.

Der Weg zum Sydney Opera House führte durch die Innenstadt Sydneys. Im Gegensatz zu Melbourne stieß ich hier auf keinerlei Fußgängerzone, dafür aber auf einige ganz schicke historische Malls.

Am Hafen angelangt durften die Selfies mit dem Opernhaus im Hintergrund natürlich nicht fehlen. Viel gibt es hier nicht zu berichten. Ein bemerkenswertes Detail ist der Hotel-Pool mit Blick aufs Opernhaus und den Rest des Hafens. Abgesehen davon sagen die Bilder eigentlich alles.

Während des Rückwegs zum Bus zurück nach Canberra gab es noch zwei kleinere Highlights: zum einen die Asian-Cup Busse — evtl. der einer Nationalmanschaft? Der Asian Cup fand nämlich gerade in Australien statt, der Gastgeber holte sich sogar den Titel. Das andere Highlight war das Bavarian Bier Café, welches bayrische Biere und Brezen verkauft. Zum Probieren war meinerseits leider nicht genug Zeit und zu viel Abneigung den Preisen gegenüber vorhanden.

Alle Bilder

Thorsten WißmannMelbourne Teil 2

Nachdem ich den vorherigen Blogeintrag in Melbourne schrieb, sind wir noch zum Eureka Skydeck, dem wahrscheinlich höchsten Wolkenkratzer in Melbourne und sicherlich auch der N-höchste auf der südlichen Hemisphäre.

Der Ausblick von dort aus dem 88. Stock war echt super. Von der Küste bis in die Innenstadt war echt alles super zu überblicken. Die Autos wirkten mit blosem Auge wie Spielzeugautos welche unglaublich langsam durch eine Miniaturewelt fuhren.

Die Aussichtsplattform war zum Glück hinter Glas. Denn auf dem Balkon draußen hat man es nicht lange ausgehalten: die Tage war es schon auf dem Boden Melbournes enorm windig, und dementsprechend sehr stürmig auf diesem Balkon.

Der ganze Spaß ist jedoch nicht so billig wie man es von einmal Aufzug hoch- und runterfahren erwarten würde. Textaufgabe: Thorsten zahlt für den Besuch der Aussichtsplattform $13.50. Das schließt jedoch schon den Studentenrabatt von 50% und den YHA-Mitgliedsrabatt von 10% ein. Wieviel kostet ein reguläres Erwachsenenticket?

Alle Bilder

January 31, 2015

Maximilian Henrynot-so-safe-for-work

Neben diesem (richtigen) Blog, gibt es seit gerade eben noch eine suppe als semiautomatisch befüllte Ansammlung von oft nsfw-Inhalten. Diese Seite ist ein planet, welcher entgegen der eigentlichen Idee aber nicht mehrere Seite zusammenfasst, sondern nur aus einer Quelle befüllt wird. Diese Quelle ist der veröffentlichte Favoriten-Feed meines Tiny Tiny RSS feedreaders, welcher durch einen chronjob statisch zu dieser Seite gebacken wird. Abgesehen von etwas CSS frickeln, war das echt schnell aufgesetzt und komplett problemlos.

January 27, 2015

Thorsten WißmannHappy Australia Day aus Melbourne

Ich wünsche euch allen einen Happy Australia Day aus Melbourne! (Wenn auch nachträglich…)

Was bisher geschah

Das Projekt endete am Freitag den 23. Januar, die Abschlussvorträge fanden sogar schon am Dienstag zuvor statt. Meinen Flug zurück nach Deutschland habe ich erst für den 9. Februar gebucht, sodass ich bis dahin noch etwas Zeit habe, mir mehr vom Canberra und auch von anderen Städten anschauen zu können.

Erste Etappe: Melbourne

Deshalb ging es am Samstag Abend um 23:55 Uhr von Canberra mit dem Nachtbus nach Melbourne, welches wir nach schlappen 8 Stunden erreichten. Der erste Eindruck bestand vor allem aus der unerwarteten Kälte die bis jetzt andauert (also unter 20°). Der Check-In in die Jugendherberge ist leider erst ab 13 Uhr möglich, und die Spints kosten stündlich. Erfreut hat mich jedoch das Ligretto-Set im Hostel.

St James' old Cathedral & Der Strand

Angeblich ist der Queen Victoria Market sehenswert. Auf dem Weg dorthin bin ich an einer Anglikanischen Kathedrale hängen geblieben: der St James' old Cathedral. Sie ist 1839 erbaut worden und damit eines der ältesten Gebäude der Stadt. Nach dem Gottestdienst, bin ich mit mehreren beim Morning Tee ins gespräch gekommen. Auf meine Frage hin, ob die Gemeinde hier eher liberal oder konservativ ist, wurde sie als konservativ eingestuft, wonach ich lieber nicht mehr nachgehakt habe.

Außerdem wurde mir angeboten, ob ich nicht Lust hätte, mit an den 30 Autominuten entfernten Strand spazieren zu gehen. Die Chance habe ich natürlich genutzt! Wie bereits am morgen war es auch hier fast eisig kalt durch den starken Wind. Der brachte auch schnelle Wellen mit sich und sorgte dafür, dass Seemöven regelmäßig in der Luft an einer Stelle schwebten. Abgesehen davon war der Strand schön, der Himmel Blau, der Sand hell, … (hier bitte beliebige weitere Strand-Feedback-Floskeln einsetzen).

Die Innenstadt

Melbourne ist sicherlich, wie Melbourne selbst von sich behauptet, die Kulturhauptstadt Australiens. Alle paar Straßenecken findet sich irgendein Musiker, Artist oder Maler. Da gab es z.B. denjenigen, der mit Sprühdosen Skylines von Städten malte, oder am Australia Day ein als Krümelmonster verkleideter Dudelsackspieler mit umgehängter Australien-Flagge, welcher Hits wie das Star Wars oder Auld Lang Syne trellerte. (Ein Bild war auf Grund der schlechten Lichtverhältnisse nicht möglich). Zu Kultur zähle ich jetzt auch die Gasse Hosier Lane, in welcher alle Wände durch Sprayer verziert wurden.

Angesprochen hat mich auch die eintrittsfreie Screen Worlds, eine Ausstellung rund um Unterhaltungselektronik mit Bildschirmen. Vom ersten Tomb Raider über Star Wars und C64 bis hin zu Smartphone war hier alles vertreten. Es hatte zwar gefühlt nicht viel mit Melbourne oder Australien zu tun, war aber trotzdem schön.

An alten Einkaufspassagen mit kleinen Läden mangelt es nicht in Melbourne. Da sagen die Bilder eigentlich schon alles. Selbiges gilt für historische Gebäude wie das Parlamentsgebäude, der Bibliothek und weiteren Kathedralen.

Weitere Eindrücke

  • Überall sind Deutsche anzutreffen.

  • Die Weihnachtsdekoration wurde an vielen Stellen noch nicht abgehängt.

  • Tagsüber ist so manche Hauptstraße wie leergefegt und abends ist auf der Fahrbahn und auf dem Gehsteig die Hölle los.

  • Das indische Restaurant OM Vegetarian bietet für $6,50 All-you-can eat an, insb. mit niemals endenden Brotnachschub. Für Australische Preise eine Sensation.

  • Eigentlich wollte ich ja den Queen Victoria Market besuchen. Die paar Stände davon, die ich heute sah, waren eine Mischung aus Flohmarktständen und Ramsch-Vertick-Ständen, wie man sie in Touristenballungsgebieten antrifft.

Alle Bilder

January 24, 2015

Maximilian Henryhallo auf maxfragg.de

nur als kleiner Kommentar, dieser Blog läuft von nun an unter neuer url

January 23, 2015

Maximilian HenryPostcrypto

Nach Snowden schien der Weg klar,
Verschlüsselung ist Bürgerpflicht!
Der Staat hatte nicht versagt,
es waren seine Bürger.

Doch wenn Lösungen einfach scheinen,
dann sind sie es meist doch nicht.
Wenn wir uns alle absichern,
wie soll der Staat uns da noch schützen?

Schützen vor Terroristen,
die trotz Vorratsdatenspeicherung ohne jede Spur,
perfekt versteckt verschlüsselt planen,
so gut, dass bis heute jeder Beleg fehlt.

Wollt ihr denn nicht sicher sein?
Wollt ihr denn vor uns sicher sein?
Wollt ihr nicht beschützt werden?
Wollt ihr nicht frei sein?

December 27, 2014

Thorsten WißmannRegen in Canberra

Obwohl es Vormittags oft sehr sonnig bei strahlend blauem Himmel ist, schüttete es fast täglich mittags oder nachmittags. Leider sieht das Wetter auf den Bildern deutlich unspektakulärer aus, als es vor Ort tatsächlich wirkt.

December 08, 2014

Thorsten WißmannAustralian National Botanic Garden

Am Sonntag vor zwei Wochen besichteten wir bei über 30° den National Botanic Garden, welcher wenige Hundert Meter vom Burgmann College entfernt ist.

Schlangen sind wir zum Glück keinen begegnet, dafür einigen Echsen und Vögeln.

November 30, 2014

Thorsten WißmannAustralian War Memorial

Gestern Nachmittag besuchten wir das Australian War Memorial in der Innenstadt Canberras. Die Führung erzählte uns vor allem von Australiens Beteiligung in den zwei Weltkriegen und in Vietnam.

Im Innenhof, von dem man das Parlamentsgebäude sehen kann, sind auf Metalltafeln die Namen aller Gefallenen gelistet. Regelmäßig werden dort auch konkreter Gefallener gedacht, ebenso auch gestern für einen Soldaten des ersten Weltkriegs: es wurde seine Geschichte erzählt, ein Bild war zu sehen und die Familien legten Kränze nieder.

Thorsten WißmannDie Unterkunft

Für die Zeit während des Summer Research Scholarships bin ich im Burgmann College untergebracht. Es besteht aus etlichen Gebäuden, zur Zeit scheinen aber nur Summer Scholars untergebracht zu sein, der Rest scheint leer.

Besonders ist hier die Hauseigene "Mensa", in der Frühstück, Mittag- und Abendessen serviert werden — und das sieben Tage die Woche. Eine allgemeine Mensa an der Uni gibt es jedoch nicht. Das bedeutet, dass die meisten Mitarbeiter jeden Tag das Mittagessen selbst mitbringen. Die wenigen nahen Restaurants/Imbisse/Cafes in der Nähe sind etwas zu teuer, um dort täglich Mittag zu essen. Auf dem Campus befinden sich noch weitere Wohnheime mit Essensmöglichkeiten, aber eben nur für deren Bewohner. Man kommt deshalb zwar immer ins Wohnheim zum gemeinsamen Essen den anderen Scholars, jedoch nie mit den Büro oder Studienkollegen. Ich bin ziemlich froh, dass das in Erlangen (und anderen Unis in Deutschland) nicht so ist.

Dabei ist es umso verwunderlicher, dass das Burgmann College eigentlich Teil der ANU ist. D.h. die ANU hat indirekt über die Wohnheime mehrere Mensen auf dem Campus, aber eben keine Mensa für alle Uniangehörigen und für manche Uniangehörigen sogar gar keine Mensa.

Mein Zimmer scheint auch aus den Anfangszeiten des Colleges (von 1971) zu stammen. Die Grundfläche beträgt ca. 10 m², davon besteht 1-2 m² aus einem begehbaren Kleiderschrank mit Waschbecken:

    ┌────────────────────┬───┬─────┐
    │    ┌─────────────┐ │   │     └───┐
    │    │             │ │   │     ╭───│
    │    │             │ │   │     │   │
    │    └─────────────┘ │   │     ╰───│
    │                    └───┴─   ─────│
    │                                  │
    │                               ╲  │
    │                                ╲ │
    │┌────────────────────────┐       ╲│
    ││                        │        │
    ││                        │        │
    ││                        │        │
    │└────────────────────────┘        │
    └──────────────────────────────────┘

Mein Vormieter hat mir dankenswerterweise während seiner Abwesenheit seinen Kühlschrank und seine Klimaanlage überlassen. Die Klimaanlage habe ich noch nicht getestet, jedoch bestimmt wenn sich die Wohnung (im obersten dritten Stockwerk) noch weiter aufheizt.

Einmal in der Woche werden Bettzeug und Handtücher gewechselt. Dusche und Toilette befinden sich auf dem Gang. Auf dem Gang befindet sich ebenfalls ein riesengroßer Ventilator, der seit meine Ankunft durchgehend läuft.

November 22, 2014

Thorsten WißmannDie Reise nach Canberra

Los ging es am 19. November um 3 Uhr Mittags mit dem Zug nach Frankfurt am Main. Die ICE-Fahrt war sehr angenehm, es gab keine Verspätungen, und man konnte durch das Fenster ein paar Städte anschauen, z.B. Würzburg. Damit war ich mehr als rechtzeitig um 17 Uhr am Frankfurter Flughafen.

Der erste Abflug war um 20:15 Uhr, geplante Ankunft um 9:25 (am 21.) im 10 Stunden früheren Canberra — also eine Reisedauer von 27 Stunden (exklusive Zug). Die Umstiege waren in Dubai und Melbourne. Beim Einchecken gab es dann zwei kleinere Schocks:

  1. Ich reise in Melbourne nach Australien ein, deshalb muss ich in Melbourne meinen Koffer abholen, durch den Zoll nehmen und wieder für den letzten Flug nach Canberra einchecken.

  2. Ich hätte ab 24 Stunden vor dem Reiseantritt meine Sitzplätze in den Flügen kostenfrei online reservieren können. Jetzt sind aber nur noch die schlechten Plätze übrig.

Flug Frankfurt → Dubai

Nachdem es etwas gedauert hatte, bis ich beim richtigen Gate war, ging der Flug dann um 20:15 Uhr los. Mein Platz war auch gar nicht so schlecht:

                  _X_ ___ ___ _o_
   —o— —o— —o—    _o_ _o_ _o_ _o_     —o— —o— —o—       (X = ich)
   —o— —o— —o—    _o_ _o_ _o_ _o_     —o— —o— —o—       (o = besetzter Platz)
   —o— —o— —o—    _o_ _o_ _o_ _o_     —o— —o— —o—
        .            .       .             .
        .            .       .             .
        .            .       .             .

Das Entertainment-System war leider nicht so interessant, da das Audio-System nur auf einem Ohr Ton ausspuckte. Außerdem hing das Bedienfeld immer wieder und der Touchscreen reagierte auch langsam. Zum Glück hatte ich genug zu Lesen und mehr als genug Beinfreiheit.

Aufenthalt am Dubai International Airport

Nach 5 Stunden Flug bin ich um halb sechs Ortszeit in Dubai gelandet. Kurz darauf ging die Sonne auf — gefühlt innerhalb von Minuten. Das merkte man jedoch nur an der Helligkeit der milchigen Glasfenster. Aber mehr als ein paar Flugzeuge lassen sich von innen nicht erkennen.

An sich sieht der Flughafen von innen aber genauso wie jeder andere Flughafen aus (abgesehen von der Ausschilderung und dem Personal natürlich). Wie in Deutschland wird auch hier an öffentlichem WiFi gegeizt. Mit unbegrenztem Geld könnte ich hier zwar einen Duty-Free Porsche Cayenne kaufen, aber nicht 1 Minute WiFi.

Der Flug Dubai → Melbourne

Um 10:15 Uhr Ortszeit startete dann der längste Flug von 14 Stunden. Hier war der Platz, den ich im Airbus A380 hatte, nicht so angenehm:

        .            .       .             .
        .            .       .             .
        .            .       .             .
   _o_ _o_ _o—    _o_ _o_ _o_ _o_     _o_ _o_ _o_       (X = ich)
   _o_ _o_ _o—    _o_ _o_ _X_ _o_     _o_ _o_ _o_       (o = besetzter Platz)
   _o_ _o_ _o—    _o_ _o_ _o_ _o_     _o_ _o_ _o_
        .            .       .             .
        .            .       .             .
        .            .       .             .

Zum Ausgleich dafür funktionierte das Entertainment-System sehr gut. Neben der kompletten Beatles-Diskographie gab es fast alles von Pink Floyd, ein bisschen von Jimi Hendrix und sogar In the Court of the Crimson King von King Crimson. Außerdem konnte ich mich mit meinem Laptop in das onboard Free WiFi einloggen und Mails herunterladen. Das Verbinden hat allerdings nur einmal geklappt. Bei allen späteren Versuchen konnte ich mich zwar mit dem W-Lan verbinden, aber keinerlei Netzwerkverbindungen eröffnen. Somit konnte ich das gratis 10MB-Paket gar nicht voll ausnutzen.

Auf dem langen Flug wurden drei Mahlzeiten serviert. Die Bestellung der Vegetarischen Alternative durch das Reisebüro ist aber anscheinend nicht bis zur Flugzeugbesatzung durchgedrungen. Beim fleischigen Hauptgericht war das sehr unpraktisch. Aber nach mehrfachen ansprechen der Flugbegleiter und einiger Zeit hab ich dann glücklicherweise noch eine übrig gebliebene vegetarische Portion erhalten.

Am Flughafen Melbourne

Da die letzte Etappe nach Canberra ein reiner Inlandsflug war, musste ich bereits in Melbourne in das Land Australien einreisen, meinen Koffer abholen, damit durch den Zoll und dann wieder einchecken. Der Ablauf wurde dadurch spannender, dass ich dafür nur eine gute Stunde Zeit hatte: Der Flieger aus Dubai landete um kurz vor 7 und der Flug nach Canberra startete um 8:20 Uhr.

Das Einreisen an sich war absolut problemlos: ich bekam mein bereits online beantragtes Visum in den Reisepass gestempelt und konnte weiter zum Gepäckband. Dort bangte ich bestimmt 20 bis 30 Minuten bis endlich der Koffer auf dem Band erschien.

Beim Zoll kam ich auch direkt dran. Ich sollte Koffer und Rucksack auf im Gang abstellen, sodass der Drogenspürhund schnuppern konnte. Leider schlug er beim Geruch des Rucksacks Alarm, weshalb sowohl Rucksack als auch der prall gefüllte Koffer durchsucht wurden. Schnell war klar, dass eine Tüte Weihnachtsplätzchen die Aufmerksamkeit des Hundes auf sich gezogen hatten. Aber trotzdem wurde mein Koffer weiter durchsucht. Nach ein paar Minuten des Bangens durfte ich dann das ganze Zeug wieder einpacken — bei einem durchwühlten Hartschalenkoffer nicht so einfach.

Das erneute Einchecken des Koffers verlief unerwartet: man checkt einfach an einem Automaten mit Reisepass ein und stellt seinen Koffer dann anschließend aufs Band, ohne je mit einem Angestellten zu sprechen. Danach ging es erneut durch den Security Check und zum Gate. Für das Kaufen von Getränken war leider keine Zeit, da es mittlerweile kurz vor 8 war und der Getränkeautomat meine Australischen Banknoten nicht akzeptierte.

Flug nach und Ankunft in Canberra

Zum Glück wurden auf dem um 8:20 Uhr startenden Flug nach Canberra ausreichend Getränke serviert. Außerdem konnte ich die Aussicht am Fensterplatz genießen:

        .       .      .
        .       .      .
   _o_ ___ _o_    _o_ ___ _X_
        .       .      .
        .       .      .

In Canberra angekommen wartete bereits Dirk Pattinson — mein Betreuer hier vor Ort — auf mich, der mich dankenswerterweise vom Flughafen abholte. Wir sind anschließend zum Burgmann College gefahren — eine Art Studentenwohnheim mit Mensa und Rezeption, in dem ich bis Ende Januar untergebracht bin. Dort konnte ich meinen Koffer lassen, bevor wir kurz zum Unigelände gelaufen sind und Dirk mir sogar ein Fahrrad für die Zeit hier geliehen hat. Damit bin ich nun wohl komplett angekommen und sogar mobil.

Alle Bilder