2012-06-20 27 views
8

Sto cercando un modo per chiamare una funzione C in un altro stack, ovvero salvare il puntatore stack corrente, impostare il puntatore dello stack su una posizione diversa, chiamare la funzione e ripristina il vecchio puntatore dello stack quando ritorna.Chiamare la funzione C con un altro stack pointer (gcc)

Lo scopo di questo è un sistema di threading leggero per un linguaggio di programmazione. I thread funzioneranno su stack molto piccoli, controllare quando è necessario più stack e ridimensionarli dinamicamente. Questo è così che migliaia di thread possono essere allocati senza sprecare molta memoria. Quando si chiama in codice C non è sicuro usare un piccolo stack, poiché il codice C non sa di controllo e ridimensionamento, quindi voglio usare un grosso stack pthread che viene usato solo per chiamare C (condiviso tra thread leggeri su lo stesso pthread).

Ora potrei scrivere stub di codice assembly che funzioneranno bene, ma mi chiedevo se c'è un modo migliore per farlo, come un'estensione gcc o una libreria che già la implementa. Se no, allora immagino che avrò la mia testa nascosta in ABI e manuali di linguaggio assembly ;-) Lo chiedo solo per pigrizia e non volendo reinventare la ruota.

+0

È possibile implementare i propri "thread" con stack individualizzati utilizzando il clone syscall. Se si utilizza la chiamata di sistema diretta anziché il wrapper libc, funziona in modo simile a fork, tranne che è possibile specificare quali risorse e spazi dei nomi sono condivisi. – technosaurus

risposta

2

Supponendo che si utilizzino i thread POSIX e su un sistema POSIX, è possibile ottenere questo con i segnali. Impostare uno stack di gestione del segnale alternativo (sigaltstack) e designare un segnale speciale in tempo reale per far funzionare il gestore sulla pila di segnali alternativa. Quindi il segnale raise per passare allo stack e fare in modo che il gestore di segnali legga i dati per quale funzione chiamare e quale argomento per passarlo, dai dati locali del thread.

Si noti che questo approccio è piuttosto costoso (più chiamate di sistema per cambiare stack), ma dovrebbe essere 100% portabile ai sistemi POSIX. Dal momento che è lento, è consigliabile creare funzioni di call-on-alt-stack specifiche per l'arco scritte in assembly e utilizzare solo la mia soluzione generale come fallback per gli archivi in ​​cui non è stata scritta una versione di assembly.

+0

Questa è un'idea interessante, ma troppo costosa poiché utilizza le chiamate di sistema. Grazie comunque per la risposta. –

+0

Beh, se sei disposto a scrivere asm per le cpu che ti interessano, potrebbe fornire un discreto ripiego. Si potrebbe anche considerare la vecchia API 'makecontext' (obsoleta in POSIX 2001, rimossa nel 2008) come primo ripiego dato che può essere eseguita interamente in userspace. –

+0

Generalmente, l'impostazione del proprio stack e il fatto di avere un paio di stub di assembly per scambiare i contesti funzioneranno. Tuttavia, è possibile eseguire "assegni di stack" che impongono che il puntatore dello stack si trovi in ​​un intervallo specifico di memoria. È necessario scambiare i limiti dello stack (ovunque siano memorizzati sulla piattaforma) insieme al puntatore dello stack. Ad esempio, in Windows è in _TIB :: StackLimit e _TIB :: StackBase nel segmento GS. – doug65536

Problemi correlati