Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F140308222
D20772.id59112.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
27 KB
Referenced Files
None
Subscribers
None
D20772.id59112.diff
View Options
Index: share/man/man9/casuword.9
===================================================================
--- share/man/man9/casuword.9
+++ share/man/man9/casuword.9
@@ -1,4 +1,4 @@
-.\" Copyright (c) 2014 The FreeBSD Foundation
+.\" Copyright (c) 2014, 2019 The FreeBSD Foundation
.\" All rights reserved.
.\"
.\" Part of this documentation was written by
@@ -28,7 +28,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd October 21, 2014
+.Dd April 19, 2019
.Dt CASU 9
.Os
.Sh NAME
@@ -41,13 +41,31 @@
.In sys/types.h
.In sys/systm.h
.Ft int
-.Fn casueword "volatile u_long *base" "u_long oldval" "u_long *oldvalp" "u_long newval"
+.Fo casueword
+.Fa "volatile u_long *base"
+.Fa "u_long oldval"
+.Fa "u_long *oldvalp"
+.Fa "u_long newval"
+.Fc
.Ft int
-.Fn casueword32 "volatile uint32_t *base" "uint32_t oldval" "uint32_t *oldvalp" "uint32_t newval"
+.Fo casueword32
+.Fa "volatile uint32_t *base"
+.Fa "uint32_t oldval"
+.Fa "uint32_t *oldvalp"
+.Fa "uint32_t newval"
+.Fc
.Ft u_long
-.Fn casuword "volatile u_long *base" "u_long oldval" "u_long newval"
+.Fo casuword
+.Fa "volatile u_long *base"
+.Fa "u_long oldval"
+.Fa "u_long newval"
+.Fc
.Ft uint32_t
-.Fn casuword32 "volatile uint32_t *base" "uint32_t oldval" "uint32_t newval"
+.Fo casuword32
+.Fa "volatile uint32_t *base"
+.Fa "uint32_t oldval"
+.Fa "uint32_t newval"
+.Fc
.Sh DESCRIPTION
The
.Nm
@@ -88,7 +106,9 @@
.Fn casueword
and
.Fn casueword32
-functions return 0 on success and -1 on failure.
+functions return 0 on success, -1 on failure to access memory,
+and 1 when comparison or store failed.
+The store can fail on load-linked/store-conditional architectures.
.Sh SEE ALSO
.Xr atomic 9 ,
.Xr fetch 9 ,
Index: sys/amd64/amd64/support.S
===================================================================
--- sys/amd64/amd64/support.S
+++ sys/amd64/amd64/support.S
@@ -811,6 +811,7 @@
lock
#endif
cmpxchgl %ecx,(%rdi) /* new = %ecx */
+ setne %cl
/*
* The old value is in %eax. If the store succeeded it will be the
@@ -828,6 +829,7 @@
*/
movl %esi,(%rdx) /* oldp = %rdx */
POP_FRAME_POINTER
+ movzbl %cl, %eax
ret
END(casueword32_nosmap)
@@ -847,6 +849,7 @@
#endif
cmpxchgl %ecx,(%rdi) /* new = %ecx */
clac
+ setne %cl
/*
* The old value is in %eax. If the store succeeded it will be the
@@ -864,6 +867,7 @@
*/
movl %esi,(%rdx) /* oldp = %rdx */
POP_FRAME_POINTER
+ movzbl %cl, %eax
ret
END(casueword32_smap)
@@ -886,6 +890,7 @@
lock
#endif
cmpxchgq %rcx,(%rdi) /* new = %rcx */
+ setne %cl
/*
* The old value is in %rax. If the store succeeded it will be the
@@ -897,6 +902,7 @@
movq %rax,PCB_ONFAULT(%r8)
movq %rsi,(%rdx)
POP_FRAME_POINTER
+ movzbl %cl, %eax
ret
END(casueword_nosmap)
@@ -916,6 +922,7 @@
#endif
cmpxchgq %rcx,(%rdi) /* new = %rcx */
clac
+ setne %cl
/*
* The old value is in %rax. If the store succeeded it will be the
@@ -927,6 +934,7 @@
movq %rax,PCB_ONFAULT(%r8)
movq %rsi,(%rdx)
POP_FRAME_POINTER
+ movzbl %cl, %eax
ret
END(casueword_smap)
Index: sys/arm/arm/fusu.S
===================================================================
--- sys/arm/arm/fusu.S
+++ sys/arm/arm/fusu.S
@@ -63,7 +63,7 @@
ldr r4, =(VM_MAXUSER_ADDRESS-3)
cmp r0, r4
mvncs r0, #0
- bcs 2f
+ bcs 1f
GET_PCB(r6)
ldr r6, [r6]
@@ -78,12 +78,10 @@
str r4, [r6, #PCB_ONFAULT]
#if __ARM_ARCH >= 6
-1:
+ mov r5, #1
ldrex r4, [r0]
cmp r4, r1
strexeq r5, r3, [r0]
- cmpeq r5, #1
- beq 1b
#else
ldrt r4, [r0]
cmp r4, r1
@@ -92,7 +90,10 @@
str r4, [r2]
mov r0, #0
str r0, [r6, #PCB_ONFAULT]
-2:
+#if __ARM_ARCH >= 6
+ mov r0, r5
+#endif
+1:
ldmfd sp!, {r4, r5, r6}
RET
EEND(casueword32)
Index: sys/arm64/arm64/support.S
===================================================================
--- sys/arm64/arm64/support.S
+++ sys/arm64/arm64/support.S
@@ -63,11 +63,10 @@
cmp w4, w1 /* Compare */
b.ne 2f /* Not equal, exit */
stxr w5, w3, [x0] /* Store the new data */
- cbnz w5, 1b /* Retry on failure */
2: EXIT_USER_ACCESS(w6)
SET_FAULT_HANDLER(xzr, x5) /* Reset the fault handler */
str w4, [x2] /* Store the read data */
- mov x0, #0 /* Success */
+ mov w0, w5 /* Result same as store status */
ret /* Return */
END(casueword32)
@@ -85,11 +84,10 @@
cmp x4, x1 /* Compare */
b.ne 2f /* Not equal, exit */
stxr w5, x3, [x0] /* Store the new data */
- cbnz w5, 1b /* Retry on failure */
2: EXIT_USER_ACCESS(w6)
SET_FAULT_HANDLER(xzr, x5) /* Reset the fault handler */
str x4, [x2] /* Store the read data */
- mov x0, #0 /* Success */
+ mov w0, w5 /* Result same as store status */
ret /* Return */
END(casueword)
Index: sys/i386/i386/copyout.c
===================================================================
--- sys/i386/i386/copyout.c
+++ sys/i386/i386/copyout.c
@@ -428,6 +428,7 @@
struct casueword_arg0 {
uint32_t oldval;
uint32_t newval;
+ int res;
};
static void
@@ -436,7 +437,7 @@
struct casueword_arg0 *ca;
ca = arg;
- atomic_fcmpset_int((u_int *)kva, &ca->oldval, ca->newval);
+ ca->res = atomic_fcmpset_int((u_int *)kva, &ca->oldval, ca->newval);
}
int
@@ -452,7 +453,7 @@
casueword_slow0, &ca);
if (res == 0) {
*oldvalp = ca.oldval;
- return (0);
+ return (ca.res);
}
return (-1);
}
@@ -469,7 +470,7 @@
casueword_slow0, &ca);
if (res == 0) {
*oldvalp = ca.oldval;
- return (0);
+ return (ca.res);
}
return (-1);
}
Index: sys/kern/kern_umtx.c
===================================================================
--- sys/kern/kern_umtx.c
+++ sys/kern/kern_umtx.c
@@ -691,7 +691,7 @@
}
static int
-umtxq_check_susp(struct thread *td)
+umtxq_check_susp(struct thread *td, bool sleep)
{
struct proc *p;
int error;
@@ -710,7 +710,7 @@
if (p->p_flag & P_SINGLE_EXIT)
error = EINTR;
else
- error = ERESTART;
+ error = sleep ? thread_suspend_check(0) : ERESTART;
}
PROC_UNLOCK(p);
return (error);
@@ -1026,6 +1026,7 @@
* Care must be exercised when dealing with umtx structure. It
* can fault on any access.
*/
+again:
for (;;) {
rv = fueword32(&m->m_owner, &owner);
if (rv == -1)
@@ -1049,9 +1050,12 @@
id | UMUTEX_CONTESTED);
if (rv == -1)
return (EFAULT);
- if (owner == UMUTEX_RB_OWNERDEAD)
+ if (rv == 0) {
+ MPASS(owner == UMUTEX_RB_OWNERDEAD);
return (EOWNERDEAD); /* success */
- rv = umtxq_check_susp(td);
+ }
+ MPASS(rv == 1);
+ rv = umtxq_check_susp(td, true);
if (rv != 0)
return (rv);
continue;
@@ -1059,7 +1063,6 @@
if (owner == UMUTEX_RB_NOTRECOV)
return (ENOTRECOVERABLE);
-
/*
* Try the uncontested case. This should be
* done in userland.
@@ -1071,13 +1074,16 @@
return (EFAULT);
/* The acquire succeeded. */
- if (owner == UMUTEX_UNOWNED)
+ if (rv == 0) {
+ MPASS(owner == UMUTEX_UNOWNED);
return (0);
+ }
/*
* If no one owns it but it is contested try
* to acquire it.
*/
+ MPASS(rv == 1);
if (owner == UMUTEX_CONTESTED) {
rv = casueword32(&m->m_owner,
UMUTEX_CONTESTED, &owner,
@@ -1085,13 +1091,15 @@
/* The address was invalid. */
if (rv == -1)
return (EFAULT);
-
- if (owner == UMUTEX_CONTESTED)
+ if (rv == 0) {
+ MPASS(owner == UMUTEX_CONTESTED);
return (0);
-
- rv = umtxq_check_susp(td);
- if (rv != 0)
- return (rv);
+ }
+ if (rv == 1) {
+ rv = umtxq_check_susp(td, false);
+ if (rv != 0)
+ return (rv);
+ }
/*
* If this failed the lock has
@@ -1099,6 +1107,11 @@
*/
continue;
}
+
+ /* rv == 1 but not contested, likely store failure */
+ rv = umtxq_check_susp(td, false);
+ if (rv != 0)
+ return (rv);
}
if (mode == _UMUTEX_TRY)
@@ -1129,14 +1142,21 @@
rv = casueword32(&m->m_owner, owner, &old,
owner | UMUTEX_CONTESTED);
- /* The address was invalid. */
- if (rv == -1) {
+ /* The address was invalid or casueword failed to store. */
+ if (rv == -1 || rv == 1) {
umtxq_lock(&uq->uq_key);
umtxq_remove(uq);
umtxq_unbusy(&uq->uq_key);
umtxq_unlock(&uq->uq_key);
umtx_key_release(&uq->uq_key);
- return (EFAULT);
+ if (rv == -1)
+ return (EFAULT);
+ if (rv == 1) {
+ rv = umtxq_check_susp(td, true);
+ if (rv != 0)
+ return (rv);
+ }
+ goto again;
}
/*
@@ -1154,7 +1174,7 @@
umtx_key_release(&uq->uq_key);
if (error == 0)
- error = umtxq_check_susp(td);
+ error = umtxq_check_susp(td, false);
}
return (0);
@@ -1171,6 +1191,8 @@
int error, count;
id = td->td_tid;
+
+again:
/*
* Make sure we own this mtx.
*/
@@ -1186,6 +1208,12 @@
error = casueword32(&m->m_owner, owner, &old, newlock);
if (error == -1)
return (EFAULT);
+ if (error == 1) {
+ error = umtxq_check_susp(td, true);
+ if (error != 0)
+ return (error);
+ goto again;
+ }
if (old == owner)
return (0);
owner = old;
@@ -1216,6 +1244,12 @@
umtx_key_release(&key);
if (error == -1)
return (EFAULT);
+ if (error == 1) {
+ error = umtxq_check_susp(td, true);
+ if (error != 0)
+ return (error);
+ goto again;
+ }
if (old != owner)
return (EINVAL);
return (0);
@@ -1234,6 +1268,7 @@
int error;
int count;
+again:
error = fueword32(&m->m_owner, &owner);
if (error == -1)
return (EFAULT);
@@ -1260,8 +1295,17 @@
owner != UMUTEX_RB_NOTRECOV) {
error = casueword32(&m->m_owner, UMUTEX_CONTESTED, &owner,
UMUTEX_UNOWNED);
- if (error == -1)
+ if (error == -1) {
error = EFAULT;
+ } else if (error == 1) {
+ umtxq_unbusy(&key);
+ umtxq_unlock(&key);
+ umtx_key_release(&key);
+ error = umtxq_check_susp(td, true);
+ if (error != 0)
+ return (error);
+ goto again;
+ }
}
umtxq_lock(&key);
@@ -1331,12 +1375,10 @@
error = EFAULT;
break;
}
- if (old == owner)
+ if (error == 0 && old == owner)
break;
owner = old;
- error = umtxq_check_susp(td);
- if (error != 0)
- break;
+ error = umtxq_check_susp(td, true);
}
} else if (count == 1) {
error = fueword32(&m->m_owner, &owner);
@@ -1350,12 +1392,12 @@
error = EFAULT;
break;
}
- if (old == owner)
+ if (error == 0) {
+ MPASS(old == owner);
break;
+ }
owner = old;
- error = umtxq_check_susp(td);
- if (error != 0)
- break;
+ error = umtxq_check_susp(td, true);
}
}
umtxq_lock(&key);
@@ -1843,6 +1885,11 @@
error = EFAULT;
break;
}
+ if (rv == 1) {
+ error = umtxq_check_susp(td, true);
+ if (error != 0)
+ break;
+ }
/* The acquire succeeded. */
if (owner == UMUTEX_UNOWNED) {
@@ -1865,8 +1912,15 @@
error = EFAULT;
break;
}
+ if (rv == 1) {
+ error = umtxq_check_susp(td, true);
+ if (error != 0)
+ return (error);
+ continue;
+ }
- if (owner == old_owner) {
+ if (rv == 0) {
+ MPASS(owner == old_owner);
umtxq_lock(&uq->uq_key);
umtxq_busy(&uq->uq_key);
error = umtx_pi_claim(pi, td);
@@ -1889,7 +1943,7 @@
break;
}
- error = umtxq_check_susp(td);
+ error = umtxq_check_susp(td, false);
if (error != 0)
break;
@@ -1933,6 +1987,13 @@
error = EFAULT;
break;
}
+ if (rv == 1) {
+ umtxq_unbusy_unlocked(&uq->uq_key);
+ error = umtxq_check_susp(td, true);
+ if (error != 0)
+ break;
+ continue;
+ }
umtxq_lock(&uq->uq_key);
/*
@@ -1953,7 +2014,7 @@
umtxq_unlock(&uq->uq_key);
}
- error = umtxq_check_susp(td);
+ error = umtxq_check_susp(td, true);
if (error != 0)
break;
}
@@ -1979,6 +2040,8 @@
int count, error, pri;
id = td->td_tid;
+
+usrloop:
/*
* Make sure we own this mtx.
*/
@@ -1996,6 +2059,12 @@
error = casueword32(&m->m_owner, owner, &old, new_owner);
if (error == -1)
return (EFAULT);
+ if (error == 1) {
+ error = umtxq_check_susp(td, true);
+ if (error != 0)
+ return (error);
+ goto usrloop;
+ }
if (old == owner)
return (0);
owner = old;
@@ -2075,15 +2144,20 @@
if (count > 1)
new_owner |= UMUTEX_CONTESTED;
+again:
error = casueword32(&m->m_owner, owner, &old, new_owner);
-
+ if (error == 1) {
+ error = umtxq_check_susp(td, true);
+ if (error == 0)
+ goto again;
+ }
umtxq_unbusy_unlocked(&key);
umtx_key_release(&key);
if (error == -1)
return (EFAULT);
- if (old != owner)
+ if (error == 0 && old != owner)
return (EINVAL);
- return (0);
+ return (error);
}
/*
@@ -2149,26 +2223,31 @@
if (rv == -1) {
error = EFAULT;
break;
- }
-
- if (owner == UMUTEX_CONTESTED) {
- error = 0;
- break;
- } else if (owner == UMUTEX_RB_OWNERDEAD) {
- rv = casueword32(&m->m_owner, UMUTEX_RB_OWNERDEAD,
- &owner, id | UMUTEX_CONTESTED);
- if (rv == -1) {
- error = EFAULT;
+ } else if (rv == 0) {
+ if (owner == UMUTEX_CONTESTED) {
+ error = 0;
break;
- }
- if (owner == UMUTEX_RB_OWNERDEAD) {
- error = EOWNERDEAD; /* success */
+ } else if (owner == UMUTEX_RB_OWNERDEAD) {
+ rv = casueword32(&m->m_owner,
+ UMUTEX_RB_OWNERDEAD,
+ &owner, id | UMUTEX_CONTESTED);
+ if (rv == -1) {
+ error = EFAULT;
+ break;
+ } else if (rv == 0) {
+ MPASS(owner == UMUTEX_RB_OWNERDEAD);
+ error = EOWNERDEAD; /* success */
+ break;
+ } else if (rv == 1) {
+ /* XXXKIB */
+ }
+ error = 0;
+ } else if (owner == UMUTEX_RB_NOTRECOV) {
+ error = ENOTRECOVERABLE;
break;
}
- error = 0;
- } else if (owner == UMUTEX_RB_NOTRECOV) {
- error = ENOTRECOVERABLE;
- break;
+ } else /* rv == 1 */ {
+ /* XXXKIB */
}
if (try != 0) {
@@ -2624,7 +2703,8 @@
}
static int
-do_rw_rdlock(struct thread *td, struct urwlock *rwlock, long fflag, struct _umtx_time *timeout)
+do_rw_rdlock(struct thread *td, struct urwlock *rwlock, long fflag,
+ struct _umtx_time *timeout)
{
struct abs_timeout timo;
struct umtx_q *uq;
@@ -2657,7 +2737,8 @@
/* try to lock it */
while (!(state & wrflags)) {
- if (__predict_false(URWLOCK_READER_COUNT(state) == URWLOCK_MAX_READERS)) {
+ if (__predict_false(URWLOCK_READER_COUNT(state) ==
+ URWLOCK_MAX_READERS)) {
umtx_key_release(&uq->uq_key);
return (EAGAIN);
}
@@ -2667,11 +2748,12 @@
umtx_key_release(&uq->uq_key);
return (EFAULT);
}
- if (oldstate == state) {
+ if (rv == 0) {
+ MPASS(oldstate == state);
umtx_key_release(&uq->uq_key);
return (0);
}
- error = umtxq_check_susp(td);
+ error = umtxq_check_susp(td, true);
if (error != 0)
break;
state = oldstate;
@@ -2702,10 +2784,12 @@
error = EFAULT;
break;
}
- if (oldstate == state)
+ if (rv == 0) {
+ MPASS(oldstate == state);
goto sleep;
+ }
state = oldstate;
- error = umtxq_check_susp(td);
+ error = umtxq_check_susp(td, true);
if (error != 0)
break;
}
@@ -2717,14 +2801,17 @@
/* state is changed while setting flags, restart */
if (!(state & wrflags)) {
umtxq_unbusy_unlocked(&uq->uq_key);
- error = umtxq_check_susp(td);
+ error = umtxq_check_susp(td, true);
if (error != 0)
break;
continue;
}
sleep:
- /* contention bit is set, before sleeping, increase read waiter count */
+ /*
+ * Contention bit is set, before sleeping, increase
+ * read waiter count.
+ */
rv = fueword32(&rwlock->rw_blocked_readers,
&blocked_readers);
if (rv == -1) {
@@ -2777,10 +2864,12 @@
error = EFAULT;
break;
}
- if (oldstate == state)
+ if (rv == 0) {
+ MPASS(oldstate == state);
break;
+ }
state = oldstate;
- error1 = umtxq_check_susp(td);
+ error1 = umtxq_check_susp(td, true);
if (error1 != 0) {
if (error == 0)
error = error1;
@@ -2828,29 +2917,33 @@
umtx_key_release(&uq->uq_key);
return (EFAULT);
}
- while (!(state & URWLOCK_WRITE_OWNER) && URWLOCK_READER_COUNT(state) == 0) {
+ while ((state & URWLOCK_WRITE_OWNER) == 0 &&
+ URWLOCK_READER_COUNT(state) == 0) {
rv = casueword32(&rwlock->rw_state, state,
&oldstate, state | URWLOCK_WRITE_OWNER);
if (rv == -1) {
umtx_key_release(&uq->uq_key);
return (EFAULT);
}
- if (oldstate == state) {
+ if (rv == 0) {
+ MPASS(oldstate == state);
umtx_key_release(&uq->uq_key);
return (0);
}
state = oldstate;
- error = umtxq_check_susp(td);
+ error = umtxq_check_susp(td, true);
if (error != 0)
break;
}
if (error) {
- if (!(state & (URWLOCK_WRITE_OWNER|URWLOCK_WRITE_WAITERS)) &&
+ if ((state & (URWLOCK_WRITE_OWNER |
+ URWLOCK_WRITE_WAITERS)) == 0 &&
blocked_readers != 0) {
umtxq_lock(&uq->uq_key);
umtxq_busy(&uq->uq_key);
- umtxq_signal_queue(&uq->uq_key, INT_MAX, UMTX_SHARED_QUEUE);
+ umtxq_signal_queue(&uq->uq_key, INT_MAX,
+ UMTX_SHARED_QUEUE);
umtxq_unbusy(&uq->uq_key);
umtxq_unlock(&uq->uq_key);
}
@@ -2864,8 +2957,8 @@
umtxq_unlock(&uq->uq_key);
/*
- * re-read the state, in case it changed between the try-lock above
- * and the check below
+ * Re-read the state, in case it changed between the
+ * try-lock above and the check below.
*/
rv = fueword32(&rwlock->rw_state, &state);
if (rv == -1)
@@ -2880,10 +2973,12 @@
error = EFAULT;
break;
}
- if (oldstate == state)
+ if (rv == 0) {
+ MPASS(oldstate == state);
goto sleep;
+ }
state = oldstate;
- error = umtxq_check_susp(td);
+ error = umtxq_check_susp(td, true);
if (error != 0)
break;
}
@@ -2892,9 +2987,10 @@
break;
}
- if (!(state & URWLOCK_WRITE_OWNER) && URWLOCK_READER_COUNT(state) == 0) {
+ if ((state & URWLOCK_WRITE_OWNER) == 0 &&
+ URWLOCK_READER_COUNT(state) == 0) {
umtxq_unbusy_unlocked(&uq->uq_key);
- error = umtxq_check_susp(td);
+ error = umtxq_check_susp(td, false);
if (error != 0)
break;
continue;
@@ -2907,9 +3003,10 @@
error = EFAULT;
break;
}
- suword32(&rwlock->rw_blocked_writers, blocked_writers+1);
+ suword32(&rwlock->rw_blocked_writers, blocked_writers + 1);
- while ((state & URWLOCK_WRITE_OWNER) || URWLOCK_READER_COUNT(state) != 0) {
+ while ((state & URWLOCK_WRITE_OWNER) ||
+ URWLOCK_READER_COUNT(state) != 0) {
umtxq_lock(&uq->uq_key);
umtxq_insert_queue(uq, UMTX_EXCLUSIVE_QUEUE);
umtxq_unbusy(&uq->uq_key);
@@ -2951,10 +3048,12 @@
error = EFAULT;
break;
}
- if (oldstate == state)
+ if (rv == 0) {
+ MPASS(oldstate == state);
break;
+ }
state = oldstate;
- error1 = umtxq_check_susp(td);
+ error1 = umtxq_check_susp(td, true);
/*
* We are leaving the URWLOCK_WRITE_WAITERS
* behind, but this should not harm the
@@ -3014,13 +3113,13 @@
error = EFAULT;
goto out;
}
- if (oldstate != state) {
+ if (rv == 1 || oldstate != state) {
state = oldstate;
if (!(oldstate & URWLOCK_WRITE_OWNER)) {
error = EPERM;
goto out;
}
- error = umtxq_check_susp(td);
+ error = umtxq_check_susp(td, true);
if (error != 0)
goto out;
} else
@@ -3034,13 +3133,13 @@
error = EFAULT;
goto out;
}
- if (oldstate != state) {
+ if (rv == 1 || oldstate != state) {
state = oldstate;
if (URWLOCK_READER_COUNT(oldstate) == 0) {
error = EPERM;
goto out;
}
- error = umtxq_check_susp(td);
+ error = umtxq_check_susp(td, true);
if (error != 0)
goto out;
} else
@@ -3090,7 +3189,7 @@
struct abs_timeout timo;
struct umtx_q *uq;
uint32_t flags, count, count1;
- int error, rv;
+ int error, rv, rv1;
uq = td->td_umtxq;
error = fueword32(&sem->_flags, &flags);
@@ -3107,15 +3206,24 @@
umtxq_busy(&uq->uq_key);
umtxq_insert(uq);
umtxq_unlock(&uq->uq_key);
+again:
rv = casueword32(&sem->_has_waiters, 0, &count1, 1);
if (rv == 0)
- rv = fueword32(&sem->_count, &count);
- if (rv == -1 || count != 0) {
+ rv1 = fueword32(&sem->_count, &count);
+ if (rv == -1 || (rv == 0 && (rv1 == -1 || count != 0)) || rv == 1) {
umtxq_lock(&uq->uq_key);
umtxq_unbusy(&uq->uq_key);
umtxq_remove(uq);
umtxq_unlock(&uq->uq_key);
umtx_key_release(&uq->uq_key);
+ if (rv == 1) {
+ rv = umtxq_check_susp(td, true);
+ if (rv == 0)
+ goto again;
+ return (rv);
+ }
+ if (rv == 0)
+ rv = rv1;
return (rv == -1 ? EFAULT : 0);
}
umtxq_lock(&uq->uq_key);
@@ -3194,6 +3302,7 @@
if (timeout != NULL)
abs_timeout_init2(&timo, timeout);
+again:
umtxq_lock(&uq->uq_key);
umtxq_busy(&uq->uq_key);
umtxq_insert(uq);
@@ -3219,13 +3328,18 @@
if (count == USEM_HAS_WAITERS)
break;
rv = casueword32(&sem->_count, 0, &count, USEM_HAS_WAITERS);
- if (rv == -1) {
+ if (rv == -1 || rv == 1) {
umtxq_lock(&uq->uq_key);
umtxq_unbusy(&uq->uq_key);
umtxq_remove(uq);
umtxq_unlock(&uq->uq_key);
umtx_key_release(&uq->uq_key);
- return (EFAULT);
+ if (rv == -1)
+ return (EFAULT);
+ rv = umtxq_check_susp(td, true);
+ if (rv != 0)
+ return (rv);
+ goto again;
}
if (count == 0)
break;
@@ -3281,11 +3395,19 @@
if (cnt == 1) {
umtxq_unlock(&key);
rv = fueword32(&sem->_count, &count);
- while (rv != -1 && count & USEM_HAS_WAITERS)
+ while (rv != -1 && count & USEM_HAS_WAITERS) {
rv = casueword32(&sem->_count, count, &count,
count & ~USEM_HAS_WAITERS);
+ if (rv == 1) {
+ rv = umtxq_check_susp(td, true);
+ if (rv != 0)
+ break;
+ }
+ }
if (rv == -1)
error = EFAULT;
+ if (rv > 0)
+ error = rv;
umtxq_lock(&key);
}
Index: sys/mips/mips/support.S
===================================================================
--- sys/mips/mips/support.S
+++ sys/mips/mips/support.S
@@ -336,19 +336,15 @@
GET_CPU_PCPU(v1)
PTR_L v1, PC_CURPCB(v1)
PTR_S v0, U_PCB_ONFAULT(v1)
-1:
+
+ li v0, 1
move t0, a3
ll t1, 0(a0)
- bne a1, t1, 2f
+ bne a1, t1, 1f
nop
sc t0, 0(a0) # store word
- beqz t0, 1b
- nop
- j 3f
- li v0, 0
-2:
- li v0, -1
-3:
+ xori v0, t0, 1
+1:
PTR_S zero, U_PCB_ONFAULT(v1)
jr ra
sw t1, 0(a2) # unconditionally store old word
@@ -363,19 +359,15 @@
GET_CPU_PCPU(v1)
PTR_L v1, PC_CURPCB(v1)
PTR_S v0, U_PCB_ONFAULT(v1)
-1:
+
+ li v0, 1
move t0, a3
lld t1, 0(a0)
- bne a1, t1, 2f
+ bne a1, t1, 1f
nop
scd t0, 0(a0) # store double word
- beqz t0, 1b
- nop
- j 3f
- li v0, 0
-2:
- li v0, -1
-3:
+ xori v0, t0, 1
+1:
PTR_S zero, U_PCB_ONFAULT(v1)
jr ra
sd t1, 0(a2) # unconditionally store old word
Index: sys/powerpc/powerpc/copyinout.c
===================================================================
--- sys/powerpc/powerpc/copyinout.c
+++ sys/powerpc/powerpc/copyinout.c
@@ -433,6 +433,7 @@
pmap_t pm;
jmp_buf env;
uint32_t *p, val;
+ int res;
td = curthread;
pm = &td->td_proc->p_vmspace->vm_pmap;
@@ -449,24 +450,26 @@
return (-1);
}
+ res = 0;
__asm __volatile (
- "1:\tlwarx %0, 0, %2\n\t" /* load old value */
- "cmplw %3, %0\n\t" /* compare */
- "bne 2f\n\t" /* exit if not equal */
- "stwcx. %4, 0, %2\n\t" /* attempt to store */
- "bne- 1b\n\t" /* spin if failed */
- "b 3f\n\t" /* we've succeeded */
+ "lwarx %0, 0, %3\n\t" /* load old value */
+ "cmplw %4, %0\n\t" /* compare */
+ "bne 1f\n\t" /* exit if not equal */
+ "stwcx. %5, 0, %3\n\t" /* attempt to store */
+ "bne- 1f\n\t" /* if failed */
+ "b 2f\n\t" /* we've succeeded */
+ "1:\n\t"
+ "stwcx. %0, 0, %4\n\t" /* clear reservation (74xx) */
+ "li %2, 1\n\t"
"2:\n\t"
- "stwcx. %0, 0, %2\n\t" /* clear reservation (74xx) */
- "3:\n\t"
- : "=&r" (val), "=m" (*p)
+ : "=&r" (val), "=m" (*p), "=&r" (res)
: "r" (p), "r" (old), "r" (new), "m" (*p)
: "cr0", "memory");
td->td_pcb->pcb_onfault = NULL;
*oldvalp = val;
- return (0);
+ return (res);
}
#ifndef __powerpc64__
@@ -485,6 +488,7 @@
pmap_t pm;
jmp_buf env;
u_long *p, val;
+ int res;
td = curthread;
pm = &td->td_proc->p_vmspace->vm_pmap;
@@ -501,23 +505,25 @@
return (-1);
}
+ res = 0;
__asm __volatile (
- "1:\tldarx %0, 0, %2\n\t" /* load old value */
- "cmpld %3, %0\n\t" /* compare */
- "bne 2f\n\t" /* exit if not equal */
- "stdcx. %4, 0, %2\n\t" /* attempt to store */
- "bne- 1b\n\t" /* spin if failed */
- "b 3f\n\t" /* we've succeeded */
+ "ldarx %0, 0, %3\n\t" /* load old value */
+ "cmpld %4, %0\n\t" /* compare */
+ "bne 1f\n\t" /* exit if not equal */
+ "stdcx. %5, 0, %3\n\t" /* attempt to store */
+ "bne- 1f\n\t" /* if failed */
+ "b 2f\n\t" /* we've succeeded */
+ "1:\n\t"
+ "stdcx. %0, 0, %3\n\t" /* clear reservation (74xx) */
+ "li %2, 1\n\t"
"2:\n\t"
- "stdcx. %0, 0, %2\n\t" /* clear reservation (74xx) */
- "3:\n\t"
- : "=&r" (val), "=m" (*p)
+ : "=&r" (val), "=m" (*p), "=&r" (res)
: "r" (p), "r" (old), "r" (new), "m" (*p)
: "cr0", "memory");
td->td_pcb->pcb_onfault = NULL;
*oldvalp = val;
- return (0);
+ return (res);
}
#endif
Index: sys/riscv/riscv/support.S
===================================================================
--- sys/riscv/riscv/support.S
+++ sys/riscv/riscv/support.S
@@ -60,14 +60,15 @@
la a6, fsu_fault /* Load the fault handler */
SET_FAULT_HANDLER(a6, a4) /* And set it */
ENTER_USER_ACCESS(a4)
-1: lr.w a4, 0(a0) /* Load-exclusive the data */
- bne a4, a1, 2f /* If not equal then exit */
+ lr.w a4, 0(a0) /* Load-exclusive the data */
+ bne a4, a1, 1f /* If not equal then exit */
sc.w a5, a3, 0(a0) /* Store the new data */
- bnez a5, 1b /* Retry on failure */
-2: EXIT_USER_ACCESS(a5)
+ beq x0, a5, 1f /* Success */
+ li a5, 1 /* Normalize failure result */
+1: EXIT_USER_ACCESS(a5)
SET_FAULT_HANDLER(x0, a5) /* Reset the fault handler */
sw a4, 0(a2) /* Store the read data */
- li a0, 0 /* Success */
+ mv a0, a5 /* Success indicator */
ret /* Return */
END(casueword32)
@@ -80,14 +81,15 @@
la a6, fsu_fault /* Load the fault handler */
SET_FAULT_HANDLER(a6, a4) /* And set it */
ENTER_USER_ACCESS(a4)
-1: lr.d a4, 0(a0) /* Load-exclusive the data */
- bne a4, a1, 2f /* If not equal then exit */
+ lr.d a4, 0(a0) /* Load-exclusive the data */
+ bne a4, a1, 1f /* If not equal then exit */
sc.d a5, a3, 0(a0) /* Store the new data */
- bnez a5, 1b /* Retry on failure */
-2: EXIT_USER_ACCESS(a5)
+ beq x0, a5, 1f /* Success */
+ li a5, 1 /* Normalize failure result */
+1: EXIT_USER_ACCESS(a5)
SET_FAULT_HANDLER(x0, a5) /* Reset the fault handler */
sd a4, 0(a2) /* Store the read data */
- li a0, 0 /* Success */
+ mv a0, a5 /* Success indicator */
ret /* Return */
END(casueword)
Index: sys/sparc64/sparc64/support.S
===================================================================
--- sys/sparc64/sparc64/support.S
+++ sys/sparc64/sparc64/support.S
@@ -403,28 +403,27 @@
.set susword, suword16
.set suword, suword64
- .globl casuword32, casuword, fuptr, suptr
- .set casuword, casuword64
+ .globl casuword32_int, casuword64_int, fuptr, suptr
.set fuptr, fuword64
.set suptr, suword64
/*
* int32_t casuword32(volatile int32_t *p, int32_t e, int32_t s)
*/
-ENTRY(casuword32)
+ENTRY(casuword32_int)
casa [%o0] ASI_AIUP, %o1, %o2
retl
mov %o2, %o0
-END(casuword32)
+END(casuword32_int)
/*
* int64_t casuword64(volatile int64_t *p, int64_t e, int64_t s)
*/
-ENTRY(casuword64)
+ENTRY(casuword64_int)
casxa [%o0] ASI_AIUP, %o1, %o2
retl
mov %o2, %o0
-END(casuword64)
+END(casuword64_int)
/*
* int fuword8(const void *base)
Index: sys/sparc64/sparc64/vm_machdep.c
===================================================================
--- sys/sparc64/sparc64/vm_machdep.c
+++ sys/sparc64/sparc64/vm_machdep.c
@@ -462,3 +462,28 @@
pmap_qremove(sf->kva, 1);
return (1);
}
+
+uint32_t casuword32_int(volatile uint32_t *base, uint32_t oldval,
+ uint32_t newval);
+uint32_t
+casuword32(volatile uint32_t *base, uint32_t oldval, uint32_t newval)
+{
+ uint32_t ret;
+
+ ret = casuword32_int(base, oldval, newval);
+ if (ret != -1)
+ ret = ret != oldval;
+ return (ret);
+}
+
+u_long casuword64_int(volatile u_long *p, u_long oldval, u_long newval);
+u_long
+casuword(volatile u_long *p, u_long oldval, u_long newval)
+{
+ u_long ret;
+
+ ret = casuword64_int(p, oldval, newval);
+ if (ret != -1L)
+ ret = ret != oldval;
+ return (ret);
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Dec 23, 1:48 PM (2 h, 48 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
27182436
Default Alt Text
D20772.id59112.diff (27 KB)
Attached To
Mode
D20772: Provide protection against starvation of the ll/sc loops when accessing userpace.
Attached
Detach File
Event Timeline
Log In to Comment