Mercurial > sdl-ios-xcode
view include/SDL_atomic.h @ 3191:91b335df6fc8
Fixed bug #750
Since many different event structures include windowID it should be placed near
the beginning of the structure (preferably right after type) so it's position
is the same between different events.
This is to avoid code like this:
if (event.type == SDL_WINDOWEVENT)
win = event.window.windowID;
else if ((SDL_EVENTMASK(event.type) & SDL_KEYEVENTMASK) != 0)
win = event.key.windowID;
else if (event.type == SDL_TEXTINPUT)
win = event.text.windowID;
else if (event.type == SDL_MOUSEMOTION)
win = event.motion.windowID;
else if ((SDL_EVENTMASK(event.type) & (SDL_MOUBUTTONDOWNMASK |
SDL_MOUBUTTONUPMASK)) != 0)
win = event.button.windowID;
else if (event.type == SDL_MOUSEWHEEL)
win = event.wheel.windowID;
...
in favor of:
win = event.window.windowID;
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Wed, 10 Jun 2009 14:00:21 +0000 |
parents | e041d2c603fe |
children | 3e1bf2b8bd81 |
line wrap: on
line source
/* SDL - Simple DirectMedia Layer Copyright (C) 1997-2006 Sam Lantinga This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Sam Lantinga slouken@libsdl.org */ /** * \file SDL_atomic.h * * Atomic int and pointer magic */ #ifndef _SDL_atomic_h_ #define _SDL_atomic_h_ #include "SDL_stdinc.h" #include "SDL_platform.h" #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus /* *INDENT-OFF* */ extern "C" { /* *INDENT-ON* */ #endif /* indent is really bad at handling assembly */ /* *INDENT-OFF* */ #if defined(__GNUC__) && (defined(i386) || defined(__i386__) || defined(__x86_64__)) static __inline__ void SDL_atomic_int_add(volatile int* atomic, int value) { __asm__ __volatile__("lock;" "addl %1, %0" : "=m" (*atomic) : "ir" (value), "m" (*atomic)); } static __inline__ int SDL_atomic_int_xchg_add(volatile int* atomic, int value) { int rv; __asm__ __volatile__("lock;" "xaddl %0, %1" : "=r" (rv), "=m" (*atomic) : "0" (value), "m" (*atomic)); return rv; } static __inline__ SDL_bool SDL_atomic_int_cmp_xchg(volatile int* atomic, int oldvalue, int newvalue) { int rv; __asm__ __volatile__("lock;" "cmpxchgl %2, %1" : "=a" (rv), "=m" (*atomic) : "r" (newvalue), "m" (*atomic), "0" (oldvalue)); return (SDL_bool)(rv == oldvalue); } static __inline__ SDL_bool SDL_atomic_ptr_cmp_xchg(volatile void** atomic, void* oldvalue, void* newvalue) { void* rv; __asm__ __volatile__("lock;" # if defined(__x86_64__) "cmpxchgq %q2, %1" # else "cmpxchgl %2, %1" # endif : "=a" (rv), "=m" (*atomic) : "r" (newvalue), "m" (*atomic), "0" (oldvalue)); return (SDL_bool)(rv == oldvalue); } #elif defined(__GNUC__) && defined(__alpha__) # define ATOMIC_MEMORY_BARRIER (__asm__ __volatile__ ("mb" : : : "memory")) # define ATOMIC_INT_CMP_XCHG(atomic,value) \ ({ \ int rv,prev; \ __asm__ __volatile__(" mb\n" \ "1: ldl_l %0,%2\n" \ " cmpeq %0,%3,%1\n" \ " beq %1,2f\n" \ " mov %4,%1\n" \ " stl_c %1,%2\n" \ " beq %1,1b\n" \ " mb\n" \ "2:" \ : "=&r" (prev), \ "=&r" (rv) \ : "m" (*(atomic)), \ "Ir" (oldvalue), \ "Ir" (newvalue) \ : "memory"); \ (rv != 0); \ }) # if (SIZEOF_VOIDP == 4) static __inline__ SDL_bool SDL_atomic_ptr_cmp_xchg(volatile void** atomic, void* oldvalue, void* newvalue) { int rv; void* prev; __asm__ __volatile__(" mb\n" "1: ldl_l %0,%2\n" " cmpeq %0,%3,%1\n" " beq $1,2f\n" " mov %4,%1\n" " stl_c %1,%2\n" " beq %1,1b\n" " mb\n" "2:" : "=&r" (prev), "=&r" (rv) : "m" (*atomic), "Ir" (oldvalue), "Ir" (newvalue) : "memory"); return (SDL_bool)(rv != 0); } # elif (SIZEOF_VOIDP == 8) static __inline__ SDL_bool SDL_atomic_ptr_cmp_xchg(volatile void** atomic, void* oldvalue, void* newvalue) { int rv; void* prev; __asm__ __volatile__(" mb\n" "1: ldq_l %0,%2\n" " cmpeq %0,%3,%1\n" " beq %1,2f\n" " mov %4,%1\n" " stq_c %1,%2\n" " beq %1,1b\n" " mb\n" "2:" : "=&r" (prev), "=&r" (rv) : "m" (*atomic), "Ir" (oldvalue), "Ir" (newvalue) : "memory"); return (SDL_bool)(rv != 0); } # else # error "Your system has an unsupported pointer size" # endif /* SIZEOF_VOIDP */ #elif defined(__GNUC__) && defined(__sparc__) # define ATOMIC_MEMORY_BARRIER \ (__asm__ __volatile__("membar #LoadLoad | #LoadStore" \ " | #StoreLoad | #StoreStore" : : : "memory")) # define ATOMIC_INT_CMP_XCHG(atomic,oldvalue,newvalue) \ ({ \ int rv; \ __asm__ __volatile__("cas [%4], %2, %0" \ : "=r" (rv), "=m" (*(atomic)) \ : "r" (oldvalue), "m" (*(atomic)), \ "r" (atomic), "0" (newvalue)); \ rv == oldvalue; \ }) # if (SIZEOF_VOIDP == 4) static __inline__ SDL_bool SDL_atomic_ptr_cmp_xchg(volatile void** atomic, void* oldvalue, void* newvalue) { void* rv; __asm__ __volatile__("cas [%4], %2, %0" : "=r" (rv), "=m" (*atomic) : "r" (oldvalue), "m" (*atomic), "r" (atomic), "0" (newvalue)); return (SDL_bool)(rv == oldvalue); } # elif (SIZEOF_VOIDP == 8) static __inline__ SDL_bool SDL_atomic_ptr_cmp_xchg(volatile void** atomic, void* oldvalue, void* newvalue) { void* rv; void** a = atomic; __asm__ __volatile__("casx [%4], %2, %0" : "=r" (rv), "=m" (*a) : "r" (oldvalue), "m" (*a), "r" (a), "0" (newvalue)); return (SDL_bool)(rv == oldvalue); } # else # error "Your system has an unsupported pointer size" # endif /* SIZEOF_VOIDP */ #elif defined(__GNUC__) && (defined(__POWERPC__) || defined(__powerpc__) || defined(__ppc__) || defined(_M_PPC)) # define ATOMIC_MEMORY_BARRIER \ (__asm__ __volatile__ ("sync" : : : "memory")) static __inline__ void SDL_atomic_int_add(volatile int* atomic, int value) { int rv,tmp; __asm__ __volatile__("1: lwarx %0, 0, %3\n" " add %1, %0, %4\n" " stwcx. %1, 0, %3\n" " bne- 1b" : "=&b" (rv), "=&r" (tmp), "=m" (*atomic) : "b" (atomic), "r" (value), "m" (*atomic) : "cr0", "memory"); } static __inline__ int SDL_atomic_int_xchg_add(volatile int* atomic, int value) { int rv,tmp; __asm__ __volatile__("1: lwarx %0, 0, %3\n" " add %1, %0, %4\n" " stwcx. %1, 0, %3\n" " bne- 1b" : "=&b" (rv), "=&r" (tmp), "=m" (*atomic) : "b" (atomic), "r" (value), "m" (*atomic) : "cr0", "memory"); return rv; } # if (SIZEOF_VOIDP == 4) static __inline__ SDL_bool SDL_atomic_int_cmp_xchg(volatile int* atomic, int oldvalue, int newvalue) { int rv; __asm__ __volatile__(" sync\n" "1: lwarx %0, 0, %1\n" " subf. %0, %2, %0\n" " bne 2f\n" " stwcx. %3, 0, %1\n" " bne- 1b\n" "2: isync" : "=&r" (rv) : "b" (atomic), "r" (oldvalue), "r" : "cr0", "memory"); return (SDL_bool)(rv == 0); } static __inline__ SDL_bool SDL_atomic_ptr_cmp_xchg(volatile void** atomic, void* oldvalue, void* newvalue) { void* rv; __asm__ __volatile__("sync\n" "1: lwarx %0, 0, %1\n" " subf. %0, %2, %0\n" " bne 2f\n" " stwcx. %3, 0, %1\n" " bne- 1b\n" "2: isync" : "=&r" (rv) : "b" (atomic), "r" (oldvalue), "r" (newvalue) : "cr0", "memory"); return (SDL_bool)(rv == 0); } # elif (SIZEOF_VOIDP == 8) static __inline__ SDL_bool SDL_atomic_int_cmp_xchg(volatile int* atomic, int oldvalue, int newvalue) { int rv; __asm__ __volatile__(" sync\n" "1: lwarx %0, 0, %1\n" " extsw %0, %0\n" " subf. %0, %2, %0\n" " bne 2f\n" " stwcx. %3, 0, %1\n" " bne- 1b\n" "2: isync" : "=&r" (rv) : "b" (atomic), "r" (oldvalue), "r" : "cr0", "memory"); return (SDL_bool)(rv == 0); } static __inline__ SDL_bool SDL_atomic_ptr_cmp_xchg(volatile void** atomic, void* oldvalue, void* newvalue) { void* rv; __asm__ __volatile__("sync\n" "1: ldarx %0, 0, %1\n" " subf. %0, %2, %0\n" " bne 2f\n" " stdcx. %3, 0, %1\n" " bne- 1b\n" "2: isync" : "=&r" (rv) : "b" (atomic), "r" (oldvalue), "r" (newvalue) : "cr0", "memory"); return (SDL_bool)(rv == 0); } # else # error "Your system has an unsupported pointer size" # endif /* SIZEOF_VOIDP */ #elif defined(__GNUC__) && (defined(__IA64__) || defined(__ia64__)) # define ATOMIC_MEMORY_BARRIER (__sync_synchronize()) # define SDL_atomic_int_xchg_add(atomic, value) \ (__sync_fetch_and_add((atomic),(value))) # define SDL_atomic_int_add(atomic, value) \ ((void)__sync_fetch_and_add((atomic),(value))) # define SDL_atomic_int_cmp_xchg(atomic,oldvalue,newvalue) \ (__sync_bool_compare_and_swap((atomic),(oldvalue),(newvalue))) # define SDL_atomic_ptr_cmp_xchg(atomic,oldvalue,newvalue) \ (__sync_bool_compare_and_swap((long*)(atomic),(long)(oldvalue),(long)(newvalue))) #elif defined(__GNUC__) && defined(__LINUX__) && (defined(__mips__) || defined(__MIPS__)) static __inline__ int SDL_atomic_int_xchg_add(volatile int* atomic, int value) { int rv,tmp; __asm__ __volatile__("1: \n" ".set push \n" ".set mips2 \n" "ll %0,%3 \n" "addu %1,%4,%0 \n" "sc %1,%2 \n" ".set pop \n" "beqz %1,1b \n" : "=&r" (rv), "=&r" (tmp), "=m" (*atomic) : "m" (*atomic), "r" (value) : "memory"); return rv; } static __inline__ void SDL_atomic_int_add(volatile int* atomic, int value) { int rv; __asm__ __volatile__("1: \n" ".set push \n" ".set mips2 \n" "ll %0,%2 \n" "addu %0,%3,%0 \n" "sc %0,%1 \n" ".set pop \n" "beqz %0,1b \n" : "=&r" (rv), "=m" (*atomic) : "m" (*atomic), "r" (value) : "memory"); } static __inline__ SDL_bool SDL_atomic_int_cmp_xchg(volatile int* atomic, int oldvalue, int newvalue) { int rv; __asm__ __volatile__(" .set push \n" " .set noat \n" " .set mips3 \n" "1: ll %0, %2 \n" " bne %0, %z3, 2f \n" " .set mips0 \n" " move $1, %z4 \n" " .set mips3 \n" " sc $1, %1 \n" " beqz $1, 1b \n" " sync \n" "2: \n" " .set pop \n" : "=&r" (rv), "=R" (*atomic) : "R" (*atomic), "Jr" (oldvalue), "Jr" (newvalue) : "memory"); return (SDL_bool)rv; } static __inline__ SDL_bool SDL_atomic_ptr_cmp_xchg(volatile void** atomic, void* oldvalue, void* newvalue) { int rv; __asm__ __volatile__(" .set push \n" " .set noat \n" " .set mips3 \n" # if defined(__mips64) "1: lld %0, %2 \n" # else "1: ll %0, %2 \n" # endif " bne %0, %z3, 2f \n" " move $1, %z4 \n" # if defined(__mips64) " sc $1, %1 \n" # else " scd $1, %1 \n" # endif " beqz $1, 1b \n" " sync \n" "2: \n" " .set pop \n" : "=&r" (rv), "=R" (*atomic) : "R" (*atomic), "Jr" (oldvalue), "Jr" (newvalue) : "memory"); return (SDL_bool)rv; } #elif defined(__GNUC__) && defined(__m68k__) static __inline__ int SDL_atomic_int_xchg_add(volatile int* atomic, int value) { int rv = *atomic; int tmp; __asm__ __volatile__("1: move%.l %0,%1 \n" " add%.l %2,%1 \n" " cas%.l %0,%1,%3 \n" " jbne 1b \n" : "=d" (rv), "=&d" (tmp) : "d" (value), "m" (*atomic), "0" (rv) : "memory"); return (SDL_bool)rv; } static __inline__ void SDL_atomic_int_add(volatile int* atomic, int value) { __asm__ __volatile__("add%.l %0,%1" : : "id" (value), "m" (*atomic) : "memory"); } static __inline__ SDL_bool SDL_atomic_int_cmp_xchg(volatile int* atomic, int oldvalue, int newvalue) { char rv; int readvalue; __asm__ __volatile__("cas%.l %2,%3,%1\n" "seq %0" : "=dm" (rv), "=m" (*atomic), "=d" (readvalue) : "d" (newvalue), "m" (*atomic), "2" (oldvalue)); return (SDL_bool)rv; } static __inline__ SDL_bool SDL_atomic_ptr_cmp_xchg(volatile void** atomic, void* oldvalue, void* newvalue) { char rv; int readvalue; __asm__ __volatile__("cas%.l %2,%3,%1\n" "seq %0" : "=dm" (rv), "=m" (*atomic), "=d" (readvalue) : "d" (newvalue), "m" (*atomic), "2" (oldvalue)); return (SDL_bool)rv; } #elif defined(__GNUC__) && defined(__s390__) # define ATOMIC_INT_CMP_XCHG(atomic,oldvalue,newvalue) \ ({ \ int rv = oldvalue; \ __asm__ __volatile__("cs %0, %2, %1" \ : "+d" (rv), \ "=Q" (*(atomic)) \ : "d" (newvalue), \ "m" (*(atomic)) \ : "cc"); \ rv == oldvalue; \ }) # if (SIZEOF_VOIDP == 4) static __inline__ SDL_bool SDL_atomic_ptr_cmp_xchg(volatile void** atomic, void* oldvalue, void* newvalue) { void* rv = oldvalue; __asm__ __volatile__("cs %0, %2, %1" : "+d" (rv), "=Q" (*atomic) : "d" (newvalue), "m" (*atomic) : "cc"); return (SDL_bool)(rv == oldvalue); } # elif (SIZEOF_VOIDP == 8) static __inline__ SDL_bool SDL_atomic_ptr_cmp_xchg(volatile void** atomic, void* oldvalue, void* newvalue) { void* rv = oldvalue; void** a = atomic; __asm__ __volatile__("csg %0, %2, %1" : "+d" (rv), "=Q" (*a) : "d" ((long)(newvalue)), "m" (*a) : "cc"); return (SDL_bool)(rv == oldvalue); } # else # error "Your system has an unsupported pointer size" # endif /* SIZEOF_VOIDP */ #elif defined(__WIN32__) # include <windows.h> static __inline__ int SDL_atomic_int_xchg_add(volatile int* atomic, int value) { return InterlockedExchangeAdd(atomic, value); } static __inline__ void SDL_atomic_int_add(volatile int* atomic, int value) { InterlockedExchangeAdd(atomic, value); } # if (WINVER > 0X0400) static __inline__ SDL_bool SDL_atmoic_int_cmp_xchg(volatile int* atomic, int oldvalue, int newvalue) { return (SDL_bool)(InterlockedCompareExchangePointer((PVOID*)atomic, (PVOID)newvalue, (PVOID)oldvalue) == oldvalue); } static __inline__ SDL_bool SDL_atomic_ptr_cmp_xchg(volatile void** atomic, void* oldvalue, void* newvalue) { return (InterlockedCompareExchangePointer(atomic, newvalue, oldvalue) == oldvalue); } # else /* WINVER <= 0x0400 */ # if (SIZEOF_VOIDP != 4) # error "InterlockedCompareExchangePointer needed" # endif static __inline__ SDL_bool SDL_atomic_int_cmp_xchg(volatile int* atomic, int oldvalue, int newvalue) { return (InterlockedCompareExchange(atomic, newvalue, oldvalue) == oldvalue); } static __inline__ SDL_bool SDL_atomic_ptr_cmp_xchg(volatile void** atomic, void* oldvalue, void* newvalue) { return (InterlockedCompareExchange(atomic, newvalue, oldvalue) == oldvalue); } # endif #else /* when all else fails */ # define SDL_ATOMIC_OPS_NOT_SUPPORTED # warning "Atomic Ops for this platform not supported!" static __inline__ int SDL_atomic_int_xchg_add(volatile int* atomic, int value) { int rv = *atomic; *(atomic) += value; return rv; } static __inline__ SDL_bool SDL_atomic_int_cmp_xchg(volatile int* atomic, int oldvalue, int newvalue) { return (*atomic == oldvalue) ? ((*atomic = newvalue), SDL_TRUE) : SDL_FALSE; } static __inline__ void SDL_atomic_int_add(volatile int* atomic, int value) { *atomic += value; } #endif /* arch & platforms */ /* *INDENT-ON* */ #ifdef ATOMIC_INT_CMP_XCHG static __inline__ SDL_bool SDL_atomic_int_cmp_xchg(volatile int *atomic, int oldvalue, int newvalue) { return (SDL_bool) ATOMIC_INT_CMP_XCHG(atomic, oldvalue, newvalue); } static __inline__ int SDL_atomic_int_xchg_add(volatile int *atomic, int value) { int rv; do rv = *atomic; while (!ATOMIC_INT_CMP_XCHG(atomic, rv, rv + value)); return rv; } static __inline__ void SDL_atomic_int_add(volatile int *atomic, int value) { int rv; do rv = *atomic; while (!ATOMIC_INT_CMP_XCHG(atomic, rv, rv + value)); } #endif /* ATOMIC_CMP_XCHG */ #ifdef ATOMIC_MEMORY_BARRIER # define SDL_atomic_int_get(atomic) \ (ATOMIC_MEMORY_BARRIER,*(atomic)) # define SDL_atomic_int_set(atomic,value) \ (*(atomic)=value,ATOMIC_MEMORY_BARRIER) #else # define SDL_atomic_int_get(atomic) (*(atomic)) # define SDL_atomic_int_set(atomic, newvalue) ((void)(*(atomic) = (newvalue))) #endif /* MEMORY_BARRIER_NEEDED */ #define SDL_atomic_int_inc(atomic) (SDL_atomic_int_add((atomic),1)) #define SDL_atomic_int_dec_test(atomic) (SDL_atomic_int_xchg_add((atomic),-1) == 1) /* Ends C function definitions when using C++ */ #ifdef __cplusplus /* *INDENT-OFF* */ } /* *INDENT-ON* */ #endif #include "close_code.h" #endif /* _SDL_atomic_h_ */ /* vi: set ts=4 sw=4 expandtab: */