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