Building GHC with hadrian on FreeBSD
[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 * These operations are not only referenced in the threaded RTS, but also in
9 * ghc (the library), via the operations in compiler/cbits/genSym.c.
10 * They are not actually called in a non-threaded environment, but we still
11 * need them in every RTS to make the linker happy, hence no
12 * #if defined(THREADED_RTS) here. See #8951.
13 *
14 * -------------------------------------------------------------------------- */
15
16 #include "PosixSource.h"
17 #include "Rts.h"
18
19 #if defined(HAVE_SCHED_H)
20 #include <sched.h>
21 #endif
22
23 #if defined(arm_HOST_ARCH) && defined(arm_HOST_ARCH_PRE_ARMv6)
24
25 static volatile int atomic_spin = 0;
26
27 static int arm_atomic_spin_trylock (void)
28 {
29 int result;
30
31 asm volatile (
32 "swp %0, %1, [%2]\n"
33 : "=&r,&r" (result)
34 : "r,0" (1), "r,r" (&atomic_spin)
35 : "memory");
36 if (result == 0)
37 return 0;
38 else
39 return -1;
40 }
41
42 void arm_atomic_spin_lock()
43 {
44 while (arm_atomic_spin_trylock())
45 #if defined(HAVE_SCHED_H)
46 sched_yield();
47 #else
48 ; // inefficient on non-POSIX.
49 #endif
50 }
51
52 void arm_atomic_spin_unlock()
53 {
54 atomic_spin = 0;
55 }
56
57 #endif /* arm_HOST_ARCH && defined(arm_HOST_ARCH_PRE_ARMv6) */