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:
David Xu 2006-10-17 02:24:47 +00:00
parent b7e440b595
commit 5f641fc0fb
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=163449
11 changed files with 68 additions and 78 deletions

View File

@ -342,10 +342,10 @@ ENTRY(casuword32)
ret 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 * dst = %rdi, old = %rsi, new = %rdx
*/ */
ENTRY(casuptr) ENTRY(casuword)
movq PCPU(CURPCB),%rcx movq PCPU(CURPCB),%rcx
movq $fusufault,PCB_ONFAULT(%rcx) movq $fusufault,PCB_ONFAULT(%rcx)

View File

@ -53,7 +53,7 @@ __FBSDID("$FreeBSD$");
*/ */
ENTRY_NP(casuword32) ENTRY_NP(casuword32)
ENTRY(casuptr) ENTRY(casuword)
#ifdef MULTIPROCESSOR #ifdef MULTIPROCESSOR
/* XXX Probably not appropriate for non-Hydra SMPs */ /* XXX Probably not appropriate for non-Hydra SMPs */
stmfd sp!, {r0, r14} stmfd sp!, {r0, r14}
@ -72,7 +72,7 @@ ENTRY(casuptr)
beq .Lfusupcbfault beq .Lfusupcbfault
#endif #endif
stmfd sp!, {r4, r5} stmfd sp!, {r4, r5}
adr r4, .Lcasuptrfault adr r4, .Lcasuwordfault
str r4, [r3, #PCB_ONFAULT] str r4, [r3, #PCB_ONFAULT]
ldrt r5, [r0] ldrt r5, [r0]
cmp r5, r1 cmp r5, r1
@ -85,10 +85,10 @@ ENTRY(casuptr)
RET RET
/* /*
* Handle faults from casuptr. Clean up and return -1. * Handle faults from casuword. Clean up and return -1.
*/ */
.Lcasuptrfault: .Lcasuwordfault:
mov r0, #0x00000000 mov r0, #0x00000000
str r0, [r3, #PCB_ONFAULT] str r0, [r3, #PCB_ONFAULT]
mvn r0, #0x00000000 mvn r0, #0x00000000

View File

@ -1140,11 +1140,11 @@ fastmove_tail_fault:
#endif /* I586_CPU && defined(DEV_NPX) */ #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) ALTENTRY(casuword32)
ENTRY(casuptr) ENTRY(casuword)
movl PCPU(CURPCB),%ecx movl PCPU(CURPCB),%ecx
movl $fusufault,PCB_ONFAULT(%ecx) movl $fusufault,PCB_ONFAULT(%ecx)
movl 4(%esp),%edx /* dst */ movl 4(%esp),%edx /* dst */

View File

@ -192,10 +192,10 @@ ENTRY(fusufault, 0)
END(fusufault) 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. * Perform a compare-exchange in user space.
*/ */
ENTRY(casuptr, 3) ENTRY(casuword, 3)
{ .mlx { .mlx
add r15=PC_CURTHREAD,r13 add r15=PC_CURTHREAD,r13
movl r14=VM_MAX_ADDRESS movl r14=VM_MAX_ADDRESS
@ -239,10 +239,10 @@ ENTRY(casuptr, 3)
br.ret.sptk rp 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. * Perform a 32-bit compare-exchange in user space.
*/ */
ENTRY(casuword32, 3) ENTRY(casuword32, 3)

View File

@ -522,11 +522,11 @@ umtx_key_release(struct umtx_key *key)
* Lock a umtx object. * Lock a umtx object.
*/ */
static int 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; struct umtx_q *uq;
intptr_t owner; u_long owner;
intptr_t old; u_long old;
int error = 0; int error = 0;
uq = td->td_umtxq; 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. * 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. */ /* The acquire succeeded. */
if (owner == UMTX_UNOWNED) 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 no one owns it but it is contested try to acquire it. */
if (owner == UMTX_CONTESTED) { if (owner == UMTX_CONTESTED) {
owner = casuptr((intptr_t *)&umtx->u_owner, owner = casuword(&umtx->u_owner,
UMTX_CONTESTED, id | UMTX_CONTESTED); UMTX_CONTESTED, id | UMTX_CONTESTED);
if (owner == 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 * either some one else has acquired the lock or it has been
* released. * released.
*/ */
old = casuptr((intptr_t *)&umtx->u_owner, owner, old = casuword(&umtx->u_owner, owner, owner | UMTX_CONTESTED);
owner | UMTX_CONTESTED);
/* The address was invalid. */ /* The address was invalid. */
if (old == -1) { 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. * Lock a umtx object.
*/ */
static int 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 *timeout)
{ {
struct timespec ts, ts2, ts3; 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. * Unlock a umtx object.
*/ */
static int 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; struct umtx_key key;
intptr_t owner; u_long owner;
intptr_t old; u_long old;
int error; int error;
int count; int count;
/* /*
* Make sure we own this mtx. * 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) if (owner == -1)
return (EFAULT); return (EFAULT);
@ -683,8 +679,7 @@ do_unlock_umtx(struct thread *td, struct umtx *umtx, uintptr_t id)
/* This should be done in userland */ /* This should be done in userland */
if ((owner & UMTX_CONTESTED) == 0) { if ((owner & UMTX_CONTESTED) == 0) {
old = casuptr((intptr_t *)&umtx->u_owner, owner, old = casuword(&umtx->u_owner, owner, UMTX_UNOWNED);
UMTX_UNOWNED);
if (old == -1) if (old == -1)
return (EFAULT); return (EFAULT);
if (old == owner) if (old == owner)
@ -707,7 +702,7 @@ do_unlock_umtx(struct thread *td, struct umtx *umtx, uintptr_t id)
* there is zero or one thread only waiting for it. * there is zero or one thread only waiting for it.
* Otherwise, it must be marked as contested. * Otherwise, it must be marked as contested.
*/ */
old = casuptr((intptr_t *)&umtx->u_owner, owner, old = casuword(&umtx->u_owner, owner,
count <= 1 ? UMTX_UNOWNED : UMTX_CONTESTED); count <= 1 ? UMTX_UNOWNED : UMTX_CONTESTED);
umtxq_lock(&key); umtxq_lock(&key);
umtxq_signal(&key,1); umtxq_signal(&key,1);
@ -873,9 +868,6 @@ do_unlock_umtx32(struct thread *td, uint32_t *m, uint32_t id)
/* /*
* Make sure we own this mtx. * 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); owner = fuword32(m);
if (owner == -1) 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. * Fetch and compare value, sleep on the address if value is not changed.
*/ */
static int 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 timespec *timeout, int compat32)
{ {
struct umtx_q *uq; struct umtx_q *uq;
struct timespec ts, ts2, ts3; struct timespec ts, ts2, ts3;
struct timeval tv; struct timeval tv;
uintptr_t tmp; u_long tmp;
int error = 0; int error = 0;
uq = td->td_umtxq; 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. * Make sure we own this mtx.
*/ */
owner = fuword32(&m->m_owner); owner = fuword32(__DEVOLATILE(uint32_t *, &m->m_owner));
if (owner == -1) if (owner == -1)
return (EFAULT); return (EFAULT);
@ -1729,7 +1721,7 @@ do_unlock_pi(struct thread *td, struct umutex *m, uint32_t flags)
/* /*
* Make sure we own this mtx. * Make sure we own this mtx.
*/ */
owner = fuword32(&m->m_owner); owner = fuword32(__DEVOLATILE(uint32_t *, &m->m_owner));
if (owner == -1) if (owner == -1)
return (EFAULT); return (EFAULT);
@ -1945,7 +1937,7 @@ do_unlock_pp(struct thread *td, struct umutex *m, uint32_t flags)
/* /*
* Make sure we own this mtx. * Make sure we own this mtx.
*/ */
owner = fuword32(&m->m_owner); owner = fuword32(__DEVOLATILE(uint32_t *, &m->m_owner));
if (owner == -1) if (owner == -1)
return (EFAULT); 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 * to lock the mutex, it is necessary because thread priority
* has to be adjusted for such mutex. * 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); umtxq_lock(&key);
if (error == 0) if (error == 0)
@ -2040,7 +2033,8 @@ do_set_ceiling(struct thread *td, struct umutex *m, uint32_t ceiling,
if (owner == UMUTEX_CONTESTED) { if (owner == UMUTEX_CONTESTED) {
suword32(&m->m_ceilings[0], ceiling); suword32(&m->m_ceilings[0], ceiling);
suword32(&m->m_owner, UMUTEX_CONTESTED); suword32(__DEVOLATILE(uint32_t *, &m->m_owner),
UMUTEX_CONTESTED);
error = 0; error = 0;
break; break;
} }

View File

@ -796,7 +796,7 @@
u_int length); } u_int length); }
453 AUE_AUDITCTL STD { int auditctl(char *path); } 453 AUE_AUDITCTL STD { int auditctl(char *path); }
454 AUE_NULL STD { int _umtx_op(void *obj, int op, \ 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, \ 455 AUE_NULL STD { int thr_new(struct thr_param *param, \
int param_size); } int param_size); }
456 AUE_NULL STD { int sigqueue(pid_t pid, int signum, void *value); } 456 AUE_NULL STD { int sigqueue(pid_t pid, int signum, void *value); }

View File

@ -322,23 +322,23 @@ fuword32(const void *addr)
return ((int32_t)fuword(addr)); return ((int32_t)fuword(addr));
} }
int32_t uint32_t
casuword32(int32_t *base, int32_t oldval, int32_t newval) casuword32(volatile uint32_t *base, uint32_t oldval, uint32_t newval)
{ {
return (casuptr(base, oldval, newval)); return (casuword(base, oldval, newval));
} }
intptr_t u_long
casuptr(intptr_t *addr, intptr_t old, intptr_t new) casuword(volatile u_long *addr, u_long old, u_long new)
{ {
struct thread *td; struct thread *td;
pmap_t pm; pmap_t pm;
faultbuf env; faultbuf env;
intptr_t *p, val; u_long *p, val;
td = PCPU_GET(curthread); td = PCPU_GET(curthread);
pm = &td->td_proc->p_vmspace->vm_pmap; 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]); set_user_sr(pm->pm_sr[(u_int)addr >> ADDR_SR_SHFT]);

View File

@ -322,23 +322,23 @@ fuword32(const void *addr)
return ((int32_t)fuword(addr)); return ((int32_t)fuword(addr));
} }
int32_t uint32_t
casuword32(int32_t *base, int32_t oldval, int32_t newval) casuword32(volatile uint32_t *base, uint32_t oldval, uint32_t newval)
{ {
return (casuptr(base, oldval, newval)); return (casuword(base, oldval, newval));
} }
intptr_t u_long
casuptr(intptr_t *addr, intptr_t old, intptr_t new) casuword(volatile u_long *addr, u_long old, u_long new)
{ {
struct thread *td; struct thread *td;
pmap_t pm; pmap_t pm;
faultbuf env; faultbuf env;
intptr_t *p, val; u_long *p, val;
td = PCPU_GET(curthread); td = PCPU_GET(curthread);
pm = &td->td_proc->p_vmspace->vm_pmap; 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]); set_user_sr(pm->pm_sr[(u_int)addr >> ADDR_SR_SHFT]);

View File

@ -402,8 +402,8 @@ fs_nofault_begin:
.set susword, suword16 .set susword, suword16
.set suword, suword64 .set suword, suword64
.globl casuword32, casuptr, fuptr, suptr .globl casuword32, casuword, fuptr, suptr
.set casuptr, casuword64 .set casuword, casuword64
.set fuptr, fuword64 .set fuptr, fuword64
.set suptr, suword64 .set suptr, suword64

View File

@ -203,8 +203,8 @@ int suword(void *base, long word);
int suword16(void *base, int word); int suword16(void *base, int word);
int suword32(void *base, int32_t word); int suword32(void *base, int32_t word);
int suword64(void *base, int64_t word); int suword64(void *base, int64_t word);
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);
intptr_t casuptr(intptr_t *p, intptr_t oldval, intptr_t newval); u_long casuword(volatile u_long *p, u_long oldval, u_long newval);
void realitexpire(void *); void realitexpire(void *);

View File

@ -41,7 +41,7 @@
#define UMTX_CONTESTED LONG_MIN #define UMTX_CONTESTED LONG_MIN
struct umtx { 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 */ #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_INHERIT 0x0004 /* Priority inherited mutex */
#define UMUTEX_PRIO_PROTECT 0x0008 /* Priority protect mutex */ #define UMUTEX_PRIO_PROTECT 0x0008 /* Priority protect mutex */
struct umutex { 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_flags; /* Flags of the mutex */
uint32_t m_ceilings[2]; /* Priority protect ceiling */ uint32_t m_ceilings[2]; /* Priority protect ceiling */
uint32_t m_spare[4]; /* Spare space */ uint32_t m_spare[4]; /* Spare space */
@ -72,11 +72,7 @@ struct umutex {
#ifndef _KERNEL #ifndef _KERNEL
/* int _umtx_op(void *obj, int op, u_long val, void *uaddr, void *uaddr2);
* 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);
/* /*
* Old (deprecated) userland mutex system calls. * Old (deprecated) userland mutex system calls.
@ -94,33 +90,33 @@ umtx_init(struct umtx *umtx)
umtx->u_owner = UMTX_UNOWNED; umtx->u_owner = UMTX_UNOWNED;
} }
static __inline uintptr_t static __inline u_long
umtx_owner(struct umtx *umtx) umtx_owner(struct umtx *umtx)
{ {
return (umtx->u_owner & ~LONG_MIN); return (umtx->u_owner & ~LONG_MIN);
} }
static __inline int 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) if (_umtx_lock(umtx) == -1)
return (errno); return (errno);
return (0); return (0);
} }
static __inline int 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 (EBUSY);
return (0); return (0);
} }
static __inline int 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, if (_umtx_op(umtx, UMTX_OP_LOCK, id, 0,
__DECONST(void *, timeout)) == -1) __DECONST(void *, timeout)) == -1)
return (errno); return (errno);
@ -128,16 +124,16 @@ umtx_timedlock(struct umtx *umtx, uintptr_t id, const struct timespec *timeout)
} }
static __inline int 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) if (_umtx_unlock(umtx) == -1)
return (errno); return (errno);
return (0); return (0);
} }
static __inline int 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, if (_umtx_op(p, UMTX_OP_WAIT, val, 0,
__DECONST(void *, timeout)) == -1) __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. */ /* Wake threads waiting on a user address. */
static __inline int 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) if (_umtx_op(p, UMTX_OP_WAKE, nr_wakeup, 0, 0) == -1)
return (errno); return (errno);