From fc574a7c61b129856bc1e5865fe560ff5befdda1 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Sat, 7 Jul 2012 20:37:16 -0700 Subject: Adding simple program for executing several instances of ABC in parallel. --- src/starter.c | 194 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 194 insertions(+) create mode 100644 src/starter.c (limited to 'src') diff --git a/src/starter.c b/src/starter.c new file mode 100644 index 00000000..ce86d62b --- /dev/null +++ b/src/starter.c @@ -0,0 +1,194 @@ +/**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 + +//ABC_NAMESPACE_IMPL_START + +// 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; + +} + +//ABC_NAMESPACE_IMPL_END + -- cgit v1.2.3