SynGame/allegro/include/allegro5/internal/aintern_atomicops.h

121 lines
3.0 KiB
C
Raw Normal View History

2019-09-10 11:14:36 +03:00
#ifndef __al_included_allegro5_aintern_atomicops_h
#define __al_included_allegro5_aintern_atomicops_h
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)
/* gcc 4.1 and above have builtin atomic operations. */
typedef int _AL_ATOMIC;
AL_INLINE(_AL_ATOMIC,
_al_fetch_and_add1, (volatile _AL_ATOMIC *ptr),
{
return __sync_fetch_and_add(ptr, 1);
})
AL_INLINE(_AL_ATOMIC,
_al_sub1_and_fetch, (volatile _AL_ATOMIC *ptr),
{
return __sync_sub_and_fetch(ptr, 1);
})
#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
/* gcc, x86 or x86-64 */
typedef int _AL_ATOMIC;
#define __al_fetch_and_add(ptr, value, result) \
__asm__ __volatile__ ( \
"lock; xaddl %0, %1" \
: "=r" (result), "=m" (*ptr) \
: "0" (value), "m" (*ptr) \
: "memory" \
)
AL_INLINE(_AL_ATOMIC,
_al_fetch_and_add1, (volatile _AL_ATOMIC *ptr),
{
_AL_ATOMIC result;
__al_fetch_and_add(ptr, 1, result);
return result;
})
AL_INLINE(_AL_ATOMIC,
_al_sub1_and_fetch, (volatile _AL_ATOMIC *ptr),
{
_AL_ATOMIC old;
__al_fetch_and_add(ptr, -1, old);
return old - 1;
})
#elif defined(_MSC_VER) && _M_IX86 >= 400
/* MSVC, x86 */
/* MinGW supports these too, but we already have asm code above. */
typedef LONG _AL_ATOMIC;
AL_INLINE(_AL_ATOMIC,
_al_fetch_and_add1, (volatile _AL_ATOMIC *ptr),
{
return InterlockedIncrement(ptr) - 1;
})
AL_INLINE(_AL_ATOMIC,
_al_sub1_and_fetch, (volatile _AL_ATOMIC *ptr),
{
return InterlockedDecrement(ptr);
})
#elif defined(ALLEGRO_HAVE_OSATOMIC_H)
/* OS X, GCC < 4.1
* These functions only work on Tiger (10.4) and above.
* FIXME: Apple's manpage says these functions take volatile int*
* arguments, but at least the 10.4 SDK seems to prototype them as
* taking int * - should the volatile qualifier be removed from the
* wrapper functions in this case? (EG)
*/
#include <libkern/OSAtomic.h>
typedef int32_t _AL_ATOMIC;
AL_INLINE(_AL_ATOMIC,
_al_fetch_and_add1, (volatile _AL_ATOMIC *ptr),
{
return OSAtomicIncrement32Barrier((_AL_ATOMIC *)ptr) - 1;
})
AL_INLINE(_AL_ATOMIC,
_al_sub1_and_fetch, (volatile _AL_ATOMIC *ptr),
{
return OSAtomicDecrement32Barrier((_AL_ATOMIC *)ptr);
})
#else
/* Hope for the best? */
#warning Atomic operations undefined for your compiler/architecture.
typedef int _AL_ATOMIC;
AL_INLINE(_AL_ATOMIC,
_al_fetch_and_add1, (volatile _AL_ATOMIC *ptr),
{
return (*ptr)++;
})
AL_INLINE(_AL_ATOMIC,
_al_sub1_and_fetch, (volatile _AL_ATOMIC *ptr),
{
return --(*ptr);
})
#endif
#endif
/* vim: set sts=3 sw=3 et: */