fix bug in SYMBOL-VALUE CAS expansion for constant arguments
[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
26 #if defined(LISP_FEATURE_X86)
27 #define LISPOBJ_ASM_SUFFIX "l"
28 #elif defined(LISP_FEATURE_X86_64)
29 #define LISPOBJ_ASM_SUFFIX "q"
30 #endif
31
32 static inline int
33 get_pseudo_atomic_atomic(struct thread *thread)
34 {
35     return SymbolValue(PSEUDO_ATOMIC_BITS, thread) & (~1);
36 }
37
38 static inline void
39 set_pseudo_atomic_atomic(struct thread *thread)
40 {
41     lispobj *p = SymbolValueAddress(PSEUDO_ATOMIC_BITS, thread);
42     if (*p)
43         lose("set_pseudo_atomic_atomic: pseudo atomic bits is %d.", *p);
44     __asm__ __volatile__
45         ("or" LISPOBJ_ASM_SUFFIX " %0,%1"
46          :
47          : "g" (~1), "m" (*p)
48          : "memory");
49 }
50
51 static inline void
52 clear_pseudo_atomic_atomic(struct thread *thread)
53 {
54     lispobj *p = SymbolValueAddress(PSEUDO_ATOMIC_BITS, thread);
55     __asm__ __volatile__
56         ("and" LISPOBJ_ASM_SUFFIX " %0,%1"
57          :
58          : "g" (1), "m" (*p)
59          : "memory");
60 }
61
62 static inline int
63 get_pseudo_atomic_interrupted(struct thread *thread)
64 {
65     return SymbolValue(PSEUDO_ATOMIC_BITS, thread) & 1;
66 }
67
68 static inline void
69 set_pseudo_atomic_interrupted(struct thread *thread)
70 {
71     if (!get_pseudo_atomic_atomic(thread))
72         lose("set_pseudo_atomic_interrupted not in pseudo atomic");
73     lispobj *p = SymbolValueAddress(PSEUDO_ATOMIC_BITS, thread);
74     __asm__ __volatile__
75         ("or" LISPOBJ_ASM_SUFFIX " %0,%1"
76          :
77          : "g" (1), "m" (*p)
78          : "memory");
79 }
80
81 static inline void
82 clear_pseudo_atomic_interrupted(struct thread *thread)
83 {
84     if (get_pseudo_atomic_atomic(thread))
85         lose("clear_pseudo_atomic_interrupted in pseudo atomic");
86     lispobj *p = SymbolValueAddress(PSEUDO_ATOMIC_BITS, thread);
87     __asm__ __volatile__
88         ("and" LISPOBJ_ASM_SUFFIX " %0,%1"
89          :
90          : "g" (~1), "m" (*p)
91          : "memory");
92 }
93
94 #undef LISPOBJ_SUFFIX
95
96 #elif defined(LISP_FEATURE_GENCGC)
97
98 /* FIXME: Are these async signal safe? Compiler reordering? */
99
100 #define set_alloc_pointer(value) \
101     (dynamic_space_free_pointer = \
102      ((lispobj *) \
103       ((value) | (((unsigned long)dynamic_space_free_pointer) & LOWTAG_MASK))))
104
105 #define get_alloc_pointer()                                     \
106     ((unsigned long) dynamic_space_free_pointer & ~LOWTAG_MASK)
107
108 #ifdef LISP_FEATURE_SB_THREAD
109 #define get_pseudo_atomic_atomic(thread) \
110     ((thread)->pseudo_atomic_bits & flag_PseudoAtomic)
111 #define set_pseudo_atomic_atomic(thread) \
112     ((thread)->pseudo_atomic_bits |= flag_PseudoAtomic)
113 #define clear_pseudo_atomic_atomic(thread) \
114     ((thread)->pseudo_atomic_bits &= ~flag_PseudoAtomic)
115 #define get_pseudo_atomic_interrupted(thread) \
116     ((thread)->pseudo_atomic_bits & flag_PseudoAtomicInterrupted)
117 #define set_pseudo_atomic_interrupted(thread) \
118     ((thread)->pseudo_atomic_bits |= flag_PseudoAtomicInterrupted)
119 #define clear_pseudo_atomic_interrupted(thread) \
120     ((thread)->pseudo_atomic_bits &= ~flag_PseudoAtomicInterrupted)
121 #else
122 #define get_pseudo_atomic_atomic(thread)                                \
123     ((unsigned long)dynamic_space_free_pointer & flag_PseudoAtomic)
124 #define set_pseudo_atomic_atomic(thread)                                \
125     (dynamic_space_free_pointer                                         \
126      = (lispobj*) ((unsigned long)dynamic_space_free_pointer | flag_PseudoAtomic))
127 #define clear_pseudo_atomic_atomic(thread)                              \
128     (dynamic_space_free_pointer                                         \
129      = (lispobj*) ((unsigned long) dynamic_space_free_pointer & ~flag_PseudoAtomic))
130 #define get_pseudo_atomic_interrupted(thread)                           \
131     ((unsigned long) dynamic_space_free_pointer & flag_PseudoAtomicInterrupted)
132 #define clear_pseudo_atomic_interrupted(thread)                         \
133     (dynamic_space_free_pointer                                         \
134      = (lispobj*) ((unsigned long) dynamic_space_free_pointer & ~flag_PseudoAtomicInterrupted))
135 #define set_pseudo_atomic_interrupted(thread)                           \
136     (dynamic_space_free_pointer                                         \
137      = (lispobj*) ((unsigned long) dynamic_space_free_pointer | flag_PseudoAtomicInterrupted))
138 #endif
139
140 #endif
141
142 #endif /* PSEUDO_ATOMIC_H */
143