Index: /pjproject/trunk/pjlib/include/pj/config.h
===================================================================
--- /pjproject/trunk/pjlib/include/pj/config.h	(revision 69)
+++ /pjproject/trunk/pjlib/include/pj/config.h	(revision 70)
@@ -98,4 +98,5 @@
 #   undef PJ_HAS_EVENT_OBJ
 #   undef PJ_ENABLE_EXTRA_CHECK
+#   undef PJ_EXCEPTION_USE_WIN32_SEH
 #endif
 
@@ -320,4 +321,25 @@
 #endif
 
+/**
+ * Should we use Windows Structured Exception Handling (SEH) for the
+ * PJLIB exceptions.
+ *
+ * Default: 0
+ */
+#ifndef PJ_EXCEPTION_USE_WIN32_SEH
+#  define PJ_EXCEPTION_USE_WIN32_SEH 0
+#endif
+
+/**
+ * Should we attempt to use Pentium's rdtsc for high resolution
+ * timestamp.
+ *
+ * Default: 0
+ */
+#ifndef PJ_TIMESTAMP_USE_RDTSC
+#   define PJ_TIMESTAMP_USE_RDTSC   0
+#endif
+
+
 /** @} */
 
@@ -354,4 +376,5 @@
 #  define PJ_DECL(type)		    type
 #  define PJ_DECL_NO_RETURN(type)   type PJ_NORETURN
+#  define PJ_IDECL_NO_RETURN(type)  PJ_INLINE(type) PJ_NORETURN
 #  define PJ_BEGIN_DECL		    extern "C" {
 #  define PJ_END_DECL		    }
@@ -359,4 +382,5 @@
 #  define PJ_DECL(type)		    extern type
 #  define PJ_DECL_NO_RETURN(type)   PJ_NORETURN type
+#  define PJ_IDECL_NO_RETURN(type)  PJ_NORETURN PJ_INLINE(type)
 #  define PJ_BEGIN_DECL
 #  define PJ_END_DECL
Index: /pjproject/trunk/pjlib/include/pj/os.h
===================================================================
--- /pjproject/trunk/pjlib/include/pj/os.h	(revision 69)
+++ /pjproject/trunk/pjlib/include/pj/os.h	(revision 70)
@@ -923,4 +923,22 @@
 
 /**
+ * Calculate the elapsed time as 32-bit miliseconds.
+ * This function calculates the elapsed time using highest precision
+ * calculation that is available for current platform, considering
+ * whether floating point or 64-bit precision arithmetic is available. 
+ * For maximum portability, application should prefer to use this function
+ * rather than calculating the elapsed time by itself.
+ *
+ * @param start     The starting timestamp.
+ * @param stop      The end timestamp.
+ *
+ * @return	    Elapsed time in milisecond.
+ *
+ * @see pj_elapsed_time(), pj_elapsed_cycle(), pj_elapsed_nanosec()
+ */
+PJ_DECL(pj_uint32_t) pj_elapsed_msec( const pj_timestamp *start,
+                                      const pj_timestamp *stop );
+
+/**
  * Calculate the elapsed time in 32-bit microseconds.
  * This function calculates the elapsed time using highest precision
Index: /pjproject/trunk/pjlib/src/pj/os_core_win32.c
===================================================================
--- /pjproject/trunk/pjlib/src/pj/os_core_win32.c	(revision 69)
+++ /pjproject/trunk/pjlib/src/pj/os_core_win32.c	(revision 70)
@@ -162,6 +162,8 @@
     {
 	pj_timestamp dummy_ts;
+	if ((rc=pj_get_timestamp_freq(&dummy_ts)) != PJ_SUCCESS) {
+	    return rc;
+	}
 	if ((rc=pj_get_timestamp(&dummy_ts)) != PJ_SUCCESS) {
-	    PJ_LOG(1, ("pj_init", "Unable to initialize timestamp"));
 	    return rc;
 	}
Index: /pjproject/trunk/pjlib/src/pj/os_timestamp_common.c
===================================================================
--- /pjproject/trunk/pjlib/src/pj/os_timestamp_common.c	(revision 69)
+++ /pjproject/trunk/pjlib/src/pj/os_timestamp_common.c	(revision 70)
@@ -27,7 +27,12 @@
 #define MSEC    (1000)
 
+#define u64tohighprec(u64)	((pj_highprec_t)((pj_int64_t)(u64)))
+
 static pj_highprec_t get_elapsed( const pj_timestamp *start,
                                   const pj_timestamp *stop )
 {
+#if defined(PJ_HAS_INT64) && PJ_HAS_INT64!=0
+    return u64tohighprec(stop->u64 - start->u64);
+#else
     pj_highprec_t elapsed_hi, elapsed_lo;
 
@@ -39,4 +44,36 @@
 
     return elapsed_hi + elapsed_lo;
+#endif
+}
+
+static pj_highprec_t elapsed_msec( const pj_timestamp *start,
+                                   const pj_timestamp *stop )
+{
+    pj_timestamp ts_freq;
+    pj_highprec_t freq, elapsed;
+
+    if (pj_get_timestamp_freq(&ts_freq) != PJ_SUCCESS)
+        return 0;
+
+    /* Convert frequency timestamp */
+#if defined(PJ_HAS_INT64) && PJ_HAS_INT64!=0
+    freq = u64tohighprec(ts_freq.u64);
+#else
+    freq = ts_freq.u32.hi;
+    pj_highprec_mul(freq, U32MAX);
+    freq += ts_freq.u32.lo;
+#endif
+
+    /* Avoid division by zero. */
+    if (freq == 0) freq = 1;
+
+    /* Get elapsed time in cycles. */
+    elapsed = get_elapsed(start, stop);
+
+    /* usec = elapsed * MSEC / freq */
+    pj_highprec_mul(elapsed, MSEC);
+    pj_highprec_div(elapsed, freq);
+
+    return elapsed;
 }
 
@@ -51,7 +88,11 @@
 
     /* Convert frequency timestamp */
+#if defined(PJ_HAS_INT64) && PJ_HAS_INT64!=0
+    freq = u64tohighprec(ts_freq.u64);
+#else
     freq = ts_freq.u32.hi;
     pj_highprec_mul(freq, U32MAX);
     freq += ts_freq.u32.lo;
+#endif
 
     /* Avoid division by zero. */
@@ -78,7 +119,11 @@
 
     /* Convert frequency timestamp */
+#if defined(PJ_HAS_INT64) && PJ_HAS_INT64!=0
+    freq = u64tohighprec(ts_freq.u64);
+#else
     freq = ts_freq.u32.hi;
     pj_highprec_mul(freq, U32MAX);
     freq += ts_freq.u32.lo;
+#endif
 
     /* Avoid division by zero. */
@@ -101,8 +146,14 @@
 }
 
+PJ_DEF(pj_uint32_t) pj_elapsed_msec( const pj_timestamp *start,
+                                     const pj_timestamp *stop )
+{
+    return (pj_uint32_t)elapsed_msec(start, stop);
+}
+
 PJ_DEF(pj_time_val) pj_elapsed_time( const pj_timestamp *start,
                                      const pj_timestamp *stop )
 {
-    pj_highprec_t elapsed = elapsed_usec(start, stop);
+    pj_highprec_t elapsed = elapsed_msec(start, stop);
     pj_time_val tv_elapsed;
 
@@ -114,10 +165,9 @@
 
         sec = elapsed;
-        pj_highprec_div(sec, USEC);
+        pj_highprec_div(sec, MSEC);
         tv_elapsed.sec = (long)sec;
 
         msec = elapsed;
-        pj_highprec_mod(msec, USEC);
-        pj_highprec_div(msec, 1000);
+        pj_highprec_mod(msec, MSEC);
         tv_elapsed.msec = (long)msec;
 
Index: /pjproject/trunk/pjlib/src/pj/os_timestamp_win32.c
===================================================================
--- /pjproject/trunk/pjlib/src/pj/os_timestamp_win32.c	(revision 69)
+++ /pjproject/trunk/pjlib/src/pj/os_timestamp_win32.c	(revision 70)
@@ -21,4 +21,73 @@
 #include <windows.h>
 
+#if defined(PJ_TIMESTAMP_USE_RDTSC) && PJ_TIMESTAMP_USE_RDTSC!=0 && \
+    defined(PJ_M_I386) && PJ_M_I386 != 0 && \
+    defined(_MSC_VER)
+/*
+ * Use rdtsc to get the OS timestamp.
+ */
+static LONG CpuMhz;
+static pj_int64_t CpuHz;
+ 
+static pj_status_t GetCpuHz(void)
+{
+    HKEY key;
+    LONG rc;
+    DWORD size;
+
+    rc = RegOpenKey( HKEY_LOCAL_MACHINE,
+		     "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0",
+		     &key);
+    if (rc != ERROR_SUCCESS)
+	return PJ_RETURN_OS_ERROR(rc);
+
+    size = sizeof(CpuMhz);
+    rc = RegQueryValueEx(key, "~MHz", NULL, NULL, (BYTE*)&CpuMhz, &size);
+    RegCloseKey(key);
+
+    if (rc != ERROR_SUCCESS) {
+	return PJ_RETURN_OS_ERROR(rc);
+    }
+
+    CpuHz = CpuMhz;
+    CpuHz = CpuHz * 1000000;
+
+    return PJ_SUCCESS;
+}
+
+/* __int64 is nicely returned in EDX:EAX */
+__declspec(naked) __int64 rdtsc() 
+{
+    __asm 
+    {
+	RDTSC
+	RET
+    }
+}
+
+PJ_DEF(pj_status_t) pj_get_timestamp(pj_timestamp *ts)
+{
+    ts->u64 = rdtsc();
+    return PJ_SUCCESS;
+}
+
+PJ_DEF(pj_status_t) pj_get_timestamp_freq(pj_timestamp *freq)
+{
+    pj_status_t status;
+
+    if (CpuHz == 0) {
+	status = GetCpuHz();
+	if (status != PJ_SUCCESS)
+	    return status;
+    }
+
+    freq->u64 = CpuHz;
+    return PJ_SUCCESS;
+}
+
+#else
+/*
+ * Use QueryPerformanceCounter and QueryPerformanceFrequency.
+ */
 PJ_DEF(pj_status_t) pj_get_timestamp(pj_timestamp *ts)
 {
@@ -43,2 +112,4 @@
 }
 
+#endif	/* PJ_TIMESTAMP_USE_RDTSC */
+
Index: /pjproject/trunk/pjlib/src/pjlib-test/sleep.c
===================================================================
--- /pjproject/trunk/pjlib/src/pjlib-test/sleep.c	(revision 69)
+++ /pjproject/trunk/pjlib/src/pjlib-test/sleep.c	(revision 70)
@@ -125,6 +125,7 @@
 	pj_time_val t1, t2;
         pj_timestamp start, stop;
-        pj_time_val elapsed;
 	pj_uint32_t msec;
+
+	pj_thread_sleep(0);
 
         /* Mark start of test. */
@@ -157,8 +158,6 @@
 	}
 
-        /* Get elapsed time in time_val */
-        elapsed = pj_elapsed_time(&start, &stop);
-
-	msec = PJ_TIME_VAL_MSEC(elapsed);
+        /* Get elapsed time in msec */
+        msec = pj_elapsed_msec(&start, &stop);
 
 	/* Check if it's within range. */
@@ -170,5 +169,11 @@
 		      "(outside %d%% err window)",
 		      msec, DURATION2, MIS));
-	    return -30;
+	    PJ_TIME_VAL_SUB(t2, t1);
+	    PJ_LOG(3,(THIS_FILE, 
+		      "...info: gettimeofday() reported duration is "
+		      "%d msec",
+		      PJ_TIME_VAL_MSEC(t2)));
+
+	    return -76;
 	}
     }
