changeset 3180:77d6336711fc

First commit for SDL atomic operations. On my linux box it compiles and installs correctly and testatomic runs without errors.
author Bob Pendleton <bob@pendleton.com>
date Tue, 09 Jun 2009 17:33:44 +0000
parents 9b34679fda8b
children 030899df1af5
files Makefile.in configure.in include/SDL.h include/SDL_atomic.h include/SDL_config.h.in include/SDL_config_dreamcast.h include/SDL_config_macosx.h include/SDL_config_os2.h include/SDL_config_win32.h test/Makefile.in test/testatomic.c
diffstat 11 files changed, 755 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile.in	Tue Jun 09 15:45:33 2009 +0000
+++ b/Makefile.in	Tue Jun 09 17:33:44 2009 +0000
@@ -42,7 +42,7 @@
 
 DIST = acinclude.m4 autogen.sh Borland.html Borland.zip BUGS build-scripts configure configure.in COPYING CREDITS docs docs.html include INSTALL Makefile.dc Makefile.minimal Makefile.in README* sdl-config.in sdl.m4 sdl.pc.in SDL.qpg.in SDL.spec SDL.spec.in src test TODO VisualC.html VisualC VisualCE Watcom-OS2.zip Watcom-Win32.zip WhatsNew Xcode
 
-HDRS = SDL.h SDL_audio.h SDL_cdrom.h SDL_compat.h SDL_cpuinfo.h SDL_endian.h SDL_error.h SDL_events.h SDL_haptic.h SDL_joystick.h SDL_keyboard.h SDL_keysym.h SDL_loadso.h SDL_main.h SDL_mouse.h SDL_mutex.h SDL_name.h SDL_opengl.h SDL_opengles.h SDL_pixels.h SDL_platform.h SDL_power.h SDL_quit.h SDL_rect.h SDL_revision.h SDL_rwops.h SDL_scancode.h SDL_stdinc.h SDL_surface.h SDL_syswm.h SDL_thread.h SDL_timer.h SDL_types.h SDL_version.h SDL_video.h begin_code.h close_code.h
+HDRS = SDL.h SDL_atomic.h SDL_audio.h SDL_cdrom.h SDL_compat.h SDL_cpuinfo.h SDL_endian.h SDL_error.h SDL_events.h SDL_haptic.h SDL_joystick.h SDL_keyboard.h SDL_keysym.h SDL_loadso.h SDL_main.h SDL_mouse.h SDL_mutex.h SDL_name.h SDL_opengl.h SDL_opengles.h SDL_pixels.h SDL_platform.h SDL_power.h SDL_quit.h SDL_rect.h SDL_revision.h SDL_rwops.h SDL_scancode.h SDL_stdinc.h SDL_surface.h SDL_syswm.h SDL_thread.h SDL_timer.h SDL_types.h SDL_version.h SDL_video.h begin_code.h close_code.h
 
 LT_AGE      = @LT_AGE@
 LT_CURRENT  = @LT_CURRENT@
--- a/configure.in	Tue Jun 09 15:45:33 2009 +0000
+++ b/configure.in	Tue Jun 09 17:33:44 2009 +0000
@@ -159,6 +159,7 @@
     AC_CHECK_FUNCS(iconv)
 fi
 
+AC_CHECK_SIZEOF(void*)
 if test x$have_inttypes != xyes; then
     AC_CHECK_SIZEOF(char, 1)
     AC_CHECK_SIZEOF(short, 2)
--- a/include/SDL.h	Tue Jun 09 15:45:33 2009 +0000
+++ b/include/SDL.h	Tue Jun 09 17:33:44 2009 +0000
@@ -76,6 +76,7 @@
 
 #include "SDL_main.h"
 #include "SDL_stdinc.h"
+#include "SDL_atomic.h"
 #include "SDL_audio.h"
 #include "SDL_cdrom.h"
 #include "SDL_cpuinfo.h"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/SDL_atomic.h	Tue Jun 09 17:33:44 2009 +0000
@@ -0,0 +1,674 @@
+/*
+    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
+
+#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 (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 (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 (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 (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 (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 (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 (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 (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 (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 (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 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 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 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 (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 (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 */
+  
+#ifdef ATOMIC_INT_CMP_XCHG
+static __inline__ SDL_bool
+SDL_atomic_int_cmp_xchg(volatile int* atomic, int oldvalue, int newvalue)
+{
+  return 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: */
--- a/include/SDL_config.h.in	Tue Jun 09 15:45:33 2009 +0000
+++ b/include/SDL_config.h.in	Tue Jun 09 17:33:44 2009 +0000
@@ -49,6 +49,7 @@
 #undef int64_t
 #undef uint64_t
 #undef uintptr_t
+#undef SIZEOF_VOIDP
 #undef SDL_HAS_64BIT_TYPE
 
 /* Endianness */
--- a/include/SDL_config_dreamcast.h	Tue Jun 09 15:45:33 2009 +0000
+++ b/include/SDL_config_dreamcast.h	Tue Jun 09 17:33:44 2009 +0000
@@ -36,6 +36,7 @@
 typedef signed long long int64_t;
 typedef unsigned long long uint64_t;
 typedef unsigned long uintptr_t;
+#define SIZEOF_VOIDP 4
 #define SDL_HAS_64BIT_TYPE	1
 
 /* Useful headers */
--- a/include/SDL_config_macosx.h	Tue Jun 09 15:45:33 2009 +0000
+++ b/include/SDL_config_macosx.h	Tue Jun 09 17:33:44 2009 +0000
@@ -30,6 +30,7 @@
 
 /* This is a set of defines to configure the SDL features */
 
+#define SIZEOF_VOIDP 4
 #define SDL_HAS_64BIT_TYPE	1
 
 /* Useful headers */
--- a/include/SDL_config_os2.h	Tue Jun 09 15:45:33 2009 +0000
+++ b/include/SDL_config_os2.h	Tue Jun 09 17:33:44 2009 +0000
@@ -38,6 +38,7 @@
 typedef signed long long int64_t;
 typedef unsigned long long uint64_t;
 
+#define SIZEOF_VOIDP 4
 #define SDL_HAS_64BIT_TYPE	1
 
 /* Use Watcom's LIBC */
--- a/include/SDL_config_win32.h	Tue Jun 09 15:45:33 2009 +0000
+++ b/include/SDL_config_win32.h	Tue Jun 09 17:33:44 2009 +0000
@@ -68,6 +68,12 @@
 #endif
 typedef unsigned int uintptr_t;
 #endif /* __GNUC__ || _MSC_VER */
+
+#ifdef _WIN64
+# define SIZEOF_VOIDP 8
+#else
+# define SIZEOF_VOIDP 4
+#endif
 #define SDL_HAS_64BIT_TYPE	1
 
 /* Enabled for SDL 1.2 (binary compatibility) */
--- a/test/Makefile.in	Tue Jun 09 15:45:33 2009 +0000
+++ b/test/Makefile.in	Tue Jun 09 17:33:44 2009 +0000
@@ -7,7 +7,7 @@
 CFLAGS  = @CFLAGS@
 LIBS	= @LIBS@
 
-TARGETS = checkkeys$(EXE) graywin$(EXE) loopwave$(EXE) testresample$(EXE) testaudioinfo$(EXE) testmultiaudio$(EXE) testpower$(EXE) testalpha$(EXE) testbitmap$(EXE) testblitspeed$(EXE) testcdrom$(EXE) testcursor$(EXE) testintersections$(EXE) testdraw2$(EXE) testdyngl$(EXE) testdyngles$(EXE) testerror$(EXE) testfile$(EXE) testgamma$(EXE) testgl$(EXE) testgl2$(EXE) testgles$(EXE) testhread$(EXE) testiconv$(EXE) testjoystick$(EXE) testkeys$(EXE) testlock$(EXE) testoverlay2$(EXE) testoverlay$(EXE) testpalette$(EXE) testplatform$(EXE) testsem$(EXE) testsprite$(EXE) testsprite2$(EXE) testtimer$(EXE) testver$(EXE) testvidinfo$(EXE) testwin$(EXE) testwm$(EXE) testwm2$(EXE) threadwin$(EXE) torturethread$(EXE) testloadso$(EXE) testhaptic$(EXE) testmmousetablet$(EXE)
+TARGETS = checkkeys$(EXE) graywin$(EXE) loopwave$(EXE) testresample$(EXE) testaudioinfo$(EXE) testmultiaudio$(EXE) testpower$(EXE) testalpha$(EXE) testbitmap$(EXE) testblitspeed$(EXE) testcdrom$(EXE) testcursor$(EXE) testintersections$(EXE) testdraw2$(EXE) testdyngl$(EXE) testdyngles$(EXE) testerror$(EXE) testfile$(EXE) testgamma$(EXE) testgl$(EXE) testgl2$(EXE) testgles$(EXE) testhread$(EXE) testiconv$(EXE) testjoystick$(EXE) testkeys$(EXE) testlock$(EXE) testoverlay2$(EXE) testoverlay$(EXE) testpalette$(EXE) testplatform$(EXE) testsem$(EXE) testsprite$(EXE) testsprite2$(EXE) testtimer$(EXE) testver$(EXE) testvidinfo$(EXE) testwin$(EXE) testwm$(EXE) testwm2$(EXE) threadwin$(EXE) torturethread$(EXE) testloadso$(EXE) testhaptic$(EXE) testmmousetablet$(EXE) testatomic$(EXE)
 
 all: Makefile $(TARGETS)
 
@@ -149,6 +149,9 @@
 testmmousetablet$(EXE): $(srcdir)/testmmousetablet.c
 	$(CC) -o $@ $? $(CFLAGS) $(LIBS)
 
+testatomic$(EXE): $(srcdir)/testatomic.c
+	$(CC) -o $@ $? $(CFLAGS) $(LIBS)
+ 
 clean:
 	rm -f $(TARGETS)
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/testatomic.c	Tue Jun 09 17:33:44 2009 +0000
@@ -0,0 +1,64 @@
+#include "SDL.h"
+
+int
+main(int argc, char** argv)
+{
+  int rv = 10;
+  volatile int atomic;
+
+  SDL_atomic_int_set(&atomic, 10);
+  if(SDL_atomic_int_get(&atomic) != 10)
+    printf("Error: ");
+  printf("SDL_atomic_int_set(atomic, 10): atomic-> %d\n",
+         SDL_atomic_int_get(&atomic));
+    
+  SDL_atomic_int_add(&atomic, 10);
+  if(SDL_atomic_int_get(&atomic) != 20)
+    printf("Error: ");
+  printf("SDL_atomic_int_add(atomic, 10): atomic-> %d\n",
+         SDL_atomic_int_get(&atomic));
+  
+  rv = SDL_atomic_int_cmp_xchg(&atomic, 20, 30);
+  if(rv != SDL_TRUE || SDL_atomic_int_get(&atomic) != 30)
+    printf("Error: ");
+  printf("SDL_atomic_int_cmp_xchg(atomic, 20, 30): rv-> %d, atomic-> %d\n",
+         rv, SDL_atomic_int_get(&atomic));
+  
+  rv = SDL_atomic_int_cmp_xchg(&atomic, 20, 30);
+  if(rv != SDL_FALSE || SDL_atomic_int_get(&atomic) != 30)
+    printf("Error: ");
+  printf("SDL_atomic_int_cmp_xchg(atomic, 20, 40): rv-> %d, atomic-> %d\n",
+         rv, SDL_atomic_int_get(&atomic));
+  
+  rv = SDL_atomic_int_xchg_add(&atomic, 10);
+  if(rv != 30 || SDL_atomic_int_get(&atomic) != 40)
+    printf("Error: ");
+  printf("SDL_atomic_int_xchg_add(atomic, 10): rv-> %d, atomic-> %d\n",
+         rv, SDL_atomic_int_get(&atomic));
+
+  SDL_atomic_int_inc(&atomic);
+  if(SDL_atomic_int_get(&atomic) != 41)
+    printf("Error: ");
+  printf("SDL_atomic_int_inc(atomic): atomic-> %d\n",
+         SDL_atomic_int_get(&atomic));
+
+  rv = SDL_atomic_int_dec_test(&atomic);
+  if(rv != SDL_FALSE || SDL_atomic_int_get(&atomic) != 40)
+    printf("Error: ");
+  printf("SDL_atomic_int_dec_test(atomic): rv-> %d, atomic-> %d\n",
+         rv, SDL_atomic_int_get(&atomic));
+  
+  SDL_atomic_int_set(&atomic, 1);
+  if(SDL_atomic_int_get(&atomic) != 1)
+    printf("Error: ");    
+    printf("SDL_atomic_int_set(atomic, 1): atomic-> %d\n",
+           SDL_atomic_int_get(&atomic));
+
+  rv = SDL_atomic_int_dec_test(&atomic);
+  if(rv != SDL_TRUE || SDL_atomic_int_get(&atomic) != 0)
+    printf("Error: ");
+  printf("SDL_atomic_int_dec_test(atomic): rv-> %d, atomic-> %d\n",
+         rv, SDL_atomic_int_get(&atomic));
+  
+  return 0;
+}