blob: 47cdd9edcd1f26b37b80daa93d4d2cba547f406d [file] [log] [blame]
/**CFile****************************************************************
FileName [cmdStarter.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Command processing package.]
Synopsis [Command to start many instances of ABC in parallel.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: cmdStarter.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "misc/util/abc_global.h"
#include "misc/extra/extra.h"
#ifdef ABC_USE_PTHREADS
#ifdef _WIN32
#include "../lib/pthread.h"
#else
#include <pthread.h>
#include <unistd.h>
#endif
#endif
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
#ifndef ABC_USE_PTHREADS
void Cmd_RunStarter( char * pFileName, char * pBinary, char * pCommand, int nCores ) {}
#else // pthreads are used
// the number of concurrently running threads
static volatile int nThreadsRunning = 0;
// mutex to control access to the number of threads
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [This procedures executes one call to system().]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void * Abc_RunThread( void * pCommand )
{
int status;
// perform the call
if ( system( (char *)pCommand ) )
{
fprintf( stderr, "The following command has returned non-zero exit status:\n" );
fprintf( stderr, "\"%s\"\n\n", (char *)pCommand );
fflush( stdout );
}
free( pCommand );
// decrement the number of threads runining
status = pthread_mutex_lock(&mutex); assert(status == 0);
nThreadsRunning--;
status = pthread_mutex_unlock(&mutex); assert(status == 0);
// quit this thread
//printf("...Finishing %s\n", (char *)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 []
***********************************************************************/
void Cmd_RunStarter( char * pFileName, char * pBinary, char * pCommand, int nCores )
{
FILE * pFile, * pFileTemp;
pthread_t * pThreadIds;
char * BufferCopy, * Buffer;
int nLines, LineMax, Line, Len;
int i, c, status, Counter;
abctime clk = Abc_Clock();
// check the number of cores
if ( nCores < 2 )
{
fprintf( stdout, "The number of cores (%d) should be more than 1.\n", nCores );
return;
}
// open the file and make sure it is available
pFile = fopen( pFileName, "rb" );
if ( pFile == NULL )
{
fprintf( stdout, "Input file \"%s\" cannot be opened.\n", pFileName );
return;
}
// count the number of lines and the longest line
nLines = LineMax = Line = 0;
while ( (c = fgetc(pFile)) != EOF )
{
Line++;
if ( c != '\n' )
continue;
nLines++;
LineMax = Abc_MaxInt( LineMax, Line );
Line = 0;
}
nLines += 10;
LineMax += LineMax + 100;
LineMax += pBinary ? strlen(pBinary) : 0;
LineMax += pCommand ? strlen(pCommand) : 0;
// allocate storage
Buffer = ABC_ALLOC( char, LineMax );
pThreadIds = ABC_ALLOC( pthread_t, nLines );
// check if all files can be opened
if ( pCommand != NULL )
{
// read file names
rewind( pFile );
for ( i = 0; fgets( Buffer, LineMax, pFile ) != NULL; i++ )
{
// remove trailing spaces
for ( Len = strlen(Buffer) - 1; Len >= 0; Len-- )
if ( Buffer[Len] == '\n' || Buffer[Len] == '\r' || Buffer[Len] == '\t' || Buffer[Len] == ' ' )
Buffer[Len] = 0;
else
break;
// get command from file
if ( Buffer[0] == 0 || Buffer[0] == '\n' || Buffer[0] == '\r' || Buffer[0] == '\t' || Buffer[0] == ' ' || Buffer[0] == '#' )
continue;
// try to open the file
pFileTemp = fopen( Buffer, "rb" );
if ( pFileTemp == NULL )
{
fprintf( stdout, "Starter cannot open file \"%s\".\n", Buffer );
fflush( stdout );
ABC_FREE( pThreadIds );
ABC_FREE( Buffer );
fclose( pFile );
return;
}
}
}
// read commands and execute at most <num> of them at a time
rewind( pFile );
for ( i = 0; fgets( Buffer, LineMax, pFile ) != NULL; i++ )
{
// remove trailing spaces
for ( Len = strlen(Buffer) - 1; Len >= 0; Len-- )
if ( Buffer[Len] == '\n' || Buffer[Len] == '\r' || Buffer[Len] == '\t' || Buffer[Len] == ' ' )
Buffer[Len] = 0;
else
break;
// get command from file
if ( Buffer[0] == 0 || Buffer[0] == '\n' || Buffer[0] == '\r' || Buffer[0] == '\t' || Buffer[0] == ' ' || Buffer[0] == '#' )
continue;
// create command
if ( pCommand != NULL )
{
BufferCopy = ABC_ALLOC( char, LineMax );
sprintf( BufferCopy, "%s -c \"%s; %s\" > %s", pBinary, Buffer, pCommand, Extra_FileNameGenericAppend(Buffer, ".txt") );
}
else
BufferCopy = Abc_UtilStrsav( Buffer );
fprintf( stdout, "Calling: %s\n", (char *)BufferCopy );
fflush( stdout );
// wait till there is an empty thread
while ( 1 )
{
status = pthread_mutex_lock(&mutex); assert(status == 0);
Counter = nThreadsRunning;
status = pthread_mutex_unlock(&mutex); assert(status == 0);
if ( Counter < nCores - 1 )
break;
// Sleep( 100 );
}
// increament the number of threads running
status = pthread_mutex_lock(&mutex); assert(status == 0);
nThreadsRunning++;
status = pthread_mutex_unlock(&mutex); assert(status == 0);
// create thread to execute this command
status = pthread_create( &pThreadIds[i], NULL, Abc_RunThread, (void *)BufferCopy ); assert(status == 0);
assert( i < nLines );
}
ABC_FREE( pThreadIds );
ABC_FREE( Buffer );
fclose( pFile );
// wait for all the threads to finish
while ( 1 )
{
status = pthread_mutex_lock(&mutex); assert(status == 0);
Counter = nThreadsRunning;
status = pthread_mutex_unlock(&mutex); assert(status == 0);
if ( Counter == 0 )
break;
}
// cleanup
// status = pthread_mutex_destroy(&mutex); assert(status == 0);
// mutex = PTHREAD_MUTEX_INITIALIZER;
fprintf( stdout, "Finished processing commands in file \"%s\". ", pFileName );
Abc_PrintTime( 1, "Total wall time", Abc_Clock() - clk );
fflush( stdout );
}
#endif // pthreads are used
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END