2012-06-20 6 views
8

Ich bin auf der Suche nach einer Möglichkeit, eine C-Funktion in einem anderen Stapel aufzurufen, dh speichern Sie den aktuellen Stapelzeiger, legen Sie den Stapelzeiger an einer anderen Stelle, rufen Sie die Funktion und Stellt den alten Stapelzeiger wieder her, wenn er zurückkehrt.Call C-Funktion mit verschiedenen Stack-Pointer (GCC)

Der Zweck ist ein leichtes Threading-System für eine Programmiersprache. Threads arbeiten auf sehr kleinen Stapeln, prüfen, wann mehr Stack benötigt wird und passen die Größe dynamisch an. Dies ist so, dass Tausende von Threads zugewiesen werden können, ohne viel Speicher zu verschwenden. Wenn man C-Code aufruft, ist es nicht sicher, einen winzigen Stack zu verwenden, da der C-Code nichts über das Überprüfen und Ändern der Größe weiß. Daher möchte ich einen großen Pthread-Stack verwenden, der nur zum Aufruf von C verwendet wird der gleiche Pthread).

Jetzt könnte ich Assembly Code Stubs schreiben, die gut funktionieren, aber ich fragte mich, ob es eine bessere Möglichkeit gibt, dies zu tun, wie eine gcc-Erweiterung oder eine Bibliothek, die es bereits implementiert. Wenn nicht, dann denke ich, werde ich meinen Kopf in ABI und Assembler-Handbüchern vergraben lassen ;-) Ich frage das nur aus Faulheit und will das Rad nicht neu erfinden.

+0

Sie können Ihre eigenen "Threads" mit individualisierten Stacks mit dem Klon syscall implementieren. Wenn Sie den direkten Systemaufruf anstelle des libc-Wrappers verwenden, funktioniert es fast wie fork, außer dass Sie angeben können, welche Ressourcen und Namespaces freigegeben sind. – technosaurus

Antwort

2

Angenommen, Sie verwenden POSIX-Threads und auf einem POSIX-System, können Sie dies mit Signalen erreichen. Richten Sie einen alternativen Signalbehandlungsstapel ein (sigaltstack) und geben Sie ein spezielles Echtzeit-Signal an, damit der Handler auf dem alternativen Signalstapel ausgeführt wird. Dann raise das Signal zum Stapel wechseln, und die Signal-Handler lesen die Daten für welche Funktion zu rufen, und welches Argument, um es übergeben, von Thread-lokalen Daten.

Beachten Sie, dass dieser Ansatz ziemlich teuer ist (mehrere Systemaufrufe zum Ändern von Stacks), aber zu POSIX-Systemen zu 100% portabel sein sollte. Da es langsam ist, möchten Sie vielleicht arch-spezifische Call-on-Alt-Stack-Funktionen in Assembly schreiben und nur meine allgemeine Lösung als Fallback für Archs verwenden, in denen Sie keine Assembly-Version geschrieben haben.

+0

Das ist eine interessante Idee, aber zu teuer, da es Systemaufrufe verwendet. Danke für die Antwort trotzdem. –

+0

Nun, wenn Sie bereit sind, asm für die CPUs zu schreiben, die Ihnen wichtig sind, könnte es einen ordentlichen Fallback bieten. Sie können auch die alte 'makecontext'-API (die in POSIX 2001 veraltet ist und 2008 entfernt wurde) als erste Alternative betrachten, da sie vollständig im Benutzerbereich ausgeführt werden kann. –

+0

Im Allgemeinen wird das Einrichten eines eigenen Stapels und einige Assembly-Stubs zum Austauschen von Kontexten funktionieren. Sie können jedoch auf "Stapelprüfungen" stoßen, die erzwingen, dass der Stapelzeiger in einem bestimmten Speicherbereich liegt. Sie müssen die Stack-Grenzen (wo auch immer es auf Ihrer Plattform gespeichert ist) mit dem Stack-Pointer tauschen. Zum Beispiel in Windows ist es in der _TIB :: StackLimit und _TIB :: StackBase im GS-Segment. – doug65536