summaryrefslogtreecommitdiffstats
path: root/lib/librthread/arch
diff options
context:
space:
mode:
authorpatrick <patrick@openbsd.org>2013-01-23 20:49:55 +0000
committerpatrick <patrick@openbsd.org>2013-01-23 20:49:55 +0000
commit091d487ac55ed35a731d92681d4678e47e329c1c (patch)
tree3b9fdac90cecdea141f4651cfde012122f2b1949 /lib/librthread/arch
parentAdd instruction fault register functions, which will be needed for further (diff)
downloadwireguard-openbsd-091d487ac55ed35a731d92681d4678e47e329c1c.tar.xz
wireguard-openbsd-091d487ac55ed35a731d92681d4678e47e329c1c.zip
ARMv7 doesn't support the atomic SWP instruction anymore. Use the atomic
load and store instructions instead. ok miod@
Diffstat (limited to 'lib/librthread/arch')
-rw-r--r--lib/librthread/arch/arm/_atomic_lock.c13
1 files changed, 12 insertions, 1 deletions
diff --git a/lib/librthread/arch/arm/_atomic_lock.c b/lib/librthread/arch/arm/_atomic_lock.c
index 01a3cef3a9f..48bca7da276 100644
--- a/lib/librthread/arch/arm/_atomic_lock.c
+++ b/lib/librthread/arch/arm/_atomic_lock.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: _atomic_lock.c,v 1.2 2006/01/05 22:33:23 marc Exp $ */
+/* $OpenBSD: _atomic_lock.c,v 1.3 2013/01/23 20:49:55 patrick Exp $ */
/*
* Copyright (c) 2004 Dale Rahn. All rights reserved.
@@ -35,9 +35,20 @@ _atomic_lock(volatile _spinlock_lock_t *lock)
{
_spinlock_lock_t old;
+#ifdef ARM_V7PLUS_LOCKS
+ uint32_t scratch = 0;
+ old = 0;
+ __asm__("1: ldrex %0, [%1] \n"
+ " strex %2, %3, [%1] \n"
+ " cmp %2, #0 \n"
+ " bne 1b \n"
+ : "+r" (old), "+r" (lock), "+r" (scratch)
+ : "r" (_SPINLOCK_LOCKED));
+#else
__asm__("swp %0, %2, [%1]"
: "=r" (old), "=r" (lock)
: "r" (_SPINLOCK_LOCKED), "1" (lock) );
+#endif
return (old != _SPINLOCK_UNLOCKED);
}