Don't assume sizeof(long) = sizeof(int) on x86; use int

instead of long types for low-level locks.

Add prototypes for some internal libc functions that are
wrapped by the library as cancellation points.

Add memory barriers to alpha atomic swap functions (submitted
by davidxu).

Requested by:	bde
This commit is contained in:
deischen 2003-09-03 17:56:26 +00:00
parent 89502bb140
commit 8271ec1da3
25 changed files with 109 additions and 42 deletions

View File

@ -33,17 +33,25 @@
* Atomic swap: * Atomic swap:
* Atomic (tmp = *dst, *dst = val), then *res = tmp * Atomic (tmp = *dst, *dst = val), then *res = tmp
* *
* void atomic_swap_long(long *dst, long val, long *res); * void atomic_swap64(intptr_t *dst, intptr_t val, intptr_t *res);
*/ */
static inline void static inline void
atomic_swap_long(long *dst, long val, long *res) atomic_swap64(intptr_t *dst, intptr_t val, intptr_t *res)
{ {
__asm __volatile( __asm __volatile(
"xchgq %2, %1; movq %2, %0" "xchgq %2, %1; movq %2, %0"
: "=m" (*res) : "m" (*dst), "r" (val) : "memory"); : "=m" (*res) : "m" (*dst), "r" (val) : "memory");
} }
static inline void
atomic_swap_int(int *dst, int val, int *res)
{
__asm __volatile(
"xchgl %2, %1; movl %2, %0"
: "=m" (*res) : "m" (*dst), "r" (val) : "memory");
}
#define atomic_swap_ptr(d, v, r) \ #define atomic_swap_ptr(d, v, r) \
atomic_swap_long((long *)(d), (long)(v), (long *)(r)) atomic_swap64((intptr_t *)(d), (intptr_t)(v), (intptr_t *)(r))
#endif #endif

View File

@ -33,19 +33,19 @@
* Atomic swap: * Atomic swap:
* Atomic (tmp = *dst, *dst = val), then *res = tmp * Atomic (tmp = *dst, *dst = val), then *res = tmp
* *
* void atomic_swap_long(long *dst, long val, long *res); * void atomic_swap32(intptr_t *dst, intptr_t val, intptr_t *res);
*/ */
static inline void static inline void
atomic_swap_long(long *dst, long val, long *res) atomic_swap32(intptr_t *dst, intptr_t val, intptr_t *res)
{ {
__asm __volatile( __asm __volatile(
"xchgl %2, %1; movl %2, %0" "xchgl %2, %1; movl %2, %0"
: "=m" (*res) : "m" (*dst), "r" (val) : "memory"); : "=m" (*res) : "m" (*dst), "r" (val) : "memory");
} }
#define atomic_swap_ptr(d, v, r) \
atomic_swap32((intptr_t *)d, (intptr_t)v, (intptr_t *)r)
#define atomic_swap_int(d, v, r) \ #define atomic_swap_int(d, v, r) \
atomic_swap_long((long *)(d), (long)(v), (long *)(r)) atomic_swap32((intptr_t *)d, (intptr_t)v, (intptr_t *)r)
#define atomic_swap_ptr atomic_swap_int
#endif #endif

View File

@ -107,7 +107,7 @@ void
_lock_acquire(struct lock *lck, struct lockuser *lu, int prio) _lock_acquire(struct lock *lck, struct lockuser *lu, int prio)
{ {
int i; int i;
long lval; int lval;
/** /**
* XXX - We probably want to remove these checks to optimize * XXX - We probably want to remove these checks to optimize
@ -167,7 +167,7 @@ _lock_acquire(struct lock *lck, struct lockuser *lu, int prio)
if (lu->lu_watchreq->lr_active == 0) if (lu->lu_watchreq->lr_active == 0)
break; break;
} }
atomic_swap_long((long *)&lu->lu_watchreq->lr_locked, atomic_swap_int((int *)&lu->lu_watchreq->lr_locked,
2, &lval); 2, &lval);
if (lval == 0) if (lval == 0)
lu->lu_watchreq->lr_locked = 0; lu->lu_watchreq->lr_locked = 0;
@ -188,7 +188,7 @@ _lock_release(struct lock *lck, struct lockuser *lu)
struct lockuser *lu_tmp, *lu_h; struct lockuser *lu_tmp, *lu_h;
struct lockreq *myreq; struct lockreq *myreq;
int prio_h; int prio_h;
long lval; int lval;
/** /**
* XXX - We probably want to remove these checks to optimize * XXX - We probably want to remove these checks to optimize
@ -240,8 +240,8 @@ _lock_release(struct lock *lck, struct lockuser *lu)
if (lu_h != NULL) { if (lu_h != NULL) {
/* Give the lock to the highest priority user. */ /* Give the lock to the highest priority user. */
if (lck->l_wakeup != NULL) { if (lck->l_wakeup != NULL) {
atomic_swap_long( atomic_swap_int(
(long *)&lu_h->lu_watchreq->lr_locked, (int *)&lu_h->lu_watchreq->lr_locked,
0, &lval); 0, &lval);
if (lval == 2) if (lval == 2)
/* Notify the sleeper */ /* Notify the sleeper */
@ -249,11 +249,11 @@ _lock_release(struct lock *lck, struct lockuser *lu)
lu_h->lu_myreq->lr_watcher); lu_h->lu_myreq->lr_watcher);
} }
else else
atomic_store_rel_long( atomic_store_rel_int(
&lu_h->lu_watchreq->lr_locked, 0); &lu_h->lu_watchreq->lr_locked, 0);
} else { } else {
if (lck->l_wakeup != NULL) { if (lck->l_wakeup != NULL) {
atomic_swap_long((long *)&myreq->lr_locked, atomic_swap_int((int *)&myreq->lr_locked,
0, &lval); 0, &lval);
if (lval == 2) if (lval == 2)
/* Notify the sleeper */ /* Notify the sleeper */
@ -261,7 +261,7 @@ _lock_release(struct lock *lck, struct lockuser *lu)
} }
else else
/* Give the lock to the previous request. */ /* Give the lock to the previous request. */
atomic_store_rel_long(&myreq->lr_locked, 0); atomic_store_rel_int(&myreq->lr_locked, 0);
} }
} else { } else {
/* /*
@ -274,14 +274,14 @@ _lock_release(struct lock *lck, struct lockuser *lu)
lu->lu_watchreq = NULL; lu->lu_watchreq = NULL;
lu->lu_myreq->lr_locked = 1; lu->lu_myreq->lr_locked = 1;
if (lck->l_wakeup) { if (lck->l_wakeup) {
atomic_swap_long((long *)&myreq->lr_locked, 0, &lval); atomic_swap_int((int *)&myreq->lr_locked, 0, &lval);
if (lval == 2) if (lval == 2)
/* Notify the sleeper */ /* Notify the sleeper */
lck->l_wakeup(lck, myreq->lr_watcher); lck->l_wakeup(lck, myreq->lr_watcher);
} }
else else
/* Give the lock to the previous request. */ /* Give the lock to the previous request. */
atomic_store_rel_long(&myreq->lr_locked, 0); atomic_store_rel_int(&myreq->lr_locked, 0);
} }
lu->lu_myreq->lr_active = 0; lu->lu_myreq->lr_active = 0;
} }
@ -289,7 +289,7 @@ _lock_release(struct lock *lck, struct lockuser *lu)
void void
_lock_grant(struct lock *lck /* unused */, struct lockuser *lu) _lock_grant(struct lock *lck /* unused */, struct lockuser *lu)
{ {
atomic_store_rel_long(&lu->lu_watchreq->lr_locked, 3); atomic_store_rel_int(&lu->lu_watchreq->lr_locked, 3);
} }
void void

View File

@ -51,9 +51,9 @@ struct lock {
/* Try to make this >= CACHELINESIZE */ /* Try to make this >= CACHELINESIZE */
struct lockreq { struct lockreq {
volatile long lr_locked; /* lock granted = 0, busy otherwise */
struct lockuser *lr_watcher; /* only used for priority locks */ struct lockuser *lr_watcher; /* only used for priority locks */
struct lockuser *lr_owner; /* only used for priority locks */ struct lockuser *lr_owner; /* only used for priority locks */
volatile int lr_locked; /* lock granted = 0, busy otherwise */
volatile int lr_active; /* non-zero if the lock is last lock for thread */ volatile int lr_active; /* non-zero if the lock is last lock for thread */
}; };

View File

@ -33,6 +33,8 @@
#include <pthread.h> #include <pthread.h>
#include "thr_private.h" #include "thr_private.h"
extern int __creat(const char *, mode_t);
__weak_reference(___creat, creat); __weak_reference(___creat, creat);
int int

View File

@ -33,6 +33,8 @@
#include <pthread.h> #include <pthread.h>
#include "thr_private.h" #include "thr_private.h"
extern int __pause(void);
__weak_reference(_pause, pause); __weak_reference(_pause, pause);
int int

View File

@ -33,6 +33,8 @@
#include <pthread.h> #include <pthread.h>
#include "thr_private.h" #include "thr_private.h"
extern unsigned int __sleep(unsigned int);
__weak_reference(_sleep, sleep); __weak_reference(_sleep, sleep);
unsigned int unsigned int

View File

@ -33,6 +33,8 @@
#include <pthread.h> #include <pthread.h>
#include "thr_private.h" #include "thr_private.h"
extern int __system(const char *);
__weak_reference(_system, system); __weak_reference(_system, system);
int int

View File

@ -33,6 +33,8 @@
#include <pthread.h> #include <pthread.h>
#include "thr_private.h" #include "thr_private.h"
extern int __tcdrain(int);
__weak_reference(_tcdrain, tcdrain); __weak_reference(_tcdrain, tcdrain);
int int

View File

@ -32,6 +32,8 @@
#include <pthread.h> #include <pthread.h>
#include "thr_private.h" #include "thr_private.h"
extern int __wait(int *);
__weak_reference(_wait, wait); __weak_reference(_wait, wait);
pid_t pid_t

View File

@ -33,9 +33,12 @@
*/ */
#include <sys/types.h> #include <sys/types.h>
#include "namespace.h"
#include <errno.h> #include <errno.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <pthread.h> #include <pthread.h>
#include "un-namespace.h"
#include "thr_private.h" #include "thr_private.h"
__weak_reference(__wait4, wait4); __weak_reference(__wait4, wait4);

View File

@ -34,6 +34,8 @@
#include <pthread.h> #include <pthread.h>
#include "thr_private.h" #include "thr_private.h"
extern int __waitpid(pid_t, int *, int);
__weak_reference(_waitpid, waitpid); __weak_reference(_waitpid, waitpid);
pid_t pid_t

View File

@ -45,6 +45,23 @@ atomic_swap_long(long *dst, long val, long *res)
" stq_c $2, %1\n" /* attempt the store; $2 clobbered */ " stq_c $2, %1\n" /* attempt the store; $2 clobbered */
" beq $2, 1b\n" /* it didn't work, loop */ " beq $2, 1b\n" /* it didn't work, loop */
" stq $1, %0\n" /* save value of *dst in *res */ " stq $1, %0\n" /* save value of *dst in *res */
" mb \n"
: "+m"(*res)
: "m"(*dst), "r"(val)
: "memory", "$1", "$2"); /* clobber t0 and t1 */
}
static inline void
atomic_swap_int(int *dst, int val, int *res)
{
/* $1 and $2 are t0 and t1 respectively. */
__asm ( " ldl $1, %1\n" /* get cache line before lock */
"1: ldl_l $1, %1\n" /* load *dst asserting lock */
" mov %2, $2\n" /* save value to be swapped */
" stl_c $2, %1\n" /* attempt the store; $2 clobbered */
" beq $2, 1b\n" /* it didn't work, loop */
" stl $1, %0\n" /* save value of *dst in *res */
" mb \n"
: "+m"(*res) : "+m"(*res)
: "m"(*dst), "r"(val) : "m"(*dst), "r"(val)
: "memory", "$1", "$2"); /* clobber t0 and t1 */ : "memory", "$1", "$2"); /* clobber t0 and t1 */

View File

@ -33,17 +33,25 @@
* Atomic swap: * Atomic swap:
* Atomic (tmp = *dst, *dst = val), then *res = tmp * Atomic (tmp = *dst, *dst = val), then *res = tmp
* *
* void atomic_swap_long(long *dst, long val, long *res); * void atomic_swap64(intptr_t *dst, intptr_t val, intptr_t *res);
*/ */
static inline void static inline void
atomic_swap_long(long *dst, long val, long *res) atomic_swap64(intptr_t *dst, intptr_t val, intptr_t *res)
{ {
__asm __volatile( __asm __volatile(
"xchgq %2, %1; movq %2, %0" "xchgq %2, %1; movq %2, %0"
: "=m" (*res) : "m" (*dst), "r" (val) : "memory"); : "=m" (*res) : "m" (*dst), "r" (val) : "memory");
} }
static inline void
atomic_swap_int(int *dst, int val, int *res)
{
__asm __volatile(
"xchgl %2, %1; movl %2, %0"
: "=m" (*res) : "m" (*dst), "r" (val) : "memory");
}
#define atomic_swap_ptr(d, v, r) \ #define atomic_swap_ptr(d, v, r) \
atomic_swap_long((long *)(d), (long)(v), (long *)(r)) atomic_swap64((intptr_t *)(d), (intptr_t)(v), (intptr_t *)(r))
#endif #endif

View File

@ -33,19 +33,19 @@
* Atomic swap: * Atomic swap:
* Atomic (tmp = *dst, *dst = val), then *res = tmp * Atomic (tmp = *dst, *dst = val), then *res = tmp
* *
* void atomic_swap_long(long *dst, long val, long *res); * void atomic_swap32(intptr_t *dst, intptr_t val, intptr_t *res);
*/ */
static inline void static inline void
atomic_swap_long(long *dst, long val, long *res) atomic_swap32(intptr_t *dst, intptr_t val, intptr_t *res)
{ {
__asm __volatile( __asm __volatile(
"xchgl %2, %1; movl %2, %0" "xchgl %2, %1; movl %2, %0"
: "=m" (*res) : "m" (*dst), "r" (val) : "memory"); : "=m" (*res) : "m" (*dst), "r" (val) : "memory");
} }
#define atomic_swap_ptr(d, v, r) \
atomic_swap32((intptr_t *)d, (intptr_t)v, (intptr_t *)r)
#define atomic_swap_int(d, v, r) \ #define atomic_swap_int(d, v, r) \
atomic_swap_long((long *)(d), (long)(v), (long *)(r)) atomic_swap32((intptr_t *)d, (intptr_t)v, (intptr_t *)r)
#define atomic_swap_ptr atomic_swap_int
#endif #endif

View File

@ -107,7 +107,7 @@ void
_lock_acquire(struct lock *lck, struct lockuser *lu, int prio) _lock_acquire(struct lock *lck, struct lockuser *lu, int prio)
{ {
int i; int i;
long lval; int lval;
/** /**
* XXX - We probably want to remove these checks to optimize * XXX - We probably want to remove these checks to optimize
@ -167,7 +167,7 @@ _lock_acquire(struct lock *lck, struct lockuser *lu, int prio)
if (lu->lu_watchreq->lr_active == 0) if (lu->lu_watchreq->lr_active == 0)
break; break;
} }
atomic_swap_long((long *)&lu->lu_watchreq->lr_locked, atomic_swap_int((int *)&lu->lu_watchreq->lr_locked,
2, &lval); 2, &lval);
if (lval == 0) if (lval == 0)
lu->lu_watchreq->lr_locked = 0; lu->lu_watchreq->lr_locked = 0;
@ -188,7 +188,7 @@ _lock_release(struct lock *lck, struct lockuser *lu)
struct lockuser *lu_tmp, *lu_h; struct lockuser *lu_tmp, *lu_h;
struct lockreq *myreq; struct lockreq *myreq;
int prio_h; int prio_h;
long lval; int lval;
/** /**
* XXX - We probably want to remove these checks to optimize * XXX - We probably want to remove these checks to optimize
@ -240,8 +240,8 @@ _lock_release(struct lock *lck, struct lockuser *lu)
if (lu_h != NULL) { if (lu_h != NULL) {
/* Give the lock to the highest priority user. */ /* Give the lock to the highest priority user. */
if (lck->l_wakeup != NULL) { if (lck->l_wakeup != NULL) {
atomic_swap_long( atomic_swap_int(
(long *)&lu_h->lu_watchreq->lr_locked, (int *)&lu_h->lu_watchreq->lr_locked,
0, &lval); 0, &lval);
if (lval == 2) if (lval == 2)
/* Notify the sleeper */ /* Notify the sleeper */
@ -249,11 +249,11 @@ _lock_release(struct lock *lck, struct lockuser *lu)
lu_h->lu_myreq->lr_watcher); lu_h->lu_myreq->lr_watcher);
} }
else else
atomic_store_rel_long( atomic_store_rel_int(
&lu_h->lu_watchreq->lr_locked, 0); &lu_h->lu_watchreq->lr_locked, 0);
} else { } else {
if (lck->l_wakeup != NULL) { if (lck->l_wakeup != NULL) {
atomic_swap_long((long *)&myreq->lr_locked, atomic_swap_int((int *)&myreq->lr_locked,
0, &lval); 0, &lval);
if (lval == 2) if (lval == 2)
/* Notify the sleeper */ /* Notify the sleeper */
@ -261,7 +261,7 @@ _lock_release(struct lock *lck, struct lockuser *lu)
} }
else else
/* Give the lock to the previous request. */ /* Give the lock to the previous request. */
atomic_store_rel_long(&myreq->lr_locked, 0); atomic_store_rel_int(&myreq->lr_locked, 0);
} }
} else { } else {
/* /*
@ -274,14 +274,14 @@ _lock_release(struct lock *lck, struct lockuser *lu)
lu->lu_watchreq = NULL; lu->lu_watchreq = NULL;
lu->lu_myreq->lr_locked = 1; lu->lu_myreq->lr_locked = 1;
if (lck->l_wakeup) { if (lck->l_wakeup) {
atomic_swap_long((long *)&myreq->lr_locked, 0, &lval); atomic_swap_int((int *)&myreq->lr_locked, 0, &lval);
if (lval == 2) if (lval == 2)
/* Notify the sleeper */ /* Notify the sleeper */
lck->l_wakeup(lck, myreq->lr_watcher); lck->l_wakeup(lck, myreq->lr_watcher);
} }
else else
/* Give the lock to the previous request. */ /* Give the lock to the previous request. */
atomic_store_rel_long(&myreq->lr_locked, 0); atomic_store_rel_int(&myreq->lr_locked, 0);
} }
lu->lu_myreq->lr_active = 0; lu->lu_myreq->lr_active = 0;
} }
@ -289,7 +289,7 @@ _lock_release(struct lock *lck, struct lockuser *lu)
void void
_lock_grant(struct lock *lck /* unused */, struct lockuser *lu) _lock_grant(struct lock *lck /* unused */, struct lockuser *lu)
{ {
atomic_store_rel_long(&lu->lu_watchreq->lr_locked, 3); atomic_store_rel_int(&lu->lu_watchreq->lr_locked, 3);
} }
void void

View File

@ -51,9 +51,9 @@ struct lock {
/* Try to make this >= CACHELINESIZE */ /* Try to make this >= CACHELINESIZE */
struct lockreq { struct lockreq {
volatile long lr_locked; /* lock granted = 0, busy otherwise */
struct lockuser *lr_watcher; /* only used for priority locks */ struct lockuser *lr_watcher; /* only used for priority locks */
struct lockuser *lr_owner; /* only used for priority locks */ struct lockuser *lr_owner; /* only used for priority locks */
volatile int lr_locked; /* lock granted = 0, busy otherwise */
volatile int lr_active; /* non-zero if the lock is last lock for thread */ volatile int lr_active; /* non-zero if the lock is last lock for thread */
}; };

View File

@ -33,6 +33,8 @@
#include <pthread.h> #include <pthread.h>
#include "thr_private.h" #include "thr_private.h"
extern int __creat(const char *, mode_t);
__weak_reference(___creat, creat); __weak_reference(___creat, creat);
int int

View File

@ -33,6 +33,8 @@
#include <pthread.h> #include <pthread.h>
#include "thr_private.h" #include "thr_private.h"
extern int __pause(void);
__weak_reference(_pause, pause); __weak_reference(_pause, pause);
int int

View File

@ -33,6 +33,8 @@
#include <pthread.h> #include <pthread.h>
#include "thr_private.h" #include "thr_private.h"
extern unsigned int __sleep(unsigned int);
__weak_reference(_sleep, sleep); __weak_reference(_sleep, sleep);
unsigned int unsigned int

View File

@ -33,6 +33,8 @@
#include <pthread.h> #include <pthread.h>
#include "thr_private.h" #include "thr_private.h"
extern int __system(const char *);
__weak_reference(_system, system); __weak_reference(_system, system);
int int

View File

@ -33,6 +33,8 @@
#include <pthread.h> #include <pthread.h>
#include "thr_private.h" #include "thr_private.h"
extern int __tcdrain(int);
__weak_reference(_tcdrain, tcdrain); __weak_reference(_tcdrain, tcdrain);
int int

View File

@ -32,6 +32,8 @@
#include <pthread.h> #include <pthread.h>
#include "thr_private.h" #include "thr_private.h"
extern int __wait(int *);
__weak_reference(_wait, wait); __weak_reference(_wait, wait);
pid_t pid_t

View File

@ -33,9 +33,12 @@
*/ */
#include <sys/types.h> #include <sys/types.h>
#include "namespace.h"
#include <errno.h> #include <errno.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <pthread.h> #include <pthread.h>
#include "un-namespace.h"
#include "thr_private.h" #include "thr_private.h"
__weak_reference(__wait4, wait4); __weak_reference(__wait4, wait4);

View File

@ -34,6 +34,8 @@
#include <pthread.h> #include <pthread.h>
#include "thr_private.h" #include "thr_private.h"
extern int __waitpid(pid_t, int *, int);
__weak_reference(_waitpid, waitpid); __weak_reference(_waitpid, waitpid);
pid_t pid_t