_THREAD PROGRAMMING IN UNIXWARE 2.0_ by John Rodley Listing One // A program to create and control a command line specifiable // number of threads interactively. // command line arguments: // -b Create BOUND threads, defaults to multiplexed // -nthreads Create number threads // see code for explanation of interactive commands. #include "defines.h" #include #include #include #include #include #include #include #include #include #include "listing1.hpp" #define MAX_THREADOBJECTS 65000 #define IDTUNE_CMD "grep MAXULWP /etc/conf/cf.d/mtune | awk '{print $2}'" #define BUFSIZE 80 bool bBound; // are we using bound or multiplexed threads?? pid_t getpid(), child1_pid, child2_pid; int GetMAXULWP(); int flagset( int argc, char *argv[], char *flag ); // Main - create the number of threads specified on the command line, then sit // in a loop accepting and executing interactive commands from the user. int main( int argc, char *argv[] ) { int i, k, iNumThreads; Thread *pt[MAX_THREADOBJECTS]; int iMaxThreads; int maxulwp; int iNumRequestedThreads; int thread_index; int thread_id; char kar; char buffer[80]; int iConcurrencyLevel = 1; int iRet; maxulwp = GetMAXULWP(); if(( k = flagset( argc, argv, "-nthreads" )) > 0 ) iNumRequestedThreads = atoi( argv[k+1] ); else iNumRequestedThreads = MAX_THREADOBJECTS; if( flagset( argc, argv, "-b" ) > 0 ) { bBound = TRUE; iMaxThreads = maxulwp + 1; } else { bBound = FALSE; iMaxThreads = (maxulwp*4) + 1; if(( iRet = thr_setconcurrency( iConcurrencyLevel )) != 0 ) printf( "Error: thr_setconcurrency(%d) = %d\n", iConcurrencyLevel, iRet ); } printf( "P%d LWP%d - Creating %d %s threads\n", getpid(), _lwp_self(), iNumRequestedThreads, bBound?"bound":"multiplexed" ); for( i = 0, iNumThreads = 0; i < MAX_THREADOBJECTS && i < iNumRequestedThreads ; i++ ) { if( bBound ) pt[i] = new BoundThread(); else pt[i] = new MultiplexedThread(); if( !pt[i] ) break; if( pt[i]->iCreateError != 0 ) { printf( "P%d - Thread create error %d\n", getpid(), pt[i]->iCreateError ); delete pt[i]; break; } iNumThreads++; if( iNumThreads == iMaxThreads) printf( "P%d -\tNext thread will exceed MAXULWP (%d)\n", getpid(), maxulwp ); } printf( "Following thread commands are available:\n" ); printf( "\ti - shows the status of all the threads\n" ); printf( "\ta - increments concurrency level\n" ); printf( "\tc - continues all the threads\n" ); printf( "\tc - continues the specified thread\n" ); printf( "\ts - suspends all the threads\n" ); printf( "\ts - suspends the specified thread\n" ); printf( "\tk - sends SIGTERM to all threads\n" ); printf( "\tk - sends SIGTERM to the specified thread\n" ); printf( "\tv - turns iteration printing on/off\n" ); printf( "\tq - ends the program\n" ); sigignore( SIGTERM ); bool bKeepRunning = TRUE; while( bKeepRunning ) { thread_id = -1; thread_index = -1; gets( buffer ); kar = toupper( buffer[0] ); for( i = 1; buffer[i] != '\0'; i++ ) { if( !isspace( buffer[i] )) { thread_id = atoi( &buffer[i] ); for( i = 0; i < iNumThreads; i++ ) { if( thread_id == pt[i]->tid ) { thread_index = i; break; } } break; } } switch( kar ) { case 'A': iConcurrencyLevel++; // iConcurr... is 1 based, while iNumThreads is 0 based if( iConcurrencyLevel > (iNumThreads+1)) printf( "Error: would have more LWPs than threads!\n" ); else { if(( iRet = thr_setconcurrency( iConcurrencyLevel )) != 0 ) printf( "Error: thr_setconcurrency(%d) = %d\n", iConcurrencyLevel, iRet ); } break; case 'I': for( i = 0; i < iNumThreads; i++ ) printf( "\tThread id %d - %s\n", pt[i]->tid, pt[i]->Ended?"GONE":"STILL RUNNING" ); break; case 'C': if( thread_id >= 0 ) pt[thread_index]->Continue(); else for( i = 0; i < iNumThreads; i++ ) pt[i]->Continue(); break; case 'S': if( thread_id >= 0 ) pt[thread_index]->Suspend(); else for( i = 0; i < iNumThreads; i++ ) pt[i]->Suspend(); break; case 'K': if( thread_id >= 0 ) pt[thread_index]->Kill( SIGTERM ); else for( i = 0; i < iNumThreads; i++ ) pt[i]->Kill(SIGTERM); break; case 'V': for( i = 0; i < iNumThreads; i++ ) pt[i]->bVerbose = pt[i]->bVerbose^0x1; break; case 'Q': bKeepRunning = FALSE; break; default: printf( "Unknown command (%c) (%s)\n", kar, buffer ); break; } } // We really don't have to call End, because the return kills the // threads anyway, but cleanliness counts. for( i = 0; i < iNumThreads; i++ ) pt[i]->End(); printf( "P%d - Ending thread 0\n", getpid() ); return( 0 ); } // flagset - tells whether a command-line flag was set. returns an index into // argv where flag was detected. Use return val+1 to get arg following a flag int flagset( int argc, char *argv[], char *flag ) { for( int i = 1; i < argc; i++ ) { if( strcmp( argv[i], flag ) == 0 ) return( i ); } return( -1 ); } // This function greps MAXULWP out of mtune so that we can tell // when we're about to exceed the maximum allowable number of LWPs per user id. int GetMAXULWP() { int maxulwp, i; FILE *fp; char buf[BUFSIZE]; if(( fp = popen( IDTUNE_CMD, "r" )) < 0 ) printf( "P%d - Couldn't exec %s - skipping MAXULWP check\n", getpid(), IDTUNE_CMD ); else { i = 0; while (fgets(buf, BUFSIZ, fp ) != NULL) { maxulwp = atoi( buf ); printf( "P%d - Got MAXULWP value of %d\n", getpid(), maxulwp ); i++; } if( i > 1 ) printf( "P%d - ambiguous value for MAXULWP, skipping check\n", getpid() ); pclose( fp ); } return( maxulwp ); }