00001
00005 #include "system.h"
00006 #include <rpmsw.h>
00007 #include "debug.h"
00008
00009 #if defined(__LCLINT__)
00010
00011 extern int nanosleep(const struct timespec *__requested_time,
00012 struct timespec *__remaining)
00013
00014 ;
00015
00016 #endif
00017
00018
00019 static rpmtime_t rpmsw_overhead = 0;
00020
00021
00022 static rpmtime_t rpmsw_cycles = 1;
00023
00024
00025 static int rpmsw_type = 0;
00026
00027
00028 static int rpmsw_initialized = 0;
00029
00030 #if defined(__i386__)
00031
00032
00033 #define HP_TIMING_ZERO(Var) (Var) = (0)
00034 #define HP_TIMING_NOW(Var) __asm__ __volatile__ ("rdtsc" : "=A" (Var))
00035
00036
00037 #define HP_TIMING_DIFF(Diff, Start, End) (Diff) = ((End) - (Start))
00038
00039
00040 #define HP_TIMING_ACCUM(Sum, Diff) \
00041 do { \
00042 char __not_done; \
00043 hp_timing_t __oldval = (Sum); \
00044 hp_timing_t __diff = (Diff) - GL(dl_hp_timing_overhead); \
00045 do \
00046 { \
00047 hp_timing_t __newval = __oldval + __diff; \
00048 int __temp0, __temp1; \
00049 __asm__ __volatile__ ("xchgl %4, %%ebx\n\t" \
00050 "lock; cmpxchg8b %1\n\t" \
00051 "sete %0\n\t" \
00052 "movl %4, %%ebx" \
00053 : "=q" (__not_done), "=m" (Sum), \
00054 "=A" (__oldval), "=c" (__temp0), \
00055 "=SD" (__temp1) \
00056 : "1" (Sum), "2" (__oldval), \
00057 "3" (__newval >> 32), \
00058 "4" (__newval & 0xffffffff) \
00059 : "memory"); \
00060 } \
00061 while (__not_done); \
00062 } while (0)
00063
00064
00065 #define HP_TIMING_ACCUM_NT(Sum, Diff) (Sum) += (Diff)
00066
00067
00068 #define HP_TIMING_PRINT(Buf, Len, Val) \
00069 do { \
00070 char __buf[20]; \
00071 char *__cp = _itoa (Val, __buf + sizeof (__buf), 10, 0); \
00072 int __len = (Len); \
00073 char *__dest = (Buf); \
00074 while (__len-- > 0 && __cp < __buf + sizeof (__buf)) \
00075 *__dest++ = *__cp++; \
00076 memcpy (__dest, " clock cycles", MIN (__len, sizeof (" clock cycles"))); \
00077 } while (0)
00078 #endif
00079
00080 rpmsw rpmswNow(rpmsw sw)
00081 {
00082 if (!rpmsw_initialized)
00083 (void) rpmswInit();
00084 if (sw == NULL)
00085 return NULL;
00086 switch (rpmsw_type) {
00087 case 0:
00088 if (gettimeofday(&sw->u.tv, NULL))
00089 return NULL;
00090 break;
00091 #if defined(HP_TIMING_NOW)
00092 case 1:
00093 HP_TIMING_NOW(sw->u.ticks);
00094 break;
00095 #endif
00096 }
00097 return sw;
00098 }
00099
00106 static inline
00107 rpmtime_t tvsub( const struct timeval * etv,
00108 const struct timeval * btv)
00109
00110 {
00111 time_t secs, usecs;
00112 if (etv == NULL || btv == NULL) return 0;
00113 secs = etv->tv_sec - btv->tv_sec;
00114 for (usecs = etv->tv_usec - btv->tv_usec; usecs < 0; usecs += 1000000)
00115 secs--;
00116 return ((secs * 1000000) + usecs);
00117 }
00118
00119 rpmtime_t rpmswDiff(rpmsw end, rpmsw begin)
00120 {
00121 unsigned long long ticks = 0;
00122
00123 if (end == NULL || begin == NULL)
00124 return 0;
00125 switch (rpmsw_type) {
00126 default:
00127 case 0:
00128 ticks = tvsub(&end->u.tv, &begin->u.tv);
00129 break;
00130 #if defined(HP_TIMING_NOW)
00131 case 1:
00132 if (end->u.ticks > begin->u.ticks)
00133 HP_TIMING_DIFF(ticks, begin->u.ticks, end->u.ticks);
00134 break;
00135 #endif
00136 }
00137 if (ticks >= rpmsw_overhead)
00138 ticks -= rpmsw_overhead;
00139 if (rpmsw_cycles > 1)
00140 ticks /= rpmsw_cycles;
00141 return ticks;
00142 }
00143
00144 #if defined(HP_TIMING_NOW)
00145 static rpmtime_t rpmswCalibrate(void)
00146
00147
00148 {
00149 struct rpmsw_s begin, end;
00150 rpmtime_t ticks;
00151 struct timespec req, rem;
00152 int rc;
00153 int i;
00154
00155
00156 (void) rpmswNow(&begin);
00157
00158 req.tv_sec = 0;
00159 req.tv_nsec = 20 * 1000 * 1000;
00160 for (i = 0; i < 100; i++) {
00161 rc = nanosleep(&req, &rem);
00162 if (rc == 0)
00163 break;
00164 if (rem.tv_sec == 0 && rem.tv_nsec == 0)
00165 break;
00166 req = rem;
00167 }
00168
00169 ticks = rpmswDiff(rpmswNow(&end), &begin);
00170
00171
00172 return ticks;
00173 }
00174 #endif
00175
00176 rpmtime_t rpmswInit(void)
00177
00178
00179
00180
00181 {
00182 struct rpmsw_s begin, end;
00183 unsigned long long sum_cycles = 0;
00184 rpmtime_t sum_usecs = 0;
00185 rpmtime_t sum_overhead = 0;
00186 rpmtime_t cycles;
00187 int i;
00188
00189 rpmsw_initialized = 1;
00190
00191 rpmsw_overhead = 0;
00192 rpmsw_cycles = 0;
00193
00194
00195 for (i = 0; i < 3; i++) {
00196 #if defined(HP_TIMING_NOW)
00197 rpmtime_t save_cycles = rpmsw_cycles;
00198
00199
00200 rpmsw_cycles = 1;
00201
00202
00203 rpmsw_type = 0;
00204
00205 (void) rpmswNow(&begin);
00206
00207
00208
00209 rpmsw_type = 1;
00210 cycles = rpmswCalibrate();
00211 if (save_cycles > 0 && rpmsw_overhead > 0)
00212 cycles -= (save_cycles * rpmsw_overhead);
00213 sum_cycles += cycles;
00214
00215
00216 rpmsw_type = 0;
00217
00218 sum_usecs += rpmswDiff(rpmswNow(&end), &begin);
00219
00220 rpmsw_type = 1;
00221
00222
00223 rpmsw_cycles = sum_cycles/sum_usecs;
00224 #else
00225 rpmsw_type = 0;
00226 #endif
00227
00228
00229
00230 (void) rpmswNow(&begin);
00231 sum_overhead += rpmswDiff(rpmswNow(&end), &begin);
00232
00233
00234 rpmsw_overhead = sum_overhead/(i+1);
00235
00236 }
00237
00238 return rpmsw_overhead;
00239 }
00240
00241 int rpmswEnter(rpmop op, ssize_t rc)
00242 {
00243 if (op == NULL)
00244 return 0;
00245
00246 op->count++;
00247 if (rc < 0) {
00248 op->bytes = 0;
00249 op->usecs = 0;
00250 }
00251
00252 (void) rpmswNow(&op->begin);
00253
00254 return 0;
00255 }
00256
00257 rpmtime_t rpmswExit(rpmop op, ssize_t rc)
00258 {
00259 struct rpmsw_s end;
00260
00261 if (op == NULL)
00262 return 0;
00263
00264
00265 op->usecs += rpmswDiff(rpmswNow(&end), &op->begin);
00266
00267 if (rc > 0)
00268 op->bytes += rc;
00269 op->begin = end;
00270 return op->usecs;
00271 }
00272
00273 rpmtime_t rpmswAdd(rpmop to, rpmop from)
00274 {
00275 rpmtime_t usecs = 0;
00276 if (to != NULL && from != NULL) {
00277 to->count += from->count;
00278 to->bytes += from->bytes;
00279 to->usecs += from->usecs;
00280 usecs = to->usecs;
00281 }
00282 return usecs;
00283 }
00284
00285 rpmtime_t rpmswSub(rpmop to, rpmop from)
00286 {
00287 rpmtime_t usecs = 0;
00288 if (to != NULL && from != NULL) {
00289 to->count -= from->count;
00290 to->bytes -= from->bytes;
00291 to->usecs -= from->usecs;
00292 usecs = to->usecs;
00293 }
00294 return usecs;
00295 }