1.0.25.24: x86/x86-64 runtime pseudo atomic fixes
[sbcl.git] / src / runtime / pseudo-atomic.h
1 /*
2  * macros for manipulating pseudo-atomic flags (per thread)
3  */
4
5 /*
6  * This software is part of the SBCL system. See the README file for
7  * more information.
8  *
9  * This software is derived from the CMU CL system, which was
10  * written at Carnegie Mellon University and released into the
11  * public domain. The software is in the public domain and is
12  * provided with absolutely no warranty. See the COPYING and CREDITS
13  * files for more information.
14  */
15
16 #ifndef PSEUDO_ATOMIC_H
17 #define PSEUDO_ATOMIC_H
18
19 #if defined(LISP_FEATURE_X86) || defined(LISP_FEATURE_X86_64)
20
21 #define set_alloc_pointer(value)                \
22     SetSymbolValue(ALLOCATION_POINTER, value, 0)
23 #define get_alloc_pointer()                     \
24     SymbolValue(ALLOCATION_POINTER, 0)
25 #define get_binding_stack_pointer(thread)       \
26     SymbolValue(BINDING_STACK_POINTER, thread)
27
28 #if defined(LISP_FEATURE_X86)
29 #define LISPOBJ_ASM_SUFFIX "l"
30 #elif defined(LISP_FEATURE_X86_64)
31 #define LISPOBJ_ASM_SUFFIX "q"
32 #endif
33
34 static inline int
35 get_pseudo_atomic_atomic(struct thread *thread)
36 {
37     return fixnum_value(SymbolValue(PSEUDO_ATOMIC_BITS, thread) &
38                         make_fixnum(1));
39 }
40
41 static inline void
42 set_pseudo_atomic_atomic(struct thread *thread)
43 {
44     lispobj *p = SymbolValueAddress(PSEUDO_ATOMIC_BITS, thread);
45     __asm__ __volatile__
46         ("or" LISPOBJ_ASM_SUFFIX " %0,%1"
47          :
48          : "g" (make_fixnum(1)), "m" (*p)
49          : "memory");
50 }
51
52 static inline void
53 clear_pseudo_atomic_atomic(struct thread *thread)
54 {
55     lispobj *p = SymbolValueAddress(PSEUDO_ATOMIC_BITS, thread);
56     __asm__ __volatile__
57         ("and" LISPOBJ_ASM_SUFFIX " %0,%1"
58          :
59          : "g" (~make_fixnum(1)), "m" (*p)
60          : "memory");
61 }
62
63 static inline int
64 get_pseudo_atomic_interrupted(struct thread *thread)
65 {
66     return fixnum_value(SymbolValue(PSEUDO_ATOMIC_BITS, thread) &
67                         make_fixnum(2));
68 }
69
70 static inline void
71 set_pseudo_atomic_interrupted(struct thread *thread)
72 {
73     lispobj *p = SymbolValueAddress(PSEUDO_ATOMIC_BITS, thread);
74     __asm__ __volatile__
75         ("or" LISPOBJ_ASM_SUFFIX " %0,%1"
76          :
77          : "g" (make_fixnum(2)), "m" (*p)
78          : "memory");
79 }
80
81 static inline void
82 clear_pseudo_atomic_interrupted(struct thread *thread)
83 {
84     lispobj *p = SymbolValueAddress(PSEUDO_ATOMIC_BITS, thread);
85     __asm__ __volatile__
86         ("and" LISPOBJ_ASM_SUFFIX " %0,%1"
87          :
88          : "g" (~make_fixnum(2)), "m" (*p)
89          : "memory");
90 }
91
92 #undef LISPOBJ_SUFFIX
93
94 #elif defined(LISP_FEATURE_PPC) && defined(LISP_FEATURE_GENCGC)
95
96 /* FIXME: Are these async signal safe? Compiler reordering? */
97
98 #define set_alloc_pointer(value) \
99     (dynamic_space_free_pointer = \
100      ((lispobj *) \
101       ((value) | (((unsigned long)dynamic_space_free_pointer) & LOWTAG_MASK))))
102
103 #define get_alloc_pointer()                                     \
104     ((unsigned long) dynamic_space_free_pointer & ~LOWTAG_MASK)
105 #define get_binding_stack_pointer(thread)       \
106     (current_binding_stack_pointer)
107 #define get_pseudo_atomic_atomic(thread)                                \
108     ((unsigned long)dynamic_space_free_pointer & flag_PseudoAtomic)
109 #define set_pseudo_atomic_atomic(thread)                                \
110     (dynamic_space_free_pointer                                         \
111      = (lispobj*) ((unsigned long)dynamic_space_free_pointer | flag_PseudoAtomic))
112 #define clear_pseudo_atomic_atomic(thread)                              \
113     (dynamic_space_free_pointer                                         \
114      = (lispobj*) ((unsigned long) dynamic_space_free_pointer & ~flag_PseudoAtomic))
115 #define get_pseudo_atomic_interrupted(thread)                           \
116     ((unsigned long) dynamic_space_free_pointer & flag_PseudoAtomicInterrupted)
117 #define clear_pseudo_atomic_interrupted(thread)                         \
118     (dynamic_space_free_pointer                                         \
119      = (lispobj*) ((unsigned long) dynamic_space_free_pointer & ~flag_PseudoAtomicInterrupted))
120 #define set_pseudo_atomic_interrupted(thread)                           \
121     (dynamic_space_free_pointer                                         \
122      = (lispobj*) ((unsigned long) dynamic_space_free_pointer | flag_PseudoAtomicInterrupted))
123
124 #endif
125
126 #endif /* PSEUDO_ATOMIC_H */
127