Fix segfault with STM; fixes #8035. Patch from errge.
[ghc.git] / rts / OldARMAtomic.c
1 /* -----------------------------------------------------------------------------
2 *
3 * (c) The GHC Team, 2011
4 *
5 * Inefficient but necessary atomic locks used for implementing atomic
6 * operations on ARM architectures pre-ARMv6.
7 *
8 * -------------------------------------------------------------------------- */
9
10 #include "PosixSource.h"
11 #include "Rts.h"
12
13 #if defined(HAVE_SCHED_H)
14 #include <sched.h>
15 #endif
16
17 #if defined(THREADED_RTS)
18
19 #if arm_HOST_ARCH && defined(arm_HOST_ARCH_PRE_ARMv6)
20
21 static volatile int atomic_spin = 0;
22
23 static int arm_atomic_spin_trylock (void)
24 {
25 int result;
26
27 asm volatile (
28 "swp %0, %1, [%2]\n"
29 : "=&r,&r" (result)
30 : "r,0" (1), "r,r" (&atomic_spin)
31 : "memory");
32 if (result == 0)
33 return 0;
34 else
35 return -1;
36 }
37
38 void arm_atomic_spin_lock()
39 {
40 while (arm_atomic_spin_trylock())
41 #if defined(HAVE_SCHED_H)
42 sched_yield();
43 #else
44 ; // inefficient on non-POSIX.
45 #endif
46 }
47
48 void arm_atomic_spin_unlock()
49 {
50 atomic_spin = 0;
51 }
52
53 #endif /* arm_HOST_ARCH && defined(arm_HOST_ARCH_PRE_ARMv6) */
54
55 #endif /* defined(THREADED_RTS) */
56