BTW, here is a nice clock_gettime() replacement that Jeremy wrote up:

<https://github.com/macports/macports-ports/blob/master/graphics/cogl/files/patch-clock_gettime.diff>


Thanks. That is a bit better than what I cooked up for xrootd. I might replace it ;)

Actually, I take that back. I am not convinced the implementation in the above link is giving results consistent with the method it is supposed to be provide. See the attached example test code...

test1 is the output from clock_gettime(CLOCK_REALTIME, &ts);, whether that be from the system ( 10.12+) or from the link above (older).

test2 is my own workaround.

One 10.12 I get

 > ./mac1013.exe
time1 1540311943653502000
time2 1540311943653580000
time1 1540311943653606000
time2 1540311943653619000

so the two give the same times (note time of course moves on between each call, but the two clearly agree).

on 10.9 though I get

 > ./mac109.exe
time1 1156992536990
time2 1540311478974454000
time1 1156992628574
time2 1540311478974495000

see how the values of time2 agree, but time1 (now from Jeremy's implementation) clearly has a completely different scale.

Not sure why, but for sure its not quite a drop in replacement...

Chris


#include <iostream>
#include <cstdint>

#include <sys/time.h>
#include <time.h>

#include <mach/clock.h>
#include <mach/mach.h>

static std::uint64_t kSecondsToNanos = 1000ULL * 1000ULL * 1000ULL;

#if __APPLE__ && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101200
#include <mach/mach_time.h>
#ifndef CLOCK_REALTIME
#define CLOCK_REALTIME 0
#define CLOCK_MONOTONIC 0
#endif
static int 
clock_gettime(int clk_id, struct timespec *t)
{
  mach_timebase_info_data_t timebase;
  mach_timebase_info(&timebase);
  const std::uint64_t time = mach_absolute_time();
  const double nseconds = ((double)time * (double)timebase.numer)/((double)timebase.denom);
  const double seconds  = ((double)time * (double)timebase.numer)/((double)timebase.denom * 1e9);
  t->tv_sec  = seconds;
  t->tv_nsec = nseconds;
  return 0;
}
#else
#include <time.h>
#endif

std::uint64_t time1()
{
  struct timespec ts;

  clock_gettime(CLOCK_REALTIME, &ts);

  return (static_cast<std::uint64_t>(ts.tv_sec) * kSecondsToNanos +
          static_cast<std::uint64_t>(ts.tv_nsec));
}

std::uint64_t time2()
{
  struct timespec ts;

  clock_serv_t cclock;
  mach_timespec_t mts;
  host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
  clock_get_time(cclock, &mts);
  mach_port_deallocate(mach_task_self(), cclock);
  ts.tv_sec  = mts.tv_sec;
  ts.tv_nsec = ( mts.tv_nsec / 1000 ) * 1000;
  
  return (static_cast<std::uint64_t>(ts.tv_sec) * kSecondsToNanos +
          static_cast<std::uint64_t>(ts.tv_nsec));
}

int main()
{
  
  int c(0);
  while ( ++c < 10 )
  {

    std::cout << "time1 " << time1() << std::endl;
    std::cout << "time2 " << time2() << std::endl;
    
//#ifdef CLOCK_REALTIME
    //std::cout << "time1 " << time1() << std::endl;
//#else
    //std::cout << "time2 " << time2() << std::endl;
//#endif
    
  }

  return 0;
}

Reply via email to