support for read/write-lock and read/write-trylock
Change-Id: I609071c0f6234d0d413c8b312d8a8379abf6846e Refs: #1323
This commit is contained in:
committed by
Masamichi Takagi
parent
8efced7bf7
commit
258156b57e
@ -659,5 +659,102 @@ static inline int irqflags_can_interrupt(unsigned long flags)
|
||||
}
|
||||
#endif /* CONFIG_HAS_NMI */
|
||||
|
||||
struct ihk_rwlock {
|
||||
unsigned int lock;
|
||||
};
|
||||
|
||||
static inline void ihk_mc_rwlock_init(struct ihk_rwlock *rw)
|
||||
{
|
||||
rw->lock = 0;
|
||||
}
|
||||
|
||||
static inline void ihk_mc_read_lock(struct ihk_rwlock *rw)
|
||||
{
|
||||
unsigned int tmp, tmp2;
|
||||
|
||||
asm volatile(
|
||||
" sevl\n"
|
||||
"1: wfe\n"
|
||||
"2: ldaxr %w0, %2\n"
|
||||
" add %w0, %w0, #1\n"
|
||||
" tbnz %w0, #31, 1b\n"
|
||||
" stxr %w1, %w0, %2\n"
|
||||
" cbnz %w1, 2b\n"
|
||||
: "=&r" (tmp), "=&r" (tmp2), "+Q" (rw->lock)
|
||||
:
|
||||
: "cc", "memory");
|
||||
}
|
||||
|
||||
static inline int ihk_mc_read_trylock(struct ihk_rwlock *rw)
|
||||
{
|
||||
unsigned int tmp, tmp2 = 1;
|
||||
|
||||
asm volatile(
|
||||
" ldaxr %w0, %2\n"
|
||||
" add %w0, %w0, #1\n"
|
||||
" tbnz %w0, #31, 1f\n"
|
||||
" stxr %w1, %w0, %2\n"
|
||||
"1:\n"
|
||||
: "=&r" (tmp), "+r" (tmp2), "+Q" (rw->lock)
|
||||
:
|
||||
: "cc", "memory");
|
||||
|
||||
return !tmp2;
|
||||
}
|
||||
|
||||
static inline void ihk_mc_read_unlock(struct ihk_rwlock *rw)
|
||||
{
|
||||
unsigned int tmp, tmp2;
|
||||
|
||||
asm volatile(
|
||||
"1: ldxr %w0, %2\n"
|
||||
" sub %w0, %w0, #1\n"
|
||||
" stlxr %w1, %w0, %2\n"
|
||||
" cbnz %w1, 1b\n"
|
||||
: "=&r" (tmp), "=&r" (tmp2), "+Q" (rw->lock)
|
||||
:
|
||||
: "cc", "memory");
|
||||
}
|
||||
|
||||
static inline void ihk_mc_write_lock(struct ihk_rwlock *rw)
|
||||
{
|
||||
unsigned int tmp;
|
||||
|
||||
asm volatile(
|
||||
" sevl\n"
|
||||
"1: wfe\n"
|
||||
"2: ldaxr %w0, %1\n"
|
||||
" cbnz %w0, 1b\n"
|
||||
" stxr %w0, %w2, %1\n"
|
||||
" cbnz %w0, 2b\n"
|
||||
: "=&r" (tmp), "+Q" (rw->lock)
|
||||
: "r" (0x80000000)
|
||||
: "cc", "memory");
|
||||
}
|
||||
|
||||
static inline int ihk_mc_write_trylock(struct ihk_rwlock *rw)
|
||||
{
|
||||
unsigned int tmp;
|
||||
|
||||
asm volatile(
|
||||
" ldaxr %w0, %1\n"
|
||||
" cbnz %w0, 1f\n"
|
||||
" stxr %w0, %w2, %1\n"
|
||||
"1:\n"
|
||||
: "=&r" (tmp), "+Q" (rw->lock)
|
||||
: "r" (0x80000000)
|
||||
: "cc", "memory");
|
||||
|
||||
return !tmp;
|
||||
}
|
||||
|
||||
static inline void ihk_mc_write_unlock(struct ihk_rwlock *rw)
|
||||
{
|
||||
asm volatile(
|
||||
" stlr %w1, %0\n"
|
||||
: "=Q" (rw->lock) : "r" (0) : "memory");
|
||||
}
|
||||
|
||||
#define ihk_mc_read_can_lock(rw) ((rw)->lock < 0x80000000)
|
||||
#define ihk_mc_write_can_lock(rw) ((rw)->lock == 0)
|
||||
#endif /* !__HEADER_ARM64_COMMON_ARCH_LOCK_H */
|
||||
|
||||
@ -592,4 +592,90 @@ static inline int irqflags_can_interrupt(unsigned long flags)
|
||||
return !!(flags & 0x200);
|
||||
}
|
||||
|
||||
struct ihk_rwlock {
|
||||
union {
|
||||
long lock;
|
||||
struct {
|
||||
unsigned int read;
|
||||
int write;
|
||||
};
|
||||
} lock;
|
||||
};
|
||||
|
||||
static inline void ihk_mc_rwlock_init(struct ihk_rwlock *rw)
|
||||
{
|
||||
rw->lock.read = 0;
|
||||
rw->lock.write = 1;
|
||||
}
|
||||
|
||||
static inline void ihk_mc_read_lock(struct ihk_rwlock *rw)
|
||||
{
|
||||
asm volatile("1:\t"
|
||||
"lock; decq %0\n\t"
|
||||
"jns 3f\n\t"
|
||||
"lock incq %0\n\t"
|
||||
"2:\t"
|
||||
"pause\n\t"
|
||||
"cmpq $0x1, %0\n\t"
|
||||
"jns 1b\n\t"
|
||||
"jmp 2b\n\t"
|
||||
"3:"
|
||||
: "+m" (rw->lock.lock) : : "memory");
|
||||
}
|
||||
|
||||
static inline void ihk_mc_write_lock(struct ihk_rwlock *rw)
|
||||
{
|
||||
asm volatile("1:\t"
|
||||
"lock; decl %0\n\t"
|
||||
"je 3f\n\t"
|
||||
"lock; incl %0\n\t"
|
||||
"2:\t"
|
||||
"pause\n\t"
|
||||
"cmpl $0x1,%0\n\t"
|
||||
"je 1b\n\t"
|
||||
"jmp 2b\n\t"
|
||||
"3:"
|
||||
: "+m" (rw->lock.write) : "i" (((1L) << 32)) : "memory");
|
||||
}
|
||||
|
||||
static inline int ihk_mc_read_trylock(struct ihk_rwlock *rw)
|
||||
{
|
||||
ihk_atomic64_t *count = (ihk_atomic64_t *)rw;
|
||||
|
||||
if (ihk_atomic64_sub_return(1, count) >= 0)
|
||||
return 1;
|
||||
ihk_atomic64_inc(count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int ihk_mc_write_trylock(struct ihk_rwlock *rw)
|
||||
{
|
||||
ihk_atomic_t *count = (ihk_atomic_t *)&rw->lock.write;
|
||||
|
||||
if (ihk_atomic_dec_and_test(count))
|
||||
return 1;
|
||||
ihk_atomic_inc(count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void ihk_mc_read_unlock(struct ihk_rwlock *rw)
|
||||
{
|
||||
asm volatile("lock; incq %0" : "+m" (rw->lock.lock) : : "memory");
|
||||
}
|
||||
|
||||
static inline void ihk_mc_write_unlock(struct ihk_rwlock *rw)
|
||||
{
|
||||
asm volatile("lock; incl %0"
|
||||
: "+m" (rw->lock.write) : "i" (((1L) << 32)) : "memory");
|
||||
}
|
||||
|
||||
static inline int ihk_mc_write_can_lock(struct ihk_rwlock *rw)
|
||||
{
|
||||
return rw->lock.write == 1;
|
||||
}
|
||||
|
||||
static inline int ihk_mc_read_can_lock(struct ihk_rwlock *rw)
|
||||
{
|
||||
return rw->lock.lock > 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -126,6 +126,22 @@ static inline void ihk_atomic64_inc(ihk_atomic64_t *v)
|
||||
asm volatile ("lock incq %0" : "+m"(v->counter64));
|
||||
}
|
||||
|
||||
static inline long ihk_atomic64_add_return(long i, ihk_atomic64_t *v)
|
||||
{
|
||||
long __i;
|
||||
|
||||
__i = i;
|
||||
asm volatile("lock xaddq %0, %1"
|
||||
: "+r" (i), "+m" (v->counter64)
|
||||
: : "memory");
|
||||
return i + __i;
|
||||
}
|
||||
|
||||
static inline long ihk_atomic64_sub_return(long i, ihk_atomic64_t *v)
|
||||
{
|
||||
return ihk_atomic64_add_return(-i, v);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* others
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user