| rev |
line source |
|
seanhalle@0
|
1 /*
|
|
seanhalle@0
|
2 *
|
|
seanhalle@0
|
3 */
|
|
seanhalle@0
|
4 #include <stdio.h>
|
|
seanhalle@0
|
5 #include <stdlib.h>
|
|
seanhalle@0
|
6 #include <string.h>
|
|
seanhalle@0
|
7 #include <math.h>
|
|
seanhalle@0
|
8 #include <ctype.h>
|
|
seanhalle@0
|
9 #include <errno.h>
|
|
seanhalle@0
|
10 #include <pthread.h>
|
|
seanhalle@0
|
11 #include <sched.h>
|
|
seanhalle@0
|
12 #include <unistd.h>
|
|
seanhalle@0
|
13
|
|
seanhalle@0
|
14 #include <linux/perf_event.h>
|
|
seanhalle@0
|
15 #include <sys/syscall.h>
|
|
seanhalle@0
|
16
|
|
seanhalle@0
|
17 //==========================
|
|
seanhalle@0
|
18 //#define TURN_ON_DEBUG
|
|
seanhalle@0
|
19
|
|
seanhalle@0
|
20 //==========================
|
|
seanhalle@0
|
21 #define NUM_CORES 4
|
|
seanhalle@0
|
22
|
|
seanhalle@0
|
23 //==========================
|
|
seanhalle@0
|
24
|
|
seanhalle@0
|
25 //SELECT how the measurement is done
|
|
seanhalle@0
|
26 //only one must be enabled
|
|
seanhalle@0
|
27 #define MEASURE_TSC
|
|
seanhalle@0
|
28 //#define MEASURE_PERF
|
|
seanhalle@0
|
29
|
|
seanhalle@0
|
30
|
|
seanhalle@0
|
31 #if !defined(unix) && !defined(__unix__)
|
|
seanhalle@0
|
32 #ifdef __MACH__
|
|
seanhalle@0
|
33 #define unix 1
|
|
seanhalle@0
|
34 #define __unix__ 1
|
|
seanhalle@0
|
35 #endif /* __MACH__ */
|
|
seanhalle@0
|
36 #endif /* unix */
|
|
seanhalle@0
|
37
|
|
seanhalle@0
|
38 /* find the appropriate way to define explicitly sized types */
|
|
seanhalle@0
|
39 /* for C99 or GNU libc (also mach's libc) we can use stdint.h */
|
|
seanhalle@0
|
40 #if (__STDC_VERSION__ >= 199900) || defined(__GLIBC__) || defined(__MACH__)
|
|
seanhalle@0
|
41 #include <stdint.h>
|
|
seanhalle@0
|
42 #elif defined(unix) || defined(__unix__) /* some UNIX systems have them in sys/types.h */
|
|
seanhalle@0
|
43 #include <sys/types.h>
|
|
seanhalle@0
|
44 #elif defined(__WIN32__) || defined(WIN32) /* the nameless one */
|
|
seanhalle@0
|
45 typedef unsigned __int8 uint8_t;
|
|
seanhalle@0
|
46 typedef unsigned __int32 uint32_t;
|
|
seanhalle@0
|
47 #endif /* sized type detection */
|
|
seanhalle@0
|
48
|
|
seanhalle@0
|
49
|
|
seanhalle@0
|
50 //==================
|
|
seanhalle@0
|
51 #ifdef TURN_ON_DEBUG
|
|
seanhalle@0
|
52 #define DEBUG__printf(msg) printf(msg)
|
|
seanhalle@0
|
53 #define DEBUG__printf1(msg, arg1) printf(msg, arg1)
|
|
seanhalle@0
|
54 #define DEBUG__printf2(msg, arg1, arg2) printf(msg, arg1, arg2)
|
|
seanhalle@0
|
55 #else
|
|
seanhalle@0
|
56 #define DEBUG__printf(msg)
|
|
seanhalle@0
|
57 #define DEBUG__printf1(msg, arg1)
|
|
seanhalle@0
|
58 #define DEBUG__printf2(msg, arg1, arg2)
|
|
seanhalle@0
|
59 #endif
|
|
seanhalle@0
|
60 //===== RDTSC wrapper ===== //Does work for x86_64 compile
|
|
seanhalle@0
|
61
|
|
seanhalle@0
|
62 #define saveTimeStampCountInto(low, high) \
|
|
seanhalle@0
|
63 asm volatile("RDTSC; \
|
|
seanhalle@0
|
64 movl %%eax, %0; \
|
|
seanhalle@0
|
65 movl %%edx, %1;" \
|
|
seanhalle@0
|
66 /* outputs */ : "=m" (low), "=m" (high)\
|
|
seanhalle@0
|
67 /* inputs */ : \
|
|
seanhalle@0
|
68 /* clobber */ : "%eax", "%edx" \
|
|
seanhalle@0
|
69 );
|
|
seanhalle@0
|
70
|
|
seanhalle@0
|
71 #define saveLowTimeStampCountInto(low) \
|
|
seanhalle@0
|
72 asm volatile("RDTSC; \
|
|
seanhalle@0
|
73 movl %%eax, %0;" \
|
|
seanhalle@0
|
74 /* outputs */ : "=m" (low) \
|
|
seanhalle@0
|
75 /* inputs */ : \
|
|
seanhalle@0
|
76 /* clobber */ : "%eax", "%edx" \
|
|
seanhalle@0
|
77 );
|
|
seanhalle@0
|
78
|
|
seanhalle@0
|
79 //====================
|
|
seanhalle@0
|
80
|
|
seanhalle@0
|
81 union timeStamp
|
|
seanhalle@0
|
82 {
|
|
seanhalle@0
|
83 uint32_t lowHigh[2]; //lowHigh[0] is low, lowHigh[1] is high
|
|
seanhalle@0
|
84 uint64_t total;
|
|
seanhalle@0
|
85 };
|
|
seanhalle@0
|
86
|
|
seanhalle@0
|
87 struct perfData
|
|
seanhalle@0
|
88 {
|
|
seanhalle@0
|
89 uint64_t cycles;
|
|
seanhalle@0
|
90 uint64_t instructions;
|
|
seanhalle@0
|
91 };
|
|
seanhalle@0
|
92
|
|
seanhalle@0
|
93 //MEASURE_TSC should be mutually exclusive with MEASURE_PERF
|
|
seanhalle@0
|
94 #ifdef MEASURE_TSC
|
|
seanhalle@0
|
95 typedef union timeStamp MeasStruct;
|
|
seanhalle@0
|
96 #else
|
|
seanhalle@0
|
97 #ifdef MEASURE_PERF
|
|
seanhalle@0
|
98 typedef struct perfData MeasStruct;
|
|
seanhalle@0
|
99 #endif
|
|
seanhalle@0
|
100 #endif
|
|
seanhalle@0
|
101
|
|
seanhalle@0
|
102 //fast way to collect time intervals, by putting into hist right away
|
|
seanhalle@0
|
103 #define makeAMeasHist( idx, name, numBins, startVal, binWidth ) \
|
|
seanhalle@0
|
104 makeHighestDynArrayIndexBeAtLeast( _VMSMasterEnv->measHistsInfo, idx ); \
|
|
seanhalle@0
|
105 _VMSMasterEnv->measHists[idx] = \
|
|
seanhalle@0
|
106 makeFixedBinHist( numBins, startVal, binWidth, name );
|
|
seanhalle@0
|
107
|
|
seanhalle@0
|
108 //read and save current perf-counter readings for cycles and instrs
|
|
seanhalle@0
|
109 #ifdef MEASURE_PERF
|
|
seanhalle@0
|
110 #define takeAMeas(core, perfDataStruct) do{ \
|
|
seanhalle@0
|
111 int cycles_fd = cycles_counter_fd[core]; \
|
|
seanhalle@0
|
112 int nread; \
|
|
seanhalle@0
|
113 \
|
|
seanhalle@0
|
114 nread = read(cycles_fd,&(perfDataStruct.cycles),sizeof(perfDataStruct.cycles)); \
|
|
seanhalle@0
|
115 if(nread<0){ \
|
|
seanhalle@0
|
116 perror("Error reading cycles counter"); \
|
|
seanhalle@0
|
117 cycles = 0; \
|
|
seanhalle@0
|
118 } \
|
|
seanhalle@0
|
119 } while (0) //macro magic for scoping
|
|
seanhalle@0
|
120 #else
|
|
seanhalle@0
|
121 #define takeAMeas(core, timeStampStruct) do{ \
|
|
seanhalle@0
|
122 saveTimeStampCountInto(timeStampStruct.lowHigh[0], timeStampStruct.lowHigh[1]);\
|
|
seanhalle@0
|
123 } while (0) //macro magic for scoping
|
|
seanhalle@0
|
124 #endif
|
|
seanhalle@0
|
125
|
|
seanhalle@0
|
126
|
|
seanhalle@0
|
127 typedef struct
|
|
seanhalle@0
|
128 {
|
|
seanhalle@0
|
129 int coreID;
|
|
seanhalle@0
|
130 int numTuplesToCreate;
|
|
seanhalle@0
|
131 int producerID;
|
|
seanhalle@0
|
132
|
|
seanhalle@0
|
133 }
|
|
seanhalle@0
|
134 ProducerParams;
|
|
seanhalle@0
|
135
|
|
seanhalle@0
|
136 typedef struct
|
|
seanhalle@0
|
137 {
|
|
seanhalle@0
|
138 int coreID;
|
|
seanhalle@0
|
139 int numTuplesToCreate;
|
|
seanhalle@0
|
140 int numProducers;
|
|
seanhalle@0
|
141
|
|
seanhalle@0
|
142 }
|
|
seanhalle@0
|
143 ConsumerParams;
|
|
seanhalle@0
|
144
|
|
seanhalle@0
|
145 //=========== Global Vars =============
|
|
seanhalle@0
|
146 pthread_mutex_t tupleIterLock;
|
|
seanhalle@0
|
147 pthread_cond_t tupleIterCond;
|
|
seanhalle@0
|
148 int tupleIter;
|
|
seanhalle@0
|
149
|
|
seanhalle@0
|
150 pthread_mutex_t producerAccessMutex;
|
|
seanhalle@0
|
151 pthread_mutex_t productionReadyLock;
|
|
seanhalle@0
|
152 pthread_cond_t productionReadyCond;
|
|
seanhalle@0
|
153 int currProductionNum;
|
|
seanhalle@0
|
154 int producerMessage;
|
|
seanhalle@0
|
155
|
|
seanhalle@0
|
156 pthread_mutex_t consumerReceivedAckLock;
|
|
seanhalle@0
|
157 pthread_cond_t consumerReceivedAckCond;
|
|
seanhalle@0
|
158 int currConsumerReceivedACKNum;
|
|
seanhalle@0
|
159
|
|
seanhalle@0
|
160 //=======
|
|
seanhalle@0
|
161 void*
|
|
seanhalle@0
|
162 producer_birthFn( void* _params );
|
|
seanhalle@0
|
163 void*
|
|
seanhalle@0
|
164 consumer_birthFn( void* _params );
|
|
seanhalle@0
|
165
|
|
seanhalle@0
|
166
|