2010-11-28 7 views

Respuesta

15

Si realmente desea hacer algo como lo que las funciones ucontext.h permiten, seguiría usándolas. Cualquier otra cosa será menos portátil. Marcarlos como obsoletos en POSIX parece haber sido un error horrible de pedantería por parte de alguien en el comité. POSIX en sí requiere que los punteros de función y de datos sean del mismo tamaño y que los punteros a las funciones sean representables para el void *, y que C requiera un molde entre los tipos de puntero a la función y sea seguro para el viaje de ida y vuelta, este problema podría haber sido resuelto

Hay un problema real, que la conversión de la int argc, ... pasado a makecontext en una forma para pasar a la función no se puede hacer sin ayuda importante del compilador a menos que la convención de llamada para funciones variadic y no variadic pasa a ser el mismo (y aún así es bastante cuestionable si se puede hacer de manera robusta). Sin embargo, este problema podría haberse resuelto simplemente desaprobando el uso de makecontext en cualquier forma que no sea makecontext(ucp, func, 1, (void *)arg);.

Quizás una pregunta mejor es por qué cree que las funciones ucontext.h son la mejor manera de manejar el enhebrado. Si desea ir con ellos, le sugiero que escriba una interfaz de contenedor que puede implementar ya sea con ucontext.ho con pthreads, y luego comparar el rendimiento y la hinchazón. Esto también tendrá la ventaja de que, si los sistemas futuros dejan de admitir el ucontext.h, simplemente puede pasar a la compilación con la implementación pthread y todo funcionará. (Para entonces, la hinchazón puede ser menos importante, el beneficio de varios núcleos/SMP probablemente será enorme, y es de esperar implementaciones pthread será menos hinchado.)

Editar (basado en la solicitud de OP): Para implementar "threading cooperativo" con pthreads, necesita variables de condición.He aquí una pthreads decente tutorial con información sobre el uso de ellos:

https://computing.llnl.gov/tutorials/pthreads/#ConditionVariables

Su cooperativa multitarea primitiva de "mano de ejecución para enhebrar X" sería algo como:

self->flag = 0; 
other_thread->flag = 1; 
pthread_mutex_lock(other_thread->mutex); 
pthread_cond_signal(other_thread->cond); 
pthread_mutex_unlock(other_thread->mutex); 
pthread_mutex_lock(self->mutex); 
while (!self->flag) 
    pthread_cond_wait(self->cond, self->mutex); 
pthread_mutex_unlock(self->mutex); 

Esperanza Tengo que todos derecho; al menos la idea general es correcta. Si alguien ve errores, por favor coméntalo para que pueda solucionarlo. La mitad del bloqueo (mutex other_thread) probablemente sea completamente innecesario con este tipo de uso, por lo que quizás pueda hacer que el mutex sea una variable local en la función task_switch. Todo lo que realmente estaría haciendo es usar pthread_cond_wait y pthread_cond_signal como primitivas "ir a dormir" y "despertar otro hilo".

+1

Estoy buscando un enhebrado cooperativo, que es lo que pthread no hace. En el enhebrado cooperativo/subprocesamiento de usuario, cada subproceso es responsable de dejar que los demás se ejecuten. Los subprocesos están programados por el sistema operativo, lo que dificulta implementar el enhebrado cooperativo. – zneak

+0

¿Quizás estás buscando variables condicionales? https://computing.llnl.gov/tutorials/pthreads/#ConditionVariables –

+0

Agregó algunos detalles sobre cómo puede hacer esto con pthreads. –

4

No, no hay un reemplazo estándar para ellos.

opciones

Ustedes son

  • <ucontext.h> siguen utilizando a pesar de que contienen obsoleta C. interruptor
  • a pthreads
  • escribir su propia biblioteca de co-hilo
  • utilizar una ya existente (y posiblemente no -so-portable) biblioteca de subprocesos tal como http://swtch.com/libtask/, aunque muchas de estas bibliotecas están implementadas en la parte superior de ucontext.h
+0

Me pregunto si estas bibliotecas no tan portátiles podrían ser portadas para usar pthreads en lugar de hacks específicos de OS/máquina, similar al enfoque en mi respuesta ... –

+1

Posiblemente, pero eso es mucho más pesado. – nos

+0

No diría "mucho". Unos miles de ciclos más para el cambio de contexto (o tal vez menos con SMP/multi-core), y algunas decenas de kb adicionales por hilo (supongo que de 2 a 4 páginas en el kernel y la misma cantidad en el espacio de usuario). –

0

Especificaciones La Base Open Group Número 6 IEEE Std 1003.1, 2004 Edición

aún muestra makecontext() y swapcontext() con la misma sintaxis obsoleta. No he visto nada más reciente.

10

Por lo que vale, hay una biblioteca Boost.Context que era recently accepted y solo necesita fusionarse en una versión oficial de Boost. Boost.Context se ocupa de los mismos casos de uso que la familia POSIX ucontext: cambio de contexto cooperativo de bajo costo general. El autor se ha tomado muchas molestias con los problemas de rendimiento.

+0

Eso es muy interesante. Ya no lo necesito, pero si alguna vez vuelvo a necesitar algo así, sabré dónde buscar. – zneak

Cuestiones relacionadas