diff options
author | James Hogan <james.hogan@imgtec.com> | 2012-10-09 11:00:24 +0100 |
---|---|---|
committer | James Hogan <james.hogan@imgtec.com> | 2013-03-02 20:09:50 +0000 |
commit | 6006c0d8ce9441dd1363bf14f18a8e28d3588460 (patch) | |
tree | 786183053c89e11b3058b8a16f7953744b819340 /arch/metag/include/asm/global_lock.h | |
parent | 9b802d1f43978869fcd98e92b854fd8785cefee7 (diff) |
metag: Atomics, locks and bitops
Add header files to implement Meta hardware thread locks (used by some
other atomic operations), atomics, spinlocks, and bitops.
There are 2 main types of atomic primitives for metag (in addition to
IRQs off on UP):
- LOCK instructions provide locking between hardware threads.
- LNKGET/LNKSET instructions provide load-linked/store-conditional
operations allowing for lighter weight atomics on Meta2
LOCK instructions allow for hardware threads to acquire voluntary or
exclusive hardware thread locks:
- LOCK0 releases exclusive and voluntary lock from the running hardware
thread.
- LOCK1 acquires the voluntary hardware lock, blocking until it becomes
available.
- LOCK2 implies LOCK1, and additionally acquires the exclusive hardware
lock, blocking all other hardware threads from executing.
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Diffstat (limited to 'arch/metag/include/asm/global_lock.h')
-rw-r--r-- | arch/metag/include/asm/global_lock.h | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/arch/metag/include/asm/global_lock.h b/arch/metag/include/asm/global_lock.h new file mode 100644 index 000000000000..fc831c88c22a --- /dev/null +++ b/arch/metag/include/asm/global_lock.h @@ -0,0 +1,100 @@ +#ifndef __ASM_METAG_GLOBAL_LOCK_H +#define __ASM_METAG_GLOBAL_LOCK_H + +#include <asm/metag_mem.h> + +/** + * __global_lock1() - Acquire global voluntary lock (LOCK1). + * @flags: Variable to store flags into. + * + * Acquires the Meta global voluntary lock (LOCK1), also taking care to disable + * all triggers so we cannot be interrupted, and to enforce a compiler barrier + * so that the compiler cannot reorder memory accesses across the lock. + * + * No other hardware thread will be able to acquire the voluntary or exclusive + * locks until the voluntary lock is released with @__global_unlock1, but they + * may continue to execute as long as they aren't trying to acquire either of + * the locks. + */ +#define __global_lock1(flags) do { \ + unsigned int __trval; \ + asm volatile("MOV %0,#0\n\t" \ + "SWAP %0,TXMASKI\n\t" \ + "LOCK1" \ + : "=r" (__trval) \ + : \ + : "memory"); \ + (flags) = __trval; \ +} while (0) + +/** + * __global_unlock1() - Release global voluntary lock (LOCK1). + * @flags: Variable to restore flags from. + * + * Releases the Meta global voluntary lock (LOCK1) acquired with + * @__global_lock1, also taking care to re-enable triggers, and to enforce a + * compiler barrier so that the compiler cannot reorder memory accesses across + * the unlock. + * + * This immediately allows another hardware thread to acquire the voluntary or + * exclusive locks. + */ +#define __global_unlock1(flags) do { \ + unsigned int __trval = (flags); \ + asm volatile("LOCK0\n\t" \ + "MOV TXMASKI,%0" \ + : \ + : "r" (__trval) \ + : "memory"); \ +} while (0) + +/** + * __global_lock2() - Acquire global exclusive lock (LOCK2). + * @flags: Variable to store flags into. + * + * Acquires the Meta global voluntary lock and global exclusive lock (LOCK2), + * also taking care to disable all triggers so we cannot be interrupted, to take + * the atomic lock (system event) and to enforce a compiler barrier so that the + * compiler cannot reorder memory accesses across the lock. + * + * No other hardware thread will be able to execute code until the locks are + * released with @__global_unlock2. + */ +#define __global_lock2(flags) do { \ + unsigned int __trval; \ + unsigned int __aloc_hi = LINSYSEVENT_WR_ATOMIC_LOCK & 0xFFFF0000; \ + asm volatile("MOV %0,#0\n\t" \ + "SWAP %0,TXMASKI\n\t" \ + "LOCK2\n\t" \ + "SETD [%1+#0x40],D1RtP" \ + : "=r&" (__trval) \ + : "u" (__aloc_hi) \ + : "memory"); \ + (flags) = __trval; \ +} while (0) + +/** + * __global_unlock2() - Release global exclusive lock (LOCK2). + * @flags: Variable to restore flags from. + * + * Releases the Meta global exclusive lock (LOCK2) and global voluntary lock + * acquired with @__global_lock2, also taking care to release the atomic lock + * (system event), re-enable triggers, and to enforce a compiler barrier so that + * the compiler cannot reorder memory accesses across the unlock. + * + * This immediately allows other hardware threads to continue executing and one + * of them to acquire locks. + */ +#define __global_unlock2(flags) do { \ + unsigned int __trval = (flags); \ + unsigned int __alock_hi = LINSYSEVENT_WR_ATOMIC_LOCK & 0xFFFF0000; \ + asm volatile("SETD [%1+#0x00],D1RtP\n\t" \ + "LOCK0\n\t" \ + "MOV TXMASKI,%0" \ + : \ + : "r" (__trval), \ + "u" (__alock_hi) \ + : "memory"); \ +} while (0) + +#endif /* __ASM_METAG_GLOBAL_LOCK_H */ |