Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 22 Feb 2012 03:22:50 +0000 (UTC)
From:      David Xu <davidxu@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r231989 - in head: lib/libthr/thread sys/kern sys/sys
Message-ID:  <201202220322.q1M3MoFE032330@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201202220322.q1M3MoFE032330>