I'm testing libcoro , a very simple and low-level library that provides coroutines more or less portable . Supposedly, it is valid for systems in production.
My code is as follows:
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include "coro.h"
// Argumentos pasados a los 'thread's.
struct Arg {
const char *message;
coro_context coro;
struct coro_stack stack;
};
// Datos de cada 'thread'.
// Args[0] es el 'thread' principal, en el que empezamos y que controla
// al resto.
struct Arg Args[4] = {
{ NULL, { 0 }, { 0 } },
{ "Mensaje 1", { 0 }, { 0 } },
{ "Mensaje 2", { 0 }, { 0 } },
{ "Mensaje 3", { 0 }, { 0 } }
};
// Selector del 'thread' actual; usado al planificar.
volatile int idx;
// 'cuerpo' de los 'thread's.
void body( struct Arg * );
// Manejador de la interrupcion SIGALRM.
void handler( int );
int main( void ) {
// Reservamos la memória a usar como pila por cada 'thread',
// y los inicializamos.
for( idx = 1; idx < 4; ++idx ) {
coro_stack_alloc( &( Args[idx].stack ), 0 );
coro_create( &( Args[idx].coro ),
(coro_func)&body,
(void *)&Args[idx],
Args[idx].stack.sptr,
Args[idx].stack.ssze );
}
signal( SIGALRM, &handler );
idx = 4;
coro_create( &( Args[0].coro ), NULL, NULL, NULL, 0 );
// Planificador.
// Los ejecutamos en secuencia, del último al primero.
while( --idx ) {
printf( "Dentro del bucle. idx = %d\n", idx );
alarm( 1 );
coro_transfer( &( Args[0].coro ), &( Args[idx].coro ) );
}
printf( "Fuera del bucle. idx = %d\n", idx );
return 0;
}
void body( struct Arg *arg ) {
printf( "%s.\n", arg->message );
while( 1 );
coro_transfer( &( arg->coro ), &( Args[0].coro ) );
printf( "Saliendo de body. idx = %d", idx );
}
void handler( int sig ) {
(void)sig;
coro_transfer( &( Args[idx].coro ), &( Args[0].coro ) );
}
In a similar code that I used as a skeleton, which did not use alarm( )
or signal( )
, nor the while( 1 )
(without forcing the task change in the interrupt handler), it produced the following output:
Inside the loop. idx = 3
Message 3.
Inside the loop. idx = 2
Message 2.
Inside the loop. idx = 1
Message 1.
Out of the loop. idx = 0
The expected output of the displayed code is the same; the messages on the screen should be identical; however, the following is displayed:
Inside the loop. idx = 3
Message 3.
Inside the loop. idx = 2
Message 2.
There it stops, and the CPU usage is set to 100%; that is, it stops at while( 1 )
within function body( )
; it gives the impression that it does not enter the interrupt function.
I'm sure the bug is in my operating logic, but I do not hit the key . It is rare for to interrupt the while( 1 )
2 times and then stop doing it. My common sense dictates that, or I would never interrupt, or I would always.