seanhalle@0: /* seanhalle@0: * seanhalle@0: */ seanhalle@0: #include seanhalle@0: #include seanhalle@0: #include seanhalle@0: #include seanhalle@0: #include seanhalle@0: #include seanhalle@0: #include seanhalle@0: #include seanhalle@0: #include seanhalle@0: seanhalle@0: #include seanhalle@0: #include seanhalle@0: seanhalle@0: //========================== seanhalle@0: //#define TURN_ON_DEBUG seanhalle@0: seanhalle@0: //========================== seanhalle@0: #define NUM_CORES 4 seanhalle@0: seanhalle@0: //========================== seanhalle@0: seanhalle@0: //SELECT how the measurement is done seanhalle@0: //only one must be enabled seanhalle@0: #define MEASURE_TSC seanhalle@0: //#define MEASURE_PERF seanhalle@0: seanhalle@0: seanhalle@0: #if !defined(unix) && !defined(__unix__) seanhalle@0: #ifdef __MACH__ seanhalle@0: #define unix 1 seanhalle@0: #define __unix__ 1 seanhalle@0: #endif /* __MACH__ */ seanhalle@0: #endif /* unix */ seanhalle@0: seanhalle@0: /* find the appropriate way to define explicitly sized types */ seanhalle@0: /* for C99 or GNU libc (also mach's libc) we can use stdint.h */ seanhalle@0: #if (__STDC_VERSION__ >= 199900) || defined(__GLIBC__) || defined(__MACH__) seanhalle@0: #include seanhalle@0: #elif defined(unix) || defined(__unix__) /* some UNIX systems have them in sys/types.h */ seanhalle@0: #include seanhalle@0: #elif defined(__WIN32__) || defined(WIN32) /* the nameless one */ seanhalle@0: typedef unsigned __int8 uint8_t; seanhalle@0: typedef unsigned __int32 uint32_t; seanhalle@0: #endif /* sized type detection */ seanhalle@0: seanhalle@0: seanhalle@0: //================== seanhalle@0: #ifdef TURN_ON_DEBUG seanhalle@0: #define DEBUG__printf(msg) printf(msg) seanhalle@0: #define DEBUG__printf1(msg, arg1) printf(msg, arg1) seanhalle@0: #define DEBUG__printf2(msg, arg1, arg2) printf(msg, arg1, arg2) seanhalle@0: #else seanhalle@0: #define DEBUG__printf(msg) seanhalle@0: #define DEBUG__printf1(msg, arg1) seanhalle@0: #define DEBUG__printf2(msg, arg1, arg2) seanhalle@0: #endif seanhalle@0: //===== RDTSC wrapper ===== //Does work for x86_64 compile seanhalle@0: seanhalle@0: #define saveTimeStampCountInto(low, high) \ seanhalle@0: asm volatile("RDTSC; \ seanhalle@0: movl %%eax, %0; \ seanhalle@0: movl %%edx, %1;" \ seanhalle@0: /* outputs */ : "=m" (low), "=m" (high)\ seanhalle@0: /* inputs */ : \ seanhalle@0: /* clobber */ : "%eax", "%edx" \ seanhalle@0: ); seanhalle@0: seanhalle@0: #define saveLowTimeStampCountInto(low) \ seanhalle@0: asm volatile("RDTSC; \ seanhalle@0: movl %%eax, %0;" \ seanhalle@0: /* outputs */ : "=m" (low) \ seanhalle@0: /* inputs */ : \ seanhalle@0: /* clobber */ : "%eax", "%edx" \ seanhalle@0: ); seanhalle@0: seanhalle@0: //==================== seanhalle@0: seanhalle@0: union timeStamp seanhalle@0: { seanhalle@0: uint32_t lowHigh[2]; //lowHigh[0] is low, lowHigh[1] is high seanhalle@0: uint64_t total; seanhalle@0: }; seanhalle@0: seanhalle@0: struct perfData seanhalle@0: { seanhalle@0: uint64_t cycles; seanhalle@0: uint64_t instructions; seanhalle@0: }; seanhalle@0: seanhalle@0: //MEASURE_TSC should be mutually exclusive with MEASURE_PERF seanhalle@0: #ifdef MEASURE_TSC seanhalle@0: typedef union timeStamp MeasStruct; seanhalle@0: #else seanhalle@0: #ifdef MEASURE_PERF seanhalle@0: typedef struct perfData MeasStruct; seanhalle@0: #endif seanhalle@0: #endif seanhalle@0: seanhalle@0: //fast way to collect time intervals, by putting into hist right away seanhalle@0: #define makeAMeasHist( idx, name, numBins, startVal, binWidth ) \ seanhalle@0: makeHighestDynArrayIndexBeAtLeast( _VMSMasterEnv->measHistsInfo, idx ); \ seanhalle@0: _VMSMasterEnv->measHists[idx] = \ seanhalle@0: makeFixedBinHist( numBins, startVal, binWidth, name ); seanhalle@0: seanhalle@0: //read and save current perf-counter readings for cycles and instrs seanhalle@0: #ifdef MEASURE_PERF seanhalle@0: #define takeAMeas(core, perfDataStruct) do{ \ seanhalle@0: int cycles_fd = cycles_counter_fd[core]; \ seanhalle@0: int nread; \ seanhalle@0: \ seanhalle@0: nread = read(cycles_fd,&(perfDataStruct.cycles),sizeof(perfDataStruct.cycles)); \ seanhalle@0: if(nread<0){ \ seanhalle@0: perror("Error reading cycles counter"); \ seanhalle@0: cycles = 0; \ seanhalle@0: } \ seanhalle@0: } while (0) //macro magic for scoping seanhalle@0: #else seanhalle@0: #define takeAMeas(core, timeStampStruct) do{ \ seanhalle@0: saveTimeStampCountInto(timeStampStruct.lowHigh[0], timeStampStruct.lowHigh[1]);\ seanhalle@0: } while (0) //macro magic for scoping seanhalle@0: #endif seanhalle@0: seanhalle@0: seanhalle@0: typedef struct seanhalle@0: { seanhalle@0: int coreID; seanhalle@0: int numTuplesToCreate; seanhalle@0: int producerID; seanhalle@0: seanhalle@0: } seanhalle@0: ProducerParams; seanhalle@0: seanhalle@0: typedef struct seanhalle@0: { seanhalle@0: int coreID; seanhalle@0: int numTuplesToCreate; seanhalle@0: int numProducers; seanhalle@0: seanhalle@0: } seanhalle@0: ConsumerParams; seanhalle@0: seanhalle@0: //=========== Global Vars ============= seanhalle@0: pthread_mutex_t tupleIterLock; seanhalle@0: pthread_cond_t tupleIterCond; seanhalle@0: int tupleIter; seanhalle@0: seanhalle@0: pthread_mutex_t producerAccessMutex; seanhalle@0: pthread_mutex_t productionReadyLock; seanhalle@0: pthread_cond_t productionReadyCond; seanhalle@0: int currProductionNum; seanhalle@0: int producerMessage; seanhalle@0: seanhalle@0: pthread_mutex_t consumerReceivedAckLock; seanhalle@0: pthread_cond_t consumerReceivedAckCond; seanhalle@0: int currConsumerReceivedACKNum; seanhalle@0: seanhalle@0: //======= seanhalle@0: void* seanhalle@0: producer_birthFn( void* _params ); seanhalle@0: void* seanhalle@0: consumer_birthFn( void* _params ); seanhalle@0: seanhalle@0: