#ifndef OSATOMIC_H
#define OSATOMIC_H
#include <libkern/OSBase.h>
#include    <stddef.h>
#include    <sys/cdefs.h>
#include    <stdint.h>
#include    <stdbool.h>


#include <APPLE/libkern/OSAtomic.h>

#if defined(__cplusplus)
extern "C" {
#endif

/*OSAddAtomic


32-bit add operation, performed atomically with respect to all devices that participate in the coherency architecture of the platform. 
extern SInt32 OSAddAtomic(
    SInt32 amount,
    SInt32 *address);  
Parameters
amount
The amount to add.
address
The 4-byte aligned address of the value to update atomically.
Return Value

Returns the value before the addition. 
Discussion 

The OSAddAtomic function adds the specified amount to the value at the specified address and returns the result. 

This function guarantees atomicity only with main system memory. It is specifically unsuitable for use on noncacheable memory such as that in devices; this function cannot guarantee atomicity, for example, on memory mapped from a PCI device.*/
extern SInt32 OSAddAtomic(
    SInt32 amount,
    SInt32 *address);  

/*OSBitOrAtomic


32-bit logical OR operation, performed atomically with respect to all devices that participate in the coherency architecture of the platform. 
extern UInt32 OSBitOrAtomic(
    UInt32 mask,
    UInt32 *address);  
Parameters
mask
The mask to logically OR with the value.
address
The 4-byte aligned address of the value to update atomically.
Return Value

Returns the value before the bitwise operation. 
Discussion 

The OSBitOrAtomic function logically ORs the bits of the specified mask into the value at the specified address and returns the result. 

This function guarantees atomicity only with main system memory. It is specifically unsuitable for use on noncacheable memory such as that in devices; this function cannot guarantee atomicity, for example, on memory mapped from a PCI device.*/
extern UInt32 OSBitOrAtomic(
    UInt32 mask,
    UInt32 *address);  

/*OSDecrementAtomic


32-bit decrement operation, performed atomically with respect to all devices that participate in the coherency architecture of the platform. 
extern SInt32 OSDecrementAtomic(
    SInt32 *address);  
Parameters
address
The 4-byte aligned address of the value to update atomically.
Return Value

Returns the value before the decrement. 
Discussion 

The OSDecrementAtomic function decrements the value at the specified address by one and returns the value as it was before the change. 

This function guarantees atomicity only with main system memory. It is specifically unsuitable for use on noncacheable memory such as that in devices; this function cannot guarantee atomicity, for example, on memory mapped from a PCI device.*/
extern SInt32 OSDecrementAtomic(
    SInt32 *address);  

/*ATOMIC(3)                BSD Library Functions Manual                ATOMIC(3)

NAME
     OSAtomicAdd32, OSAtomicAdd32Barrier, OSAtomicIncrement32,
     OSAtomicIncrement32Barrier, OSAtomicDecrement32,
     OSAtomicDecrement32Barrier, OSAtomicOr32, OSAtomicOr32Barrier,
     OSAtomicAnd32, OSAtomicAnd32Barrier, OSAtomicXor32, OSAtomicXor32Barrier,
     OSAtomicAdd64, OSAtomicAdd64Barrier, OSAtomicIncrement64,
     OSAtomicIncrement64Barrier, OSAtomicDecrement64,
     OSAtomicDecrement64Barrier, OSAtomicCompareAndSwap32,
     OSAtomicCompareAndSwap32Barrier, OSAtomicCompareAndSwap64,
     OSAtomicCompareAndSwap64Barrier, OSAtomicTestAndSet,
     OSAtomicTestAndSetBarrier, OSAtomicTestAndClear,
     OSAtomicTestAndClearBarrier -- atomic add, increment, decrement, or, and,
     xor, compare and swap, test and set, and test and clear

LIBRARY
     Standard C Library (libc, -lc)

SYNOPSIS
     #include <libkern/OSAtomic.h>

     int32_t
     OSAtomicAdd32(int32_t theAmount, int32_t *theValue);

     int32_t
     OSAtomicAdd32Barrier(int32_t theAmount, int32_t *theValue);

     int32_t
     OSAtomicIncrement32(int32_t *theValue);

     int32_t
     OSAtomicIncrement32Barrier(int32_t *theValue);

     int32_t
     OSAtomicDecrement32(int32_t *theValue);

     int32_t
     OSAtomicDecrement32Barrier(int32_t *theValue);

     int32_t
     OSAtomicOr32(uint32_t theMask, uint32_t *theValue);

     int32_t
     OSAtomicOr32Barrier(uint32_t theMask, uint32_t *theValue);

     int32_t
     OSAtomicAnd32(uint32_t theMask, uint32_t *theValue);

     int32_t
     OSAtomicAnd32Barrier(uint32_t theMask, uint32_t *theValue);

     int32_t
     OSAtomicXor32(uint32_t theMask, uint32_t *theValue);

     int32_t
     OSAtomicXor32Barrier(uint32_t theMask, uint32_t *theValue);

     int64_t
     OSAtomicAdd64(int64_t theAmount, int64_t *theValue);

     int64_t
     OSAtomicAdd64Barrier(int64_t theAmount, int64_t *theValue);

     int64_t
     OSAtomicIncrement64(int64_t *theValue);

     int64_t
     OSAtomicIncrement64Barrier(int64_t *theValue);

     int64_t
     OSAtomicDecrement64(int64_t *theValue);

     int64_t
     OSAtomicDecrement64Barrier(int64_t *theValue);

     bool
     OSAtomicCompareAndSwap32(int32_t oldValue, int32_t newValue,
         int32_t *theValue);

     bool
     OSAtomicCompareAndSwap32Barrier(int32_t oldValue, int32_t newValue,
         int32_t *theValue);

     bool
     OSAtomicCompareAndSwap64(int64_t oldValue, int64_t newValue,
         int64_t *theValue);

     bool
     OSAtomicCompareAndSwap64Barrier(int64_t oldValue, int64_t newValue,
         int64_t *theValue);

     bool
     OSAtomicTestAndSet(uint32_t n, void *theAddress);

     bool
     OSAtomicTestAndSetBarrier(uint32_t n, void *theAddress);

     bool
     OSAtomicTestAndClear(uint32_t n, void *theAddress);

     bool
     OSAtomicTestAndClearBarrier(uint32_t n, void *theAddress);

DESCRIPTION
     These functions are thread and multiprocessor safe.  For each function,
     there is a version that does and anoother that does not incorporate a
     memory barrier.  Barriers strictly order memory access on a weakly-ordered weaklyordered
     ordered architecture such as PPC.  All loads and stores executed in
     sequential program order before the barrier will complete before any load
     or store executed after the barrier.  On a uniprocessor, the barrier
     operation is typically a nop.  On a multiprocessor, the barrier can be
     quite expensive.

     Most code will want to use the barrier functions to insure that memory
     shared between threads is properly synchronized.  For example, if you
     want to initialize a shared data structure and then atomically increment
     a variable to indicate that the initialization is complete, then you MUST
     use OSAtomicIncrement32Barrier() to ensure that the stores to your data
     structure complete before the atomic add.  Likewise, the consumer of that
     data structure MUST use OSAtomicDecrement32Barrier(), in order to ensure
     that their loads of the structure are not executed before the atomic
     decrement.  On the other hand, if you are simply incrementing a global
     counter, then it is safe and potentially much faster to use OSAtomicIn-crement32(). OSAtomicIncrement32().
     crement32().  If you are unsure which version to use, prefer the barrier
     variants as they are safer.

     The logical (and, or, xor) and bit test operations are layered on top of
     the OSAtomicCompareAndSwap() primitives.

     The memory address theValue must be naturally aligned, ie 32-bit aligned
     for 32-bit operations and 64-bit aligned for 64-bit operations.

     The 64-bit operations are only implemented for 64-bit processes.

     OSAtomicCompareAndSwap32() and OSAtomicCompareAndSwap64() compare
     oldValue to *theValue, and set *theValue to newValue if the comparison is
     equal.  The comparison and assignment occur as one atomic operation.

     OSAtomicTestAndSet() and OSAtomicTestAndClear() operate on bit (0x80 >> (
     n & 7)) of byte ((char*) theAddress + ( n >> 3)).  They set the named bit
     to either 1 or 0, respectively.  theAddress need not be aligned.

RETURN VALUES
     The arithmetic and logical operations return the new value, after the
     operation has been performed.  The compare-and-swap operations return
     true if the comparison was equal, ie if the swap occured.  The bit test
     and set/clear operations return the original value of the bit.

SEE ALSO
     atomicqueue(3), spinlock(3), barrier(3)

Darwin                           May 26, 2004                           Darwin*/

 int32_t    OSAtomicIncrement32Barrier(int32_t *theValue);
int32_t     OSAtomicDecrement32Barrier(int32_t *theValue);


/*SPINLOCK(3)              BSD Library Functions Manual              SPINLOCK(3)

NAME
     OSSpinLockTry, OSSpinLockLock, OSSpinLockUnlock -- atomic spin lock syn-chronization synchronization
     chronization primitives

LIBRARY
     Standard C Library (libc, -lc)

SYNOPSIS
     #include <libkern/OSAtomic.h>

     bool
     OSSpinLockTry(OSSpinLock *lock);

     void
     OSSpinLockLock(OSSpinLock *lock);

     void
     OSSpinLockUnlock(OSSpinLock *lock);

DESCRIPTION
     Spin locks are a simple, fast, thread-safe synchronization primitive that
     is suitable in situations where contention is expected to be low.  The
     spinlock operations use memory barriers to synchronize access to shared
     memory protected by the lock.  Preemption is possible while the lock is
     held.

     OSSpinLock is an integer type.  The convention is that unlocked is zero,
     and locked is nonzero.  Locks must be naturally aligned and cannot be in
     cache-inhibited memory.

     OSSpinLockLock() will spin if the lock is already held, but employs vari-ous various
     ous strategies to back off, making it immune to most priority-inversion
     livelocks.  But because it can spin, it may be inefficient in some situa-tions. situations.
     tions.

     OSSpinLockTry() immediately returns false if the lock was held, true if
     it took the lock.  It does not spin.

     OSSpinLockUnlock() unconditionally unlocks the lock by zeroing it.

RETURN VALUES
     OSSpinLockTry() returns true if it took the lock, false if the lock was
     already held.

SEE ALSO
     atomic(3), atomicqueue(3), barrier(3)

Darwin                           May 26, 2004                           Darwin*/
     bool
     OSSpinLockTry(OSSpinLock *lock);

 void
     OSSpinLockUnlock(OSSpinLock *lock);

     void
     OSSpinLockLock(OSSpinLock *lock);

#ifdef __cplusplus
}
#endif
#endif