/**CFile**************************************************************** FileName [starter.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Wrapper for calling ABC.] Synopsis [A demo program illustrating parallel execution of ABC.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - October 22, 2009.] Revision [$Id: starter.c,v 1.00 2009/10/22 00:00:00 alanmi Exp $] ***********************************************************************/ // To compile on Linux run: gcc -pthread -o starter starter.c #include #include #include #include #ifdef WIN32 #include "pthread.h" #else #include #include #endif // the max number of commands to execute from the input file #define MAX_COMM_NUM 1000 // time printing #define ABC_PRT(a,t) (printf("%s = ", (a)), printf("%7.2f sec\n", (float)(t)/(float)(CLOCKS_PER_SEC))) // the number of currently running threads static int nThreadsRunning = 0; // mutext to control access to the number of threads pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; // procedure for duplicating strings char * Abc_UtilStrsav( char * s ) { return s ? strcpy(malloc(strlen(s)+1), s) : NULL; } /**Function************************************************************* Synopsis [This procedures executes one call to system().] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void * Abc_RunThread( void * Command ) { // perform the call if ( system( (char *)Command ) ) { assert(pthread_mutex_lock(&mutex) == 0); fprintf( stderr, "The following command has returned non-zero exit status:\n" ); fprintf( stderr, "\"%s\"\n", (char *)Command ); fprintf( stderr, "Sorry for the inconvenience.\n" ); fflush( stdout ); assert(pthread_mutex_unlock(&mutex) == 0); } // decrement the number of threads runining assert(pthread_mutex_lock(&mutex) == 0); nThreadsRunning--; assert(pthread_mutex_unlock(&mutex) == 0); // quit this thread //printf("...Finishing %s\n", (char *)Command); free( Command ); pthread_exit( NULL ); assert(0); return NULL; } /**Function************************************************************* Synopsis [Takes file with commands to be executed and the number of CPUs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int main( int argc, char * argv[] ) { FILE * pFile, * pOutput = stdout; pthread_t ThreadIds[MAX_COMM_NUM]; char * pBufferCopy, Buffer[MAX_COMM_NUM]; int i, nCPUs = 0, nLines = 0, Counter; clock_t clk = clock(); // check command line arguments if ( argc != 3 ) { fprintf( stderr, "Wrong number of command line arguments.\n" ); goto usage; } // get the number of CPUs nCPUs = atoi( argv[1] ); if ( nCPUs <= 0 ) { fprintf( pOutput, "Cannot read an integer represting the number of CPUs.\n" ); goto usage; } // open the file and make sure it is available pFile = fopen( argv[2], "r" ); if ( pFile == NULL ) { fprintf( pOutput, "Input file \"%s\" cannot be opened.\n", argv[2] ); goto usage; } // read commands and execute at most of them at a time // assert(mutex == PTHREAD_MUTEX_INITIALIZER); while ( fgets( Buffer, MAX_COMM_NUM, pFile ) != NULL ) { // get the command from the file if ( Buffer[0] == '\n' || Buffer[0] == '\r' || Buffer[0] == '\t' || Buffer[0] == ' ' || Buffer[0] == '#') { continue; } if ( Buffer[strlen(Buffer)-1] == '\n' ) Buffer[strlen(Buffer)-1] = 0; if ( Buffer[strlen(Buffer)-1] == '\r' ) Buffer[strlen(Buffer)-1] = 0; // wait till there is an empty thread while ( 1 ) { assert(pthread_mutex_lock(&mutex) == 0); Counter = nThreadsRunning; assert(pthread_mutex_unlock(&mutex) == 0); if ( Counter < nCPUs - 1 ) break; // Sleep( 100 ); } // increament the number of threads running assert(pthread_mutex_lock(&mutex) == 0); nThreadsRunning++; printf( "Calling: %s\n", (char *)Buffer ); fflush( stdout ); assert(pthread_mutex_unlock(&mutex) == 0); // create thread to execute this command pBufferCopy = Abc_UtilStrsav( Buffer ); assert(pthread_create( &ThreadIds[nLines], NULL, Abc_RunThread, (void *)pBufferCopy ) == 0); if ( ++nLines == MAX_COMM_NUM ) { fprintf( pOutput, "Cannot execute more than %d commands from file \"%s\".\n", nLines, argv[2] ); break; } } // wait for all the threads to finish while ( 1 ) { assert(pthread_mutex_lock(&mutex) == 0); Counter = nThreadsRunning; assert(pthread_mutex_unlock(&mutex) == 0); if ( Counter == 0 ) break; } // cleanup assert(pthread_mutex_destroy(&mutex) == 0); // assert(mutex == NULL); fclose( pFile ); printf( "Finished processing commands in file \"%s\". ", argv[2] ); ABC_PRT( "Total time", clock() - clk ); return 0; usage: // skip the path name till the binary name for ( i = strlen(argv[0]) - 1; i > 0; i-- ) if ( argv[0][i-1] == '\\' || argv[0][i-1] == '/' ) break; // print usage message fprintf( pOutput, "usage: %s \n", argv[0]+i ); fprintf( pOutput, " executes command listed in in parallel on CPUs\n" ); fprintf( pOutput, "\n" ); return 1; } id='n94' href='#n94'>94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149