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