/*
 * macros for manipulating pseudo-atomic flags (per thread)
 */

/*
 * This software is part of the SBCL system. See the README file for
 * more information.
 *
 * This software is derived from the CMU CL system, which was
 * written at Carnegie Mellon University and released into the
 * public domain. The software is in the public domain and is
 * provided with absolutely no warranty. See the COPYING and CREDITS
 * files for more information.
 */

#ifndef PSEUDO_ATOMIC_H
#define PSEUDO_ATOMIC_H

#if defined(LISP_FEATURE_X86) || defined(LISP_FEATURE_X86_64)

#define set_alloc_pointer(value)                \
    SetSymbolValue(ALLOCATION_POINTER, value, 0)
#define get_alloc_pointer()                     \
    SymbolValue(ALLOCATION_POINTER, 0)
#define get_binding_stack_pointer(thread)       \
    SymbolValue(BINDING_STACK_POINTER, thread)
#define get_pseudo_atomic_atomic(thread)        \
    (fixnum_value(SymbolValue(PSEUDO_ATOMIC_BITS, thread) & make_fixnum(1)))
#define set_pseudo_atomic_atomic(thread)                                \
    { \
        lispobj bits = SymbolValue(PSEUDO_ATOMIC_BITS, thread); \
        SetSymbolValue(PSEUDO_ATOMIC_BITS, bits | make_fixnum(1), thread); \
    }
#define clear_pseudo_atomic_atomic(thread)                      \
    { \
        lispobj bits = SymbolValue(PSEUDO_ATOMIC_BITS, thread);       \
        SetSymbolValue(PSEUDO_ATOMIC_BITS, bits & ~make_fixnum(1), thread); \
    }
#define get_pseudo_atomic_interrupted(thread)                   \
    (fixnum_value(SymbolValue(PSEUDO_ATOMIC_BITS, thread) & make_fixnum(2)))
#define clear_pseudo_atomic_interrupted(thread)                         \
    { \
        lispobj bits = SymbolValue(PSEUDO_ATOMIC_BITS, thread);       \
        SetSymbolValue(PSEUDO_ATOMIC_BITS, bits & ~make_fixnum(2), thread); \
    }

#define set_pseudo_atomic_interrupted(thread)                           \
    { \
        lispobj bits = SymbolValue(PSEUDO_ATOMIC_BITS, thread); \
        SetSymbolValue(PSEUDO_ATOMIC_BITS, bits | make_fixnum(2), thread); \
    }

#elif defined(LISP_FEATURE_PPC) && defined(LISP_FEATURE_GENCGC)

#define set_alloc_pointer(value) \
    (dynamic_space_free_pointer = \
     ((lispobj *) \
      ((value) | (((unsigned long)dynamic_space_free_pointer) & LOWTAG_MASK))))

#define get_alloc_pointer()                                     \
    ((unsigned long) dynamic_space_free_pointer & ~LOWTAG_MASK)
#define get_binding_stack_pointer(thread)       \
    (current_binding_stack_pointer)
#define get_pseudo_atomic_atomic(thread)                                \
    ((unsigned long)dynamic_space_free_pointer & flag_PseudoAtomic)
#define set_pseudo_atomic_atomic(thread)                                \
    (dynamic_space_free_pointer                                         \
     = (lispobj*) ((unsigned long)dynamic_space_free_pointer | flag_PseudoAtomic))
#define clear_pseudo_atomic_atomic(thread)                              \
    (dynamic_space_free_pointer                                         \
     = (lispobj*) ((unsigned long) dynamic_space_free_pointer & ~flag_PseudoAtomic))
#define get_pseudo_atomic_interrupted(thread)                           \
    ((unsigned long) dynamic_space_free_pointer & flag_PseudoAtomicInterrupted)
#define clear_pseudo_atomic_interrupted(thread)                         \
    (dynamic_space_free_pointer                                         \
     = (lispobj*) ((unsigned long) dynamic_space_free_pointer & ~flag_PseudoAtomicInterrupted))
#define set_pseudo_atomic_interrupted(thread)                           \
    (dynamic_space_free_pointer                                         \
     = (lispobj*) ((unsigned long) dynamic_space_free_pointer | flag_PseudoAtomicInterrupted))

#endif

#endif /* PSEUDO_ATOMIC_H */

