Bug 757593: Make PR_IntervalNow monotonic for Android, Linux, Mac OS X, and
authorwtc%google.com
Wed, 24 Oct 2012 22:33:36 +0000
changeset 4421 13eb3a1cdc270a82a4e9d4fafc87c78168b62d55
parent 4420 38ad147364380195d823b59cc9a313fecf3eeb5e
child 4422 39f3d1ab7a88a15187af5da7dafb0c464c19cf65
push idunknown
push userunknown
push dateunknown
bugs757593
Bug 757593: Make PR_IntervalNow monotonic for Android, Linux, Mac OS X, and iOS. r=bsmith. Modified Files: _aix.h _bsdi.h _darwin.h _dgux.h _freebsd.h _hpux.h _linux.h _netbsd.h _nto.h _openbsd.h _osf1.h _qnx.h _riscos.h _scoos.h _symbian.h _unixos.h _unixware.h pr/src/Makefile.in darwin.c unix.c prinrval.c
pr/include/md/_aix.h
pr/include/md/_bsdi.h
pr/include/md/_darwin.h
pr/include/md/_dgux.h
pr/include/md/_freebsd.h
pr/include/md/_hpux.h
pr/include/md/_linux.h
pr/include/md/_netbsd.h
pr/include/md/_nto.h
pr/include/md/_openbsd.h
pr/include/md/_osf1.h
pr/include/md/_qnx.h
pr/include/md/_riscos.h
pr/include/md/_scoos.h
pr/include/md/_symbian.h
pr/include/md/_unixos.h
pr/include/md/_unixware.h
pr/src/Makefile.in
pr/src/md/unix/darwin.c
pr/src/md/unix/unix.c
pr/src/misc/prinrval.c
--- a/pr/include/md/_aix.h
+++ b/pr/include/md/_aix.h
@@ -50,25 +50,26 @@
 #endif
 #endif
 #define _PR_HAVE_SYSV_SEMAPHORES
 #define PR_HAVE_SYSV_NAMED_SHARED_MEMORY
 #define _PR_ACCEPT_INHERIT_NONBLOCK
 
 /* Timer operations */
 #if defined(AIX_TIMERS)
+#define _MD_INTERVAL_INIT()
+
 extern PRIntervalTime _MD_AixGetInterval(void);
 #define _MD_GET_INTERVAL _MD_AixGetInterval
 
 extern PRIntervalTime _MD_AixIntervalPerSec(void);
 #define _MD_INTERVAL_PER_SEC _MD_AixIntervalPerSec
 
 #else  /* defined(AIX_TIMERS) */
-#define _MD_GET_INTERVAL        _PR_UNIX_GetInterval
-#define _MD_INTERVAL_PER_SEC    _PR_UNIX_TicksPerSecond
+#define _MD_INTERVAL_USE_GTOD
 #endif  /* defined(AIX_TIMERS) */
 
 #ifdef AIX_HAVE_ATOMIC_OP_H
 /* The atomic operations */
 #include <sys/atomic_op.h>
 #define _PR_HAVE_ATOMIC_OPS
 #ifndef IS_64
 #define _PR_HAVE_ATOMIC_CAS
--- a/pr/include/md/_bsdi.h
+++ b/pr/include/md/_bsdi.h
@@ -171,12 +171,11 @@ struct _MDCPU {
 #endif /* ! _PR_PTHREADS */
 
 #define _MD_EARLY_INIT          _MD_EarlyInit
 #define _MD_FINAL_INIT			_PR_UnixInit
 
 #include <sys/syscall.h>
 #define _MD_SELECT(nfds,r,w,e,tv) syscall(SYS_select,nfds,r,w,e,tv)
 
-#define _MD_GET_INTERVAL                  _PR_UNIX_GetInterval
-#define _MD_INTERVAL_PER_SEC              _PR_UNIX_TicksPerSecond
+#define _MD_INTERVAL_USE_GTOD
 
 #endif /* nspr_bsdi_defs_h___ */
--- a/pr/include/md/_darwin.h
+++ b/pr/include/md/_darwin.h
@@ -275,22 +275,24 @@ extern void _MD_SET_PRIORITY(struct _MDT
 extern PRStatus _MD_WAIT(PRThread *, PRIntervalTime timeout);
 extern PRStatus _MD_WAKEUP_WAITER(PRThread *);
 extern void _MD_YIELD(void);
 
 #endif /* ! _PR_PTHREADS */
 
 #define _MD_EARLY_INIT          _MD_EarlyInit
 #define _MD_FINAL_INIT			_PR_UnixInit
-#define _MD_GET_INTERVAL        _PR_UNIX_GetInterval
-#define _MD_INTERVAL_PER_SEC    _PR_UNIX_TicksPerSecond
+#define _MD_INTERVAL_INIT       _PR_Mach_IntervalInit
+#define _MD_GET_INTERVAL        _PR_Mach_GetInterval
+#define _MD_INTERVAL_PER_SEC    _PR_Mach_TicksPerSecond
 
 extern void             _MD_EarlyInit(void);
-extern PRIntervalTime   _PR_UNIX_GetInterval(void);
-extern PRIntervalTime   _PR_UNIX_TicksPerSecond(void);
+extern void             _PR_Mach_IntervalInit(void);
+extern PRIntervalTime   _PR_Mach_GetInterval(void);
+extern PRIntervalTime   _PR_Mach_TicksPerSecond(void);
 
 /*
  * We wrapped the select() call.  _MD_SELECT refers to the built-in,
  * unwrapped version.
  */
 #define _MD_SELECT(nfds,r,w,e,tv) syscall(SYS_select,nfds,r,w,e,tv)
 
 /* For writev() */
--- a/pr/include/md/_dgux.h
+++ b/pr/include/md/_dgux.h
@@ -153,18 +153,17 @@ struct _MDCPU {
 #define _MD_IOQ_LOCK()
 #define _MD_IOQ_UNLOCK()
 
 /*
  * The following are copied from _sunos.h, _aix.h.  This means
  * some of them should probably be moved into _unixos.h.  But
  * _irix.h seems to be quite different in regard to these macros.
  */
-#define _MD_GET_INTERVAL                  _PR_UNIX_GetInterval
-#define _MD_INTERVAL_PER_SEC              _PR_UNIX_TicksPerSecond
+#define _MD_INTERVAL_USE_GTOD
 
 #define _MD_EARLY_INIT		_MD_EarlyInit
 #define _MD_FINAL_INIT		_PR_UnixInit
 #define _MD_INIT_RUNNING_CPU(cpu) _MD_unix_init_running_cpu(cpu)
 #define _MD_INIT_THREAD         _MD_InitializeThread
 #define _MD_EXIT_THREAD(thread)
 #define	_MD_SUSPEND_THREAD(thread)
 #define	_MD_RESUME_THREAD(thread)
--- a/pr/include/md/_freebsd.h
+++ b/pr/include/md/_freebsd.h
@@ -210,23 +210,20 @@ extern PRStatus _MD_CREATE_THREAD(
 extern void _MD_SET_PRIORITY(struct _MDThread *thread, PRUintn newPri);
 extern PRStatus _MD_WAIT(PRThread *, PRIntervalTime timeout);
 extern PRStatus _MD_WAKEUP_WAITER(PRThread *);
 extern void _MD_YIELD(void);
 
 #endif /* ! _PR_PTHREADS */
 
 extern void _MD_EarlyInit(void);
-extern PRIntervalTime _PR_UNIX_GetInterval(void);
-extern PRIntervalTime _PR_UNIX_TicksPerSecond(void);
 
 #define _MD_EARLY_INIT                  _MD_EarlyInit
 #define _MD_FINAL_INIT			_PR_UnixInit
-#define _MD_GET_INTERVAL                  _PR_UNIX_GetInterval
-#define _MD_INTERVAL_PER_SEC              _PR_UNIX_TicksPerSecond
+#define _MD_INTERVAL_USE_GTOD
 
 /*
  * We wrapped the select() call.  _MD_SELECT refers to the built-in,
  * unwrapped version.
  */
 #define _MD_SELECT(nfds,r,w,e,tv) syscall(SYS_select,nfds,r,w,e,tv)
 
 #if defined(_PR_POLL_AVAILABLE)
--- a/pr/include/md/_hpux.h
+++ b/pr/include/md/_hpux.h
@@ -264,18 +264,17 @@ struct _MDCPU {
 
 #if defined(HPUX_LW_TIMER)
 extern void _PR_HPUX_LW_IntervalInit(void);
 extern PRIntervalTime _PR_HPUX_LW_GetInterval(void);
 #define _MD_INTERVAL_INIT                 _PR_HPUX_LW_IntervalInit
 #define _MD_GET_INTERVAL                  _PR_HPUX_LW_GetInterval
 #define _MD_INTERVAL_PER_SEC()            1000
 #else
-#define _MD_GET_INTERVAL                  _PR_UNIX_GetInterval
-#define _MD_INTERVAL_PER_SEC              _PR_UNIX_TicksPerSecond
+#define _MD_INTERVAL_USE_GTOD
 #endif
 
 /*
  * We wrapped the select() call.  _MD_SELECT refers to the built-in,
  * unwrapped version.
  */
 #define _MD_SELECT(nfds,r,w,e,tv) syscall(SYS_select,nfds,r,w,e,tv)
 
--- a/pr/include/md/_linux.h
+++ b/pr/include/md/_linux.h
@@ -621,23 +621,20 @@ extern PRStatus _MD_CREATE_THREAD(
 extern void _MD_SET_PRIORITY(struct _MDThread *thread, PRUintn newPri);
 extern PRStatus _MD_WAIT(PRThread *, PRIntervalTime timeout);
 extern PRStatus _MD_WAKEUP_WAITER(PRThread *);
 extern void _MD_YIELD(void);
 
 #endif /* ! _PR_PTHREADS */
 
 extern void _MD_EarlyInit(void);
-extern PRIntervalTime _PR_UNIX_GetInterval(void);
-extern PRIntervalTime _PR_UNIX_TicksPerSecond(void);
 
 #define _MD_EARLY_INIT                  _MD_EarlyInit
 #define _MD_FINAL_INIT                  _PR_UnixInit
-#define _MD_GET_INTERVAL                _PR_UNIX_GetInterval
-#define _MD_INTERVAL_PER_SEC            _PR_UNIX_TicksPerSecond
+#define HAVE_MONOTONIC_CLOCK
 
 /*
  * We wrapped the select() call.  _MD_SELECT refers to the built-in,
  * unwrapped version.
  */
 #define _MD_SELECT __select
 
 #ifdef _PR_POLL_AVAILABLE
--- a/pr/include/md/_netbsd.h
+++ b/pr/include/md/_netbsd.h
@@ -203,23 +203,20 @@ struct _MDCPU {
 #define _MD_EXIT_THREAD(thread)
 #define _MD_SUSPEND_THREAD(thread)      _MD_suspend_thread
 #define _MD_RESUME_THREAD(thread)       _MD_resume_thread
 #define _MD_CLEAN_THREAD(_thread)
 
 #endif /* ! _PR_PTHREADS */
 
 extern void _MD_EarlyInit(void);
-extern PRIntervalTime _PR_UNIX_GetInterval(void);
-extern PRIntervalTime _PR_UNIX_TicksPerSecond(void);
 
 #define _MD_EARLY_INIT                  _MD_EarlyInit
 #define _MD_FINAL_INIT			_PR_UnixInit
-#define _MD_GET_INTERVAL                  _PR_UNIX_GetInterval
-#define _MD_INTERVAL_PER_SEC              _PR_UNIX_TicksPerSecond
+#define _MD_INTERVAL_USE_GTOD
 
 /*
  * We wrapped the select() call.  _MD_SELECT refers to the built-in,
  * unwrapped version.
  */
 #define _MD_SELECT(nfds,r,w,e,tv) syscall(SYS_select,nfds,r,w,e,tv)
 #if defined(_PR_POLL_AVAILABLE)
 #include <poll.h>
--- a/pr/include/md/_nto.h
+++ b/pr/include/md/_nto.h
@@ -162,18 +162,17 @@ struct _MDCPU {
 #define _MD_NEW_LOCK(lock)		PR_SUCCESS
 #define _MD_FREE_LOCK(lock)
 #define _MD_LOCK(lock)
 #define _MD_UNLOCK(lock)
 #define _MD_INIT_IO()
 #define _MD_IOQ_LOCK()
 #define _MD_IOQ_UNLOCK()
 
-#define _MD_GET_INTERVAL		_PR_UNIX_GetInterval
-#define _MD_INTERVAL_PER_SEC		_PR_UNIX_TicksPerSecond
+#define _MD_INTERVAL_USE_GTOD
 #define _MD_EARLY_INIT			_MD_EarlyInit
 #define _MD_FINAL_INIT			_PR_UnixInit
 #define _MD_INIT_RUNNING_CPU(cpu)	_MD_unix_init_running_cpu(cpu)
 #define _MD_INIT_THREAD			_MD_InitializeThread
 #define _MD_EXIT_THREAD(thread)
 #define	_MD_SUSPEND_THREAD(thread)
 #define	_MD_RESUME_THREAD(thread)
 #define _MD_CLEAN_THREAD(_thread)
--- a/pr/include/md/_openbsd.h
+++ b/pr/include/md/_openbsd.h
@@ -187,18 +187,17 @@ struct _MDCPU {
 #define _MD_SUSPEND_THREAD(thread)      _MD_suspend_thread
 #define _MD_RESUME_THREAD(thread)       _MD_resume_thread
 #define _MD_CLEAN_THREAD(_thread)
 
 #endif /* ! _PR_PTHREADS */
 
 #define _MD_EARLY_INIT                  _MD_EarlyInit
 #define _MD_FINAL_INIT			_PR_UnixInit
-#define _MD_GET_INTERVAL                  _PR_UNIX_GetInterval
-#define _MD_INTERVAL_PER_SEC              _PR_UNIX_TicksPerSecond
+#define _MD_INTERVAL_USE_GTOD
 
 /*
  * We wrapped the select() call.  _MD_SELECT refers to the built-in,
  * unwrapped version.
  */
 #define _MD_SELECT(nfds,r,w,e,tv) syscall(SYS_select,nfds,r,w,e,tv)
 #include <poll.h>
 #define _MD_POLL(fds,nfds,timeout) syscall(SYS_poll,fds,nfds,timeout)
--- a/pr/include/md/_osf1.h
+++ b/pr/include/md/_osf1.h
@@ -181,18 +181,17 @@ struct _MDCPU {
 #define _MD_IOQ_LOCK()
 #define _MD_IOQ_UNLOCK()
 
 /*
  * The following are copied from _sunos.h, _aix.h.  This means
  * some of them should probably be moved into _unixos.h.  But
  * _irix.h seems to be quite different in regard to these macros.
  */
-#define _MD_GET_INTERVAL                  _PR_UNIX_GetInterval
-#define _MD_INTERVAL_PER_SEC              _PR_UNIX_TicksPerSecond
+#define _MD_INTERVAL_USE_GTOD
 
 #define _MD_EARLY_INIT		_MD_EarlyInit
 #define _MD_FINAL_INIT		_PR_UnixInit
 #define _MD_INIT_RUNNING_CPU(cpu) _MD_unix_init_running_cpu(cpu)
 #define _MD_INIT_THREAD         _MD_InitializeThread
 #define _MD_EXIT_THREAD(thread)
 #define	_MD_SUSPEND_THREAD(thread)
 #define	_MD_RESUME_THREAD(thread)
--- a/pr/include/md/_qnx.h
+++ b/pr/include/md/_qnx.h
@@ -153,18 +153,17 @@ struct _MDCPU {
 #define _MD_NEW_LOCK(lock)		PR_SUCCESS
 #define _MD_FREE_LOCK(lock)
 #define _MD_LOCK(lock)
 #define _MD_UNLOCK(lock)
 #define _MD_INIT_IO()
 #define _MD_IOQ_LOCK()
 #define _MD_IOQ_UNLOCK()
 
-#define _MD_GET_INTERVAL		_PR_UNIX_GetInterval
-#define _MD_INTERVAL_PER_SEC		_PR_UNIX_TicksPerSecond
+#define _MD_INTERVAL_USE_GTOD
 #define _MD_EARLY_INIT			_MD_EarlyInit
 #define _MD_FINAL_INIT			_PR_UnixInit
 #define _MD_INIT_RUNNING_CPU(cpu)	_MD_unix_init_running_cpu(cpu)
 #define _MD_INIT_THREAD			_MD_InitializeThread
 #define _MD_EXIT_THREAD(thread)
 #define	_MD_SUSPEND_THREAD(thread)
 #define	_MD_RESUME_THREAD(thread)
 #define _MD_CLEAN_THREAD(_thread)
--- a/pr/include/md/_riscos.h
+++ b/pr/include/md/_riscos.h
@@ -149,18 +149,17 @@ struct _MDCPU {
 #define _MD_NEW_LOCK(lock)		PR_SUCCESS
 #define _MD_FREE_LOCK(lock)
 #define _MD_LOCK(lock)
 #define _MD_UNLOCK(lock)
 #define _MD_INIT_IO()
 #define _MD_IOQ_LOCK()
 #define _MD_IOQ_UNLOCK()
 
-#define _MD_GET_INTERVAL		_PR_UNIX_GetInterval
-#define _MD_INTERVAL_PER_SEC		_PR_UNIX_TicksPerSecond
+#define _MD_INTERVAL_USE_GTOD
 #define _MD_EARLY_INIT			_MD_EarlyInit
 #define _MD_FINAL_INIT			_PR_UnixInit
 #define _MD_INIT_RUNNING_CPU(cpu)	_MD_unix_init_running_cpu(cpu)
 #define _MD_INIT_THREAD			_MD_InitializeThread
 #define _MD_EXIT_THREAD(thread)
 #define	_MD_SUSPEND_THREAD(thread)
 #define	_MD_RESUME_THREAD(thread)
 #define _MD_CLEAN_THREAD(_thread)
--- a/pr/include/md/_scoos.h
+++ b/pr/include/md/_scoos.h
@@ -158,15 +158,14 @@ struct _MDCPU {
 #define _MD_FINAL_INIT				_PR_UnixInit
 #define _MD_INIT_RUNNING_CPU(cpu) 	_MD_unix_init_running_cpu(cpu)
 #define _MD_INIT_THREAD         	_MD_InitializeThread
 #define _MD_EXIT_THREAD(thread)
 #define	_MD_SUSPEND_THREAD(thread)
 #define	_MD_RESUME_THREAD(thread)
 #define _MD_CLEAN_THREAD(_thread)
 
-#define _MD_GET_INTERVAL                  _PR_UNIX_GetInterval
-#define _MD_INTERVAL_PER_SEC              _PR_UNIX_TicksPerSecond
+#define _MD_INTERVAL_USE_GTOD
 
 #define _MD_SELECT		_select
 #define _MD_POLL		_poll
 
 #endif /* nspr_scoos5_defs_h___ */
--- a/pr/include/md/_symbian.h
+++ b/pr/include/md/_symbian.h
@@ -34,20 +34,17 @@
 #define _PR_HAVE_SYSV_SEMAPHORES
 #define PR_HAVE_SYSV_NAMED_SHARED_MEMORY
 
 #ifndef _PR_PTHREADS
 #error "Classic NSPR is not implemented"
 #endif
 
 extern void _MD_EarlyInit(void);
-extern PRIntervalTime _PR_UNIX_GetInterval(void);
-extern PRIntervalTime _PR_UNIX_TicksPerSecond(void);
 
 #define _MD_EARLY_INIT                  _MD_EarlyInit
 #define _MD_FINAL_INIT                  _PR_UnixInit
-#define _MD_GET_INTERVAL                _PR_UNIX_GetInterval
-#define _MD_INTERVAL_PER_SEC            _PR_UNIX_TicksPerSecond
+#define _MD_INTERVAL_USE_GTOD
 
 /* For writev() */
 #include <sys/uio.h>
 
 #endif /* nspr_symbian_defs_h___ */
--- a/pr/include/md/_unixos.h
+++ b/pr/include/md/_unixos.h
@@ -289,19 +289,32 @@ extern void		_MD_FreeSegment(PRSegment *
 #define _MD_INIT_SEGS			_MD_InitSegs
 #define _MD_ALLOC_SEGMENT		_MD_AllocSegment
 #define _MD_FREE_SEGMENT		_MD_FreeSegment
 
 #endif /* !defined(_PR_PTHREADS) */
 
 /************************************************************************/
 
-#if !defined(HPUX_LW_TIMER)
+#ifdef _MD_INTERVAL_USE_GTOD
+extern PRIntervalTime   _PR_UNIX_GetInterval(void);
+extern PRIntervalTime   _PR_UNIX_TicksPerSecond(void);
 #define _MD_INTERVAL_INIT()
+#define _MD_GET_INTERVAL		_PR_UNIX_GetInterval
+#define _MD_INTERVAL_PER_SEC		_PR_UNIX_TicksPerSecond
 #endif
+
+#ifdef HAVE_MONOTONIC_CLOCK
+extern PRIntervalTime   _PR_UNIX_GetInterval2(void);
+extern PRIntervalTime   _PR_UNIX_TicksPerSecond2(void);
+#define _MD_INTERVAL_INIT()
+#define _MD_GET_INTERVAL		_PR_UNIX_GetInterval2
+#define _MD_INTERVAL_PER_SEC		_PR_UNIX_TicksPerSecond2
+#endif
+
 #define _MD_INTERVAL_PER_MILLISEC()	(_PR_MD_INTERVAL_PER_SEC() / 1000)
 #define _MD_INTERVAL_PER_MICROSEC()	(_PR_MD_INTERVAL_PER_SEC() / 1000000)
 
 /************************************************************************/
 
 #define _MD_ERRNO()             	(errno)
 #define _MD_GET_SOCKET_ERROR()		(errno)
 
--- a/pr/include/md/_unixware.h
+++ b/pr/include/md/_unixware.h
@@ -153,18 +153,17 @@ struct _MDCPU {
 #define _MD_IOQ_LOCK()
 #define _MD_IOQ_UNLOCK()
 
 /*
  * The following are copied from _sunos.h, _aix.h.  This means
  * some of them should probably be moved into _unixos.h.  But
  * _irix.h seems to be quite different in regard to these macros.
  */
-#define _MD_GET_INTERVAL                  _PR_UNIX_GetInterval
-#define _MD_INTERVAL_PER_SEC              _PR_UNIX_TicksPerSecond
+#define _MD_INTERVAL_USE_GTOD
 
 #define _MD_EARLY_INIT		_MD_EarlyInit
 #define _MD_FINAL_INIT		_PR_UnixInit
 #define _MD_INIT_RUNNING_CPU(cpu) _MD_unix_init_running_cpu(cpu)
 #define _MD_INIT_THREAD         _MD_InitializeThread
 #define _MD_EXIT_THREAD(thread)
 #define	_MD_SUSPEND_THREAD(thread)
 #define	_MD_RESUME_THREAD(thread)
--- a/pr/src/Makefile.in
+++ b/pr/src/Makefile.in
@@ -128,16 +128,17 @@ ifeq ($(OS_TARGET),Android)
 # Android has no libpthread.so in NDK
 OS_LIBS		= -ldl
 else
 OS_LIBS		= -lpthread -ldl
 endif
 else
 OS_LIBS		= -ldl
 endif
+OS_LIBS		+= -lrt
 endif
 
 ifeq ($(OS_ARCH),HP-UX)
 ifeq ($(USE_PTHREADS), 1)
 ifeq (,$(filter-out B.10.10 B.10.20,$(OS_RELEASE)))
 OS_LIBS 	= -ldce
 else
 OS_LIBS 	= -lpthread -lrt
--- a/pr/src/md/unix/darwin.c
+++ b/pr/src/md/unix/darwin.c
@@ -1,19 +1,50 @@
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "primpl.h"
 
+#include <mach/mach_time.h>
+
 void _MD_EarlyInit(void)
 {
 }
 
+static mach_timebase_info_data_t machTimebaseInfo;
+
+void _PR_Mach_IntervalInit(void)
+{
+    kern_return_t rv;
+
+    rv = mach_timebase_info(&machTimebaseInfo);
+    PR_ASSERT(rv == KERN_SUCCESS);
+}
+
+PRIntervalTime _PR_Mach_GetInterval(void)
+{
+    uint64_t time;
+
+    /*
+     * mach_absolute_time returns the number of nanoseconds since boot.
+     * Convert it to the number of 10-microseconds. See Mac Technical Q&A
+     * QA1398.
+     */
+    time = mach_absolute_time();
+    time = time / 10000 * machTimebaseInfo.numer / machTimebaseInfo.denom;
+    return (PRIntervalTime)time;
+}  /* _PR_Mach_GetInterval */
+
+PRIntervalTime _PR_Mach_TicksPerSecond(void)
+{
+    return 100000;
+}
+
 PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np)
 {
 #if !defined(_PR_PTHREADS)
     if (isCurrent) {
 	(void) setjmp(CONTEXT(t));
     }
     *np = sizeof(CONTEXT(t)) / sizeof(PRWord);
     return (PRWord *) CONTEXT(t);
--- a/pr/src/md/unix/unix.c
+++ b/pr/src/md/unix/unix.c
@@ -3012,31 +3012,61 @@ PR_Now(void)
     LL_I2L(s2us, PR_USEC_PER_SEC);
     LL_I2L(s, tv.tv_sec);
     LL_I2L(us, tv.tv_usec);
     LL_MUL(s, s, s2us);
     LL_ADD(s, s, us);
     return s;
 }
 
+#if defined(_MD_INTERVAL_USE_GTOD)
+/*
+ * This version of interval times is based on the time of day
+ * capability offered by the system. This isn't valid for two reasons:
+ * 1) The time of day is neither linear nor montonically increasing
+ * 2) The units here are milliseconds. That's not appropriate for our use.
+ */
 PRIntervalTime _PR_UNIX_GetInterval()
 {
     struct timeval time;
     PRIntervalTime ticks;
 
     (void)GETTIMEOFDAY(&time);  /* fallicy of course */
     ticks = (PRUint32)time.tv_sec * PR_MSEC_PER_SEC;  /* that's in milliseconds */
     ticks += (PRUint32)time.tv_usec / PR_USEC_PER_MSEC;  /* so's that */
     return ticks;
-}  /* _PR_SUNOS_GetInterval */
+}  /* _PR_UNIX_GetInterval */
 
 PRIntervalTime _PR_UNIX_TicksPerSecond()
 {
     return 1000;  /* this needs some work :) */
 }
+#endif
+
+#if defined(HAVE_MONOTONIC_CLOCK)
+PRIntervalTime _PR_UNIX_GetInterval2()
+{
+    struct timespec time;
+    PRIntervalTime ticks;
+
+    if (clock_gettime(CLOCK_MONOTONIC, &time) != 0) {
+        fprintf(stderr, "clock_gettime failed: %d\n", errno);
+        abort();
+    }
+
+    ticks = (PRUint32)time.tv_sec * 100000;
+    ticks += (PRUint32)time.tv_nsec / 10000;
+    return ticks;
+}
+
+PRIntervalTime _PR_UNIX_TicksPerSecond2()
+{
+    return 100000;
+}
+#endif
 
 #if !defined(_PR_PTHREADS)
 /*
  * Wait for I/O on multiple descriptors.
  *
  * Return 0 if timed out, return -1 if interrupted,
  * else return the number of ready descriptors.
  */
--- a/pr/src/misc/prinrval.c
+++ b/pr/src/misc/prinrval.c
@@ -27,23 +27,16 @@ void _PR_InitClock(void)
         PRIntervalTime ticksPerSec = PR_TicksPerSecond();
 
         PR_ASSERT(ticksPerSec >= PR_INTERVAL_MIN);
         PR_ASSERT(ticksPerSec <= PR_INTERVAL_MAX);
     }
 #endif /* DEBUG */
 }
 
-/*
- * This version of interval times is based on the time of day
- * capability offered by system. This isn't valid for two reasons:
- * 1) The time of day is neither linear nor montonically increasing
- * 2) The units here are milliseconds. That's not appropriate for our use.
- */
-
 PR_IMPLEMENT(PRIntervalTime) PR_IntervalNow(void)
 {
     if (!_pr_initialized) _PR_ImplicitInitialization();
     return _PR_MD_GET_INTERVAL();
 }  /* PR_IntervalNow */
 
 PR_EXTERN(PRUint32) PR_TicksPerSecond(void)
 {