提交 c303d067 创建 作者: Silas Boyd-Wickizer's avatar Silas Boyd-Wickizer

A qlock implementation.

上级 64137fa7
...@@ -39,6 +39,17 @@ xchg32(volatile u32 *addr, u32 newval) ...@@ -39,6 +39,17 @@ xchg32(volatile u32 *addr, u32 newval)
} }
static inline u64 static inline u64
xchg(u64 *ptr, u64 val)
{
__asm volatile(
"lock; xchgq %0, %1\n\t"
: "+m" (*ptr), "+r" (val)
:
: "memory", "cc");
return val;
}
static inline u64
readrflags(void) readrflags(void)
{ {
u64 rflags; u64 rflags;
...@@ -65,6 +76,18 @@ nop_pause(void) ...@@ -65,6 +76,18 @@ nop_pause(void)
} }
static inline void static inline void
rep_nop(void)
{
__asm volatile("rep; nop" ::: "memory");
}
static inline void
barrier(void)
{
__asm volatile("" ::: "memory");
}
static inline void
lidt(void *p) lidt(void *p)
{ {
__asm volatile("lidt (%0)" : : "r" (p) : "memory"); __asm volatile("lidt (%0)" : : "r" (p) : "memory");
......
struct qnode {
volatile void *next;
volatile char locked;
__padout__;
};
typedef struct {
struct qnode *v __mpalign__;
} qlock_t;
static inline void
ql_init(qlock_t *l)
{
l->v = NULL;
}
static inline void
ql_lock(qlock_t *l, volatile struct qnode *mynode)
{
struct qnode *predecessor;
mynode->next = NULL;
predecessor = (struct qnode *)xchg((u64 *)&l->v, (u64)mynode);
if (predecessor) {
mynode->locked = 1;
barrier();
predecessor->next = mynode;
while (mynode->locked)
rep_nop();
}
}
static inline int
ql_trylock(qlock_t *l, volatile struct qnode *mynode)
{
mynode->next = NULL;
return cmpswap((long *)&l->v, 0, (long)mynode);
}
static inline void
ql_unlock(qlock_t *l, volatile struct qnode *mynode)
{
if (!mynode->next) {
if (cmpswap((long *)&l->v, (long)mynode, 0))
return;
while (!mynode->next)
rep_nop();
}
((struct qnode *)mynode->next)->locked = 0;
}
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论