uptime.cpp 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. #include "uptime.h"
  2. #if defined(_win_)
  3. #include <util/system/winint.h>
  4. #elif defined(_linux_)
  5. #include <util/stream/file.h>
  6. #include <util/string/cast.h>
  7. #elif defined(_darwin_)
  8. #include <sys/sysctl.h>
  9. #endif
  10. #if defined(_darwin_)
  11. namespace {
  12. TInstant GetBootTime() {
  13. struct timeval timeSinceBoot;
  14. size_t len = sizeof(timeSinceBoot);
  15. int request[2] = {CTL_KERN, KERN_BOOTTIME};
  16. if (sysctl(request, 2, &timeSinceBoot, &len, nullptr, 0) < 0) {
  17. ythrow yexception() << "cannot get kern.boottime from sysctl";
  18. }
  19. return TInstant::MicroSeconds(timeSinceBoot.tv_sec * 1'000'000 + timeSinceBoot.tv_usec);
  20. }
  21. TDuration GetDarwinUptime() {
  22. TInstant beforeNow;
  23. TInstant afterNow;
  24. TInstant now;
  25. // avoid race when NTP changes machine time between getting Now() and uptime
  26. afterNow = GetBootTime();
  27. do {
  28. beforeNow = afterNow;
  29. now = Now();
  30. afterNow = GetBootTime();
  31. } while (afterNow != beforeNow);
  32. return now - beforeNow;
  33. }
  34. }
  35. #endif // _darwin_
  36. TDuration Uptime() {
  37. #if defined(_win_)
  38. return TDuration::MilliSeconds(GetTickCount64());
  39. #elif defined(_linux_)
  40. TUnbufferedFileInput in("/proc/uptime");
  41. TString uptimeStr = in.ReadLine();
  42. double up, idle;
  43. if (sscanf(uptimeStr.data(), "%lf %lf", &up, &idle) < 2) {
  44. ythrow yexception() << "cannot read values from /proc/uptime";
  45. }
  46. return TDuration::MilliSeconds(up * 1000.0);
  47. #elif defined(_darwin_)
  48. return GetDarwinUptime();
  49. #endif
  50. }