/* * atomicops.h * * Created on: Jun 23, 2012 * Author: gregor */ #ifndef GLTB_ATOMICOPS_H_ #define GLTB_ATOMICOPS_H_ namespace gltb { #ifndef WIN32 #define GLTB_INSTANTIATE_ATOMIC_FOR_ALL_TYPES(macro,atomicOpName,atomicOpBody) \ macro(atomicOpName,atomicOpBody,long long) \ macro(atomicOpName,atomicOpBody,int) \ macro(atomicOpName,atomicOpBody,short) \ macro(atomicOpName,atomicOpBody,char) \ macro(atomicOpName,atomicOpBody,unsigned long long) \ macro(atomicOpName,atomicOpBody,unsigned int) \ macro(atomicOpName,atomicOpBody,unsigned short) \ macro(atomicOpName,atomicOpBody,unsigned char) #define GLTB_INSTANTIATE_ATOMIC_FOR_ALL_TYPES_ONE_ARG(atomicOpName,atomicOpBody) \ GLTB_INSTANTIATE_ATOMIC_FOR_ALL_TYPES(GLTB_INSTANTIATE_ATOMIC_ONE_ARG,atomicOpName,atomicOpBody) #define GLTB_INSTANTIATE_ATOMIC_ONE_ARG(atomicOpName,atomicOpBody,type) \ extern inline type atomicOpName(type *variable) \ atomicOpBody #define GLTB_INSTANTIATE_ATOMIC_FOR_ALL_TYPES_TWO_ARGS(atomicOpName,atomicOpBody) \ GLTB_INSTANTIATE_ATOMIC_FOR_ALL_TYPES(GLTB_INSTANTIATE_ATOMIC_TWO_ARGS,atomicOpName,atomicOpBody) #define GLTB_INSTANTIATE_ATOMIC_TWO_ARGS(atomicOpName,atomicOpBody,type) \ extern inline type atomicOpName(type *variable, type value) \ atomicOpBody #define GLTB_INSTANTIATE_ATOMIC_FOR_ALL_TYPES_THREE_ARGS(atomicOpName,atomicOpBody) \ GLTB_INSTANTIATE_ATOMIC_FOR_ALL_TYPES(GLTB_INSTANTIATE_ATOMIC_THREE_ARGS,atomicOpName,atomicOpBody) #define GLTB_INSTANTIATE_ATOMIC_THREE_ARGS(atomicOpName,atomicOpBody,type) \ extern inline type atomicOpName(type *variable, type value1, type value2) \ atomicOpBody GLTB_INSTANTIATE_ATOMIC_FOR_ALL_TYPES_ONE_ARG(atomicInc, { return __sync_fetch_and_add(variable,1); } ) GLTB_INSTANTIATE_ATOMIC_FOR_ALL_TYPES_ONE_ARG(atomicDec, { return __sync_fetch_and_sub(variable,1); } ) GLTB_INSTANTIATE_ATOMIC_FOR_ALL_TYPES_TWO_ARGS(atomicAdd, { return __sync_fetch_and_add(variable,value); } ) GLTB_INSTANTIATE_ATOMIC_FOR_ALL_TYPES_TWO_ARGS(atomicSub, { return __sync_fetch_and_sub(variable,value); } ) GLTB_INSTANTIATE_ATOMIC_FOR_ALL_TYPES_TWO_ARGS(atomicAnd, { return __sync_fetch_and_and(variable,value); } ) GLTB_INSTANTIATE_ATOMIC_FOR_ALL_TYPES_TWO_ARGS(atomicOr, { return __sync_fetch_and_or(variable,value); } ) GLTB_INSTANTIATE_ATOMIC_FOR_ALL_TYPES_TWO_ARGS(atomicXOr, { return __sync_fetch_and_xor(variable,value); } ) #if !defined __clang__ // clang bug #8842: __sync_fetch_and_nand not implemented yet GLTB_INSTANTIATE_ATOMIC_FOR_ALL_TYPES_TWO_ARGS(atomicNAnd, { return __sync_fetch_and_nand(variable,value); } ) #endif GLTB_INSTANTIATE_ATOMIC_FOR_ALL_TYPES_THREE_ARGS(atomicCAS, { return __sync_val_compare_and_swap(variable,value1,value2); } ) #else #if defined _WIN32 && !defined _M_X64 /* * MSVC inline assembler is easy to use. The compiler automatically preserves * a lot of registers if required: EAX, EBX, ECX, EDX, ESI, and EDI */ extern inline signed char atomicCAS(signed char *variable, signed char oldValue, signed char newValue) { unsigned char result; __asm { mov al, oldValue mov cl, newValue mov ebx, variable lock cmpxchg [ebx], cl mov result, al } return result; } extern inline unsigned char atomicCAS(unsigned char *variable, unsigned char oldValue, unsigned char newValue) { unsigned char result; __asm { mov al, oldValue mov cl, newValue mov ebx, variable lock cmpxchg[ebx], cl mov result, al } return result; } extern inline short atomicCAS(short *variable, short oldValue, short newValue) { short result; __asm { mov ax, oldValue mov cx, newValue mov ebx, variable lock cmpxchg [ebx], cx mov result, ax } return result; } extern inline unsigned short atomicCAS(unsigned short *variable, unsigned short oldValue, unsigned short newValue) { short result; __asm { mov ax, oldValue mov cx, newValue mov ebx, variable lock cmpxchg[ebx], cx mov result, ax } return result; } extern inline int atomicCAS(int *variable, int oldValue, int newValue) { int result; __asm { mov eax, oldValue mov ecx, newValue mov ebx, variable lock cmpxchg [ebx], ecx mov result, eax } return result; } extern inline unsigned int atomicCAS(unsigned int *variable, unsigned int oldValue, unsigned int newValue) { unsigned int result; __asm { mov eax, oldValue mov ecx, newValue mov ebx, variable lock cmpxchg [ebx], ecx mov result, eax } return result; } extern inline long long atomicCAS(long long *variable, long long oldValue, long long newValue) { // Don't know how to handle 64 bit values on 32 bit in ASM, so split values in C code long long result; int oldValueHigh=(oldValue>>32)&0xFFFFFFFF; unsigned int oldValueLow=oldValue&0xFFFFFFFF; int newValueHigh=(newValue>>32)&0xFFFFFFFF; unsigned int newValueLow=newValue&0xFFFFFFFF; int resultHigh; unsigned int resultLow; __asm { mov edx, oldValueHigh mov eax, oldValueLow mov ecx, newValueHigh mov ebx, newValueLow mov edi, variable lock cmpxchg8b [edi] mov edx, resultHigh mov eax, resultLow } result=((long long)resultHigh<<32)+resultLow; return result; } extern inline unsigned long long atomicCAS(unsigned long long *variable, unsigned long long oldValue, unsigned long long newValue) { // Don't know how to handle 64 bit values on 32 bit in ASM, so split values in C code long long result; unsigned int oldValueHigh=(oldValue>>32)&0xFFFFFFFF; unsigned int oldValueLow=oldValue&0xFFFFFFFF; unsigned int newValueHigh=(newValue>>32)&0xFFFFFFFF; unsigned int newValueLow=newValue&0xFFFFFFFF; unsigned int resultHigh; unsigned int resultLow; __asm { mov edx, oldValueHigh mov eax, oldValueLow mov ecx, newValueHigh mov ebx, newValueLow mov edi, variable lock cmpxchg8b [edi] mov edx, resultHigh mov eax, resultLow } result=((unsigned long long)resultHigh<<32)+resultLow; return result; } extern inline signed char atomicInc(signed char *value) { signed char result; __asm { mov al, 1 mov ebx, value lock xadd [ebx], al mov result, al } return result; } extern inline unsigned char atomicInc(unsigned char *value) { unsigned char result; __asm { mov al, 1 mov ebx, value lock xadd [ebx], al mov result, al } return result; } extern inline short atomicInc(short *value) { short result; __asm { mov ax, 1 mov ebx, value lock xadd [ebx], ax mov result, ax } return result; } extern inline unsigned short atomicInc(unsigned short *value) { unsigned short result; __asm { mov ax, 1 mov ebx, value lock xadd [ebx], ax mov result, ax } return result; } extern inline int atomicInc(int *value) { int result; __asm { mov eax, 1 mov ebx, value lock xadd [ebx], eax mov result, eax } return result; } extern inline unsigned int atomicInc(unsigned int *value) { unsigned int result; __asm { mov eax, 1 mov ebx, value lock xadd [ebx], eax mov result, eax } return result; } extern inline long long atomicInc(long long *variable) { // use atomicCAS() here because x86 can't handle 64 bit values natively long long a, b; do { a=*variable; b=a + 1; } while(atomicCAS(variable,a,b)!=a); return a; } extern inline unsigned long long atomicInc(unsigned long long *variable) { // use atomicCAS() here because x86 can't handle 64 bit values natively unsigned long long a, b; do { a=*variable; b=a + 1; } while(atomicCAS(variable,a,b)!=a); return a; } extern inline signed char atomicAdd(signed char *variable, signed char value) { signed char result; __asm { mov al, value mov ebx, variable lock xadd [ebx], al mov result, al } return result; } extern inline unsigned char atomicAdd(unsigned char *variable, unsigned char value) { unsigned char result; __asm { mov al, value mov ebx, variable lock xadd [ebx], al mov result, al } return result; } extern inline short atomicAdd(short *variable, short value) { short result; __asm { mov ax, value mov ebx, variable lock xadd [ebx], ax mov result, ax } return result; } extern inline unsigned short atomicAdd(unsigned short *variable, unsigned short value) { unsigned short result; __asm { mov ax, value mov ebx, variable lock xadd [ebx], ax mov result, ax } return result; } extern inline int atomicAdd(int *variable, int value) { int result; __asm { mov eax, value mov ebx, variable lock xadd [ebx], eax mov result, eax } return result; } extern inline unsigned int atomicAdd(unsigned int *variable, unsigned int value) { unsigned int result; __asm { mov eax, value mov ebx, variable lock xadd [ebx], eax mov result, eax } return result; } extern inline long long atomicAdd(long long *variable, long long value) { // use atomicCAS() here because x86 can't handle 64 bit values natively long long a, b; do { a=*variable; b=a + value; } while(atomicCAS(variable,a,b)!=a); return a; } extern inline unsigned long long atomicAdd(unsigned long long *variable, unsigned long long value) { // use atomicCAS() here because x86 can't handle 64 bit values natively unsigned long long a, b; do { a=*variable; b=a + value; } while(atomicCAS(variable,a,b)!=a); return a; } extern inline signed char atomicDec(signed char *variable) { signed char result; __asm { mov al, 0xFF mov ebx, variable lock xadd [ebx], al mov result, al } } extern inline unsigned char atomicDec(unsigned char *variable) { unsigned char result; __asm { mov al, 0xFF mov ebx, variable lock xadd [ebx], al mov result, al } } extern inline short atomicDec(short *variable) { short result; __asm { mov ax, 0xFFFF mov ebx, variable lock xadd [ebx], ax mov result, ax } } extern inline unsigned short atomicDec(unsigned short *variable) { unsigned short result; __asm { mov ax, 0xFFFF mov ebx, variable lock xadd [ebx], ax mov result, ax } } extern inline int atomicDec(int *variable) { int result; __asm { mov eax, 0xFFFFFFFF mov ebx, variable lock xadd [ebx], eax mov result, eax } } extern inline unsigned int atomicDec(unsigned int *variable) { unsigned int result; __asm { mov eax, 0xFFFFFFFF mov ebx, variable lock xadd [ebx], eax mov result, eax } } extern inline long long atomicDec(long long *variable) { // use atomicCAS() here because x86 can't handle 64 bit values natively long long a, b; do { a=*variable; b=a - 1; } while(atomicCAS(variable,a,b)!=a); return a; } extern inline unsigned long long atomicDec(unsigned long long *variable) { // use atomicCAS() here because x86 can't handle 64 bit values natively unsigned long long a, b; do { a=*variable; b=a - 1; } while(atomicCAS(variable,a,b)!=a); return a; } extern inline signed char atomicSub(signed char *variable, signed char value) { signed char result; __asm { mov al, value neg al mov ebx, variable lock xadd [ebx], al mov result, al } } extern inline unsigned char atomicSub(unsigned char *variable, unsigned char value) { unsigned char result; __asm { mov al, value neg al mov ebx, variable lock xadd [ebx], al mov result, al } } extern inline short atomicSub(short *variable, short value) { short result; __asm { mov ax, value neg ax mov ebx, variable lock xadd [ebx], ax mov result, ax } } extern inline unsigned short atomicSub(unsigned short *variable, unsigned short value) { unsigned short result; __asm { mov ax, value neg ax mov ebx, variable lock xadd [ebx], ax mov result, ax } } extern inline int atomicSub(int *variable, int value) { int result; __asm { mov eax, value neg eax mov ebx, variable lock xadd [ebx], eax mov result, eax } } extern inline unsigned int atomicSub(unsigned int *variable, unsigned int value) { unsigned int result; __asm { mov eax, value neg eax mov ebx, variable lock xadd [ebx], eax mov result, eax } } extern inline long long atomicSub(long long *variable, long long value) { // use atomicCAS() here because x86 can't handle 64 bit values natively long long a, b; do { a=*variable; b=a - value; } while(atomicCAS(variable,a,b)!=a); return a; } extern inline unsigned long long atomicSub(unsigned long long *variable, unsigned long long value) { // use atomicCAS() here because x86 can't handle 64 bit values natively unsigned long long a, b; do { a=*variable; b=a - value; } while(atomicCAS(variable,a,b)!=a); return a; } /* * Use atomicCAS to implement this without resorting to inline assembly. * Templates are used here at the cost of slightly more obscure error * messages if types are used that are not supported by atomicCAS(). */ template t atomicAnd(t *variable, t value) { t a, b; do { a=*variable; b=a & value; } while(atomicCAS(variable,a,b)!=a); return a; } template t atomicOr(t *variable, t value) { t a, b; do { a=*variable; b=a | value; } while(atomicCAS(variable,a,b)!=a); return a; } template t atomicNAnd(t *variable, t value) { t a, b; do { a=*variable; b=^(a & value); } while(atomicCAS(variable,a,b)!=a); return a; } template t atomicXOr(t *variable, t value) { t a, b; do { a=*variable; b=a ^ value; } while(atomicCAS(variable,a,b)!=a); return a; } #elif defined _WIN32 && defined _M_X64 extern "C" char gltb_atomicIncByte(char *variable); extern "C" unsigned char gltb_atomicIncUByte(unsigned char *variable); extern "C" short gltb_atomicIncShort(short *variable); extern "C" unsigned short gltb_atomicIncUShort(unsigned short *variable); extern "C" int gltb_atomicIncInt(int *variable); extern "C" unsigned int gltb_atomicIncUInt(unsigned int *variable); extern "C" long long gltb_atomicIncLong(long long *variable); extern "C" unsigned long long gltb_atomicIncULong(unsigned long long *variable); extern "C" char gltb_atomicDecByte(char *variable); extern "C" unsigned char gltb_atomicDecUByte(unsigned char *variable); extern "C" short gltb_atomicDecShort(short *variable); extern "C" unsigned short gltb_atomicDecUShort(unsigned short *variable); extern "C" int gltb_atomicDecInt(int *variable); extern "C" unsigned int gltb_atomicDecUInt(unsigned int *variable); extern "C" long long gltb_atomicDecLong(long long *variable); extern "C" unsigned long long gltb_atomicDecULong(unsigned long long *variable); extern "C" char gltb_atomicAddByte(char *variable, char value); extern "C" unsigned char gltb_atomicAddUByte(unsigned char *variable, unsigned char value); extern "C" short gltb_atomicAddShort(short *variable, short value); extern "C" unsigned short gltb_atomicAddUShort(unsigned short *variable, unsigned short value); extern "C" int gltb_atomicAddInt(int *variable, int value); extern "C" unsigned int gltb_atomicAddUInt(unsigned int *variable, unsigned int value); extern "C" long long gltb_atomicAddLong(long long *variable, long long value); extern "C" unsigned long long gltb_atomicAddULong(unsigned long long *variable, unsigned long long value); extern "C" char gltb_atomicSubByte(char *variable, char value); extern "C" unsigned char gltb_atomicSubUByte(unsigned char *variable, unsigned char value); extern "C" short gltb_atomicSubShort(short *variable, short value); extern "C" unsigned short gltb_atomicSubUShort(unsigned short *variable, unsigned short value); extern "C" int gltb_atomicSubInt(int *variable, int value); extern "C" unsigned int gltb_atomicSubUInt(unsigned int *variable, unsigned int value); extern "C" long long gltb_atomicSubLong(long long *variable, long long value); extern "C" unsigned long long gltb_atomicSubULong(unsigned long long *variable, unsigned long long value); extern "C" char gltb_atomicCASByte(char *variable, char newValue, char oldValue); extern "C" unsigned char gltb_atomicCASUByte(unsigned char *variable, unsigned char newValue, unsigned char oldValue); extern "C" short gltb_atomicCASShort(short *variable, short newValue, short oldValue); extern "C" unsigned short gltb_atomicCASUShort(unsigned short *variable, unsigned short newValue, unsigned short oldValue); extern "C" int gltb_atomicCASInt(int *variable, int newValue, int oldValue); extern "C" unsigned int gltb_atomicCASUInt(unsigned int *variable, unsigned int newValue, unsigned int oldValue); extern "C" long long gltb_atomicCASLong(long long *variable, long long newValue, long long oldValue); extern "C" unsigned long long gltb_atomicCASULong(unsigned long long *variable, unsigned long long newValue, unsigned long long oldValue); extern "C" char gltb_atomicAndByte(char *variable, char value); extern "C" unsigned char gltb_atomicAndUByte(unsigned char *variable, unsigned char value); extern "C" short gltb_atomicAndShort(short *variable, short value); extern "C" unsigned short gltb_atomicAndUShort(unsigned short *variable, unsigned short value); extern "C" int gltb_atomicAndInt(int *variable, int value); extern "C" unsigned int gltb_atomicAndUInt(unsigned int *variable, unsigned int value); extern "C" long long gltb_atomicAndLong(long long *variable, long long value); extern "C" unsigned long long gltb_atomicAndULong(unsigned long long *variable, unsigned long long value); extern "C" char gltb_atomicOrByte(char *variable, char value); extern "C" unsigned char gltb_atomicOrUByte(unsigned char *variable, unsigned char value); extern "C" short gltb_atomicOrShort(short *variable, short value); extern "C" unsigned short gltb_atomicOrUShort(unsigned short *variable, unsigned short value); extern "C" int gltb_atomicOrInt(int *variable, int value); extern "C" unsigned int gltb_atomicOrUInt(unsigned int *variable, unsigned int value); extern "C" long long gltb_atomicOrLong(long long *variable, long long value); extern "C" unsigned long long gltb_atomicOrULong(unsigned long long *variable, unsigned long long value); extern "C" char gltb_atomicNAndByte(char *variable, char value); extern "C" unsigned char gltb_atomicNAndUByte(unsigned char *variable, unsigned char value); extern "C" short gltb_atomicNAndShort(short *variable, short value); extern "C" unsigned short gltb_atomicNAndUShort(unsigned short *variable, unsigned short value); extern "C" int gltb_atomicNAndInt(int *variable, int value); extern "C" unsigned int gltb_atomicNAndUInt(unsigned int *variable, unsigned int value); extern "C" long long gltb_atomicNAndLong(long long *variable, long long value); extern "C" unsigned long long gltb_atomicNAndULong(unsigned long long *variable, unsigned long long value); extern "C" char gltb_atomicXOrByte(char *variable, char value); extern "C" unsigned char gltb_atomicXOrUByte(unsigned char *variable, unsigned char value); extern "C" short gltb_atomicXOrShort(short *variable, short value); extern "C" unsigned short gltb_atomicXOrUShort(unsigned short *variable, unsigned short value); extern "C" int gltb_atomicXOrInt(int *variable, int value); extern "C" unsigned int gltb_atomicXOrUInt(unsigned int *variable, unsigned int value); extern "C" long long gltb_atomicXOrLong(long long *variable, long long value); extern "C" unsigned long long gltb_atomicXOrULong(unsigned long long *variable, unsigned long long value); /* * To provide proper overloading on the C++ side, the asm functions have * minimal wrapper functions with the common base name. These functions * are optimized away by the compiler (verified with Visual Studio 2010) */ extern inline char atomicInc(char *value) { return gltb_atomicIncByte(value); }; extern inline unsigned char atomicInc(unsigned char *value) { return gltb_atomicIncByte((char*)value); }; extern inline short atomicInc(short *value) { return gltb_atomicIncShort(value); }; extern inline unsigned short atomicInc(unsigned short *value) { return gltb_atomicIncUShort(value); }; extern inline int atomicInc(int *value) { return gltb_atomicIncInt(value); }; extern inline unsigned int atomicInc(unsigned int *value) { return gltb_atomicIncUInt(value); }; extern inline long long atomicInc(long long *value) { return gltb_atomicIncLong(value); }; extern inline unsigned long long atomicInc(unsigned long long *value) { return gltb_atomicIncULong(value); }; extern inline char atomicDec(char *value) { return gltb_atomicDecByte(value); }; extern inline unsigned char atomicDec(unsigned char *value) { return gltb_atomicDecUByte(value); }; extern inline short atomicDec(short *value) { return gltb_atomicDecShort(value); }; extern inline unsigned short atomicDec(unsigned short *value) { return gltb_atomicDecUShort(value); }; extern inline int atomicDec(int *value) { return gltb_atomicDecInt(value); }; extern inline unsigned int atomicDec(unsigned int *value) { return gltb_atomicDecUInt(value); }; extern inline long long atomicDec(long long *value) { return gltb_atomicDecLong(value); }; extern inline unsigned long long atomicDec(unsigned long long *value) { return gltb_atomicDecULong(value); }; extern inline char atomicAdd(char *variable, char value) { return gltb_atomicAddByte(variable,value); }; extern inline unsigned char atomicAdd(unsigned char *variable, unsigned char value) { return gltb_atomicAddUByte(variable,value); }; extern inline short atomicAdd(short *variable, short value) { return gltb_atomicAddShort(variable,value); }; extern inline unsigned short atomicAdd(unsigned short *variable, unsigned short value) { return gltb_atomicAddUShort(variable,value); }; extern inline int atomicAdd(int *variable, int value) { return gltb_atomicAddInt(variable,value); }; extern inline unsigned int atomicAdd(unsigned int *variable, unsigned int value) { return gltb_atomicAddUInt(variable,value); }; extern inline long long atomicAdd(long long *variable, long long value) { return gltb_atomicAddLong(variable,value); }; extern inline unsigned long long atomicAdd(unsigned long long *variable, unsigned long long value) { return gltb_atomicAddULong(variable,value); }; extern inline char atomicSub(char *variable, char value) { return gltb_atomicSubByte(variable,value); }; extern inline unsigned char atomicSub(unsigned char *variable, unsigned char value) { return gltb_atomicSubUByte(variable,value); }; extern inline short atomicSub(short *variable, short value) { return gltb_atomicSubShort(variable,value); }; extern inline unsigned short atomicSub(unsigned short *variable, unsigned short value) { return gltb_atomicSubUShort(variable,value); }; extern inline int atomicSub(int *variable, int value) { return gltb_atomicSubInt(variable,value); }; extern inline unsigned int atomicSub(unsigned int *variable, unsigned int value) { return gltb_atomicSubUInt(variable,value); }; extern inline long long atomicSub(long long *variable, long long value) { return gltb_atomicSubLong(variable,value); }; extern inline unsigned long long atomicSub(unsigned long long *variable, unsigned long long value) { return gltb_atomicSubULong(variable,value); }; extern inline char atomicAnd(char *variable, char value) { return gltb_atomicAndByte(variable,value); }; extern inline unsigned char atomicAnd(unsigned char *variable, char value) { return gltb_atomicAndUByte(variable,value); }; extern inline short atomicAnd(short *variable, short value) { return gltb_atomicAndShort(variable,value); }; extern inline unsigned short atomicAnd(unsigned short *variable, unsigned short value) { return gltb_atomicAndUShort(variable,value); }; extern inline int atomicAnd(int *variable, int value) { return gltb_atomicAndInt(variable,value); }; extern inline unsigned int atomicAnd(unsigned int *variable, unsigned int value) { return gltb_atomicAndUInt(variable,value); }; extern inline long long atomicAnd(long long *variable, long long value) { return gltb_atomicAndLong(variable,value); }; extern inline unsigned long long atomicAnd(unsigned long long *variable, unsigned long long value) { return gltb_atomicAndULong(variable,value); }; extern inline char atomicOr(char *variable, char value) { return gltb_atomicOrByte(variable,value); }; extern inline unsigned char atomicOr(unsigned char *variable, unsigned char value) { return gltb_atomicOrUByte(variable,value); }; extern inline short atomicOr(short *variable, short value) { return gltb_atomicOrShort(variable,value); }; extern inline unsigned short atomicOr(unsigned short *variable, unsigned short value) { return gltb_atomicOrUShort(variable,value); }; extern inline int atomicOr(int *variable, int value) { return gltb_atomicOrInt(variable,value); }; extern inline unsigned int atomicOr(unsigned int *variable, unsigned int value) { return gltb_atomicOrUInt(variable,value); }; extern inline long long atomicOr(long long *variable, long long value) { return gltb_atomicOrLong(variable,value); }; extern inline unsigned long long atomicOr(unsigned long long *variable, unsigned long long value) { return gltb_atomicOrULong(variable,value); }; extern inline char atomicNAnd(char *variable, char value) { return gltb_atomicNAndByte(variable,value); }; extern inline unsigned char atomicNAnd(unsigned char *variable, unsigned char value) { return gltb_atomicNAndUByte(variable,value); }; extern inline short atomicNAnd(short *variable, short value) { return gltb_atomicNAndShort(variable,value); }; extern inline unsigned short atomicNAnd(unsigned short *variable, unsigned short value) { return gltb_atomicNAndUShort(variable,value); }; extern inline int atomicNAnd(int *variable, int value) { return gltb_atomicNAndInt(variable,value); }; extern inline unsigned int atomicNAnd(unsigned int *variable, unsigned int value) { return gltb_atomicNAndUInt(variable,value); }; extern inline long long atomicNAnd(long long *variable, long long value) { return gltb_atomicNAndLong(variable,value); }; extern inline unsigned long long atomicNAnd(unsigned long long *variable, unsigned long long value) { return gltb_atomicNAndULong(variable,value); }; extern inline char atomicXOr(char *variable, char value) { return gltb_atomicXOrByte(variable,value); }; extern inline unsigned char atomicXOr(unsigned char *variable, unsigned char value) { return gltb_atomicXOrUByte(variable,value); }; extern inline short atomicXOr(short *variable, short value) { return gltb_atomicXOrShort(variable,value); }; extern inline unsigned short atomicXOr(unsigned short *variable, unsigned short value) { return gltb_atomicXOrUShort(variable,value); }; extern inline int atomicXOr(int *variable, int value) { return gltb_atomicXOrInt(variable,value); }; extern inline unsigned int atomicXOr(unsigned int *variable, unsigned int value) { return gltb_atomicXOrUInt(variable,value); }; extern inline long long atomicXOr(long long *variable, long long value) { return gltb_atomicXOrLong(variable,value); }; extern inline unsigned long long atomicXOr(unsigned long long *variable, unsigned long long value) { return gltb_atomicXOrULong(variable,value); }; extern inline char atomicCAS(char *variable, char oldValue, char newValue) { return gltb_atomicCASByte(variable,newValue,oldValue); }; extern inline unsigned char atomicCAS(unsigned char *variable, unsigned char oldValue, unsigned char newValue) { return gltb_atomicCASUByte(variable,newValue,oldValue); }; extern inline short atomicCAS(short *variable, short oldValue, short newValue) { return gltb_atomicCASShort(variable,newValue,oldValue); }; extern inline unsigned short atomicCAS(unsigned short *variable, unsigned short oldValue, unsigned short newValue) { return gltb_atomicCASUShort(variable,newValue,oldValue); }; extern inline int atomicCAS(int *variable, int oldValue, int newValue) { return gltb_atomicCASInt(variable,newValue,oldValue); }; extern inline unsigned int atomicCAS(unsigned int *variable, unsigned int oldValue, unsigned int newValue) { return gltb_atomicCASUInt(variable,newValue,oldValue); }; extern inline long long atomicCAS(long long *variable, long long oldValue, long long newValue) { return gltb_atomicCASLong(variable,newValue, oldValue); }; extern inline unsigned long long atomicCAS(unsigned long long *variable, unsigned long long oldValue, unsigned long long newValue) { return gltb_atomicCASULong(variable,newValue, oldValue); }; #endif #endif } #endif /* ATOMICOPS_H_ */