o Add keyword volatile for user mutex owner field.
o Fix type consistent problem by using type long for old umtx and wait channel. o Rename casuptr to casuword.
This commit is contained in:
parent
b7e440b595
commit
5f641fc0fb
@ -342,10 +342,10 @@ ENTRY(casuword32)
|
||||
ret
|
||||
|
||||
/*
|
||||
* casuptr. Compare and set user pointer. Returns -1 or the current value.
|
||||
* casuword. Compare and set user word. Returns -1 or the current value.
|
||||
* dst = %rdi, old = %rsi, new = %rdx
|
||||
*/
|
||||
ENTRY(casuptr)
|
||||
ENTRY(casuword)
|
||||
movq PCPU(CURPCB),%rcx
|
||||
movq $fusufault,PCB_ONFAULT(%rcx)
|
||||
|
||||
|
@ -53,7 +53,7 @@ __FBSDID("$FreeBSD$");
|
||||
*/
|
||||
|
||||
ENTRY_NP(casuword32)
|
||||
ENTRY(casuptr)
|
||||
ENTRY(casuword)
|
||||
#ifdef MULTIPROCESSOR
|
||||
/* XXX Probably not appropriate for non-Hydra SMPs */
|
||||
stmfd sp!, {r0, r14}
|
||||
@ -72,7 +72,7 @@ ENTRY(casuptr)
|
||||
beq .Lfusupcbfault
|
||||
#endif
|
||||
stmfd sp!, {r4, r5}
|
||||
adr r4, .Lcasuptrfault
|
||||
adr r4, .Lcasuwordfault
|
||||
str r4, [r3, #PCB_ONFAULT]
|
||||
ldrt r5, [r0]
|
||||
cmp r5, r1
|
||||
@ -85,10 +85,10 @@ ENTRY(casuptr)
|
||||
RET
|
||||
|
||||
/*
|
||||
* Handle faults from casuptr. Clean up and return -1.
|
||||
* Handle faults from casuword. Clean up and return -1.
|
||||
*/
|
||||
|
||||
.Lcasuptrfault:
|
||||
.Lcasuwordfault:
|
||||
mov r0, #0x00000000
|
||||
str r0, [r3, #PCB_ONFAULT]
|
||||
mvn r0, #0x00000000
|
||||
|
@ -1140,11 +1140,11 @@ fastmove_tail_fault:
|
||||
#endif /* I586_CPU && defined(DEV_NPX) */
|
||||
|
||||
/*
|
||||
* casuptr. Compare and set user pointer. Returns -1 or the current value.
|
||||
* casuword. Compare and set user word. Returns -1 or the current value.
|
||||
*/
|
||||
|
||||
ALTENTRY(casuword32)
|
||||
ENTRY(casuptr)
|
||||
ENTRY(casuword)
|
||||
movl PCPU(CURPCB),%ecx
|
||||
movl $fusufault,PCB_ONFAULT(%ecx)
|
||||
movl 4(%esp),%edx /* dst */
|
||||
|
@ -192,10 +192,10 @@ ENTRY(fusufault, 0)
|
||||
END(fusufault)
|
||||
|
||||
/*
|
||||
* casuptr(intptr_t *p, intptr_t old, intptr_t new)
|
||||
* casuword(u_long *p, u_long old, u_long new)
|
||||
* Perform a compare-exchange in user space.
|
||||
*/
|
||||
ENTRY(casuptr, 3)
|
||||
ENTRY(casuword, 3)
|
||||
{ .mlx
|
||||
add r15=PC_CURTHREAD,r13
|
||||
movl r14=VM_MAX_ADDRESS
|
||||
@ -239,10 +239,10 @@ ENTRY(casuptr, 3)
|
||||
br.ret.sptk rp
|
||||
;;
|
||||
}
|
||||
END(casuptr)
|
||||
END(casuword)
|
||||
|
||||
/*
|
||||
* casuword32(int32_t *p, int32_t old, int32_t new)
|
||||
* casuword32(uint32_t *p, uint32_t old, uint32_t new)
|
||||
* Perform a 32-bit compare-exchange in user space.
|
||||
*/
|
||||
ENTRY(casuword32, 3)
|
||||
|
@ -522,11 +522,11 @@ umtx_key_release(struct umtx_key *key)
|
||||
* Lock a umtx object.
|
||||
*/
|
||||
static int
|
||||
_do_lock_umtx(struct thread *td, struct umtx *umtx, uintptr_t id, int timo)
|
||||
_do_lock_umtx(struct thread *td, struct umtx *umtx, u_long id, int timo)
|
||||
{
|
||||
struct umtx_q *uq;
|
||||
intptr_t owner;
|
||||
intptr_t old;
|
||||
u_long owner;
|
||||
u_long old;
|
||||
int error = 0;
|
||||
|
||||
uq = td->td_umtxq;
|
||||
@ -539,7 +539,7 @@ _do_lock_umtx(struct thread *td, struct umtx *umtx, uintptr_t id, int timo)
|
||||
/*
|
||||
* Try the uncontested case. This should be done in userland.
|
||||
*/
|
||||
owner = casuptr((intptr_t *)&umtx->u_owner, UMTX_UNOWNED, id);
|
||||
owner = casuword(&umtx->u_owner, UMTX_UNOWNED, id);
|
||||
|
||||
/* The acquire succeeded. */
|
||||
if (owner == UMTX_UNOWNED)
|
||||
@ -551,7 +551,7 @@ _do_lock_umtx(struct thread *td, struct umtx *umtx, uintptr_t id, int timo)
|
||||
|
||||
/* If no one owns it but it is contested try to acquire it. */
|
||||
if (owner == UMTX_CONTESTED) {
|
||||
owner = casuptr((intptr_t *)&umtx->u_owner,
|
||||
owner = casuword(&umtx->u_owner,
|
||||
UMTX_CONTESTED, id | UMTX_CONTESTED);
|
||||
|
||||
if (owner == UMTX_CONTESTED)
|
||||
@ -588,8 +588,7 @@ _do_lock_umtx(struct thread *td, struct umtx *umtx, uintptr_t id, int timo)
|
||||
* either some one else has acquired the lock or it has been
|
||||
* released.
|
||||
*/
|
||||
old = casuptr((intptr_t *)&umtx->u_owner, owner,
|
||||
owner | UMTX_CONTESTED);
|
||||
old = casuword(&umtx->u_owner, owner, owner | UMTX_CONTESTED);
|
||||
|
||||
/* The address was invalid. */
|
||||
if (old == -1) {
|
||||
@ -620,7 +619,7 @@ _do_lock_umtx(struct thread *td, struct umtx *umtx, uintptr_t id, int timo)
|
||||
* Lock a umtx object.
|
||||
*/
|
||||
static int
|
||||
do_lock_umtx(struct thread *td, struct umtx *umtx, uintptr_t id,
|
||||
do_lock_umtx(struct thread *td, struct umtx *umtx, u_long id,
|
||||
struct timespec *timeout)
|
||||
{
|
||||
struct timespec ts, ts2, ts3;
|
||||
@ -660,21 +659,18 @@ do_lock_umtx(struct thread *td, struct umtx *umtx, uintptr_t id,
|
||||
* Unlock a umtx object.
|
||||
*/
|
||||
static int
|
||||
do_unlock_umtx(struct thread *td, struct umtx *umtx, uintptr_t id)
|
||||
do_unlock_umtx(struct thread *td, struct umtx *umtx, u_long id)
|
||||
{
|
||||
struct umtx_key key;
|
||||
intptr_t owner;
|
||||
intptr_t old;
|
||||
u_long owner;
|
||||
u_long old;
|
||||
int error;
|
||||
int count;
|
||||
|
||||
/*
|
||||
* Make sure we own this mtx.
|
||||
*
|
||||
* XXX Need a {fu,su}ptr this is not correct on arch where
|
||||
* sizeof(intptr_t) != sizeof(long).
|
||||
*/
|
||||
owner = fuword(&umtx->u_owner);
|
||||
owner = fuword(__DEVOLATILE(u_long *, &umtx->u_owner));
|
||||
if (owner == -1)
|
||||
return (EFAULT);
|
||||
|
||||
@ -683,8 +679,7 @@ do_unlock_umtx(struct thread *td, struct umtx *umtx, uintptr_t id)
|
||||
|
||||
/* This should be done in userland */
|
||||
if ((owner & UMTX_CONTESTED) == 0) {
|
||||
old = casuptr((intptr_t *)&umtx->u_owner, owner,
|
||||
UMTX_UNOWNED);
|
||||
old = casuword(&umtx->u_owner, owner, UMTX_UNOWNED);
|
||||
if (old == -1)
|
||||
return (EFAULT);
|
||||
if (old == owner)
|
||||
@ -707,8 +702,8 @@ do_unlock_umtx(struct thread *td, struct umtx *umtx, uintptr_t id)
|
||||
* there is zero or one thread only waiting for it.
|
||||
* Otherwise, it must be marked as contested.
|
||||
*/
|
||||
old = casuptr((intptr_t *)&umtx->u_owner, owner,
|
||||
count <= 1 ? UMTX_UNOWNED : UMTX_CONTESTED);
|
||||
old = casuword(&umtx->u_owner, owner,
|
||||
count <= 1 ? UMTX_UNOWNED : UMTX_CONTESTED);
|
||||
umtxq_lock(&key);
|
||||
umtxq_signal(&key,1);
|
||||
umtxq_unbusy(&key);
|
||||
@ -873,9 +868,6 @@ do_unlock_umtx32(struct thread *td, uint32_t *m, uint32_t id)
|
||||
|
||||
/*
|
||||
* Make sure we own this mtx.
|
||||
*
|
||||
* XXX Need a {fu,su}ptr this is not correct on arch where
|
||||
* sizeof(intptr_t) != sizeof(long).
|
||||
*/
|
||||
owner = fuword32(m);
|
||||
if (owner == -1)
|
||||
@ -928,13 +920,13 @@ do_unlock_umtx32(struct thread *td, uint32_t *m, uint32_t id)
|
||||
* Fetch and compare value, sleep on the address if value is not changed.
|
||||
*/
|
||||
static int
|
||||
do_wait(struct thread *td, void *addr, uintptr_t id,
|
||||
do_wait(struct thread *td, void *addr, u_long id,
|
||||
struct timespec *timeout, int compat32)
|
||||
{
|
||||
struct umtx_q *uq;
|
||||
struct timespec ts, ts2, ts3;
|
||||
struct timeval tv;
|
||||
uintptr_t tmp;
|
||||
u_long tmp;
|
||||
int error = 0;
|
||||
|
||||
uq = td->td_umtxq;
|
||||
@ -1132,7 +1124,7 @@ do_unlock_normal(struct thread *td, struct umutex *m, uint32_t flags)
|
||||
/*
|
||||
* Make sure we own this mtx.
|
||||
*/
|
||||
owner = fuword32(&m->m_owner);
|
||||
owner = fuword32(__DEVOLATILE(uint32_t *, &m->m_owner));
|
||||
if (owner == -1)
|
||||
return (EFAULT);
|
||||
|
||||
@ -1729,7 +1721,7 @@ do_unlock_pi(struct thread *td, struct umutex *m, uint32_t flags)
|
||||
/*
|
||||
* Make sure we own this mtx.
|
||||
*/
|
||||
owner = fuword32(&m->m_owner);
|
||||
owner = fuword32(__DEVOLATILE(uint32_t *, &m->m_owner));
|
||||
if (owner == -1)
|
||||
return (EFAULT);
|
||||
|
||||
@ -1945,7 +1937,7 @@ do_unlock_pp(struct thread *td, struct umutex *m, uint32_t flags)
|
||||
/*
|
||||
* Make sure we own this mtx.
|
||||
*/
|
||||
owner = fuword32(&m->m_owner);
|
||||
owner = fuword32(__DEVOLATILE(uint32_t *, &m->m_owner));
|
||||
if (owner == -1)
|
||||
return (EFAULT);
|
||||
|
||||
@ -1977,7 +1969,8 @@ 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(&m->m_owner, UMUTEX_CONTESTED);
|
||||
error = suword32(__DEVOLATILE(uint32_t *, &m->m_owner),
|
||||
UMUTEX_CONTESTED);
|
||||
|
||||
umtxq_lock(&key);
|
||||
if (error == 0)
|
||||
@ -2040,7 +2033,8 @@ do_set_ceiling(struct thread *td, struct umutex *m, uint32_t ceiling,
|
||||
|
||||
if (owner == UMUTEX_CONTESTED) {
|
||||
suword32(&m->m_ceilings[0], ceiling);
|
||||
suword32(&m->m_owner, UMUTEX_CONTESTED);
|
||||
suword32(__DEVOLATILE(uint32_t *, &m->m_owner),
|
||||
UMUTEX_CONTESTED);
|
||||
error = 0;
|
||||
break;
|
||||
}
|
||||
|
@ -796,7 +796,7 @@
|
||||
u_int length); }
|
||||
453 AUE_AUDITCTL STD { int auditctl(char *path); }
|
||||
454 AUE_NULL STD { int _umtx_op(void *obj, int op, \
|
||||
uintptr_t val, void *uaddr1, void *uaddr2); }
|
||||
u_long val, void *uaddr1, void *uaddr2); }
|
||||
455 AUE_NULL STD { int thr_new(struct thr_param *param, \
|
||||
int param_size); }
|
||||
456 AUE_NULL STD { int sigqueue(pid_t pid, int signum, void *value); }
|
||||
|
@ -322,23 +322,23 @@ fuword32(const void *addr)
|
||||
return ((int32_t)fuword(addr));
|
||||
}
|
||||
|
||||
int32_t
|
||||
casuword32(int32_t *base, int32_t oldval, int32_t newval)
|
||||
uint32_t
|
||||
casuword32(volatile uint32_t *base, uint32_t oldval, uint32_t newval)
|
||||
{
|
||||
return (casuptr(base, oldval, newval));
|
||||
return (casuword(base, oldval, newval));
|
||||
}
|
||||
|
||||
intptr_t
|
||||
casuptr(intptr_t *addr, intptr_t old, intptr_t new)
|
||||
u_long
|
||||
casuword(volatile u_long *addr, u_long old, u_long new)
|
||||
{
|
||||
struct thread *td;
|
||||
pmap_t pm;
|
||||
faultbuf env;
|
||||
intptr_t *p, val;
|
||||
u_long *p, val;
|
||||
|
||||
td = PCPU_GET(curthread);
|
||||
pm = &td->td_proc->p_vmspace->vm_pmap;
|
||||
p = (intptr_t *)((u_int)USER_ADDR + ((u_int)addr & ~SEGMENT_MASK));
|
||||
p = (u_long *)((u_int)USER_ADDR + ((u_int)addr & ~SEGMENT_MASK));
|
||||
|
||||
set_user_sr(pm->pm_sr[(u_int)addr >> ADDR_SR_SHFT]);
|
||||
|
||||
|
@ -322,23 +322,23 @@ fuword32(const void *addr)
|
||||
return ((int32_t)fuword(addr));
|
||||
}
|
||||
|
||||
int32_t
|
||||
casuword32(int32_t *base, int32_t oldval, int32_t newval)
|
||||
uint32_t
|
||||
casuword32(volatile uint32_t *base, uint32_t oldval, uint32_t newval)
|
||||
{
|
||||
return (casuptr(base, oldval, newval));
|
||||
return (casuword(base, oldval, newval));
|
||||
}
|
||||
|
||||
intptr_t
|
||||
casuptr(intptr_t *addr, intptr_t old, intptr_t new)
|
||||
u_long
|
||||
casuword(volatile u_long *addr, u_long old, u_long new)
|
||||
{
|
||||
struct thread *td;
|
||||
pmap_t pm;
|
||||
faultbuf env;
|
||||
intptr_t *p, val;
|
||||
u_long *p, val;
|
||||
|
||||
td = PCPU_GET(curthread);
|
||||
pm = &td->td_proc->p_vmspace->vm_pmap;
|
||||
p = (intptr_t *)((u_int)USER_ADDR + ((u_int)addr & ~SEGMENT_MASK));
|
||||
p = (u_long *)((u_int)USER_ADDR + ((u_int)addr & ~SEGMENT_MASK));
|
||||
|
||||
set_user_sr(pm->pm_sr[(u_int)addr >> ADDR_SR_SHFT]);
|
||||
|
||||
|
@ -402,8 +402,8 @@ fs_nofault_begin:
|
||||
.set susword, suword16
|
||||
.set suword, suword64
|
||||
|
||||
.globl casuword32, casuptr, fuptr, suptr
|
||||
.set casuptr, casuword64
|
||||
.globl casuword32, casuword, fuptr, suptr
|
||||
.set casuword, casuword64
|
||||
.set fuptr, fuword64
|
||||
.set suptr, suword64
|
||||
|
||||
|
@ -203,8 +203,8 @@ 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);
|
||||
int32_t casuword32(int32_t *base, int32_t oldval, int32_t newval);
|
||||
intptr_t casuptr(intptr_t *p, intptr_t oldval, intptr_t newval);
|
||||
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);
|
||||
|
||||
void realitexpire(void *);
|
||||
|
||||
|
@ -41,7 +41,7 @@
|
||||
#define UMTX_CONTESTED LONG_MIN
|
||||
|
||||
struct umtx {
|
||||
uintptr_t u_owner; /* Owner of the mutex. */
|
||||
volatile u_long u_owner; /* Owner of the mutex. */
|
||||
};
|
||||
|
||||
#define USYNC_PROCESS_SHARED 0x0001 /* Process shared sync objs */
|
||||
@ -53,7 +53,7 @@ struct umtx {
|
||||
#define UMUTEX_PRIO_INHERIT 0x0004 /* Priority inherited mutex */
|
||||
#define UMUTEX_PRIO_PROTECT 0x0008 /* Priority protect mutex */
|
||||
struct umutex {
|
||||
__lwpid_t m_owner; /* Owner of the mutex */
|
||||
volatile __lwpid_t m_owner; /* Owner of the mutex */
|
||||
uint32_t m_flags; /* Flags of the mutex */
|
||||
uint32_t m_ceilings[2]; /* Priority protect ceiling */
|
||||
uint32_t m_spare[4]; /* Spare space */
|
||||
@ -72,11 +72,7 @@ struct umutex {
|
||||
|
||||
#ifndef _KERNEL
|
||||
|
||||
/*
|
||||
* System call for userland mutex operations.
|
||||
* Bug: assume sizeof(uintptr_t) == sizeof(long)
|
||||
*/
|
||||
int _umtx_op(void *obj, int op, uintptr_t val, void *uaddr, void *uaddr2);
|
||||
int _umtx_op(void *obj, int op, u_long val, void *uaddr, void *uaddr2);
|
||||
|
||||
/*
|
||||
* Old (deprecated) userland mutex system calls.
|
||||
@ -94,33 +90,33 @@ umtx_init(struct umtx *umtx)
|
||||
umtx->u_owner = UMTX_UNOWNED;
|
||||
}
|
||||
|
||||
static __inline uintptr_t
|
||||
static __inline u_long
|
||||
umtx_owner(struct umtx *umtx)
|
||||
{
|
||||
return (umtx->u_owner & ~LONG_MIN);
|
||||
}
|
||||
|
||||
static __inline int
|
||||
umtx_lock(struct umtx *umtx, uintptr_t id)
|
||||
umtx_lock(struct umtx *umtx, u_long id)
|
||||
{
|
||||
if (atomic_cmpset_acq_ptr(&umtx->u_owner, UMTX_UNOWNED, id) == 0)
|
||||
if (atomic_cmpset_acq_long(&umtx->u_owner, UMTX_UNOWNED, id) == 0)
|
||||
if (_umtx_lock(umtx) == -1)
|
||||
return (errno);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static __inline int
|
||||
umtx_trylock(struct umtx *umtx, uintptr_t id)
|
||||
umtx_trylock(struct umtx *umtx, u_long id)
|
||||
{
|
||||
if (atomic_cmpset_acq_ptr(&umtx->u_owner, UMTX_UNOWNED, id) == 0)
|
||||
if (atomic_cmpset_acq_long(&umtx->u_owner, UMTX_UNOWNED, id) == 0)
|
||||
return (EBUSY);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static __inline int
|
||||
umtx_timedlock(struct umtx *umtx, uintptr_t id, const struct timespec *timeout)
|
||||
umtx_timedlock(struct umtx *umtx, u_long id, const struct timespec *timeout)
|
||||
{
|
||||
if (atomic_cmpset_acq_ptr(&umtx->u_owner, UMTX_UNOWNED, id) == 0)
|
||||
if (atomic_cmpset_acq_long(&umtx->u_owner, UMTX_UNOWNED, id) == 0)
|
||||
if (_umtx_op(umtx, UMTX_OP_LOCK, id, 0,
|
||||
__DECONST(void *, timeout)) == -1)
|
||||
return (errno);
|
||||
@ -128,16 +124,16 @@ umtx_timedlock(struct umtx *umtx, uintptr_t id, const struct timespec *timeout)
|
||||
}
|
||||
|
||||
static __inline int
|
||||
umtx_unlock(struct umtx *umtx, uintptr_t id)
|
||||
umtx_unlock(struct umtx *umtx, u_long id)
|
||||
{
|
||||
if (atomic_cmpset_rel_ptr(&umtx->u_owner, id, UMTX_UNOWNED) == 0)
|
||||
if (atomic_cmpset_rel_long(&umtx->u_owner, id, UMTX_UNOWNED) == 0)
|
||||
if (_umtx_unlock(umtx) == -1)
|
||||
return (errno);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static __inline int
|
||||
umtx_wait(long *p, long val, const struct timespec *timeout)
|
||||
umtx_wait(u_long *p, long val, const struct timespec *timeout)
|
||||
{
|
||||
if (_umtx_op(p, UMTX_OP_WAIT, val, 0,
|
||||
__DECONST(void *, timeout)) == -1)
|
||||
@ -147,7 +143,7 @@ umtx_wait(long *p, long val, const struct timespec *timeout)
|
||||
|
||||
/* Wake threads waiting on a user address. */
|
||||
static __inline int
|
||||
umtx_wake(long *p, int nr_wakeup)
|
||||
umtx_wake(u_long *p, int nr_wakeup)
|
||||
{
|
||||
if (_umtx_op(p, UMTX_OP_WAKE, nr_wakeup, 0, 0) == -1)
|
||||
return (errno);
|
||||
|
Loading…
Reference in New Issue
Block a user