view src/Application/main.c @ 0:9cf9b2091eeb

working condition variable version
author Sean Halle <seanhalle@yahoo.com>
date Wed, 10 Jul 2013 14:13:46 -0700
parents
children 88db7b62b961
line source
1 /*
2 *
3 */
5 #include "main.h"
7 //========== Global Vars ===========
9 const char *usage =
10 {
11 "Usage: k_tuple_async [options]\n"
12 " Creates a number of workers, and one consumer that packages productions "
13 " into a tuple.\n\n"
14 "Options:\n"
15 " -p <num> The number of producer threads to create.\n"
16 " -t <num> the number of tuples to create\n"
17 " -h this help screen\n\n"
18 };
20 char __ProgrammName[] = "K-tuple_async";
21 char __DataSet[255];
23 #ifdef MEASURE_PERF
24 int cycles_counter_fd[NUM_CORES];
25 int instrs_counter_fd[NUM_CORES];
26 int cycles_counter_main_fd;
27 #endif
29 pthread_mutex_t waitForAllDoneLock;
30 pthread_cond_t waitForAllDoneCond;
33 //===================================
34 /* provide a millisecond-resolution timer for each system */
35 #if defined(unix) || defined(__unix__)
36 #include <time.h>
37 #include <sys/time.h>
38 unsigned long get_msec(void) {
39 static struct timeval timeval, first_timeval;
41 gettimeofday(&timeval, 0);
42 if(first_timeval.tv_sec == 0) {
43 first_timeval = timeval;
44 return 0;
45 }
46 return (timeval.tv_sec - first_timeval.tv_sec) * 1000 + (timeval.tv_usec - first_timeval.tv_usec) / 1000;
47 }
48 #elif defined(__WIN32__) || defined(WIN32)
49 #include <windows.h>
50 unsigned long get_msec(void) {
51 return GetTickCount();
52 }
53 #else
54 #error "I don't know how to measure time on your platform"
55 #endif
57 /*Initializes the performance counters, and opens the file descriptors used
58 * to read from the performance counters
59 */
60 void
61 set_up_performance_counters()
62 { int i;
64 #ifdef MEASURE_PERF
65 //setup performance counters
66 struct perf_event_attr hw_event;
67 memset(&hw_event,0,sizeof(hw_event));
68 hw_event.type = PERF_TYPE_HARDWARE;
69 hw_event.size = sizeof(hw_event);
70 hw_event.disabled = 0;
71 hw_event.freq = 0;
72 hw_event.inherit = 1; /* children inherit it */
73 hw_event.pinned = 1; /* must always be on PMU */
74 hw_event.exclusive = 0; /* only group on PMU */
75 hw_event.exclude_user = 0; /* don't count user */
76 hw_event.exclude_kernel = 1; /* ditto kernel */
77 hw_event.exclude_hv = 1; /* ditto hypervisor */
78 hw_event.exclude_idle = 1; /* don't count when idle */
79 hw_event.mmap = 0; /* include mmap data */
80 hw_event.comm = 0; /* include comm data */
83 for( i = 0; i < NUM_CORES; i++ )
84 {
85 hw_event.config = PERF_COUNT_HW_CPU_CYCLES; //cycles
86 cycles_counter_fd[i] = syscall(__NR_perf_event_open, &hw_event,
87 0,//pid_t pid,
88 i,//int cpu,
89 -1,//int group_fd,
90 0//unsigned long flags
91 );
92 if (cycles_counter_fd[i]<0){
93 fprintf(stderr,"On core %d: ",i);
94 perror("Failed to open cycles counter");
95 }
96 }
98 int cycles_counter_main_fd;
99 hw_event.config = PERF_COUNT_HW_CPU_CYCLES; //cycles
100 hw_event.exclude_kernel=0;
101 cycles_counter_main_fd = syscall(__NR_perf_event_open, &hw_event,
102 0,//pid_t pid,
103 -1,//int cpu,
104 -1,//int group_fd,
105 0//unsigned long flags
106 );
107 if (cycles_counter_main_fd<0){
108 perror("Failed to open main cycles counter");
109 }
111 #endif
112 }
115 void
116 init_stuff()
117 {
118 pthread_mutex_init(&tupleIterLock, NULL);
119 pthread_cond_init( &tupleIterCond, NULL );
120 tupleIter = 0;
122 pthread_mutex_init(&producerAccessMutex, NULL);
123 pthread_mutex_init(&productionReadyLock, NULL);
124 pthread_cond_init( &productionReadyCond, NULL );
125 currProductionNum = 0;
127 pthread_mutex_init(&consumerReceivedAckLock, NULL);
128 pthread_cond_init( &consumerReceivedAckCond, NULL );
129 currConsumerReceivedACKNum = 0;
130 }
133 typedef struct
134 {
135 int numProducers;
136 int numTuplesToCreate;
137 }
138 ParsedArgs;
140 /*The benchmark Fn creates the producers and the consumer, then gives the
141 * "go" signal. It measures time from go until the consumer produces the
142 * last tuple as output.
143 */
144 void
145 benchmark( ParsedArgs *args )
146 {
147 int i;
148 ProducerParams producerParams[args->numProducers];
149 pthread_t producerThds[args->numProducers];
150 pthread_t consumerThd;
152 ConsumerParams consumerParams;
154 //Set up the param structs for producers.. gives them the mutex and cond var
155 // to communicate with consumer
156 //Also the core the producer should pin its thread to
157 for(i=0; i < args->numProducers; i++)
158 {
159 producerParams[i].producerID = i + 1; //no ID of 0, a fact used in handshake
160 producerParams[i].numTuplesToCreate = args->numTuplesToCreate;
161 producerParams[i].coreID = i % NUM_CORES;
162 }
164 consumerParams.numProducers = args->numProducers;
165 consumerParams.numTuplesToCreate = args->numTuplesToCreate;
167 //take measurement before creation of threads, to get total exetime
168 MeasStruct benchStartMeas, benchEndMeas;
170 takeAMeas(0, benchStartMeas);
172 for(i=0; i < args->numProducers; i++)
173 { pthread_create( &producerThds[i], NULL, &producer_birthFn, (void*)&producerParams[i]);
174 }
176 pthread_create( &consumerThd, NULL, &consumer_birthFn, (void*)&consumerParams );
178 for(i=0; i<args->numProducers; i++)
179 { pthread_join( producerThds[i], NULL );
180 }
181 pthread_join( consumerThd, NULL );
183 //work is all done, so take a measurement snapshot at end
184 takeAMeas(0, benchEndMeas);
187 #ifdef MEASURE_PERF
188 uint64_t totalExeCycles = ( benchEndMeas.cycles - benchStartMeas.cycles);
189 printf("Total Execution: %lu\n", totalExeCycles);
190 #else
191 uint64_t totalExeCycles = ( benchEndMeas.total - benchStartMeas.total);
192 printf("Total Cycles of Execution: %lu\n", totalExeCycles);
193 #endif
195 //======================================================
196 }
199 /*This parsed the command line arguments and returns the values in a struct
200 * Command line args should be a '-' followed by a single letter, then a value
201 */
202 ParsedArgs *
203 parse_arguments( int argc, char **argv )
204 { ParsedArgs *parsedArgs;
205 int i;
207 parsedArgs = malloc(sizeof(ParsedArgs));
208 if(argc < 2)
209 { fprintf(stdout, "must give arguments");
210 fputs(usage, stdout);
211 return EXIT_FAILURE;
212 }
213 for( i=1; i < argc; i++ )
214 { if(argv[i][0] == '-' && argv[i][2] == 0)
215 { switch(argv[i][1])
216 { case 'p':
217 { if(!isdigit(argv[++i][0]))
218 { fprintf(stderr, "-p must be followed by the number of producer threads to spawn\n");
219 return EXIT_FAILURE;
220 }
221 parsedArgs->numProducers = atoi(argv[i]);
222 if( parsedArgs->numProducers == 0 )
223 { fprintf(stderr, "invalid number of producers specified: %d\n", parsedArgs->numProducers);
224 return EXIT_FAILURE;
225 }
226 else
227 { DEBUG__printf1("num producers: %d\n", parsedArgs->numProducers );
228 }
229 }
230 break;
231 case 't':
232 { if( !isdigit( argv[++i][0] ) )
233 { fputs("-t must be followed by a number\n", stderr);
234 return EXIT_FAILURE;
235 }
236 parsedArgs->numTuplesToCreate = atoi(argv[i]);
237 DEBUG__printf1("num tuples to produce: %d\n", parsedArgs->numTuplesToCreate );
238 }
239 break;
240 case 'h':
241 { fputs(usage, stdout);
242 return 0;
243 }
244 default:
245 { fprintf(stderr, "unrecognized argument: %s\n", argv[i]);
246 fputs(usage, stderr);
247 return EXIT_FAILURE;
248 }
249 }
250 }
251 else
252 { fprintf(stdout, "unrecognized argument: %s\n", argv[i]);
253 fputs(usage, stdout);
254 return EXIT_FAILURE;
255 }
256 }//for
257 return parsedArgs;
258 }
260 int main(int argc, char **argv)
261 { ParsedArgs *args;
262 int i;
265 set_up_performance_counters();
267 init_stuff();
269 args = parse_arguments( argc, argv);
271 if( args < 10 ) return args +1; //non-zero exit when parsing went wrong
273 benchmark( args );
275 return 0;
276 }