Author: davidxu
Date: Wed Feb 22 03:22:49 2012
New Revision: 231989
URL: http://svn.freebsd.org/changeset/base/231989

Log:
  Use unused fourth argument of umtx_op to pass flags to kernel for operation
  UMTX_OP_WAIT. Upper 16bits is enough to hold a clock id, and lower
  16bits is used to pass flags. The change saves a clock_gettime() syscall
  from libthr.

Modified:
  head/lib/libthr/thread/thr_umtx.c
  head/sys/kern/kern_umtx.c
  head/sys/sys/umtx.h

Modified: head/lib/libthr/thread/thr_umtx.c
==============================================================================
--- head/lib/libthr/thread/thr_umtx.c   Wed Feb 22 01:50:13 2012        
(r231988)
+++ head/lib/libthr/thread/thr_umtx.c   Wed Feb 22 03:22:49 2012        
(r231989)
@@ -200,20 +200,10 @@ int
 _thr_umtx_timedwait_uint(volatile u_int *mtx, u_int id, int clockid,
        const struct timespec *abstime, int shared)
 {
-       struct timespec ts, ts2, *tsp;
-
-       if (abstime != NULL) {
-               clock_gettime(clockid, &ts);
-               TIMESPEC_SUB(&ts2, abstime, &ts);
-               if (ts2.tv_sec < 0 || (ts2.tv_sec == 0 && ts2.tv_nsec <= 0))
-                       return (ETIMEDOUT);
-               tsp = &ts2;
-       } else {
-               tsp = NULL;
-       }
        return _umtx_op_err(__DEVOLATILE(void *, mtx), 
-               shared ? UMTX_OP_WAIT_UINT : UMTX_OP_WAIT_UINT_PRIVATE, id, 
NULL,
-                       tsp);
+               shared ? UMTX_OP_WAIT_UINT : UMTX_OP_WAIT_UINT_PRIVATE, id, 
+               abstime != NULL ? (void *)(uintptr_t)((clockid << 16) | 
UMTX_WAIT_ABSTIME) : 0, 
+               __DECONST(void *, abstime));
 }
 
 int

Modified: head/sys/kern/kern_umtx.c
==============================================================================
--- head/sys/kern/kern_umtx.c   Wed Feb 22 01:50:13 2012        (r231988)
+++ head/sys/kern/kern_umtx.c   Wed Feb 22 03:22:49 2012        (r231989)
@@ -970,17 +970,26 @@ do_unlock_umtx32(struct thread *td, uint
 }
 #endif
 
+static inline int 
+tstohz(const struct timespec *tsp)
+{
+       struct timeval tv;
+
+       TIMESPEC_TO_TIMEVAL(&tv, tsp);
+       return tvtohz(&tv);
+}
+
 /*
  * Fetch and compare value, sleep on the address if value is not changed.
  */
 static int
 do_wait(struct thread *td, void *addr, u_long id,
-       struct timespec *timeout, int compat32, int is_private)
+       struct timespec *timeout, int compat32, int is_private, uint32_t flags)
 {
        struct umtx_q *uq;
-       struct timespec ts, ts2, ts3;
-       struct timeval tv;
+       struct timespec ets, cts, tts;
        u_long tmp;
+       int clockid = (flags >> 16) & 0xFFFF;
        int error = 0;
 
        uq = td->td_umtxq;
@@ -1005,12 +1014,22 @@ do_wait(struct thread *td, void *addr, u
                umtxq_remove(uq);
                umtxq_unlock(&uq->uq_key);
        } else {
-               getnanouptime(&ts);
-               timespecadd(&ts, timeout);
-               TIMESPEC_TO_TIMEVAL(&tv, timeout);
+               kern_clock_gettime(td, clockid, &cts);
+               if ((flags & UMTX_WAIT_ABSTIME) == 0) {
+                       ets = cts;
+                       timespecadd(&ets, timeout);
+               } else {
+                       ets = *timeout;
+               }
                umtxq_lock(&uq->uq_key);
                for (;;) {
-                       error = umtxq_sleep(uq, "uwait", tvtohz(&tv));
+                       if (timespeccmp(&cts, &ets, >=)) {
+                               error = ETIMEDOUT;
+                               break;
+                       }
+                       tts = ets;
+                       timespecsub(&tts, &cts);
+                       error = umtxq_sleep(uq, "uwait", tstohz(&tts));
                        if (!(uq->uq_flags & UQF_UMTXQ)) {
                                error = 0;
                                break;
@@ -1018,15 +1037,7 @@ do_wait(struct thread *td, void *addr, u
                        if (error != ETIMEDOUT)
                                break;
                        umtxq_unlock(&uq->uq_key);
-                       getnanouptime(&ts2);
-                       if (timespeccmp(&ts2, &ts, >=)) {
-                               error = ETIMEDOUT;
-                               umtxq_lock(&uq->uq_key);
-                               break;
-                       }
-                       ts3 = ts;
-                       timespecsub(&ts3, &ts2);
-                       TIMESPEC_TO_TIMEVAL(&tv, &ts3);
+                       kern_clock_gettime(td, clockid, &cts);
                        umtxq_lock(&uq->uq_key);
                }
                umtxq_remove(uq);
@@ -2941,6 +2952,7 @@ __umtx_op_wait(struct thread *td, struct
 {
        struct timespec *ts, timeout;
        int error;
+       uint32_t flags;
 
        if (uap->uaddr2 == NULL)
                ts = NULL;
@@ -2950,7 +2962,8 @@ __umtx_op_wait(struct thread *td, struct
                        return (error);
                ts = &timeout;
        }
-       return do_wait(td, uap->obj, uap->val, ts, 0, 0);
+       flags = (uint32_t)(uintptr_t)uap->uaddr1;
+       return do_wait(td, uap->obj, uap->val, ts, 0, 0, flags);
 }
 
 static int
@@ -2958,6 +2971,7 @@ __umtx_op_wait_uint(struct thread *td, s
 {
        struct timespec *ts, timeout;
        int error;
+       uint32_t flags;
 
        if (uap->uaddr2 == NULL)
                ts = NULL;
@@ -2967,7 +2981,8 @@ __umtx_op_wait_uint(struct thread *td, s
                        return (error);
                ts = &timeout;
        }
-       return do_wait(td, uap->obj, uap->val, ts, 1, 0);
+       flags = (uint32_t)(uintptr_t)uap->uaddr1;
+       return do_wait(td, uap->obj, uap->val, ts, 1, 0, flags);
 }
 
 static int
@@ -2975,6 +2990,7 @@ __umtx_op_wait_uint_private(struct threa
 {
        struct timespec *ts, timeout;
        int error;
+       uint32_t flags;
 
        if (uap->uaddr2 == NULL)
                ts = NULL;
@@ -2984,7 +3000,8 @@ __umtx_op_wait_uint_private(struct threa
                        return (error);
                ts = &timeout;
        }
-       return do_wait(td, uap->obj, uap->val, ts, 1, 1);
+       flags = (uint32_t)(uintptr_t)uap->uaddr1;
+       return do_wait(td, uap->obj, uap->val, ts, 1, 1, flags);
 }
 
 static int
@@ -3286,6 +3303,7 @@ __umtx_op_wait_compat32(struct thread *t
 {
        struct timespec *ts, timeout;
        int error;
+       uint32_ flags;
 
        if (uap->uaddr2 == NULL)
                ts = NULL;
@@ -3295,7 +3313,8 @@ __umtx_op_wait_compat32(struct thread *t
                        return (error);
                ts = &timeout;
        }
-       return do_wait(td, uap->obj, uap->val, ts, 1, 0);
+       flags = (uint32_t)(uintptr_t)uap->uaddr1;
+       return do_wait(td, uap->obj, uap->val, ts, 1, 0, flags);
 }
 
 static int
@@ -3394,6 +3413,7 @@ __umtx_op_wait_uint_private_compat32(str
 {
        struct timespec *ts, timeout;
        int error;
+       uint32_t flags;
 
        if (uap->uaddr2 == NULL)
                ts = NULL;
@@ -3403,7 +3423,8 @@ __umtx_op_wait_uint_private_compat32(str
                        return (error);
                ts = &timeout;
        }
-       return do_wait(td, uap->obj, uap->val, ts, 1, 1);
+       flags = (uint32_t)(uintptr_t)uap->uaddr1;
+       return do_wait(td, uap->obj, uap->val, ts, 1, 1, flags);
 }
 
 static int

Modified: head/sys/sys/umtx.h
==============================================================================
--- head/sys/sys/umtx.h Wed Feb 22 01:50:13 2012        (r231988)
+++ head/sys/sys/umtx.h Wed Feb 22 03:22:49 2012        (r231989)
@@ -87,6 +87,8 @@
 #define        CVWAIT_ABSTIME          0x02
 #define        CVWAIT_CLOCKID          0x04
 
+#define        UMTX_WAIT_ABSTIME       0x01
+
 #define        UMTX_CHECK_UNPARKING    CVWAIT_CHECK_UNPARKING
 
 #ifndef _KERNEL
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to