commit 598854767a317fb51c7e93decb3ff064fdbd76ab
parent ed0733d172a0506a20b723e7fae321d7e2913cab
Author: oblique <psyberbits@gmail.com>
Date: Sun, 28 Oct 2012 02:02:40 +0300
add memory barriers and event signaling in spinlocks
Diffstat:
1 file changed, 19 insertions(+), 6 deletions(-)
diff --git a/include/spinlock.h b/include/spinlock.h
@@ -1,9 +1,13 @@
#ifndef __SPINLOCK_H
#define __SPINLOCK_H
-#define SPINLOCK_INIT ((spinlock_t)0)
+#include <io.h>
-typedef unsigned int spinlock_t;
+typedef struct {
+ u32 lock;
+} spinlock_t;
+
+#define SPINLOCK_INIT { 0 }
static inline void
spinlock_lock(spinlock_t *sl)
@@ -12,24 +16,32 @@ spinlock_lock(spinlock_t *sl)
"1: \n\t"
"ldrex v1, [%0] \n\t"
"teq v1, #0 \n\t"
- "strexeq v1, %1, [%0] \n\t"
+ /* wait for event */
+ "wfene \n\t"
+ "bne 1b \n\t"
+ "strex v1, %1, [%0] \n\t"
"teq v1, #0 \n\t"
"bne 1b \n\t"
:
: "r" (sl), "r" (0x80000000)
: "v1", "memory"
);
+ dmb();
}
static inline void
spinlock_unlock(spinlock_t *sl)
{
+ dmb();
asm volatile (
"str %1, [%0]"
:
: "r" (sl), "r" (0)
: "memory"
);
+ dsb();
+ /* signal event */
+ asm volatile("sev");
}
/* returns 1 if locked and 0 if not */
@@ -47,16 +59,17 @@ spinlock_trylock(spinlock_t *sl)
: "memory"
);
- if (tmp == 0)
+ if (tmp == 0) {
+ dmb();
return 1;
- else
+ } else
return 0;
}
static inline void
INIT_SPINLOCK(spinlock_t *sl)
{
- *sl = 0;
+ sl->lock = 0;
}
#endif /* __SPINLOCK_H */