1 /**CFile****************************************************************
2 
3   FileName    [cmdStarter.c]
4 
5   SystemName  [ABC: Logic synthesis and verification system.]
6 
7   PackageName [Command processing package.]
8 
9   Synopsis    [Command to start many instances of ABC in parallel.]
10 
11   Author      [Alan Mishchenko]
12 
13   Affiliation [UC Berkeley]
14 
15   Date        [Ver. 1.0. Started - June 20, 2005.]
16 
17   Revision    [$Id: cmdStarter.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
18 
19 ***********************************************************************/
20 
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <assert.h>
25 #include "misc/util/abc_global.h"
26 #include "misc/extra/extra.h"
27 
28 #ifdef ABC_USE_PTHREADS
29 
30 #ifdef _WIN32
31 #include "../lib/pthread.h"
32 #else
33 #include <pthread.h>
34 #include <unistd.h>
35 #endif
36 
37 #endif
38 
39 ABC_NAMESPACE_IMPL_START
40 
41 ////////////////////////////////////////////////////////////////////////
42 ///                        DECLARATIONS                              ///
43 ////////////////////////////////////////////////////////////////////////
44 
45 #ifndef ABC_USE_PTHREADS
46 
Cmd_RunStarter(char * pFileName,char * pBinary,char * pCommand,int nCores)47 void Cmd_RunStarter( char * pFileName, char * pBinary, char * pCommand, int nCores ) {}
48 
49 #else // pthreads are used
50 
51 // the number of concurrently running threads
52 static volatile int nThreadsRunning = 0;
53 
54 // mutex to control access to the number of threads
55 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
56 
57 ////////////////////////////////////////////////////////////////////////
58 ///                     FUNCTION DEFINITIONS                         ///
59 ////////////////////////////////////////////////////////////////////////
60 
61 /**Function*************************************************************
62 
63   Synopsis    [This procedures executes one call to system().]
64 
65   Description []
66 
67   SideEffects []
68 
69   SeeAlso     []
70 
71 ***********************************************************************/
72 void * Abc_RunThread( void * pCommand )
73 {
74     int status;
75     // perform the call
76     if ( system( (char *)pCommand ) )
77     {
78         fprintf( stderr, "The following command has returned non-zero exit status:\n" );
79         fprintf( stderr, "\"%s\"\n\n", (char *)pCommand );
80         fflush( stdout );
81     }
82     free( pCommand );
83 
84     // decrement the number of threads runining
85     status = pthread_mutex_lock(&mutex);   assert(status == 0);
86     nThreadsRunning--;
87     status = pthread_mutex_unlock(&mutex); assert(status == 0);
88 
89     // quit this thread
90     //printf("...Finishing %s\n", (char *)Command);
91     pthread_exit( NULL );
92     assert(0);
93     return NULL;
94 }
95 
96 /**Function*************************************************************
97 
98   Synopsis    [Takes file with commands to be executed and the number of CPUs.]
99 
100   Description []
101 
102   SideEffects []
103 
104   SeeAlso     []
105 
106 ***********************************************************************/
107 void Cmd_RunStarter( char * pFileName, char * pBinary, char * pCommand, int nCores )
108 {
109     FILE * pFile, * pFileTemp;
110     pthread_t * pThreadIds;
111     char * BufferCopy, * Buffer;
112     int nLines, LineMax, Line, Len;
113     int i, c, status, Counter;
114     abctime clk = Abc_Clock();
115 
116     // check the number of cores
117     if ( nCores < 2 )
118     {
119         fprintf( stdout, "The number of cores (%d) should be more than 1.\n", nCores );
120         return;
121     }
122 
123     // open the file and make sure it is available
124     pFile = fopen( pFileName, "rb" );
125     if ( pFile == NULL )
126     {
127         fprintf( stdout, "Input file \"%s\" cannot be opened.\n", pFileName );
128         return;
129     }
130 
131     // count the number of lines and the longest line
132     nLines = LineMax = Line = 0;
133     while ( (c = fgetc(pFile)) != EOF )
134     {
135         Line++;
136         if ( c != '\n' )
137             continue;
138         nLines++;
139         LineMax = Abc_MaxInt( LineMax, Line );
140         Line = 0;
141     }
142     nLines += 10;
143     LineMax += LineMax + 100;
144     LineMax += pBinary  ? strlen(pBinary) : 0;
145     LineMax += pCommand ? strlen(pCommand) : 0;
146 
147     // allocate storage
148     Buffer = ABC_ALLOC( char, LineMax );
149     pThreadIds = ABC_ALLOC( pthread_t, nLines );
150 
151     // check if all files can be opened
152     if ( pCommand != NULL )
153     {
154         // read file names
155         rewind( pFile );
156         for ( i = 0; fgets( Buffer, LineMax, pFile ) != NULL; i++ )
157         {
158             // remove trailing spaces
159             for ( Len = strlen(Buffer) - 1; Len >= 0; Len-- )
160                 if ( Buffer[Len] == '\n' || Buffer[Len] == '\r' || Buffer[Len] == '\t' || Buffer[Len] == ' ' )
161                     Buffer[Len] = 0;
162                 else
163                     break;
164 
165             // get command from file
166             if ( Buffer[0] == 0 || Buffer[0] == '\n' || Buffer[0] == '\r' || Buffer[0] == '\t' || Buffer[0] == ' ' || Buffer[0] == '#' )
167                 continue;
168 
169             // try to open the file
170             pFileTemp = fopen( Buffer, "rb" );
171             if ( pFileTemp == NULL )
172             {
173                 fprintf( stdout, "Starter cannot open file \"%s\".\n", Buffer );
174                 fflush( stdout );
175                 ABC_FREE( pThreadIds );
176                 ABC_FREE( Buffer );
177                 fclose( pFile );
178                 return;
179             }
180             fclose( pFileTemp );
181         }
182     }
183 
184     // read commands and execute at most <num> of them at a time
185     rewind( pFile );
186     for ( i = 0; fgets( Buffer, LineMax, pFile ) != NULL; i++ )
187     {
188         // remove trailing spaces
189         for ( Len = strlen(Buffer) - 1; Len >= 0; Len-- )
190             if ( Buffer[Len] == '\n' || Buffer[Len] == '\r' || Buffer[Len] == '\t' || Buffer[Len] == ' ' )
191                 Buffer[Len] = 0;
192             else
193                 break;
194 
195         // get command from file
196         if ( Buffer[0] == 0 || Buffer[0] == '\n' || Buffer[0] == '\r' || Buffer[0] == '\t' || Buffer[0] == ' ' || Buffer[0] == '#' )
197             continue;
198 
199         // create command
200         if ( pCommand != NULL )
201         {
202             BufferCopy = ABC_ALLOC( char, LineMax );
203             sprintf( BufferCopy, "%s -c \"%s; %s\" > %s", pBinary, Buffer, pCommand, Extra_FileNameGenericAppend(Buffer, ".txt") );
204         }
205         else
206             BufferCopy = Abc_UtilStrsav( Buffer );
207         fprintf( stdout, "Calling:  %s\n", (char *)BufferCopy );
208         fflush( stdout );
209 
210         // wait till there is an empty thread
211         while ( 1 )
212         {
213             status = pthread_mutex_lock(&mutex);   assert(status == 0);
214             Counter = nThreadsRunning;
215             status = pthread_mutex_unlock(&mutex); assert(status == 0);
216             if ( Counter < nCores - 1 )
217                 break;
218 //            Sleep( 100 );
219         }
220 
221         // increament the number of threads running
222         status = pthread_mutex_lock(&mutex);   assert(status == 0);
223         nThreadsRunning++;
224         status = pthread_mutex_unlock(&mutex); assert(status == 0);
225 
226         // create thread to execute this command
227         status = pthread_create( &pThreadIds[i], NULL, Abc_RunThread, (void *)BufferCopy );  assert(status == 0);
228         assert( i < nLines );
229     }
230     ABC_FREE( pThreadIds );
231     ABC_FREE( Buffer );
232     fclose( pFile );
233 
234     // wait for all the threads to finish
235     while ( 1 )
236     {
237         status = pthread_mutex_lock(&mutex);   assert(status == 0);
238         Counter = nThreadsRunning;
239         status = pthread_mutex_unlock(&mutex); assert(status == 0);
240         if ( Counter == 0 )
241             break;
242     }
243 
244     // cleanup
245 //    status = pthread_mutex_destroy(&mutex);   assert(status == 0);
246 //    mutex = PTHREAD_MUTEX_INITIALIZER;
247     fprintf( stdout, "Finished processing commands in file \"%s\".  ", pFileName );
248     Abc_PrintTime( 1, "Total wall time", Abc_Clock() - clk );
249     fflush( stdout );
250 }
251 
252 #endif // pthreads are used
253 
254 ////////////////////////////////////////////////////////////////////////
255 ///                       END OF FILE                                ///
256 ////////////////////////////////////////////////////////////////////////
257 
258 
259 ABC_NAMESPACE_IMPL_END
260 
261