Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 29 Oct 2014 17:52:30 +0200
From:      Konstantin Belousov <kostikbel@gmail.com>
To:        Bruce Evans <brde@optusnet.com.au>
Cc:        svn-src-head@freebsd.org, svn-src-all@freebsd.org, src-committers@freebsd.org, jhb@freebsd.org
Subject:   Re: svn commit: r273784 - in head/sys: amd64/ia32 compat/freebsd32 i386/i386 kern net
Message-ID:  <20141029155230.GE53947@kib.kiev.ua>
In-Reply-To: <20141029042007.N2423@besplex.bde.org>
References:  <201410281528.s9SFSLs2013764@svn.freebsd.org> <20141029042007.N2423@besplex.bde.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Wed, Oct 29, 2014 at 06:26:42AM +1100, Bruce Evans wrote:
> On Tue, 28 Oct 2014, Konstantin Belousov wrote:
> 
> > Log:
> >  Replace some calls to fuword() by fueword() with proper error checking.
> 
> I just noticed some more API design errors.  The pointer type for new
> APIs should be [qualifed] wordsize_t *, not [qualified] void *.  Using
> void * reduces type safety for almost no benefits.  The casuword()
> family already doesn't use void *.
casuword() has very limited use, it was invented for umtx, and used
only there.  That said, I tend to agree with somewhat implicit note
that base argument for fuword() and family should be vm_offset_t.

Still, lets move by small steps. Below is the patch to add volatile
qualifier to base, and remove __DEVOLATILE() from kern_umtx.c. I
converted suword() as well, since I do not see why the same arguments
which support change for fuword() are not applicable to suword().

The intr variants are left alone.

Patch was only compile-tested on x86.

diff --git a/share/man/man9/fetch.9 b/share/man/man9/fetch.9
index 7e13cbc..1d46784 100644
--- a/share/man/man9/fetch.9
+++ b/share/man/man9/fetch.9
@@ -34,7 +34,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd October 21, 2014
+.Dd October 29, 2014
 .Dt FETCH 9
 .Os
 .Sh NAME
@@ -53,21 +53,21 @@
 .In sys/types.h
 .In sys/systm.h
 .Ft int
-.Fn fubyte "const void *base"
+.Fn fubyte "volatile const void *base"
 .Ft long
-.Fn fuword "const void *base"
+.Fn fuword "volatile const void *base"
 .Ft int
-.Fn fuword16 "void *base"
+.Fn fuword16 "volatile const void *base"
 .Ft int32_t
-.Fn fuword32 "const void *base"
+.Fn fuword32 "volatile const void *base"
 .Ft int64_t
-.Fn fuword64 "const void *base"
+.Fn fuword64 "volatile const void *base"
 .Ft long
-.Fn fueword "const void *base" "long *val"
+.Fn fueword "volatile const void *base" "long *val"
 .Ft int32_t
-.Fn fueword32 "const void *base" "int32_t *val"
+.Fn fueword32 "volatile const void *base" "int32_t *val"
 .Ft int64_t
-.Fn fueword64 "const void *base" "int64_t *val"
+.Fn fueword64 "volatile const void *base" "int64_t *val"
 .In sys/resourcevar.h
 .Ft int
 .Fn fuswintr "void *base"
diff --git a/share/man/man9/store.9 b/share/man/man9/store.9
index d333eff..cc442f2 100644
--- a/share/man/man9/store.9
+++ b/share/man/man9/store.9
@@ -34,7 +34,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd October 5, 2009
+.Dd October 29, 2014
 .Dt STORE 9
 .Os
 .Sh NAME
@@ -48,15 +48,15 @@
 .In sys/time.h
 .In sys/systm.h
 .Ft int
-.Fn subyte "void *base" "int byte"
+.Fn subyte "volatile void *base" "int byte"
 .Ft int
-.Fn suword "void *base" "long word"
+.Fn suword "volatile void *base" "long word"
 .Ft int
-.Fn suword16 "void *base" "int word"
+.Fn suword16 "volatile void *base" "int word"
 .Ft int
-.Fn suword32 "void *base" "int32_t word"
+.Fn suword32 "volatile void *base" "int32_t word"
 .Ft int
-.Fn suword64 "void *base" "int64_t word"
+.Fn suword64 "volatile void *base" "int64_t word"
 .In sys/resourcevar.h
 .Ft int
 .Fn suswintr "void *base" "int word"
@@ -64,6 +64,8 @@
 The
 .Nm
 functions are designed to copy small amounts of data to user-space.
+If write is successful, it is performed atomically.
+The data written must be naturally aligned.
 .Pp
 The
 .Nm
diff --git a/sys/kern/kern_umtx.c b/sys/kern/kern_umtx.c
index 58e76bc..33fdf71 100644
--- a/sys/kern/kern_umtx.c
+++ b/sys/kern/kern_umtx.c
@@ -942,7 +942,7 @@ do_lock_normal(struct thread *td, struct umutex *m, uint32_t flags,
 	 * can fault on any access.
 	 */
 	for (;;) {
-		rv = fueword32(__DEVOLATILE(void *, &m->m_owner), &owner);
+		rv = fueword32(&m->m_owner, &owner);
 		if (rv == -1)
 			return (EFAULT);
 		if (mode == _UMUTEX_WAIT) {
@@ -1057,7 +1057,7 @@ do_unlock_normal(struct thread *td, struct umutex *m, uint32_t flags)
 	/*
 	 * Make sure we own this mtx.
 	 */
-	error = fueword32(__DEVOLATILE(uint32_t *, &m->m_owner), &owner);
+	error = fueword32(&m->m_owner, &owner);
 	if (error == -1)
 		return (EFAULT);
 
@@ -1115,7 +1115,7 @@ do_wake_umutex(struct thread *td, struct umutex *m)
 	int error;
 	int count;
 
-	error = fueword32(__DEVOLATILE(uint32_t *, &m->m_owner), &owner);
+	error = fueword32(&m->m_owner, &owner);
 	if (error == -1)
 		return (EFAULT);
 
@@ -1192,8 +1192,7 @@ do_wake2_umutex(struct thread *td, struct umutex *m, uint32_t flags)
 	 * any memory.
 	 */
 	if (count > 1) {
-		error = fueword32(__DEVOLATILE(uint32_t *, &m->m_owner),
-		    &owner);
+		error = fueword32(&m->m_owner, &owner);
 		if (error == -1)
 			error = EFAULT;
 		while (error == 0 && (owner & UMUTEX_CONTESTED) == 0) {
@@ -1211,8 +1210,7 @@ do_wake2_umutex(struct thread *td, struct umutex *m, uint32_t flags)
 				break;
 		}
 	} else if (count == 1) {
-		error = fueword32(__DEVOLATILE(uint32_t *, &m->m_owner),
-		    &owner);
+		error = fueword32(&m->m_owner, &owner);
 		if (error == -1)
 			error = EFAULT;
 		while (error == 0 && (owner & ~UMUTEX_CONTESTED) != 0 &&
@@ -1776,7 +1774,7 @@ do_unlock_pi(struct thread *td, struct umutex *m, uint32_t flags)
 	/*
 	 * Make sure we own this mtx.
 	 */
-	error = fueword32(__DEVOLATILE(uint32_t *, &m->m_owner), &owner);
+	error = fueword32(&m->m_owner, &owner);
 	if (error == -1)
 		return (EFAULT);
 
@@ -2008,7 +2006,7 @@ do_unlock_pp(struct thread *td, struct umutex *m, uint32_t flags)
 	/*
 	 * Make sure we own this mtx.
 	 */
-	error = fueword32(__DEVOLATILE(uint32_t *, &m->m_owner), &owner);
+	error = fueword32(&m->m_owner, &owner);
 	if (error == -1)
 		return (EFAULT);
 
@@ -2040,8 +2038,7 @@ do_unlock_pp(struct thread *td, struct umutex *m, uint32_t flags)
 	 * to lock the mutex, it is necessary because thread priority
 	 * has to be adjusted for such mutex.
 	 */
-	error = suword32(__DEVOLATILE(uint32_t *, &m->m_owner),
-		UMUTEX_CONTESTED);
+	error = suword32(&m->m_owner, UMUTEX_CONTESTED);
 
 	umtxq_lock(&key);
 	if (error == 0)
@@ -2116,8 +2113,7 @@ do_set_ceiling(struct thread *td, struct umutex *m, uint32_t ceiling,
 
 		if (owner == UMUTEX_CONTESTED) {
 			suword32(&m->m_ceilings[0], ceiling);
-			suword32(__DEVOLATILE(uint32_t *, &m->m_owner),
-				UMUTEX_CONTESTED);
+			suword32(&m->m_owner, UMUTEX_CONTESTED);
 			error = 0;
 			break;
 		}
@@ -2263,10 +2259,9 @@ do_cv_wait(struct thread *td, struct ucond *cv, struct umutex *m,
 	 * Set c_has_waiters to 1 before releasing user mutex, also
 	 * don't modify cache line when unnecessary.
 	 */
-	error = fueword32(__DEVOLATILE(uint32_t *, &cv->c_has_waiters),
-	    &hasw);
+	error = fueword32(&cv->c_has_waiters, &hasw);
 	if (error == 0 && hasw == 0)
-		suword32(__DEVOLATILE(uint32_t *, &cv->c_has_waiters), 1);
+		suword32(&cv->c_has_waiters, 1);
 
 	umtxq_unbusy_unlocked(&uq->uq_key);
 
@@ -2296,9 +2291,7 @@ do_cv_wait(struct thread *td, struct ucond *cv, struct umutex *m,
 			umtxq_remove(uq);
 			if (oldlen == 1) {
 				umtxq_unlock(&uq->uq_key);
-				suword32(
-				    __DEVOLATILE(uint32_t *,
-					 &cv->c_has_waiters), 0);
+				suword32(&cv->c_has_waiters, 0);
 				umtxq_lock(&uq->uq_key);
 			}
 		}
@@ -2333,8 +2326,7 @@ do_cv_signal(struct thread *td, struct ucond *cv)
 	nwake = umtxq_signal(&key, 1);
 	if (cnt <= nwake) {
 		umtxq_unlock(&key);
-		error = suword32(
-		    __DEVOLATILE(uint32_t *, &cv->c_has_waiters), 0);
+		error = suword32(&cv->c_has_waiters, 0);
 		if (error == -1)
 			error = EFAULT;
 		umtxq_lock(&key);
@@ -2363,7 +2355,7 @@ do_cv_broadcast(struct thread *td, struct ucond *cv)
 	umtxq_signal(&key, INT_MAX);
 	umtxq_unlock(&key);
 
-	error = suword32(__DEVOLATILE(uint32_t *, &cv->c_has_waiters), 0);
+	error = suword32(&cv->c_has_waiters, 0);
 	if (error == -1)
 		error = EFAULT;
 
@@ -2399,8 +2391,7 @@ do_rw_rdlock(struct thread *td, struct urwlock *rwlock, long fflag, struct _umtx
 		wrflags |= URWLOCK_WRITE_WAITERS;
 
 	for (;;) {
-		rv = fueword32(__DEVOLATILE(int32_t *, &rwlock->rw_state),
-		    &state);
+		rv = fueword32(&rwlock->rw_state, &state);
 		if (rv == -1) {
 			umtx_key_release(&uq->uq_key);
 			return (EFAULT);
@@ -2440,8 +2431,7 @@ do_rw_rdlock(struct thread *td, struct urwlock *rwlock, long fflag, struct _umtx
 		 * re-read the state, in case it changed between the try-lock above
 		 * and the check below
 		 */
-		rv = fueword32(__DEVOLATILE(int32_t *, &rwlock->rw_state),
-		    &state);
+		rv = fueword32(&rwlock->rw_state, &state);
 		if (rv == -1)
 			error = EFAULT;
 
@@ -2499,8 +2489,7 @@ sleep:
 			umtxq_unlock(&uq->uq_key);
 			if (error)
 				break;
-			rv = fueword32(__DEVOLATILE(int32_t *,
-			    &rwlock->rw_state), &state);
+			rv = fueword32(&rwlock->rw_state, &state);
 			if (rv == -1) {
 				error = EFAULT;
 				break;
@@ -2517,8 +2506,7 @@ sleep:
 		}
 		suword32(&rwlock->rw_blocked_readers, blocked_readers-1);
 		if (blocked_readers == 1) {
-			rv = fueword32(__DEVOLATILE(int32_t *,
-			    &rwlock->rw_state), &state);
+			rv = fueword32(&rwlock->rw_state, &state);
 			if (rv == -1)
 				error = EFAULT;
 			while (error == 0) {
@@ -2569,8 +2557,7 @@ do_rw_wrlock(struct thread *td, struct urwlock *rwlock, struct _umtx_time *timeo
 
 	blocked_readers = 0;
 	for (;;) {
-		rv = fueword32(__DEVOLATILE(int32_t *, &rwlock->rw_state),
-		    &state);
+		rv = fueword32(&rwlock->rw_state, &state);
 		if (rv == -1) {
 			umtx_key_release(&uq->uq_key);
 			return (EFAULT);
@@ -2614,8 +2601,7 @@ do_rw_wrlock(struct thread *td, struct urwlock *rwlock, struct _umtx_time *timeo
 		 * re-read the state, in case it changed between the try-lock above
 		 * and the check below
 		 */
-		rv = fueword32(__DEVOLATILE(int32_t *, &rwlock->rw_state),
-		    &state);
+		rv = fueword32(&rwlock->rw_state, &state);
 		if (rv == -1)
 			error = EFAULT;
 
@@ -2670,8 +2656,7 @@ sleep:
 			umtxq_unlock(&uq->uq_key);
 			if (error)
 				break;
-			rv = fueword32(__DEVOLATILE(int32_t *,
-			    &rwlock->rw_state), &state);
+			rv = fueword32(&rwlock->rw_state, &state);
 			if (rv == -1) {
 				error = EFAULT;
 				break;
@@ -2687,8 +2672,7 @@ sleep:
 		}
 		suword32(&rwlock->rw_blocked_writers, blocked_writers-1);
 		if (blocked_writers == 1) {
-			rv = fueword32(__DEVOLATILE(int32_t *,
-			    &rwlock->rw_state), &state);
+			rv = fueword32(&rwlock->rw_state, &state);
 			if (rv == -1) {
 				umtxq_unbusy_unlocked(&uq->uq_key);
 				error = EFAULT;
@@ -2748,7 +2732,7 @@ do_rw_unlock(struct thread *td, struct urwlock *rwlock)
 	if (error != 0)
 		return (error);
 
-	error = fueword32(__DEVOLATILE(int32_t *, &rwlock->rw_state), &state);
+	error = fueword32(&rwlock->rw_state, &state);
 	if (error == -1) {
 		error = EFAULT;
 		goto out;
@@ -2856,7 +2840,7 @@ do_sem_wait(struct thread *td, struct _usem *sem, struct _umtx_time *timeout)
 	umtxq_unlock(&uq->uq_key);
 	rv = casueword32(&sem->_has_waiters, 0, &count1, 1);
 	if (rv == 0)
-		rv = fueword32(__DEVOLATILE(uint32_t *, &sem->_count), &count);
+		rv = fueword32(&sem->_count, &count);
 	if (rv == -1 || count != 0) {
 		umtxq_lock(&uq->uq_key);
 		umtxq_unbusy(&uq->uq_key);
@@ -2911,8 +2895,7 @@ do_sem_wake(struct thread *td, struct _usem *sem)
 		 */
 		if (cnt == 1) {
 			umtxq_unlock(&key);
-			error = suword32(
-			    __DEVOLATILE(uint32_t *, &sem->_has_waiters), 0);
+			error = suword32(&sem->_has_waiters, 0);
 			umtxq_lock(&key);
 			if (error == -1)
 				error = EFAULT;
@@ -2946,7 +2929,7 @@ do_sem2_wait(struct thread *td, struct _usem2 *sem, struct _umtx_time *timeout)
 	umtxq_busy(&uq->uq_key);
 	umtxq_insert(uq);
 	umtxq_unlock(&uq->uq_key);
-	rv = fueword32(__DEVOLATILE(uint32_t *, &sem->_count), &count);
+	rv = fueword32(&sem->_count, &count);
 	if (rv == -1) {
 		umtxq_lock(&uq->uq_key);
 		umtxq_unbusy(&uq->uq_key);
@@ -3024,8 +3007,7 @@ do_sem2_wake(struct thread *td, struct _usem2 *sem)
 		 */
 		if (cnt == 1) {
 			umtxq_unlock(&key);
-			rv = fueword32(__DEVOLATILE(uint32_t *, &sem->_count),
-			    &count);
+			rv = fueword32(&sem->_count, &count);
 			while (rv != -1 && count & USEM_HAS_WAITERS)
 				rv = casueword32(&sem->_count, count, &count,
 				    count & ~USEM_HAS_WAITERS);
diff --git a/sys/kern/subr_uio.c b/sys/kern/subr_uio.c
index f2bbb0c..87892fd 100644
--- a/sys/kern/subr_uio.c
+++ b/sys/kern/subr_uio.c
@@ -453,7 +453,7 @@ copyout_unmap(struct thread *td, vm_offset_t addr, size_t sz)
  */
 
 int
-fueword(const void *base, long *val)
+fueword(volatile const void *base, long *val)
 {
 	long res;
 
@@ -465,7 +465,7 @@ fueword(const void *base, long *val)
 }
 
 int
-fueword32(const void *base, int32_t *val)
+fueword32(volatile const void *base, int32_t *val)
 {
 	int32_t res;
 
@@ -478,7 +478,7 @@ fueword32(const void *base, int32_t *val)
 
 #ifdef _LP64
 int
-fueword64(const void *base, int64_t *val)
+fueword64(volatile const void *base, int64_t *val)
 {
 	int32_t res;
 
@@ -516,7 +516,7 @@ casueword(volatile u_long *p, u_long oldval, u_long *oldvalp, u_long newval)
 }
 #else /* NO_FUEWORD */
 int32_t
-fuword32(const void *addr)
+fuword32(volatile const void *addr)
 {
 	int rv;
 	int32_t val;
@@ -527,7 +527,7 @@ fuword32(const void *addr)
 
 #ifdef _LP64
 int64_t
-fuword64(const void *addr)
+fuword64(volatile const void *addr)
 {
 	int rv;
 	int64_t val;
@@ -538,7 +538,7 @@ fuword64(const void *addr)
 #endif /* _LP64 */
 
 long
-fuword(const void *addr)
+fuword(volatile const void *addr)
 {
 	long val;
 	int rv;
diff --git a/sys/powerpc/powerpc/copyinout.c b/sys/powerpc/powerpc/copyinout.c
index a337c8b..ddaf33f 100644
--- a/sys/powerpc/powerpc/copyinout.c
+++ b/sys/powerpc/powerpc/copyinout.c
@@ -281,7 +281,7 @@ copyinstr(const void *udaddr, void *kaddr, size_t len, size_t *done)
 }
 
 int
-subyte(void *addr, int byte)
+subyte(volatile void *addr, int byte)
 {
 	struct		thread *td;
 	pmap_t		pm;
@@ -309,7 +309,7 @@ subyte(void *addr, int byte)
 
 #ifdef __powerpc64__
 int
-suword32(void *addr, int word)
+suword32(volatile void *addr, int word)
 {
 	struct		thread *td;
 	pmap_t		pm;
@@ -337,7 +337,7 @@ suword32(void *addr, int word)
 #endif
 
 int
-suword(void *addr, long word)
+suword(volatile void *addr, long word)
 {
 	struct		thread *td;
 	pmap_t		pm;
@@ -365,20 +365,20 @@ suword(void *addr, long word)
 
 #ifdef __powerpc64__
 int
-suword64(void *addr, int64_t word)
+suword64(volatile void *addr, int64_t word)
 {
 	return (suword(addr, (long)word));
 }
 #else
 int
-suword32(void *addr, int32_t word)
+suword32(volatile void *addr, int32_t word)
 {
 	return (suword(addr, (long)word));
 }
 #endif
 
 int
-fubyte(const void *addr)
+fubyte(volatile const void *addr)
 {
 	struct		thread *td;
 	pmap_t		pm;
@@ -406,7 +406,7 @@ fubyte(const void *addr)
 }
 
 int
-fuword16(const void *addr)
+fuword16(volatile const void *addr)
 {
 	struct		thread *td;
 	pmap_t		pm;
@@ -433,7 +433,7 @@ fuword16(const void *addr)
 }
 
 int
-fueword32(const void *addr, int32_t *val)
+fueword32(volatile const void *addr, int32_t *val)
 {
 	struct		thread *td;
 	pmap_t		pm;
@@ -461,7 +461,7 @@ fueword32(const void *addr, int32_t *val)
 
 #ifdef __powerpc64__
 int
-fueword64(const void *addr, int64_t *val)
+fueword64(volatile const void *addr, int64_t *val)
 {
 	struct		thread *td;
 	pmap_t		pm;
@@ -489,7 +489,7 @@ fueword64(const void *addr, int64_t *val)
 #endif
 
 int
-fueword(const void *addr, long *val)
+fueword(volatile const void *addr, long *val)
 {
 	struct		thread *td;
 	pmap_t		pm;
diff --git a/sys/sys/systm.h b/sys/sys/systm.h
index 6e5ee61..47156fb 100644
--- a/sys/sys/systm.h
+++ b/sys/sys/systm.h
@@ -252,19 +252,19 @@ int	copyout(const void * __restrict kaddr, void * __restrict udaddr,
 int	copyout_nofault(const void * __restrict kaddr, void * __restrict udaddr,
 	    size_t len) __nonnull(1) __nonnull(2);
 
-int	fubyte(const void *base);
-long	fuword(const void *base);
-int	fuword16(const void *base);
-int32_t	fuword32(const void *base);
-int64_t	fuword64(const void *base);
-int	fueword(const void *base, long *val);
-int	fueword32(const void *base, int32_t *val);
-int	fueword64(const void *base, int64_t *val);
-int	subyte(void *base, int byte);
-int	suword(void *base, long word);
-int	suword16(void *base, int word);
-int	suword32(void *base, int32_t word);
-int	suword64(void *base, int64_t word);
+int	fubyte(volatile const void *base);
+long	fuword(volatile const void *base);
+int	fuword16(volatile const void *base);
+int32_t	fuword32(volatile const void *base);
+int64_t	fuword64(volatile const void *base);
+int	fueword(volatile const void *base, long *val);
+int	fueword32(volatile const void *base, int32_t *val);
+int	fueword64(volatile const void *base, int64_t *val);
+int	subyte(volatile void *base, int byte);
+int	suword(volatile void *base, long word);
+int	suword16(volatile void *base, int word);
+int	suword32(volatile void *base, int32_t word);
+int	suword64(volatile void *base, int64_t word);
 uint32_t casuword32(volatile uint32_t *base, uint32_t oldval, uint32_t newval);
 u_long	casuword(volatile u_long *p, u_long oldval, u_long newval);
 int	casueword32(volatile uint32_t *base, uint32_t oldval, uint32_t *oldvalp,



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