Patchwork Autodetect clock_gettime

login
register
mail settings
Submitter Tristan Gingold
Date March 15, 2011, 1:16 p.m.
Message ID <1300195001-51765-1-git-send-email-gingold@adacore.com>
Download mbox | patch
Permalink /patch/86981/
State New
Headers show

Comments

Tristan Gingold - March 15, 2011, 1:16 p.m.
Some POSIX OSes (such as Darwin) doesn't have clock_gettime.  This patch
falls back on gettimeofday if clock_gettime is not available.

Signed-off-by: Tristan Gingold <gingold@adacore.com>
---
 configure           |   11 ++++++++---
 qemu-thread-posix.c |   17 +++++++++++++++--
 2 files changed, 23 insertions(+), 5 deletions(-)
Paolo Bonzini - March 15, 2011, 1:34 p.m.
On 03/15/2011 02:16 PM, Tristan Gingold wrote:
> Some POSIX OSes (such as Darwin) doesn't have clock_gettime.  This patch
> falls back on gettimeofday if clock_gettime is not available.

This may be okay as a stopgap measure, but any sane porting target for 
QEMU should have a monotonic clock.  In fact, Darwin has it.

http://www.wand.net.nz/~smr26/wordpress/2009/01/19/monotonic-time-in-mac-os-x/ 
hints that code such as the following should work and return nanoseconds:

#import <mach/mach_time.h>

     uint64_t t = mach_absolute_time();
     static mach_timebase_info_data_t info;
     if (info.denom == 0) {
         mach_timebase_info(&info);
     }
     return muldiv64(t, info.numer, info.denom);

Paolo
Tristan Gingold - March 15, 2011, 1:47 p.m.
On Mar 15, 2011, at 2:34 PM, Paolo Bonzini wrote:

> On 03/15/2011 02:16 PM, Tristan Gingold wrote:
>> Some POSIX OSes (such as Darwin) doesn't have clock_gettime.  This patch
>> falls back on gettimeofday if clock_gettime is not available.
> 
> This may be okay as a stopgap measure, but any sane porting target for QEMU should have a monotonic clock.  In fact, Darwin has it.

Yes mach primitives could be used.  But why isn't a monotonic clock used on Linux ?  According to man, CLOCK_MONOTONIC is monotonic
while CLOCK_REALTIME isn't.

Tristan.
Paolo Bonzini - March 15, 2011, 1:58 p.m.
On 03/15/2011 02:47 PM, Tristan Gingold wrote:
>
> On Mar 15, 2011, at 2:34 PM, Paolo Bonzini wrote:
>
>> On 03/15/2011 02:16 PM, Tristan Gingold wrote:
>>> Some POSIX OSes (such as Darwin) doesn't have clock_gettime.  This patch
>>> falls back on gettimeofday if clock_gettime is not available.
>>
>> This may be okay as a stopgap measure, but any sane porting target for QEMU should have a monotonic clock.  In fact, Darwin has it.
>
> Yes mach primitives could be used.  But why isn't a monotonic clock used on Linux ?  According to man, CLOCK_MONOTONIC is monotonic
> while CLOCK_REALTIME isn't.

/me rereads the patch

Unfortunately, pthread timed wait/lock functions are documented to use 
the realtime clock by default.  Using pthread_condattr_setclock is 
probably not portable enough, and anyway there is no such function for 
mutexes so we're stuck with CLOCK_REALTIME.  What you're patching is 
fine, but those functions might actually go away soon as they're not 
supported on Win32.

So, in addition to what you've done, you should probably use those Mach 
primitives in qemu-timer.h.

Paolo
Tristan Gingold - March 15, 2011, 2:17 p.m.
On Mar 15, 2011, at 2:58 PM, Paolo Bonzini wrote:

> On 03/15/2011 02:47 PM, Tristan Gingold wrote:
>> 
>> On Mar 15, 2011, at 2:34 PM, Paolo Bonzini wrote:
>> 
>>> On 03/15/2011 02:16 PM, Tristan Gingold wrote:
>>>> Some POSIX OSes (such as Darwin) doesn't have clock_gettime.  This patch
>>>> falls back on gettimeofday if clock_gettime is not available.
>>> 
>>> This may be okay as a stopgap measure, but any sane porting target for QEMU should have a monotonic clock.  In fact, Darwin has it.
>> 
>> Yes mach primitives could be used.  But why isn't a monotonic clock used on Linux ?  According to man, CLOCK_MONOTONIC is monotonic
>> while CLOCK_REALTIME isn't.
> 
> /me rereads the patch
> 
> Unfortunately, pthread timed wait/lock functions are documented to use the realtime clock by default.  Using pthread_condattr_setclock is probably not portable enough, and anyway there is no such function for mutexes so we're stuck with CLOCK_REALTIME.  What you're patching is fine, but those functions might actually go away soon as they're not supported on Win32.

Fine.

> So, in addition to what you've done, you should probably use those Mach primitives in qemu-timer.h.

Yes.  But note that the first aim of this patch is to make qemu compiling again on Darwin.

Tristan.

Patch

diff --git a/configure b/configure
index c18f571..6e6cd35 100755
--- a/configure
+++ b/configure
@@ -2236,17 +2236,18 @@  if compile_prog "" "" ; then
 fi
 
 ##########################################
-# Do we need librt
+# Do we need clock_gettime + librt
+clock_gettime=no
 cat > $TMPC <<EOF
-#include <signal.h>
 #include <time.h>
 int main(void) { clockid_t id; return clock_gettime(id, NULL); }
 EOF
 
 if compile_prog "" "" ; then
-  :
+  clock_gettime=yes
 elif compile_prog "" "-lrt" ; then
   LIBS="-lrt $LIBS"
+  clock_gettime=yes
 fi
 
 if test "$darwin" != "yes" -a "$mingw32" != "yes" -a "$solaris" != yes -a \
@@ -2530,6 +2531,7 @@  echo "preadv support    $preadv"
 echo "fdatasync         $fdatasync"
 echo "madvise           $madvise"
 echo "posix_madvise     $posix_madvise"
+echo "clock_gettime     $clock_gettime"
 echo "uuid support      $uuid"
 echo "vhost-net support $vhost_net"
 echo "Trace backend     $trace_backend"
@@ -2679,6 +2681,9 @@  fi
 if test "$fnmatch" = "yes" ; then
   echo "CONFIG_FNMATCH=y" >> $config_host_mak
 fi
+if test "$clock_gettime" = "yes" ; then
+  echo "CONFIG_CLOCK_GETTIME=y" >> $config_host_mak
+fi
 if test "$uuid" = "yes" ; then
   echo "CONFIG_UUID=y" >> $config_host_mak
 fi
diff --git a/qemu-thread-posix.c b/qemu-thread-posix.c
index 87c1a9f..dbe14c3 100644
--- a/qemu-thread-posix.c
+++ b/qemu-thread-posix.c
@@ -61,6 +61,19 @@  int qemu_mutex_trylock(QemuMutex *mutex)
     return pthread_mutex_trylock(&mutex->lock);
 }
 
+static void qemu_gettime(struct timespec *ts)
+{
+#ifdef CONFIG_CLOCK_GETTIME
+    clock_gettime(CLOCK_REALTIME, ts);
+#else
+    struct timeval tv;
+
+    gettimeofday(&tv, NULL);
+    ts->tv_sec = tv.tv_sec;
+    ts->tv_nsec = tv.tv_usec * 1000;
+#endif
+}
+
 static void timespec_add_ms(struct timespec *ts, uint64_t msecs)
 {
     ts->tv_sec = ts->tv_sec + (long)(msecs / 1000);
@@ -76,7 +89,7 @@  int qemu_mutex_timedlock(QemuMutex *mutex, uint64_t msecs)
     int err;
     struct timespec ts;
 
-    clock_gettime(CLOCK_REALTIME, &ts);
+    qemu_gettime(&ts);
     timespec_add_ms(&ts, msecs);
 
     err = pthread_mutex_timedlock(&mutex->lock, &ts);
@@ -144,7 +157,7 @@  int qemu_cond_timedwait(QemuCond *cond, QemuMutex *mutex, uint64_t msecs)
     struct timespec ts;
     int err;
 
-    clock_gettime(CLOCK_REALTIME, &ts);
+    qemu_gettime(&ts);
     timespec_add_ms(&ts, msecs);
 
     err = pthread_cond_timedwait(&cond->cond, &mutex->lock, &ts);