2012-06-20 8 views
8

Estoy buscando una manera de llamar a una función C en una pila diferente, es decir, guardar el puntero de pila actual, establecer el puntero de pila en una ubicación diferente, llamar a la función y restablece el antiguo puntero de pila cuando vuelve.Función de llamada C con diferente puntero de pila (gcc)

El propósito de esto es un sistema de enhebrado liviano para un lenguaje de programación. Los subprocesos operarán en pilas muy pequeñas, verificará cuándo se necesita más pila y cambiará el tamaño dinámicamente. Esto es para que se puedan asignar miles de subprocesos sin desperdiciar mucha memoria. Cuando se llama al código C no es seguro usar una pila pequeña, ya que el código C no sabe cómo controlar y redimensionar, así que quiero usar una gran pila de subprocesos que se usa solo para llamar a C (compartida entre subprocesos ligeros en el mismo pthread).

Ahora podría escribir stubs de código ensamblador que funcionarán bien, pero me preguntaba si hay una mejor manera de hacerlo, como una extensión gcc o una biblioteca que ya lo implemente. Si no, entonces supongo que tendré mi cabeza enterrada en ABI y en los manuales del lenguaje ensamblador ;-) Solo pregunto esto por pereza y por no querer reinventar la rueda.

+0

Puede implementar sus propios "hilos" con pilas individualizadas utilizando el clon de syscall. Si utiliza la llamada directa al sistema en lugar de la envoltura de libc, funciona de manera muy parecida a fork excepto que puede especificar qué recursos y espacios de nombres se comparten. – technosaurus

Respuesta

2

Suponiendo que está utilizando subprocesos POSIX y en un sistema POSIX, puede lograrlo con señales. Configure una pila de manejo de señal alternativa (sigaltstack) y designe una señal especial en tiempo real para que su controlador se ejecute en la pila de señal alternativa. A continuación, raise la señal para cambiar a la pila, y haga que el manejador de señal lea los datos para qué función llamar y qué argumento para pasar, desde los datos locales de subprocesos.

Tenga en cuenta que este enfoque es bastante caro (varias llamadas al sistema para cambiar pilas), pero debe ser 100% portátil para los sistemas POSIX. Dado que es lento, es posible que desee crear funciones de call-on-alt-stack específicas del arco escritas en ensamblaje, y solo use mi solución general como respaldo para archios en los que no haya escrito una versión de ensamblaje.

+0

Esa es una idea interesante, pero demasiado cara ya que usa llamadas al sistema. Gracias por la respuesta de todos modos. –

+0

Bueno, si estás dispuesto a escribir asm para la CPU que te importa, puede proporcionarte una buena inversión. También podría considerar la antigua API 'makecontext' (obsoleta en POSIX 2001, eliminada en 2008) como una primera alternativa, ya que puede realizarse completamente en el espacio de usuario. –

+0

En general, configurar su propia pila y tener un par de stubs de ensamblaje para intercambiar contextos funcionará. Sin embargo, puede encontrarse con "comprobaciones de pila" que hacen que el puntero de pila se encuentre dentro de un rango específico de memoria. Necesita intercambiar los límites de la pila (donde sea que esté almacenado en su plataforma) junto con el puntero de la pila. Por ejemplo, en Windows está en _TIB :: StackLimit y _TIB :: StackBase en el segmento GS. – doug65536

Cuestiones relacionadas