//------------------------------------------------------------------- // switcher.cpp // // This program implements a crude version of user-mode thread- // scheduling (as distinguished from the kernel-mode scheduling // of threads which is directly supported by Linux). We create // a queue of read-to-run threads, and we use signals generated // by an interval timer to trigger our "round-robin" scheduling // among four distinct threads (which all exist within a common // process address-space). What is unusual here is that we use // a common stack for all of our threads, for simplicity. This // is possible because our threads always resume execution from // their initial entry-point (i.e., they "start over"), instead // of resuming from the point where they were interrupted. But // this is purely a demo, to illustrate the concept of threads. // // programmer: ALLAN CRUSE // written on: 27 SEP 2004 //------------------------------------------------------------------- #include // for printf() #include // for exit() #include // for signal() #include // for setitimer() int done = 0; // global variable int thread1( void ) { printf( "Hello from thread1 \n" ); while ( !done ); printf( "\nThread1 is quitting\n" ); exit(0); } int thread2( void ) { printf( "Hello from thread2 \n" ); while ( !done ); printf( "\nThread2 is quitting\n" ); exit(0); } int thread3( void ) { printf( "Hello from thread3 \n" ); while ( !done ); printf( "\nThread3 is quitting\n" ); exit(0); } int thread4( void ) { printf( "Hello from thread4 \n" ); while ( !done ); printf( "\nThread4 is quitting\n" ); exit(0); } typedef int (*THREAD)(void); THREAD ready[] = { thread1, thread2, thread3, thread4 }; const int thread_count = sizeof( ready )/sizeof( THREAD ); int next_thread = 0; // array-index for 'ready' list void upon_signal( int signum ) { unsigned long *tos; // this is used for addressing the stack-frame asm(" movl %%ebp, %0 " : "=m" (tos) ); // initializes frame-pointer // This was useful during development -- to display the stack elements // for (int i = 0; i < 22; i++) printf( "tos[%d]=%08X \n", i, tos[i] ); tos[17] = (unsigned long)ready[ next_thread ]; // modify return-point next_thread = ( 1 + next_thread ) % thread_count; // "circular" array if ( signum == SIGINT ) done = 1; // to terminate on -C } int main( int argc, char **argv ) { signal( SIGINT, upon_signal ); struct itimerval it; it.it_value.tv_sec = 1; it.it_value.tv_usec = 0; it.it_interval.tv_sec = 0; it.it_interval.tv_usec = 200000; setitimer( ITIMER_REAL, &it, NULL ); signal( SIGALRM, upon_signal ); while ( !done ); printf( "\nQuitting\n" ); }