00001 #include "ace_pch.h"
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "ace/High_Res_Timer.h"
00012
00013 #if !defined (__ACE_INLINE__)
00014 #include "ace/High_Res_Timer.i"
00015 #endif
00016
00017 #include "ace/Stats.h"
00018
00019 ACE_RCSID(ace, High_Res_Timer, "$Id: High_Res_Timer.cpp,v 1.1.1.4.2.1 2003/03/13 19:44:21 chad Exp $")
00020
00021 ACE_ALLOC_HOOK_DEFINE(ACE_High_Res_Timer)
00022
00023
00024
00025
00026 #if (defined (ACE_WIN32) || defined (ACE_HAS_POWERPC_TIMER) || \
00027 defined (ACE_HAS_PENTIUM) || defined (ACE_HAS_ALPHA_TIMER)) && \
00028 !defined (ACE_HAS_HI_RES_TIMER)
00029
00030 # include "ace/Synch.h"
00031 # include "ace/Object_Manager.h"
00032
00033
00034
00035
00036
00037 ACE_UINT32 ACE_High_Res_Timer::global_scale_factor_ = 1u;
00038
00039 #else
00040
00041
00042
00043
00044
00045 ACE_UINT32 ACE_High_Res_Timer::global_scale_factor_ = 1000u;
00046 #endif
00047
00048
00049
00050
00051
00052
00053 int ACE_High_Res_Timer::global_scale_factor_status_ = 0;
00054
00055
00056 #if defined (linux)
00057
00058 ACE_UINT32
00059 ACE_High_Res_Timer::get_cpuinfo (void)
00060 {
00061 ACE_UINT32 scale_factor = 1u;
00062
00063
00064
00065
00066
00067
00068 #if !defined (__alpha__)
00069 int supported = 0;
00070 #endif
00071
00072 FILE *cpuinfo = ACE_OS::fopen ("/proc/cpuinfo", "r");
00073
00074 if (cpuinfo != 0)
00075 {
00076 ACE_TCHAR buf[128];
00077
00078
00079
00080 while (ACE_OS::fgets (buf, sizeof buf, cpuinfo))
00081 {
00082 #if defined (__alpha__)
00083 ACE_UINT32 whole;
00084 ACE_UINT32 fractional;
00085 if (::sscanf (buf,
00086 "BogoMIPS : %d.%d\n",
00087 &whole,
00088 &fractional) == 2
00089 || ::sscanf (buf,
00090 "bogomips : %d.%d\n",
00091 &whole,
00092 &fractional) == 2)
00093 {
00094 scale_factor = whole;
00095 break;
00096 }
00097 #else
00098 double mhertz = 1;
00099 double bmips = 1;
00100 ACE_TCHAR arg[128];
00101
00102
00103 if (::sscanf (buf, "cpu : %s\n", arg) == 1)
00104 {
00105
00106
00107 if (ACE_OS::strncmp (arg,
00108 "Alpha",
00109 5) == 0)
00110 {
00111 supported = 1;
00112
00113 }
00114 }
00115
00116 else if (supported == 0
00117 && ::sscanf (buf, "model name : Pentium %s\n", arg) == 1)
00118 {
00119
00120
00121 if (ACE_OS::strcmp (arg, "II") == 0
00122 || ACE_OS::strcmp (arg, "III") == 0
00123 || ACE_OS::strcmp (arg, "IV") == 0
00124 || ACE_OS::strcmp (arg, "Pro") == 0)
00125 {
00126 supported = 1;
00127
00128 }
00129 }
00130 else if (::sscanf (buf, "cpu MHz : %lf\n", &mhertz) == 1)
00131 {
00132
00133
00134
00135 scale_factor = (ACE_UINT32) (mhertz + 0.5);
00136 break;
00137 }
00138 else if (::sscanf (buf, "bogomips : %lf\n", &bmips) == 1
00139 || ::sscanf (buf, "BogoMIPS : %lf\n", &bmips) == 1)
00140 {
00141 if (supported)
00142 {
00143 scale_factor = (ACE_UINT32) (bmips + 0.5);
00144
00145 }
00146 #if 0
00147 else
00148 {
00149 ACE_DEBUG ((LM_DEBUG,
00150 ACE_LIB_TEXT ("\nThe BogoMIPS metric is not supported on this platform"
00151 "\n\tReport the results of the clock calibration and"
00152 "\n\tthe contents of /proc/cpuinfo to the ace-users mailing list")));
00153 }
00154 #endif
00155 break;
00156 }
00157 #endif
00158 }
00159
00160
00161
00162 ACE_OS::fclose (cpuinfo);
00163 }
00164
00165 return scale_factor;
00166 }
00167 #endif
00168
00169 ACE_UINT32
00170 ACE_High_Res_Timer::global_scale_factor (void)
00171 {
00172 #if (defined (ACE_WIN32) || defined (ACE_HAS_POWERPC_TIMER) || \
00173 defined (ACE_HAS_PENTIUM) || defined (ACE_HAS_ALPHA_TIMER)) && \
00174 !defined (ACE_HAS_HI_RES_TIMER) && \
00175 ((defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)) || \
00176 defined (ghs) || defined (__GNUG__) || defined (__KCC) || \
00177 defined (__INTEL_COMPILER))
00178
00179 if (ACE_High_Res_Timer::global_scale_factor_status_ == 0)
00180 {
00181
00182
00183 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
00184 *ACE_Static_Object_Lock::instance (), 0));
00185
00186
00187 if (ACE_High_Res_Timer::global_scale_factor_status_ == 0)
00188 {
00189 # if defined (ACE_WIN32)
00190 LARGE_INTEGER freq;
00191 if (::QueryPerformanceFrequency (&freq))
00192 {
00193
00194 # if defined (ACE_LACKS_LONGLONG_T)
00195 ACE_UINT64 uint64_freq(freq.u.LowPart, (ACE_UINT32) freq.u.HighPart);
00196 ACE_High_Res_Timer::global_scale_factor
00197 (uint64_freq / (ACE_UINT32) ACE_ONE_SECOND_IN_USECS);
00198 # else
00199 ACE_High_Res_Timer::global_scale_factor
00200 (ACE_static_cast (unsigned int,
00201 freq.QuadPart / ACE_HR_SCALE_CONVERSION));
00202 # endif // (ACE_LACKS_LONGLONG_T)
00203
00204 ACE_High_Res_Timer::global_scale_factor_status_ = 1;
00205 }
00206 else
00207
00208 ACE_High_Res_Timer::global_scale_factor_status_ = -1;
00209
00210 return ACE_High_Res_Timer::global_scale_factor_;
00211
00212 # elif defined (linux)
00213 ACE_High_Res_Timer::global_scale_factor (ACE_High_Res_Timer::get_cpuinfo ());
00214 # endif
00215
00216 # if !defined (ACE_WIN32)
00217 if (ACE_High_Res_Timer::global_scale_factor_ == 1u)
00218
00219 ACE_High_Res_Timer::calibrate ();
00220 # endif // (ACE_WIN32)
00221 }
00222 }
00223
00224 ACE_High_Res_Timer::global_scale_factor_status_ = 1;
00225 #endif
00226
00227
00228
00229
00230 return ACE_High_Res_Timer::global_scale_factor_;
00231 }
00232
00233 ACE_High_Res_Timer::ACE_High_Res_Timer (void)
00234 {
00235 ACE_TRACE ("ACE_High_Res_Timer::ACE_High_Res_Timer");
00236
00237 this->reset ();
00238
00239
00240 (void) global_scale_factor ();
00241 }
00242
00243 ACE_UINT32
00244 ACE_High_Res_Timer::calibrate (const ACE_UINT32 usec,
00245 const u_int iterations)
00246 {
00247 const ACE_Time_Value sleep_time (0, usec);
00248 ACE_Stats delta_hrtime;
00249
00250 ACE_Stats actual_sleeps;
00251
00252 for (u_int i = 0;
00253 i < iterations;
00254 ++i)
00255 {
00256 const ACE_Time_Value actual_start =
00257 ACE_OS::gettimeofday ();
00258 const ACE_hrtime_t start =
00259 ACE_OS::gethrtime ();
00260 ACE_OS::sleep (sleep_time);
00261 const ACE_hrtime_t stop =
00262 ACE_OS::gethrtime ();
00263 const ACE_Time_Value actual_delta =
00264 ACE_OS::gettimeofday () - actual_start;
00265
00266
00267 delta_hrtime.sample (ACE_U64_TO_U32 (stop - start));
00268 actual_sleeps.sample (actual_delta.msec () * 100u);
00269 }
00270
00271
00272
00273 ACE_Stats_Value ticks (0);
00274 delta_hrtime.mean (ticks);
00275
00276 ACE_Stats_Value actual_sleep (0);
00277 actual_sleeps.mean (actual_sleep);
00278
00279
00280 const ACE_UINT32 scale_factor =
00281 (ticks.whole () / actual_sleep.whole () + 5) /
00282 10u ;
00283 ACE_High_Res_Timer::global_scale_factor (scale_factor);
00284
00285 return scale_factor;
00286 }
00287
00288 void
00289 ACE_High_Res_Timer::dump (void) const
00290 {
00291 ACE_TRACE ("ACE_High_Res_Timer::dump");
00292
00293 ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
00294 ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nglobal_scale_factor_: %u\n"),
00295 global_scale_factor ()));
00296 #if defined (ACE_LACKS_LONGLONG_T)
00297 ACE_DEBUG ((LM_DEBUG,
00298 ACE_LIB_TEXT (":\nstart_.hi (): %8x; start_.lo (): %8x;\n")
00299 ACE_LIB_TEXT ("end_.hi (): %8x; end_.lo (): %8x;\n")
00300 ACE_LIB_TEXT ("total_.hi (): %8x; total_.lo (): %8x;\n")
00301 ACE_LIB_TEXT ("start_incr_.hi () %8x; start_incr_.lo (): %8x;\n"),
00302 start_.hi (), start_.lo (),
00303 end_.hi (), end_.lo (),
00304 total_.hi (), total_.lo (),
00305 start_incr_.hi (), start_incr_.lo ()));
00306 #else
00307 ACE_DEBUG ((LM_DEBUG,
00308 ACE_LIB_TEXT (":\nstart_.hi (): %8x; start_.lo (): %8x;\n")
00309 ACE_LIB_TEXT ("end_.hi (): %8x; end_.lo (): %8x;\n")
00310 ACE_LIB_TEXT ("total_.hi (): %8x; total_.lo (): %8x;\n")
00311 ACE_LIB_TEXT ("start_incr_.hi () %8x; start_incr_.lo (): %8x;\n"),
00312 ACE_CU64_TO_CU32 (start_ >> 32),
00313 ACE_CU64_TO_CU32 (start_ & 0xfffffffful),
00314 ACE_CU64_TO_CU32 (end_ >> 32),
00315 ACE_CU64_TO_CU32 (end_ & 0xfffffffful),
00316 ACE_CU64_TO_CU32 (total_ >> 32),
00317 ACE_CU64_TO_CU32 (total_ & 0xfffffffful),
00318 ACE_CU64_TO_CU32 (start_incr_ >> 32),
00319 ACE_CU64_TO_CU32 (start_incr_ & 0xfffffffful)));
00320 #endif
00321 ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
00322 }
00323
00324 void
00325 ACE_High_Res_Timer::reset (void)
00326 {
00327 ACE_TRACE ("ACE_High_Res_Timer::reset");
00328
00329 start_ = 0;
00330 end_ = 0;
00331 total_ = 0;
00332 start_incr_ = 0;
00333 }
00334
00335 void
00336 ACE_High_Res_Timer::elapsed_time (ACE_Time_Value &tv) const
00337 {
00338 hrtime_to_tv (tv, end_ - start_);
00339 }
00340
00341 #if defined (ACE_HAS_POSIX_TIME)
00342
00343
00344
00345 void
00346 ACE_High_Res_Timer::elapsed_time (struct timespec &elapsed_time) const
00347 {
00348
00349
00350
00351
00352
00353
00354
00355
00356 u_long nseconds = ACE_static_cast (u_long,
00357 (this->end_ - this->start_) %
00358 global_scale_factor () * 1000u /
00359 global_scale_factor ());
00360
00361
00362 ACE_UINT32 useconds = (ACE_UINT32) ((this->end_ - this->start_) / global_scale_factor ());
00363
00364 #if ! defined(ACE_HAS_BROKEN_TIMESPEC_MEMBERS)
00365 elapsed_time.tv_sec = (time_t) (useconds / ACE_ONE_SECOND_IN_USECS);
00366
00367 elapsed_time.tv_nsec = (time_t) ((useconds % ACE_ONE_SECOND_IN_USECS) * 1000u + nseconds);
00368 #else
00369 elapsed_time.ts_sec = (time_t) (useconds / ACE_ONE_SECOND_IN_USECS);
00370
00371 elapsed_time.ts_nsec = (time_t) ((useconds % ACE_ONE_SECOND_IN_USECS) * 1000u + nseconds);
00372 #endif
00373 }
00374 #endif
00375
00376 void
00377 ACE_High_Res_Timer::elapsed_time_incr (ACE_Time_Value &tv) const
00378 {
00379 hrtime_to_tv (tv, total_);
00380 }
00381
00382 void
00383 ACE_High_Res_Timer::elapsed_time (ACE_hrtime_t &nanoseconds) const
00384 {
00385
00386
00387
00388
00389 #if defined (ACE_WIN32)
00390 nanoseconds = (this->end_ - this->start_)
00391 * (1024000000u / ACE_High_Res_Timer::global_scale_factor());
00392 #else
00393 nanoseconds = (this->end_ - this->start_)
00394 * (1024000u / ACE_High_Res_Timer::global_scale_factor ());
00395 #endif
00396
00397 nanoseconds = nanoseconds >> 10;
00398
00399
00400 }
00401
00402 void
00403 ACE_High_Res_Timer::elapsed_time_incr (ACE_hrtime_t &nanoseconds) const
00404 {
00405
00406 #if defined (ACE_WIN32)
00407 nanoseconds = this->total_
00408 * (1024000000u / ACE_High_Res_Timer::global_scale_factor());
00409 #else
00410 nanoseconds = this->total_
00411 * (1024000u / ACE_High_Res_Timer::global_scale_factor ());
00412 #endif
00413
00414 nanoseconds = nanoseconds >> 10;
00415 }
00416
00417 #if !defined (ACE_HAS_WINCE)
00418 void
00419 ACE_High_Res_Timer::print_ave (const ACE_TCHAR *str,
00420 const int count,
00421 ACE_HANDLE handle) const
00422 {
00423 ACE_TRACE ("ACE_High_Res_Timer::print_ave");
00424
00425
00426 ACE_hrtime_t total_nanoseconds;
00427 this->elapsed_time (total_nanoseconds);
00428
00429
00430 u_long total_secs =
00431 ACE_static_cast (u_long,
00432 total_nanoseconds / (ACE_UINT32) ACE_ONE_SECOND_IN_NSECS);
00433 ACE_UINT32 extra_nsecs =
00434 ACE_static_cast (ACE_UINT32,
00435 total_nanoseconds % (ACE_UINT32) ACE_ONE_SECOND_IN_NSECS);
00436
00437 ACE_TCHAR buf[100];
00438 if (count > 1)
00439 {
00440 ACE_hrtime_t avg_nsecs = total_nanoseconds / (ACE_UINT32) count;
00441 ACE_OS::sprintf (buf,
00442 ACE_LIB_TEXT (" count = %d, total (secs %lu, usecs %u), avg usecs = %lu\n"),
00443 count,
00444 total_secs,
00445 (extra_nsecs + 500u) / 1000u,
00446 (u_long) ((avg_nsecs + 500u) / 1000u));
00447 }
00448 else
00449 ACE_OS::sprintf (buf,
00450 ACE_LIB_TEXT (" total %3lu.%06lu secs\n"),
00451 total_secs,
00452 (extra_nsecs + 500lu) / 1000lu);
00453
00454 ACE_OS::write (handle,
00455 str,
00456 ACE_OS::strlen (str));
00457 ACE_OS::write (handle,
00458 buf,
00459 ACE_OS::strlen (buf));
00460 }
00461
00462 void
00463 ACE_High_Res_Timer::print_total (const ACE_TCHAR *str,
00464 const int count,
00465 ACE_HANDLE handle) const
00466 {
00467 ACE_TRACE ("ACE_High_Res_Timer::print_total");
00468
00469
00470 ACE_hrtime_t total_nanoseconds;
00471 this->elapsed_time (total_nanoseconds);
00472
00473
00474 u_long total_secs =
00475 (u_long) (total_nanoseconds / (ACE_UINT32) ACE_ONE_SECOND_IN_NSECS);
00476 ACE_UINT32 extra_nsecs =
00477 (ACE_UINT32) (total_nanoseconds % (ACE_UINT32) ACE_ONE_SECOND_IN_NSECS);
00478
00479 ACE_TCHAR buf[100];
00480 if (count > 1)
00481 {
00482 ACE_hrtime_t avg_nsecs = this->total_ / (ACE_UINT32) count;
00483
00484 ACE_OS::sprintf (buf,
00485 ACE_LIB_TEXT (" count = %d, total (secs %lu, usecs %u), avg usecs = %lu\n"),
00486 count,
00487 total_secs,
00488 (extra_nsecs + 500u) / 1000u,
00489 (u_long) ((avg_nsecs + 500u) / 1000u));
00490 }
00491 else
00492 ACE_OS::sprintf (buf,
00493 ACE_LIB_TEXT (" total %3lu.%06u secs\n"),
00494 total_secs,
00495 (extra_nsecs + 500u) / 1000u);
00496
00497 ACE_OS::write (handle,
00498 str,
00499 ACE_OS::strlen (str));
00500 ACE_OS::write (handle,
00501 buf,
00502 ACE_OS::strlen (buf));
00503 }
00504 #endif
00505
00506 int
00507 ACE_High_Res_Timer::get_env_global_scale_factor (const ACE_TCHAR *env)
00508 {
00509 #if !defined (ACE_HAS_WINCE)
00510 if (env != 0)
00511 {
00512 const ACE_TCHAR *env_value = ACE_OS::getenv (env);
00513 if (env_value != 0)
00514 {
00515 int value = ACE_OS::atoi (env_value);
00516 if (value > 0)
00517 {
00518 ACE_High_Res_Timer::global_scale_factor (value);
00519 return 0;
00520 }
00521 }
00522 }
00523 #else
00524 ACE_UNUSED_ARG (env);
00525 #endif
00526 return -1;
00527 }