Hallo, möchte euch hier mein Betriebssystem für AVRs (momentan ATmega32) vorstellen. Es kann - Multithreading - Prozesssynchronisation mit Mutex - verschiedene Timerfunktionen - FIFOs Das OS ist an Win32 angelehnt und hat auch entsprechend ähnlich klingende Funktionsnamen. Die Threads können dynamisch erstellt und beendet werden, man kann auf Threads warten und mit Mutex verwendete Ressourcen blockieren/freigeben. Zusätlich sind ein einfaches Massage-Event-System und dynamische 10-ms Timer implementiert. Im Zip-Ordner befindet sich zusätzlich ein Bespiel, welches die Funktionen des OS demonstriert und sich mit einem ATmega32 mit RS232 (z.b. Pollin Evaluation Board) ausprobieren lässt. Vor der Verwendung bitte die readme.txt lesen. MfG Mark
Hm, ich wusste doch, dass ich igendwas vergessen habe :). Danke für den Hinweis.
Moin, ... und wo ist die Multithreading fähige C-Laufzeitbibliothek MfG
Was verstehst Du unter Laufzeitbibliothek? Da der AVR architekturbedingt nur einen Prozess (Prozess != Thread) ausführen kann, macht so etwas wie eine Laufzeitbibliothek keinen Sinn.
Mark P. wrote: > Was verstehst Du unter Laufzeitbibliothek? Schlag es nach. Das ist kein Begriff, bei dem es einen sonderlich großen "was verstehst du darunter"-Spielraum gibt. > Da der AVR architekturbedingt > nur einen Prozess (Prozess != Thread) ausführen kann, macht so etwas wie > eine Laufzeitbibliothek keinen Sinn. Sorry, aber das ist schlicht Unsinn. Worauf Gast hinaus wollte, ist, dass die AVR-Libc nicht unbedingt mit dem Hintergedanken Multithreading-OS entwickelt wurde. Die eine oder andere Funktion darin ist nicht reentrant.
@ Stefan Dann hab ich wohl etwas falsch verstanden. Eine Laufzeitbibliothek ist für mich eine Lib, die von mehreren Prozessen, die nichts von einander wissen, benutzt weden kann um Platz zu sparen, weil dann gleicher Code nicht mehrmals vorhanden sein muss. Der AVR kann aber keine unabhängigen Prozesse ausführen, da er weder eine MMU hat, noch Code aus dem RAM ausführen kann. Dass die avr-libc nicht unbedingt thread-save ist, ist mir klar. Das ist aber bei Verwendung von Interrupts dann genauso, dass der Anwender bei "gefährdeten" Funkionen genauer hinschauen muss. Und bei meinem OS gibt es Funktionen, die einen Thread blockieren, so dass er nicht von anderen unterbrochen werden kann. Eine spezielle c-lib wird deshalb meiner Mainung nach nicht benötigt. MfG Mark
Mark P. wrote: > Dann hab ich wohl etwas falsch verstanden. Ja, hast du. Schlag den Begriff einfach nach (z.B. bei Wikipedia). > Der AVR kann aber keine unabhängigen > Prozesse ausführen, da er weder eine MMU hat, noch Code aus dem RAM > ausführen kann. Beides sind keine Ausschlusskriterien für "unabhängige Prozesse". > Dass die avr-libc nicht unbedingt thread-save ist, ist mir klar. Das ist > aber bei Verwendung von Interrupts dann genauso, dass der Anwender bei > "gefährdeten" Funkionen genauer hinschauen muss. Ja, aber bei der Verwendung von Threads rückt das Problem deutlich stärker in den Vordergrund. > Und bei meinem OS gibt > es Funktionen, die einen Thread blockieren, so dass er nicht von anderen > unterbrochen werden kann. Eine spezielle c-lib wird deshalb meiner > Mainung nach nicht benötigt. "Nötig" nicht (sagt ja auch keiner), aber eine Lib mit threadsicheren Varianten der Funktionen (eben unter Zuhilfenahme der vom OS angebotenen Funktionalität) wäre nicht unbedingt eine überflüssige Zugabe.
Hört sich sehr interessant an. Deine Implementierung werd ich mir mal anschauen. Ich hatte vor ein paar Tagen selbst ein bischen Assemblercode geposted (siehe 'multithreading auf dem AVR') der es erlaubt genau einen weiteren Thread aufzumachen. Mein Gedanke war, das ganze so klein wie möglich zu halten. Immerhin braucht ja jeder Thread seinen eigenen Stack Space und zusammen mit z.B. einem Ethernet Device Driver + TCP/IP Stack + Webserver wird es ja dann irgendwann schon ein bischen eng bez. RAM. Mich interressiert vor allem, wie du das ganze pop/push aller Register beim Thread Wechsel gelößt hast...
@Stefan Ok ok hab mir die Definition von Laufzeitbibliothek nochmal genau angeguckt und Du hattest da recht. Ich hab es mit einer dynamischen Bibliothek verwechelt. >> Der AVR kann aber keine unabhängigen >> Prozesse ausführen, da er weder eine MMU hat, noch Code aus dem RAM >> ausführen kann. >Beides sind keine Ausschlusskriterien für "unabhängige Prozesse". Man könnte natürlich einen Compiler+Linker bauen, der Code für den AVR erzeugt, bei dem sowohl das text- als auch das data-Segment zur Laufzeit beliebig verschoben werden könnten. Mit dem normalen avr-gcc geht das aber nicht, weder das eine noch das andere. >> Dass die avr-libc nicht unbedingt thread-save ist, ist mir klar. Das ist >> aber bei Verwendung von Interrupts dann genauso, dass der Anwender bei >> "gefährdeten" Funkionen genauer hinschauen muss. >Ja, aber bei der Verwendung von Threads rückt das Problem deutlich >stärker in den Vordergrund. >> Und bei meinem OS gibt >> es Funktionen, die einen Thread blockieren, so dass er nicht von anderen >> unterbrochen werden kann. Eine spezielle c-lib wird deshalb meiner >> Mainung nach nicht benötigt. >"Nötig" nicht (sagt ja auch keiner), aber eine Lib mit threadsicheren >Varianten der Funktionen (eben unter Zuhilfenahme der vom OS angebotenen >Funktionalität) wäre nicht unbedingt eine überflüssige Zugabe. Mein OS war nicht dazu gedacht, um einen PC durch einen AVR ersetzen zu können, sondern ist nur deswegen entstanden, weil man mit Threads gewisse Sachen einfacher bzw. schneller lösen kann als ohne. Deshalb bein ich persönlich der Meinung, dass eine extra angepasste C-Bibliothek komplett oversized wäre. MfG Mark
@Harald Ich hab mir mal Deinen Code angeschaut, und im Prinzip macht es das selbe wie meiner, nur dass bei mir der nächste Thread aus einem Ringbuffer ausgelesen wird. >Mich interressiert vor allem, wie du das ganze pop/push aller Register >beim Thread Wechsel gelößt hast... Genauso wie Du, sprich es werden alle Register gepusht, der SP gewechselt und alle Register wieder gepoppt. Hab das mal nechgerechnet, bei 1000Hz Threadwechsel @16MHz sind es etwa 1.1% Rechenleistung. Geht eben nicht anders. MfG Mark
Mark P. wrote: > Man könnte natürlich einen Compiler+Linker bauen, der Code für den AVR > erzeugt, bei dem sowohl das text- als auch das data-Segment zur Laufzeit > beliebig verschoben werden könnten. Mit dem normalen avr-gcc geht das > aber nicht, weder das eine noch das andere. text-Segment zur Laufzeit verschieben: Unnötig. data-Segment zur Laufzeit verschieben: Umkopieren des Speichers, was vom OS beim Prozesswechsel zu erledigen wäre. Startupcode und Linkerscript wären zu ändern, aber mit dem Compiler an sich hat das alles nichts zu tun. Auch mit dem avr-gcc in seiner jetzigen Form wäre ein OS mit "unabhängigen Prozessen" machbar. Natürlich wäre das weit entfernt von "effizient" oder "sinnvoll", aber prinzipiell machbar wäre es schon. > Mein OS war nicht dazu gedacht, um einen PC durch einen AVR ersetzen zu > können, sondern ist nur deswegen entstanden, weil man mit Threads > gewisse Sachen einfacher bzw. schneller lösen kann als ohne. Wass soll das denn jetzt mit dem Vergleich zum PC? Wie ich bereits sagte, ist es natürlich nicht absolut nötig, aber es wäre auch alles andere als "oversized" oder "überflüssiger Luxus", wenn man z.B. eine malloc-Variante anbieten würde, die einfach das vorhandene malloc im Rahmen der OS-Möglichkeiten kapselt.
@Stefan >text-Segment zur Laufzeit verschieben: >Unnötig. Und wie soll das gehen? Wenn auf einem Controller ohne MMU zwei Prozesse laufen sollen, die nichts von einander wissen, dann bedeutet es, dass sie sich an verschiedenen Stellen im Speicher befinden. Da der Compiler aber nicht zu compile-Zeit weiss, wo sich die erstellte Anwendung im Flash befinden wird, muss er den Code so schreiben, dass er von jedem Ort aus lauffähig wär. Und das kann_ der normale avr-gcc _nicht. >data-Segment zur Laufzeit verschieben: >Umkopieren des Speichers, was vom OS beim Prozesswechsel zu erledigen >wäre. Sollen da bei jedem einzelnen Prozesswechsel Kilobytes an Speicher bewegt werden oder wie stellst Du Dir das vor? >Wass soll das denn jetzt mit dem Vergleich zum PC? Das war eine sehr starke Übertreibung, um mein Anliegen zu verdeutlichen. >Wie ich bereits sagte, ist es natürlich nicht absolut nötig, aber es >wäre auch alles andere als "oversized" oder "überflüssiger Luxus", wenn >man z.B. eine malloc-Variante anbieten würde, die einfach das vorhandene >malloc im Rahmen der OS-Möglichkeiten kapselt. Finde ich nicht. Wenn Du solche Funktionen haben willst, kannst Du sie ja gerne schreiben. Ich benutze das OS seit ein paar Monaten (kein allzu langer Zeitraum, ich weiss) und hab sowas noch nie benötigt. MfG Mark
Mark P. wrote: > Und wie soll das gehen? Wenn auf einem Controller ohne MMU zwei Prozesse > laufen sollen, die nichts von einander wissen, dann bedeutet es, dass > sie sich an verschiedenen Stellen im Speicher befinden. Da der Compiler > aber nicht zu compile-Zeit weiss, wo sich die erstellte Anwendung im > Flash befinden wird, muss er den Code so schreiben, dass er von jedem > Ort aus lauffähig wär. Und das kann_ der normale avr-gcc _nicht. Totaler Quatsch. Auch jetzt weiß der Compiler nicht, wo im Flash der Code letztlich landen wird. Schlag mal nach, was der Linker ist und macht. > Sollen da bei jedem einzelnen Prozesswechsel Kilobytes an Speicher > bewegt werden oder wie stellst Du Dir das vor? Ja natürlich. Was meinst du, wie es ein "richtiges" Multitasking-BS (wie z.B. Linux) auf einem Prozessor ohne MMU (z.B. 68000) macht? Außerdem sagte ich ja bereits, dass es ineffizient ist. Es geht ja auch nur ums Prinzipielle, schließlich hast du behauptet, dass es grundsätzlich nicht gehen würde.
@Stefan >Totaler Quatsch. Auch jetzt weiß der Compiler nicht, wo im Flash der >Code letztlich landen wird. Schlag mal nach, was der Linker ist und >macht. Dann weiss es eben der Linker. Und dieser muss nun mal z.B. beim jmp-Befehl die Labels in absolute Adressen auflösen können. Und das ist der Knackpunkt. >Ja natürlich. Was meinst du, wie es ein "richtiges" Multitasking-BS (wie >z.B. Linux) auf einem Prozessor ohne MMU (z.B. 68000) macht? >Außerdem sagte ich ja bereits, dass es ineffizient ist. Es geht ja auch >nur ums Prinzipielle, schließlich hast du behauptet, dass es >grundsätzlich nicht gehen würde. Das bei z.B. µCLinux bei jedem Prozesswechsel das ganze data-Segment, welches durchaus einige MB haben kann, umkopiert, wird glaube ich nicht. Ich weiss zwar nicht wie es gemacht wird, aber ich vermute, dass das OS dem Prozess beim Start das Offset des data-Segments übergibt, sodass der Prozess auf globale Variablen immer über dieses Offset zugreift. MfG Mark
Da der Thread sowieso schon stark off topic ist, mal eine eher allgemeine Frage zum Multithreading auf AVRs: Wie sieht das eigentlich bei 16bit Zugriffen auf Register aus? Diese benutzen doch dieses interne Highbyte Register. Wenn genau zwischen dem Zugriff auf die beiden High/Low Register umgeschaltet wird, und der andere Thread auch ein 16bit Register liest oder schreibt, dürfte im ersten Thread Mist rauskommen, da der alter Wert in dem Highbyte Register dann überschrieben ist. Oder sehe ich das falsch?
@ Benedikt Du siehst es richtig. Deshalb sollte man den Zugriff auf Ressourcen, die von mehreren Threads verwendet werden, mit Mutex regeln oder bei kurzen Zugriffen die Interrupts abschalten. Um zu vermeiden, dass ein Thread über einen längeren Zeitraum nicht von einem anderen Thread unterbrochen werden darf, aber die Interrupts trotzdem aktiviert bleiben sollen, gibt es bei meinem OS extra Funktionen, die das regeln. MfG Mark
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.