From c4a7a39b1bfdc9a101a28fb4df55a795ee2a0cbf Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 15 Jan 2011 12:41:59 -0800 Subject: [PATCH] Updated the atomic API for better use cases --- Android.mk | 3 +- VisualC/SDL/SDL_VS2005.vcproj | 6 +- VisualC/SDL/SDL_VS2008.vcproj | 6 +- VisualC/SDL/SDL_VS2010.vcxproj | 5 +- .../SDL/SDLiPhoneOS.xcodeproj/project.pbxproj | 39 +- Xcode/SDL/SDL.xcodeproj/project.pbxproj | 26 +- configure.in | 41 +- include/SDL_atomic.h | 232 ++++---- src/atomic/SDL_atomic.c | 179 ++++++ src/atomic/SDL_spinlock.c | 99 ++++ src/atomic/dummy/SDL_atomic.c | 469 ---------------- src/atomic/linux/SDL_atomic.c | 510 ----------------- src/atomic/macosx/SDL_atomic.c | 469 ---------------- src/atomic/qnx/SDL_atomic.c | 505 ----------------- src/atomic/win32/SDL_atomic.c | 512 ------------------ test/testatomic.c | 161 ++---- 16 files changed, 496 insertions(+), 2766 deletions(-) create mode 100644 src/atomic/SDL_atomic.c create mode 100644 src/atomic/SDL_spinlock.c delete mode 100644 src/atomic/dummy/SDL_atomic.c delete mode 100644 src/atomic/linux/SDL_atomic.c delete mode 100644 src/atomic/macosx/SDL_atomic.c delete mode 100644 src/atomic/qnx/SDL_atomic.c delete mode 100644 src/atomic/win32/SDL_atomic.c diff --git a/Android.mk b/Android.mk index 12f534ded..12f683b3d 100755 --- a/Android.mk +++ b/Android.mk @@ -16,6 +16,8 @@ LOCAL_SRC_FILES := src/SDL_android.cpp \ $(subst $(LOCAL_PATH)/,, \ $(wildcard $(LOCAL_PATH)/src/*.c) \ $(wildcard $(LOCAL_PATH)/src/audio/*.c) \ + $(LOCAL_PATH)/src/atomic/SDL_atomic.c \ + $(LOCAL_PATH)/src/atomic/SDL_spinlock.c.arm \ $(wildcard $(LOCAL_PATH)/src/cpuinfo/*.c) \ $(wildcard $(LOCAL_PATH)/src/events/*.c) \ $(wildcard $(LOCAL_PATH)/src/file/*.c) \ @@ -31,7 +33,6 @@ LOCAL_SRC_FILES := src/SDL_android.cpp \ $(wildcard $(LOCAL_PATH)/src/video/android/*.c) \ $(wildcard $(LOCAL_PATH)/src/joystick/android/*.c) \ $(wildcard $(LOCAL_PATH)/src/haptic/dummy/*.c) \ - $(wildcard $(LOCAL_PATH)/src/atomic/dummy/*.c) \ $(wildcard $(LOCAL_PATH)/src/thread/pthread/*.c) \ $(wildcard $(LOCAL_PATH)/src/timer/unix/*.c) \ $(wildcard $(LOCAL_PATH)/src/loadso/dlopen/*.c)) diff --git a/VisualC/SDL/SDL_VS2005.vcproj b/VisualC/SDL/SDL_VS2005.vcproj index bffdedb2e..7d769b268 100644 --- a/VisualC/SDL/SDL_VS2005.vcproj +++ b/VisualC/SDL/SDL_VS2005.vcproj @@ -644,7 +644,11 @@ > + + + + - + + @@ -457,4 +458,4 @@ echo #define SDL_REVISION 0 >"$(ProjectDir)\..\..\include\SDL_revision.h" - \ No newline at end of file + diff --git a/Xcode-iPhoneOS/SDL/SDLiPhoneOS.xcodeproj/project.pbxproj b/Xcode-iPhoneOS/SDL/SDLiPhoneOS.xcodeproj/project.pbxproj index 58cbbdd65..e5abacf3b 100755 --- a/Xcode-iPhoneOS/SDL/SDLiPhoneOS.xcodeproj/project.pbxproj +++ b/Xcode-iPhoneOS/SDL/SDLiPhoneOS.xcodeproj/project.pbxproj @@ -93,7 +93,6 @@ 04B2ECEC1025CE4800F9BC5F /* SDL_atomic.h in Headers */ = {isa = PBXBuildFile; fileRef = 04B2ECE61025CE4800F9BC5F /* SDL_atomic.h */; settings = {ATTRIBUTES = (Public, ); }; }; 04B2ECED1025CE4800F9BC5F /* SDL_power.h in Headers */ = {isa = PBXBuildFile; fileRef = 04B2ECE71025CE4800F9BC5F /* SDL_power.h */; settings = {ATTRIBUTES = (Public, ); }; }; 04B2ECEE1025CE4800F9BC5F /* SDL_revision.h in Headers */ = {isa = PBXBuildFile; fileRef = 04B2ECE81025CE4800F9BC5F /* SDL_revision.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 04B2ECFF1025CEB900F9BC5F /* SDL_atomic.c in Sources */ = {isa = PBXBuildFile; fileRef = 04B2ECF11025CEB900F9BC5F /* SDL_atomic.c */; }; 04B2ED081025CF9E00F9BC5F /* SDL_config.h in Headers */ = {isa = PBXBuildFile; fileRef = 04B2ED061025CF9E00F9BC5F /* SDL_config.h */; settings = {ATTRIBUTES = (Public, ); }; }; 04BA9D6311EF474A00B60E01 /* SDL_gesture_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BA9D5F11EF474A00B60E01 /* SDL_gesture_c.h */; }; 04BA9D6411EF474A00B60E01 /* SDL_gesture.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BA9D6011EF474A00B60E01 /* SDL_gesture.c */; }; @@ -104,6 +103,11 @@ 04EC8B521025D12900431D42 /* SDL_config_iphoneos.h in Headers */ = {isa = PBXBuildFile; fileRef = 04EC8B501025D12900431D42 /* SDL_config_iphoneos.h */; }; 04F2AF541104ABC300D6DDF7 /* SDL_assert.h in Headers */ = {isa = PBXBuildFile; fileRef = 04F2AF531104ABC300D6DDF7 /* SDL_assert.h */; }; 04F2AF561104ABD200D6DDF7 /* SDL_assert.c in Sources */ = {isa = PBXBuildFile; fileRef = 04F2AF551104ABD200D6DDF7 /* SDL_assert.c */; }; + 04FFAB8B12E23B8D00BA343D /* SDL_atomic.c in Sources */ = {isa = PBXBuildFile; fileRef = 04FFAB8912E23B8D00BA343D /* SDL_atomic.c */; }; + 04FFAB8C12E23B8D00BA343D /* SDL_spinlock.c in Sources */ = {isa = PBXBuildFile; fileRef = 04FFAB8A12E23B8D00BA343D /* SDL_spinlock.c */; }; + 04FFAB9612E23BDC00BA343D /* SDL_blendmode.h in Headers */ = {isa = PBXBuildFile; fileRef = 04FFAB9312E23BDC00BA343D /* SDL_blendmode.h */; }; + 04FFAB9712E23BDC00BA343D /* SDL_scalemode.h in Headers */ = {isa = PBXBuildFile; fileRef = 04FFAB9412E23BDC00BA343D /* SDL_scalemode.h */; }; + 04FFAB9812E23BDC00BA343D /* SDL_shape.h in Headers */ = {isa = PBXBuildFile; fileRef = 04FFAB9512E23BDC00BA343D /* SDL_shape.h */; }; 56ED04E1118A8EE200A56AA6 /* SDL_power.c in Sources */ = {isa = PBXBuildFile; fileRef = 56ED04E0118A8EE200A56AA6 /* SDL_power.c */; }; 56ED04E3118A8EFD00A56AA6 /* SDL_syspower.m in Sources */ = {isa = PBXBuildFile; fileRef = 56ED04E2118A8EFD00A56AA6 /* SDL_syspower.m */; }; FD24846D0E5655AE0021E198 /* SDL_uikitkeyboard.h in Headers */ = {isa = PBXBuildFile; fileRef = FD24846B0E5655AE0021E198 /* SDL_uikitkeyboard.h */; }; @@ -350,7 +354,6 @@ 04B2ECE61025CE4800F9BC5F /* SDL_atomic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_atomic.h; path = ../../include/SDL_atomic.h; sourceTree = SOURCE_ROOT; }; 04B2ECE71025CE4800F9BC5F /* SDL_power.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_power.h; path = ../../include/SDL_power.h; sourceTree = SOURCE_ROOT; }; 04B2ECE81025CE4800F9BC5F /* SDL_revision.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_revision.h; path = ../../include/SDL_revision.h; sourceTree = SOURCE_ROOT; }; - 04B2ECF11025CEB900F9BC5F /* SDL_atomic.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_atomic.c; sourceTree = ""; }; 04B2ED061025CF9E00F9BC5F /* SDL_config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_config.h; path = ../../include/SDL_config.h; sourceTree = SOURCE_ROOT; }; 04BA9D5F11EF474A00B60E01 /* SDL_gesture_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_gesture_c.h; sourceTree = ""; }; 04BA9D6011EF474A00B60E01 /* SDL_gesture.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_gesture.c; sourceTree = ""; }; @@ -361,6 +364,11 @@ 04EC8B501025D12900431D42 /* SDL_config_iphoneos.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_config_iphoneos.h; path = ../../include/SDL_config_iphoneos.h; sourceTree = SOURCE_ROOT; }; 04F2AF531104ABC300D6DDF7 /* SDL_assert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_assert.h; path = ../../include/SDL_assert.h; sourceTree = SOURCE_ROOT; }; 04F2AF551104ABD200D6DDF7 /* SDL_assert.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = SDL_assert.c; path = ../../src/SDL_assert.c; sourceTree = SOURCE_ROOT; }; + 04FFAB8912E23B8D00BA343D /* SDL_atomic.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_atomic.c; sourceTree = ""; }; + 04FFAB8A12E23B8D00BA343D /* SDL_spinlock.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_spinlock.c; sourceTree = ""; }; + 04FFAB9312E23BDC00BA343D /* SDL_blendmode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_blendmode.h; path = ../../include/SDL_blendmode.h; sourceTree = SOURCE_ROOT; }; + 04FFAB9412E23BDC00BA343D /* SDL_scalemode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_scalemode.h; path = ../../include/SDL_scalemode.h; sourceTree = SOURCE_ROOT; }; + 04FFAB9512E23BDC00BA343D /* SDL_shape.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_shape.h; path = ../../include/SDL_shape.h; sourceTree = SOURCE_ROOT; }; 56ED04E0118A8EE200A56AA6 /* SDL_power.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = SDL_power.c; path = ../../src/power/SDL_power.c; sourceTree = SOURCE_ROOT; }; 56ED04E2118A8EFD00A56AA6 /* SDL_syspower.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SDL_syspower.m; path = ../../src/power/uikit/SDL_syspower.m; sourceTree = SOURCE_ROOT; }; FD0BBFEF0E3933DD00D833B1 /* SDL_uikitview.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_uikitview.h; sourceTree = ""; }; @@ -690,20 +698,13 @@ 04B2ECEF1025CEB900F9BC5F /* atomic */ = { isa = PBXGroup; children = ( - 04B2ECF01025CEB900F9BC5F /* dummy */, + 04FFAB8912E23B8D00BA343D /* SDL_atomic.c */, + 04FFAB8A12E23B8D00BA343D /* SDL_spinlock.c */, ); name = atomic; path = ../../src/atomic; sourceTree = SOURCE_ROOT; }; - 04B2ECF01025CEB900F9BC5F /* dummy */ = { - isa = PBXGroup; - children = ( - 04B2ECF11025CEB900F9BC5F /* SDL_atomic.c */, - ); - path = dummy; - sourceTree = ""; - }; 19C28FACFE9D520D11CA2CBB /* Products */ = { isa = PBXGroup; children = ( @@ -848,6 +849,9 @@ FD99B8BC0DD52E5C00FB1D6B /* Public Headers */ = { isa = PBXGroup; children = ( + 04FFAB9312E23BDC00BA343D /* SDL_blendmode.h */, + 04FFAB9412E23BDC00BA343D /* SDL_scalemode.h */, + 04FFAB9512E23BDC00BA343D /* SDL_shape.h */, FD99B8CC0DD52EB400FB1D6B /* begin_code.h */, FD99B8CD0DD52EB400FB1D6B /* close_code.h */, FD99B8F50DD52EB400FB1D6B /* SDL.h */, @@ -1213,6 +1217,9 @@ 04BA9D6511EF474A00B60E01 /* SDL_touch_c.h in Headers */, 04BA9D7D11EF497E00B60E01 /* SDL_gesture.h in Headers */, 04BA9D7E11EF497E00B60E01 /* SDL_touch.h in Headers */, + 04FFAB9612E23BDC00BA343D /* SDL_blendmode.h in Headers */, + 04FFAB9712E23BDC00BA343D /* SDL_scalemode.h in Headers */, + 04FFAB9812E23BDC00BA343D /* SDL_shape.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1262,7 +1269,14 @@ isa = PBXProject; buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "SDLiPhoneOS" */; compatibilityVersion = "Xcode 3.1"; + developmentRegion = English; hasScannedForEncodings = 1; + knownRegions = ( + English, + Japanese, + French, + German, + ); mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; projectDirPath = ""; projectRoot = ../..; @@ -1443,7 +1457,6 @@ 046387440F0B5B7D0041FD65 /* SDL_drawline.c in Sources */, 046387450F0B5B7D0041FD65 /* SDL_drawpoint.c in Sources */, 046387460F0B5B7D0041FD65 /* SDL_fillrect.c in Sources */, - 04B2ECFF1025CEB900F9BC5F /* SDL_atomic.c in Sources */, 043DD76F10FD8A0000DED673 /* SDL_alphamult.c in Sources */, 043DD77110FD8A0000DED673 /* SDL_blendfillrect.c in Sources */, 043DD77210FD8A0000DED673 /* SDL_drawrect.c in Sources */, @@ -1455,6 +1468,8 @@ 0420497111E6F03D007E7EC9 /* SDL_clipboardevents.c in Sources */, 04BA9D6411EF474A00B60E01 /* SDL_gesture.c in Sources */, 04BA9D6611EF474A00B60E01 /* SDL_touch.c in Sources */, + 04FFAB8B12E23B8D00BA343D /* SDL_atomic.c in Sources */, + 04FFAB8C12E23B8D00BA343D /* SDL_spinlock.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Xcode/SDL/SDL.xcodeproj/project.pbxproj b/Xcode/SDL/SDL.xcodeproj/project.pbxproj index 6041c21e0..29866c414 100755 --- a/Xcode/SDL/SDL.xcodeproj/project.pbxproj +++ b/Xcode/SDL/SDL.xcodeproj/project.pbxproj @@ -150,8 +150,6 @@ 00CFA68F106B44CE00758660 /* SDL_rect.h in Headers */ = {isa = PBXBuildFile; fileRef = 00CFA67F106B44CE00758660 /* SDL_rect.h */; }; 00CFA690106B44CE00758660 /* SDL_scancode.h in Headers */ = {isa = PBXBuildFile; fileRef = 00CFA680106B44CE00758660 /* SDL_scancode.h */; }; 00CFA691106B44CE00758660 /* SDL_surface.h in Headers */ = {isa = PBXBuildFile; fileRef = 00CFA681106B44CE00758660 /* SDL_surface.h */; }; - 00CFA6A8106B467B00758660 /* SDL_atomic.c in Sources */ = {isa = PBXBuildFile; fileRef = 00CFA6A1106B467B00758660 /* SDL_atomic.c */; }; - 00CFA6AD106B467B00758660 /* SDL_atomic.c in Sources */ = {isa = PBXBuildFile; fileRef = 00CFA6A1106B467B00758660 /* SDL_atomic.c */; }; 00CFA6B6106B46E500758660 /* SDL_audio_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 00CFA6B0106B46E500758660 /* SDL_audio_c.h */; }; 00CFA6B7106B46E500758660 /* SDL_audiodev_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 00CFA6B1106B46E500758660 /* SDL_audiodev_c.h */; }; 00CFA6B8106B46E500758660 /* SDL_audiomem.h in Headers */ = {isa = PBXBuildFile; fileRef = 00CFA6B2106B46E500758660 /* SDL_audiomem.h */; }; @@ -480,6 +478,10 @@ 04F2AF671104AC0800D6DDF7 /* SDL_assert.c in Sources */ = {isa = PBXBuildFile; fileRef = 04F2AF651104AC0800D6DDF7 /* SDL_assert.c */; }; 04F2AF691104AC4500D6DDF7 /* SDL_assert.h in Headers */ = {isa = PBXBuildFile; fileRef = 04F2AF681104AC4500D6DDF7 /* SDL_assert.h */; settings = {ATTRIBUTES = (Public, ); }; }; 04F2AF6A1104AC4500D6DDF7 /* SDL_assert.h in Headers */ = {isa = PBXBuildFile; fileRef = 04F2AF681104AC4500D6DDF7 /* SDL_assert.h */; }; + 04FB7D4C12E2350700A522C6 /* SDL_atomic.c in Sources */ = {isa = PBXBuildFile; fileRef = 04FB7D4A12E2350700A522C6 /* SDL_atomic.c */; }; + 04FB7D4D12E2350700A522C6 /* SDL_spinlock.c in Sources */ = {isa = PBXBuildFile; fileRef = 04FB7D4B12E2350700A522C6 /* SDL_spinlock.c */; }; + 04FB7D4E12E2350700A522C6 /* SDL_atomic.c in Sources */ = {isa = PBXBuildFile; fileRef = 04FB7D4A12E2350700A522C6 /* SDL_atomic.c */; }; + 04FB7D4F12E2350700A522C6 /* SDL_spinlock.c in Sources */ = {isa = PBXBuildFile; fileRef = 04FB7D4B12E2350700A522C6 /* SDL_spinlock.c */; }; 4537737D1207C4CE002F0F45 /* SDL_shape_internals.h in Headers */ = {isa = PBXBuildFile; fileRef = 4537737B1207C4CE002F0F45 /* SDL_shape_internals.h */; }; 4537737E1207C4CE002F0F45 /* SDL_shape.c in Sources */ = {isa = PBXBuildFile; fileRef = 4537737C1207C4CE002F0F45 /* SDL_shape.c */; }; 453773821207C518002F0F45 /* SDL_shape.h in Headers */ = {isa = PBXBuildFile; fileRef = 453773811207C518002F0F45 /* SDL_shape.h */; }; @@ -656,7 +658,6 @@ 00CFA67F106B44CE00758660 /* SDL_rect.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_rect.h; path = ../../include/SDL_rect.h; sourceTree = SOURCE_ROOT; }; 00CFA680106B44CE00758660 /* SDL_scancode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_scancode.h; path = ../../include/SDL_scancode.h; sourceTree = SOURCE_ROOT; }; 00CFA681106B44CE00758660 /* SDL_surface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_surface.h; path = ../../include/SDL_surface.h; sourceTree = SOURCE_ROOT; }; - 00CFA6A1106B467B00758660 /* SDL_atomic.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_atomic.c; sourceTree = ""; }; 00CFA6B0106B46E500758660 /* SDL_audio_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_audio_c.h; sourceTree = ""; }; 00CFA6B1106B46E500758660 /* SDL_audiodev_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_audiodev_c.h; sourceTree = ""; }; 00CFA6B2106B46E500758660 /* SDL_audiomem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_audiomem.h; sourceTree = ""; }; @@ -861,6 +862,8 @@ 04DEA57811E600A600386CAC /* SDL_cocoaclipboard.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDL_cocoaclipboard.m; sourceTree = ""; }; 04F2AF651104AC0800D6DDF7 /* SDL_assert.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = SDL_assert.c; path = ../../src/SDL_assert.c; sourceTree = SOURCE_ROOT; }; 04F2AF681104AC4500D6DDF7 /* SDL_assert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_assert.h; path = ../../include/SDL_assert.h; sourceTree = SOURCE_ROOT; }; + 04FB7D4A12E2350700A522C6 /* SDL_atomic.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_atomic.c; sourceTree = ""; }; + 04FB7D4B12E2350700A522C6 /* SDL_spinlock.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_spinlock.c; sourceTree = ""; }; 083E489D006D88D97F000001 /* SDL_joystick.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = SDL_joystick.c; sourceTree = ""; }; 0C5AF5E501191D2B7F000001 /* begin_code.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = begin_code.h; path = ../../include/begin_code.h; sourceTree = SOURCE_ROOT; }; 0C5AF5E601191D2B7F000001 /* close_code.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = close_code.h; path = ../../include/close_code.h; sourceTree = SOURCE_ROOT; }; @@ -1073,20 +1076,13 @@ 00CFA69B106B467B00758660 /* atomic */ = { isa = PBXGroup; children = ( - 00CFA6A0106B467B00758660 /* macosx */, + 04FB7D4A12E2350700A522C6 /* SDL_atomic.c */, + 04FB7D4B12E2350700A522C6 /* SDL_spinlock.c */, ); name = atomic; path = ../../src/atomic; sourceTree = SOURCE_ROOT; }; - 00CFA6A0106B467B00758660 /* macosx */ = { - isa = PBXGroup; - children = ( - 00CFA6A1106B467B00758660 /* SDL_atomic.c */, - ); - path = macosx; - sourceTree = ""; - }; 00CFA6DF106B48D800758660 /* haptic */ = { isa = PBXGroup; children = ( @@ -2273,7 +2269,6 @@ 002F32E509CA0BF600EBEB88 /* SDL_dummyaudio.c in Sources */, 046B91EC0A11B53500FB151C /* SDL_sysloadso.c in Sources */, 046B92130A11B8AD00FB151C /* SDL_dlcompat.c in Sources */, - 00CFA6A8106B467B00758660 /* SDL_atomic.c in Sources */, 00CFA6B9106B46E500758660 /* SDL_audiotypecvt.c in Sources */, 00CFA6CD106B480800758660 /* SDL_windowevents.c in Sources */, 00CFA6EC106B48D800758660 /* SDL_syshaptic.c in Sources */, @@ -2357,6 +2352,8 @@ 4537738A1207C5A2002F0F45 /* SDL_cocoashape.m in Sources */, 453773921207C6E9002F0F45 /* SDL_x11shape.c in Sources */, 046B9B6812D02EE600159CFE /* SDL_x11touch.c in Sources */, + 04FB7D4C12E2350700A522C6 /* SDL_atomic.c in Sources */, + 04FB7D4D12E2350700A522C6 /* SDL_spinlock.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2399,7 +2396,6 @@ 002F32E709CA0BF600EBEB88 /* SDL_dummyaudio.c in Sources */, 046B91ED0A11B53500FB151C /* SDL_sysloadso.c in Sources */, 046B92140A11B8AD00FB151C /* SDL_dlcompat.c in Sources */, - 00CFA6AD106B467B00758660 /* SDL_atomic.c in Sources */, 00CFA6BF106B46E500758660 /* SDL_audiotypecvt.c in Sources */, 00CFA6D3106B480800758660 /* SDL_windowevents.c in Sources */, 00CFA6F3106B48D800758660 /* SDL_syshaptic.c in Sources */, @@ -2477,6 +2473,8 @@ 04DEA57C11E600A600386CAC /* SDL_cocoaclipboard.m in Sources */, 0420496411E6EFD3007E7EC9 /* SDL_clipboardevents.c in Sources */, 046B9B6A12D02EE600159CFE /* SDL_x11touch.c in Sources */, + 04FB7D4E12E2350700A522C6 /* SDL_atomic.c in Sources */, + 04FB7D4F12E2350700A522C6 /* SDL_spinlock.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/configure.in b/configure.in index af9165771..4c1ebae16 100644 --- a/configure.in +++ b/configure.in @@ -288,6 +288,7 @@ fi # Standard C sources SOURCES="$SOURCES $srcdir/src/*.c" SOURCES="$SOURCES $srcdir/src/audio/*.c" +SOURCES="$SOURCES $srcdir/src/atomic/*.c" SOURCES="$SOURCES $srcdir/src/cpuinfo/*.c" SOURCES="$SOURCES $srcdir/src/events/*.c" SOURCES="$SOURCES $srcdir/src/file/*.c" @@ -2303,16 +2304,6 @@ case "$host" in ;; esac fi - # Set up files for the atomic operations library - if test x$enable_atomic = xyes; then - case $ARCH in - linux) - AC_DEFINE(SDL_ATOMIC_LINUX) - SOURCES="$SOURCES $srcdir/src/atomic/linux/*.c" - have_atomic=yes - ;; - esac - fi # Set up files for the joystick library if test x$enable_joystick = xyes; then case $ARCH in @@ -2395,12 +2386,6 @@ case "$host" in SOURCES="$SOURCES $srcdir/src/timer/unix/*.c" have_timers=yes fi - # Setup files for the atomic operations - if test x$enable_atomic = xyes; then - AC_DEFINE(SDL_ATOMIC_QNX) - SOURCES="$SOURCES $srcdir/src/atomic/qnx/*.c" - have_atomic=yes - fi # Set up dummy files for the joystick for now if test x$enable_joystick = xyes; then AC_DEFINE(SDL_JOYSTICK_DUMMY) @@ -2460,12 +2445,6 @@ AC_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[defau fi have_audio=yes fi - # Set up files for the atomic operations library - if test x$enable_atomic = xyes; then - AC_DEFINE(SDL_ATOMIC_WIN32) - SOURCES="$SOURCES $srcdir/src/atomic/win32/*.c" - have_atomic=yes - fi # Set up dummy files for the joystick for now if test x$enable_joystick = xyes; then AC_DEFINE(SDL_JOYSTICK_DUMMY) @@ -2555,12 +2534,6 @@ AC_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[defau fi have_audio=yes fi - # Set up files for the atomic operations library - if test x$enable_atomic = xyes; then - AC_DEFINE(SDL_ATOMIC_WIN32) - SOURCES="$SOURCES $srcdir/src/atomic/win32/*.c" - have_atomic=yes - fi # Set up files for the joystick library if test x$enable_joystick = xyes; then if test x$have_dinput = xyes; then @@ -2715,12 +2688,6 @@ AC_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[defau SOURCES="$SOURCES $srcdir/src/audio/macosx/*.c" have_audio=yes fi - # Set up files for the atomic operations library - if test x$enable_atomic = xyes; then - AC_DEFINE(SDL_ATOMIC_MACOSX) - SOURCES="$SOURCES $srcdir/src/atomic/macosx/*.c" - have_atomic=yes - fi # Set up files for the joystick library if test x$enable_joystick = xyes; then AC_DEFINE(SDL_JOYSTICK_IOKIT) @@ -2826,12 +2793,6 @@ if test x$have_loadso != xyes; then fi SOURCES="$SOURCES $srcdir/src/loadso/dummy/*.c" fi -if test x$have_atomic != xyes; then - if test x$enable_atomic = xyes; then - AC_DEFINE(SDL_ATOMIC_DISABLED) - fi - SOURCES="$SOURCES $srcdir/src/atomic/dummy/*.c" -fi if test x$SDLMAIN_SOURCES = x; then SDLMAIN_SOURCES="$srcdir/src/main/dummy/*.c" fi diff --git a/include/SDL_atomic.h b/include/SDL_atomic.h index e3711433f..df80c3c68 100644 --- a/include/SDL_atomic.h +++ b/include/SDL_atomic.h @@ -18,24 +18,34 @@ Sam Lantinga slouken@libsdl.org - - Contributed by Bob Pendleton, bob@pendleton.com */ /** - * \file SDL_atomic.h - * - * Atomic operations. - * - * These operations may, or may not, actually be implemented using - * processor specific atomic operations. When possible they are - * implemented as true processor specific atomic operations. When that - * is not possible the are implemented using locks that *do* use the - * available atomic operations. - * - * At the very minimum spin locks must be implemented. Without spin - * locks it is not possible (AFAICT) to emulate the rest of the atomic - * operations. + * \file SDL_atomic.h + * + * Atomic operations. + * + * IMPORTANT: + * If you are not an expert in concurrent lockless programming, you should + * only be using the atomic lock and reference counting functions in this + * file. In all other cases you should be protecting your data structures + * with full mutexes. + * + * The list of "safe" functions to use are: + * SDL_AtomicLock() + * SDL_AtomicUnlock() + * SDL_AtomicIncRef() + * SDL_AtomicDecRef() + * + * Seriously, here be dragons! + * + * These operations may, or may not, actually be implemented using + * processor specific atomic operations. When possible they are + * implemented as true processor specific atomic operations. When that + * is not possible the are implemented using locks that *do* use the + * available atomic operations. + * + * All of the atomic operations that modify memory are full memory barriers. */ #ifndef _SDL_atomic_h_ @@ -53,154 +63,138 @@ extern "C" { /* *INDENT-ON* */ #endif -/* Function prototypes */ - /** - * \name SDL AtomicLock - * - * The spin lock functions and type are required and can not be - * emulated because they are used in the emulation code. + * \name SDL AtomicLock + * + * The atomic locks are efficient spinlocks using CPU instructions, + * but are vulnerable to starvation and can spin forever if a thread + * holding a lock has been terminated. For this reason you should + * minimize the code executed inside an atomic lock and never do + * expensive things like API or system calls while holding them. + * + * The atomic locks are not safe to lock recursively. + * + * Porting Note: + * The spin lock functions and type are required and can not be + * emulated because they are used in the atomic emulation code. */ /*@{*/ -typedef volatile Uint32 SDL_SpinLock; +typedef int SDL_SpinLock; + +/** + * \brief Try to lock a spin lock by setting it to a non-zero value. + * + * \param lock Points to the lock. + * + * \return SDL_TRUE if the lock succeeded, SDL_FALSE if the lock is already held. + */ +extern DECLSPEC SDL_bool SDLCALL SDL_AtomicTryLock(SDL_SpinLock *lock); /** - * \brief Lock a spin lock by setting it to a none zero value. - * - * \param lock Points to the lock. + * \brief Lock a spin lock by setting it to a non-zero value. + * + * \param lock Points to the lock. */ extern DECLSPEC void SDLCALL SDL_AtomicLock(SDL_SpinLock *lock); /** - * \brief Unlock a spin lock by setting it to 0. Always returns immediately + * \brief Unlock a spin lock by setting it to 0. Always returns immediately * - * \param lock Points to the lock. + * \param lock Points to the lock. */ extern DECLSPEC void SDLCALL SDL_AtomicUnlock(SDL_SpinLock *lock); /*@}*//*SDL AtomicLock*/ -/** - * \name 32 bit atomic operations - */ -/*@{*/ +/* Platform specific optimized versions of the atomic functions */ +/* None yet... */ /** - * \brief Check to see if \c *ptr == 0 and set it to 1. - * - * \return SDL_True if the value pointed to by \c ptr was zero and - * SDL_False if it was not zero - * - * \param ptr Points to the value to be tested and set. + * \brief A type representing an atomic integer value. It is a struct + * so people don't accidentally use numeric operations on it. */ -extern DECLSPEC SDL_bool SDLCALL SDL_AtomicTestThenSet32(volatile Uint32 * ptr); - -/** - * \brief Set the value pointed to by \c ptr to be zero. - * - * \param ptr Address of the value to be set to zero - */ -extern DECLSPEC void SDLCALL SDL_AtomicClear32(volatile Uint32 * ptr); +#ifndef SDL_atomic_t_defined +typedef struct { int value; } SDL_atomic_t; +#endif /** - * \brief Fetch the current value of \c *ptr and then increment that - * value in place. - * - * \return The value before it was incremented. - * - * \param ptr Address of the value to fetch and increment + * \brief Set an atomic variable to a value. + * + * \return The previous value of the atomic variable. */ -extern DECLSPEC Uint32 SDLCALL SDL_AtomicFetchThenIncrement32(volatile Uint32 * ptr); +#ifndef SDL_AtomicSet +extern DECLSPEC int SDLCALL SDL_AtomicSet(SDL_atomic_t *a, int value); +#endif /** - * \brief Fetch \c *ptr and then decrement the value in place. - * - * \return The value before it was decremented. - * - * \param ptr Address of the value to fetch and decrement + * \brief Get the value of an atomic variable */ -extern DECLSPEC Uint32 SDLCALL SDL_AtomicFetchThenDecrement32(volatile Uint32 * ptr); +#ifndef SDL_AtomicGet +extern DECLSPEC int SDLCALL SDL_AtomicGet(SDL_atomic_t *a); +#endif /** - * \brief Fetch the current value at \c ptr and then add \c value to \c *ptr. - * - * \return \c *ptr before the addition took place. - * - * \param ptr The address of data we are changing. - * \param value The value to add to \c *ptr. + * \brief Add to an atomic variable. + * + * \return The previous value of the atomic variable. */ -extern DECLSPEC Uint32 SDLCALL SDL_AtomicFetchThenAdd32(volatile Uint32 * ptr, Uint32 value); +#ifndef SDL_AtomicAdd +extern DECLSPEC int SDLCALL SDL_AtomicAdd(SDL_atomic_t *a, int value); +#endif /** - * \brief Fetch \c *ptr and then subtract \c value from it. - * - * \return \c *ptr before the subtraction took place. - * - * \param ptr The address of the data being changed. - * \param value The value to subtract from \c *ptr. + * \brief Increment an atomic variable used as a reference count. */ -extern DECLSPEC Uint32 SDLCALL SDL_AtomicFetchThenSubtract32(volatile Uint32 * ptr, Uint32 value); +#ifndef SDL_AtomicIncRef +extern DECLSPEC void SDLCALL SDL_AtomicIncRef(SDL_atomic_t *a); +#endif /** - * \brief Add one to the data pointed to by \c ptr and return that value. - * - * \return The incremented value. - * - * \param ptr The address of the data to increment. + * \brief Decrement an atomic variable used as a reference count. + * + * \return SDL_TRUE if the variable has reached zero after decrementing, + * SDL_FALSE otherwise */ -extern DECLSPEC Uint32 SDLCALL SDL_AtomicIncrementThenFetch32(volatile Uint32 * ptr); +#ifndef SDL_AtomicDecRef +extern DECLSPEC SDL_bool SDLCALL SDL_AtomicDecRef(SDL_atomic_t *a); +#endif /** - * \brief Subtract one from data pointed to by \c ptr and return the new value. - * - * \return The decremented value. - * - * \param ptr The address of the data to decrement. - */ -extern DECLSPEC Uint32 SDLCALL SDL_AtomicDecrementThenFetch32(volatile Uint32 * ptr); + * \brief Set an atomic variable to a new value if it is currently an old value. + * + * \return The previous value of the atomic variable + * + * \note If you don't know what this function is for, you shouldn't use it! +*/ +#ifndef SDL_AtomicCAS +extern DECLSPEC int SDLCALL SDL_AtomicCAS(SDL_atomic_t *a, int oldval, int newval); +#endif /** - * \brief Add \c value to the data pointed to by \c ptr and return result. - * - * \return The sum of \c *ptr and \c value. - * - * \param ptr The address of the data to be modified. - * \param value The value to be added. + * \brief Set a pointer to a value atomically. */ -extern DECLSPEC Uint32 SDLCALL SDL_AtomicAddThenFetch32(volatile Uint32 * ptr, Uint32 value); +#ifndef SDL_AtomicSetPtr +extern DECLSPEC void SDLCALL SDL_AtomicSetPtr(void** a, void* value); +#endif /** - * \brief Subtract \c value from the data pointed to by \c ptr and return the result. - * - * \return The difference between \c *ptr and \c value. - * - * \param ptr The address of the data to be modified. - * \param value The value to be subtracted. + * \brief Get the value of a pointer atomically. */ -extern DECLSPEC Uint32 SDLCALL SDL_AtomicSubtractThenFetch32(volatile Uint32 * ptr, Uint32 value); - -/*@}*//*32 bit atomic operations*/ +#ifndef SDL_AtomicGetPtr +extern DECLSPEC void* SDLCALL SDL_AtomicGetPtr(void** a); +#endif /** - * \name 64 bit atomic operations - */ -/*@{*/ -#ifdef SDL_HAS_64BIT_TYPE - -extern DECLSPEC SDL_bool SDLCALL SDL_AtomicTestThenSet64(volatile Uint64 * ptr); -extern DECLSPEC void SDLCALL SDL_AtomicClear64(volatile Uint64 * ptr); -extern DECLSPEC Uint64 SDLCALL SDL_AtomicFetchThenIncrement64(volatile Uint64 * ptr); -extern DECLSPEC Uint64 SDLCALL SDL_AtomicFetchThenDecrement64(volatile Uint64 * ptr); -extern DECLSPEC Uint64 SDLCALL SDL_AtomicFetchThenAdd64(volatile Uint64 * ptr, Uint64 value); -extern DECLSPEC Uint64 SDLCALL SDL_AtomicFetchThenSubtract64(volatile Uint64 * ptr, Uint64 value); -extern DECLSPEC Uint64 SDLCALL SDL_AtomicIncrementThenFetch64(volatile Uint64 * ptr); -extern DECLSPEC Uint64 SDLCALL SDL_AtomicDecrementThenFetch64(volatile Uint64 * ptr); -extern DECLSPEC Uint64 SDLCALL SDL_AtomicAddThenFetch64(volatile Uint64 * ptr, Uint64 value); -extern DECLSPEC Uint64 SDLCALL SDL_AtomicSubtractThenFetch64(volatile Uint64 * ptr, Uint64 value); -#endif /* SDL_HAS_64BIT_TYPE */ - -/*@}*//*64 bit atomic operations*/ + * \brief Set a pointer to a new value if it is currently an old value. + * + * \return The previous value of the pointer + * + * \note If you don't know what this function is for, you shouldn't use it! +*/ +#ifndef SDL_AtomicCASPtr +extern DECLSPEC void* SDLCALL SDL_AtomicCASPtr(void **a, void *oldval, void *newval); +#endif /* Ends C function definitions when using C++ */ #ifdef __cplusplus diff --git a/src/atomic/SDL_atomic.c b/src/atomic/SDL_atomic.c new file mode 100644 index 000000000..320c1dd71 --- /dev/null +++ b/src/atomic/SDL_atomic.c @@ -0,0 +1,179 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2010 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 +*/ +#include "SDL_stdinc.h" + +#include "SDL_atomic.h" + +/* + If any of the operations are not provided then we must emulate some + of them. That means we need a nice implementation of spin locks + that avoids the "one big lock" problem. We use a vector of spin + locks and pick which one to use based on the address of the operand + of the function. + + To generate the index of the lock we first shift by 3 bits to get + rid on the zero bits that result from 32 and 64 bit allignment of + data. We then mask off all but 5 bits and use those 5 bits as an + index into the table. + + Picking the lock this way insures that accesses to the same data at + the same time will go to the same lock. OTOH, accesses to different + data have only a 1/32 chance of hitting the same lock. That should + pretty much eliminate the chances of several atomic operations on + different data from waiting on the same "big lock". If it isn't + then the table of locks can be expanded to a new size so long as + the new size is a power of two. + + Contributed by Bob Pendleton, bob@pendleton.com +*/ + +static SDL_SpinLock locks[32]; + +static __inline__ void +enterLock(void *a) +{ + uintptr_t index = ((((uintptr_t)a) >> 3) & 0x1f); + + SDL_AtomicLock(&locks[index]); +} + +static __inline__ void +leaveLock(void *a) +{ + uintptr_t index = ((((uintptr_t)a) >> 3) & 0x1f); + + SDL_AtomicUnlock(&locks[index]); +} + +#ifndef SDL_AtomicSet +int +SDL_AtomicSet(SDL_atomic_t *a, int value) +{ + int oldvalue; + + enterLock(a); + oldvalue = a->value; + a->value = value; + leaveLock(a); + + return oldvalue; +} +#endif + +#ifndef SDL_AtomicGet +int +SDL_AtomicGet(SDL_atomic_t *a) +{ + /* Assuming integral reads on this platform, we're safe here since the + functions that set the variable have the necessary memory barriers. + */ + return a->value; +} +#endif + +#ifndef SDL_AtomicAdd +int +SDL_AtomicAdd(SDL_atomic_t *a, int value) +{ + int oldvalue; + + enterLock(a); + oldvalue = a->value; + a->value += value; + leaveLock(a); + + return oldvalue; +} +#endif + +#ifndef SDL_AtomicIncRef +void +SDL_AtomicIncRef(SDL_atomic_t *a) +{ + SDL_AtomicAdd(a, 1); +} +#endif + +#ifndef SDL_AtomicDecRef +SDL_bool +SDL_AtomicDecRef(SDL_atomic_t *a) +{ + return SDL_AtomicAdd(a, -1) == 1; +} +#endif + +#ifndef SDL_AtomicCAS +int +SDL_AtomicCAS(SDL_atomic_t *a, int oldval, int newval) +{ + int prevval; + + enterLock(a); + prevval = a->value; + if (prevval == oldval) { + a->value = newval; + } + leaveLock(a); + + return prevval; +} +#endif + +#ifndef SDL_AtomicSetPtr +void +SDL_AtomicSetPtr(void** a, void* value) +{ + void *prevval; + do { + prevval = *a; + } while (SDL_AtomicCASPtr(a, prevval, value) != prevval); +} +#endif + +#ifndef SDL_AtomicGetPtr +void* +SDL_AtomicGetPtr(void** a) +{ + /* Assuming integral reads on this platform, we're safe here since the + functions that set the pointer have the necessary memory barriers. + */ + return *a; +} +#endif + +#ifndef SDL_AtomicCASPtr +void* SDL_AtomicCASPtr(void **a, void *oldval, void *newval) +{ + void *prevval; + + enterLock(a); + prevval = *a; + if (*a == oldval) { + *a = newval; + } + leaveLock(a); + + return prevval; +} +#endif + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/atomic/SDL_spinlock.c b/src/atomic/SDL_spinlock.c new file mode 100644 index 000000000..d0631f835 --- /dev/null +++ b/src/atomic/SDL_spinlock.c @@ -0,0 +1,99 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2010 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 +*/ +#include "SDL_stdinc.h" + +#include "SDL_atomic.h" +#include "SDL_timer.h" + +#if defined(__WIN32__) +#define WIN32_LEAN_AND_MEAN +#include + +#elif defined(__MACOSX__) +#include + +#endif + + +/* This function is where all the magic happens... */ +SDL_bool +SDL_AtomicTryLock(SDL_SpinLock *lock) +{ +#if defined(__WIN32__) + return (InterlockedExchange(lock, 1) == 0); + +#elif defined(__MACOSX__) + return OSAtomicCompareAndSwap32Barrier(0, 1, lock); + +#elif defined(__GNUC__) +#if defined(__arm__) +#ifdef __ARM_ARCH_5__ + int result; + __asm__ __volatile__ ( + "swp %0, %1, [%2]\n" + : "=&r,&r" (result) : "r,0" (1), "r,r" (lock) : "memory"); + return (result == 0); +#else + int result; + __asm__ __volatile__ ( + "ldrex %0, [%2]\nteq %0, #0\nstrexeq %0, %1, [%2]" + : "=&r" (result) : "r" (1), "r" (lock) : "cc", "memory"); + return (result == 0); +#endif +#else + return (__sync_lock_test_and_set(lock, 1) == 0); +#endif + +#else + /* Need CPU instructions for spinlock here! */ + __need_spinlock_implementation__ +#endif +} + +void +SDL_AtomicLock(SDL_SpinLock *lock) +{ + /* FIXME: Should we have an eventual timeout? */ + while (!SDL_AtomicTryLock(lock)) { + SDL_Delay(0); + } +} + +void +SDL_AtomicUnlock(SDL_SpinLock *lock) +{ +#if defined(__WIN32__) + *lock = 0; + +#elif defined(__MACOSX__) + *lock = 0; + +#elif defined(__GNUC__) && !defined(__arm__) + __sync_lock_release(lock); + +#else + /* Assuming memory barrier in lock and integral assignment operation */ + *lock = 0; +#endif +} + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/atomic/dummy/SDL_atomic.c b/src/atomic/dummy/SDL_atomic.c deleted file mode 100644 index c4ee7701b..000000000 --- a/src/atomic/dummy/SDL_atomic.c +++ /dev/null @@ -1,469 +0,0 @@ -/* - SDL - Simple DirectMedia Layer - Copyright (C) 1997-2010 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 - - Contributed by Bob Pendleton, bob@pendleton.com -*/ - -#include "SDL_stdinc.h" -#include "SDL_atomic.h" - -#include "SDL_error.h" - -/* - This file provides 32, and 64 bit atomic operations. If the - operations are provided by the native hardware and operating system - they are used. If they are not then the operations are emulated - using the SDL spin lock operations. If spin lock can not be - implemented then these functions must fail. -*/ - -/* - DUMMY VERSION. - - This version of the code assumes there is no support for atomic - operations. Therefore, every function sets the SDL error - message. Oddly enough, if you only have one thread then this - version actuallys works. -*/ - -/* - Native spinlock routines. Because this is the dummy implementation - these will always call SDL_SetError() and do nothing. -*/ - -void -SDL_AtomicLock(SDL_SpinLock *lock) -{ - SDL_SetError("SDL_atomic.c: is not implemented on this platform"); -} - -void -SDL_AtomicUnlock(SDL_SpinLock *lock) -{ - SDL_SetError("SDL_atomic.c: is not implemented on this platform"); -} - -/* - Note that platform specific versions can be built from this version - by changing the #undefs to #defines and adding platform specific - code. -*/ - -#undef nativeTestThenSet32 -#undef nativeClear32 -#undef nativeFetchThenIncrement32 -#undef nativeFetchThenDecrement32 -#undef nativeFetchThenAdd32 -#undef nativeFetchThenSubtract32 -#undef nativeIncrementThenFetch32 -#undef nativeDecrementThenFetch32 -#undef nativeAddThenFetch32 -#undef nativeSubtractThenFetch32 - -#undef nativeTestThenSet64 -#undef nativeClear64 -#undef nativeFetchThenIncrement64 -#undef nativeFetchThenDecrement64 -#undef nativeFetchThenAdd64 -#undef nativeFetchThenSubtract64 -#undef nativeIncrementThenFetch64 -#undef nativeDecrementThenFetch64 -#undef nativeAddThenFetch64 -#undef nativeSubtractThenFetch64 - -/* - If any of the operations are not provided then we must emulate some - of them. That means we need a nice implementation of spin locks - that avoids the "one big lock" problem. We use a vector of spin - locks and pick which one to use based on the address of the operand - of the function. - - To generate the index of the lock we first shift by 3 bits to get - rid on the zero bits that result from 32 and 64 bit allignment of - data. We then mask off all but 5 bits and use those 5 bits as an - index into the table. - - Picking the lock this way insures that accesses to the same data at - the same time will go to the same lock. OTOH, accesses to different - data have only a 1/32 chance of hitting the same lock. That should - pretty much eliminate the chances of several atomic operations on - different data from waiting on the same "big lock". If it isn't - then the table of locks can be expanded to a new size so long as - the new size is a power of two. -*/ - -static SDL_SpinLock locks[32] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; - -static __inline__ void -privateWaitLock(volatile void *ptr) -{ -#if SIZEOF_VOIDP == 4 - Uint32 index = ((((Uint32)ptr) >> 3) & 0x1f); -#elif SIZEOF_VOIDP == 8 - Uint64 index = ((((Uint64)ptr) >> 3) & 0x1f); -#endif - - SDL_AtomicLock(&locks[index]); -} - -static __inline__ void -privateUnlock(volatile void *ptr) -{ -#if SIZEOF_VOIDP == 4 - Uint32 index = ((((Uint32)ptr) >> 3) & 0x1f); -#elif SIZEOF_VOIDP == 8 - Uint64 index = ((((Uint64)ptr) >> 3) & 0x1f); -#endif - - SDL_AtomicUnlock(&locks[index]); -} - -/* 32 bit atomic operations */ - -SDL_bool -SDL_AtomicTestThenSet32(volatile Uint32 * ptr) -{ -#ifdef nativeTestThenSet32 -#else - SDL_bool result = SDL_FALSE; - - privateWaitLock(ptr); - result = (*ptr == 0); - if (result) - { - *ptr = 1; - } - privateUnlock(ptr); - - return result; -#endif -} - -void -SDL_AtomicClear32(volatile Uint32 * ptr) -{ -#ifdef nativeClear32 -#else - privateWaitLock(ptr); - *ptr = 0; - privateUnlock(ptr); - - return; -#endif -} - -Uint32 -SDL_AtomicFetchThenIncrement32(volatile Uint32 * ptr) -{ -#ifdef nativeFetchThenIncrement32 -#else - Uint32 tmp = 0; - - privateWaitLock(ptr); - tmp = *ptr; - (*ptr)+= 1; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint32 -SDL_AtomicFetchThenDecrement32(volatile Uint32 * ptr) -{ -#ifdef nativeFetchThenDecrement32 -#else - Uint32 tmp = 0; - - privateWaitLock(ptr); - tmp = *ptr; - (*ptr) -= 1; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint32 -SDL_AtomicFetchThenAdd32(volatile Uint32 * ptr, Uint32 value) -{ -#ifdef nativeFetchThenAdd32 -#else - Uint32 tmp = 0; - - privateWaitLock(ptr); - tmp = *ptr; - (*ptr)+= value; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint32 -SDL_AtomicFetchThenSubtract32(volatile Uint32 * ptr, Uint32 value) -{ -#ifdef nativeFetchThenSubtract32 -#else - Uint32 tmp = 0; - - privateWaitLock(ptr); - tmp = *ptr; - (*ptr)-= value; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint32 -SDL_AtomicIncrementThenFetch32(volatile Uint32 * ptr) -{ -#ifdef nativeIncrementThenFetch32 -#else - Uint32 tmp = 0; - - privateWaitLock(ptr); - (*ptr)+= 1; - tmp = *ptr; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint32 -SDL_AtomicDecrementThenFetch32(volatile Uint32 * ptr) -{ -#ifdef nativeDecrementThenFetch32 -#else - Uint32 tmp = 0; - - privateWaitLock(ptr); - (*ptr)-= 1; - tmp = *ptr; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint32 -SDL_AtomicAddThenFetch32(volatile Uint32 * ptr, Uint32 value) -{ -#ifdef nativeAddThenFetch32 -#else - Uint32 tmp = 0; - - privateWaitLock(ptr); - (*ptr)+= value; - tmp = *ptr; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint32 -SDL_AtomicSubtractThenFetch32(volatile Uint32 * ptr, Uint32 value) -{ -#ifdef nativeSubtractThenFetch32 -#else - Uint32 tmp = 0; - - privateWaitLock(ptr); - (*ptr)-= value; - tmp = *ptr; - privateUnlock(ptr); - - return tmp; -#endif -} - -/* 64 bit atomic operations */ -#ifdef SDL_HAS_64BIT_TYPE - -SDL_bool -SDL_AtomicTestThenSet64(volatile Uint64 * ptr) -{ -#ifdef nativeTestThenSet64 -#else - SDL_bool result = SDL_FALSE; - - privateWaitLock(ptr); - result = (*ptr == 0); - if (result) - { - *ptr = 1; - } - privateUnlock(ptr); - - return result; -#endif -} - -void -SDL_AtomicClear64(volatile Uint64 * ptr) -{ -#ifdef nativeClear64 -#else - privateWaitLock(ptr); - *ptr = 0; - privateUnlock(ptr); - - return; -#endif -} - -Uint64 -SDL_AtomicFetchThenIncrement64(volatile Uint64 * ptr) -{ -#ifdef nativeFetchThenIncrement64 -#else - Uint64 tmp = 0; - - privateWaitLock(ptr); - tmp = *ptr; - (*ptr)+= 1; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint64 -SDL_AtomicFetchThenDecrement64(volatile Uint64 * ptr) -{ -#ifdef nativeFetchThenDecrement64 -#else - Uint64 tmp = 0; - - privateWaitLock(ptr); - tmp = *ptr; - (*ptr) -= 1; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint64 -SDL_AtomicFetchThenAdd64(volatile Uint64 * ptr, Uint64 value) -{ -#ifdef nativeFetchThenAdd64 -#else - Uint64 tmp = 0; - - privateWaitLock(ptr); - tmp = *ptr; - (*ptr)+= value; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint64 -SDL_AtomicFetchThenSubtract64(volatile Uint64 * ptr, Uint64 value) -{ -#ifdef nativeFetchThenSubtract64 -#else - Uint64 tmp = 0; - - privateWaitLock(ptr); - tmp = *ptr; - (*ptr)-= value; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint64 -SDL_AtomicIncrementThenFetch64(volatile Uint64 * ptr) -{ -#ifdef nativeIncrementThenFetch64 -#else - Uint64 tmp = 0; - - privateWaitLock(ptr); - (*ptr)+= 1; - tmp = *ptr; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint64 -SDL_AtomicDecrementThenFetch64(volatile Uint64 * ptr) -{ -#ifdef nativeDecrementThenFetch64 -#else - Uint64 tmp = 0; - - privateWaitLock(ptr); - (*ptr)-= 1; - tmp = *ptr; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint64 -SDL_AtomicAddThenFetch64(volatile Uint64 * ptr, Uint64 value) -{ -#ifdef nativeAddThenFetch64 -#else - Uint64 tmp = 0; - - privateWaitLock(ptr); - (*ptr)+= value; - tmp = *ptr; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint64 -SDL_AtomicSubtractThenFetch64(volatile Uint64 * ptr, Uint64 value) -{ -#ifdef nativeSubtractThenFetch64 -#else - Uint64 tmp = 0; - - privateWaitLock(ptr); - (*ptr)-= value; - tmp = *ptr; - privateUnlock(ptr); - - return tmp; -#endif -} -#endif - diff --git a/src/atomic/linux/SDL_atomic.c b/src/atomic/linux/SDL_atomic.c deleted file mode 100644 index 7b74a962d..000000000 --- a/src/atomic/linux/SDL_atomic.c +++ /dev/null @@ -1,510 +0,0 @@ -/* - SDL - Simple DirectMedia Layer - Copyright (C) 1997-2010 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 - - Contributed by Bob Pendleton, bob@pendleton.com -*/ - -#include "SDL_stdinc.h" -#include "SDL_atomic.h" - -#include "SDL_error.h" - -/* - This file provides 32, and 64 bit atomic operations. If the - operations are provided by the native hardware and operating system - they are used. If they are not then the operations are emulated - using the SDL spin lock operations. If spin lock can not be - implemented then these functions must fail. -*/ - -/* - LINUX/GCC VERSION. - - This version of the code assumes support of the atomic builtins as - documented at gcc.gnu.org/onlinedocs/gcc/Atomic-Builtins.html This - code should work on any modern x86 or other processor supported by - GCC. - - Some processors will only support some of these operations so - #ifdefs will have to be added as incompatibilities are discovered -*/ - -/* - Native spinlock routines. -*/ - -void -SDL_AtomicLock(SDL_SpinLock *lock) -{ - while (0 != __sync_lock_test_and_set(lock, 1)) - { - } -} - -void -SDL_AtomicUnlock(SDL_SpinLock *lock) -{ - __sync_lock_test_and_set(lock, 0); -} - -/* - Note that platform specific versions can be built from this version - by changing the #undefs to #defines and adding platform specific - code. -*/ - -#define nativeTestThenSet32 -#define nativeClear32 -#define nativeFetchThenIncrement32 -#define nativeFetchThenDecrement32 -#define nativeFetchThenAdd32 -#define nativeFetchThenSubtract32 -#define nativeIncrementThenFetch32 -#define nativeDecrementThenFetch32 -#define nativeAddThenFetch32 -#define nativeSubtractThenFetch32 - -#ifdef SDL_HAS_64BIT_TYPE - #ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 - #define nativeTestThenSet64 - #define nativeClear64 - #define nativeFetchThenIncrement64 - #define nativeFetchThenDecrement64 - #define nativeFetchThenAdd64 - #define nativeFetchThenSubtract64 - #define nativeIncrementThenFetch64 - #define nativeDecrementThenFetch64 - #define nativeAddThenFetch64 - #define nativeSubtractThenFetch64 - #else - #undef nativeTestThenSet64 - #undef nativeClear64 - #undef nativeFetchThenIncrement64 - #undef nativeFetchThenDecrement64 - #undef nativeFetchThenAdd64 - #undef nativeFetchThenSubtract64 - #undef nativeIncrementThenFetch64 - #undef nativeDecrementThenFetch64 - #undef nativeAddThenFetch64 - #undef nativeSubtractThenFetch64 - #endif /* __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 */ -#endif /* SDL_HAS_64BIT_TYPE */ - -/* - If any of the operations are not provided then we must emulate some - of them. That means we need a nice implementation of spin locks - that avoids the "one big lock" problem. We use a vector of spin - locks and pick which one to use based on the address of the operand - of the function. - - To generate the index of the lock we first shift by 3 bits to get - rid on the zero bits that result from 32 and 64 bit allignment of - data. We then mask off all but 5 bits and use those 5 bits as an - index into the table. - - Picking the lock this way insures that accesses to the same data at - the same time will go to the same lock. OTOH, accesses to different - data have only a 1/32 chance of hitting the same lock. That should - pretty much eliminate the chances of several atomic operations on - different data from waiting on the same "big lock". If it isn't - then the table of locks can be expanded to a new size so long as - the new size is a power of two. -*/ - -static SDL_SpinLock locks[32] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; - -static __inline__ void -privateWaitLock(volatile void *ptr) -{ -#if SIZEOF_VOIDP == 4 - Uint32 index = ((((Uint32)ptr) >> 3) & 0x1f); -#elif SIZEOF_VOIDP == 8 - Uint64 index = ((((Uint64)ptr) >> 3) & 0x1f); -#endif - - SDL_AtomicLock(&locks[index]); -} - -static __inline__ void -privateUnlock(volatile void *ptr) -{ -#if SIZEOF_VOIDP == 4 - Uint32 index = ((((Uint32)ptr) >> 3) & 0x1f); -#elif SIZEOF_VOIDP == 8 - Uint64 index = ((((Uint64)ptr) >> 3) & 0x1f); -#endif - - SDL_AtomicUnlock(&locks[index]); -} - -/* 32 bit atomic operations */ - -SDL_bool -SDL_AtomicTestThenSet32(volatile Uint32 * ptr) -{ -#ifdef nativeTestThenSet32 - return 0 == __sync_lock_test_and_set(ptr, 1); -#else - SDL_bool result = SDL_FALSE; - - privateWaitLock(ptr); - result = (*ptr == 0); - if (result) - { - *ptr = 1; - } - privateUnlock(ptr); - - return result; -#endif -} - -void -SDL_AtomicClear32(volatile Uint32 * ptr) -{ -#ifdef nativeClear32 - __sync_lock_test_and_set(ptr, 0); - return; -#else - privateWaitLock(ptr); - *ptr = 0; - privateUnlock(ptr); - - return; -#endif -} - -Uint32 -SDL_AtomicFetchThenIncrement32(volatile Uint32 * ptr) -{ -#ifdef nativeFetchThenIncrement32 - return __sync_fetch_and_add(ptr, 1); -#else - Uint32 tmp = 0; - - privateWaitLock(ptr); - tmp = *ptr; - (*ptr)+= 1; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint32 -SDL_AtomicFetchThenDecrement32(volatile Uint32 * ptr) -{ -#ifdef nativeFetchThenDecrement32 - return __sync_fetch_and_sub(ptr, 1); -#else - Uint32 tmp = 0; - - privateWaitLock(ptr); - tmp = *ptr; - (*ptr) -= 1; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint32 -SDL_AtomicFetchThenAdd32(volatile Uint32 * ptr, Uint32 value) -{ -#ifdef nativeFetchThenAdd32 - return __sync_fetch_and_add(ptr, value); -#else - Uint32 tmp = 0; - - privateWaitLock(ptr); - tmp = *ptr; - (*ptr)+= value; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint32 -SDL_AtomicFetchThenSubtract32(volatile Uint32 * ptr, Uint32 value) -{ -#ifdef nativeFetchThenSubtract32 - return __sync_fetch_and_sub(ptr, value); -#else - Uint32 tmp = 0; - - privateWaitLock(ptr); - tmp = *ptr; - (*ptr)-= value; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint32 -SDL_AtomicIncrementThenFetch32(volatile Uint32 * ptr) -{ -#ifdef nativeIncrementThenFetch32 - return __sync_add_and_fetch(ptr, 1); -#else - Uint32 tmp = 0; - - privateWaitLock(ptr); - (*ptr)+= 1; - tmp = *ptr; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint32 -SDL_AtomicDecrementThenFetch32(volatile Uint32 * ptr) -{ -#ifdef nativeDecrementThenFetch32 - return __sync_sub_and_fetch(ptr, 1); -#else - Uint32 tmp = 0; - - privateWaitLock(ptr); - (*ptr)-= 1; - tmp = *ptr; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint32 -SDL_AtomicAddThenFetch32(volatile Uint32 * ptr, Uint32 value) -{ -#ifdef nativeAddThenFetch32 - return __sync_add_and_fetch(ptr, value); -#else - Uint32 tmp = 0; - - privateWaitLock(ptr); - (*ptr)+= value; - tmp = *ptr; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint32 -SDL_AtomicSubtractThenFetch32(volatile Uint32 * ptr, Uint32 value) -{ -#ifdef nativeSubtractThenFetch32 - return __sync_sub_and_fetch(ptr, value); -#else - Uint32 tmp = 0; - - privateWaitLock(ptr); - (*ptr)-= value; - tmp = *ptr; - privateUnlock(ptr); - - return tmp; -#endif -} - -/* 64 bit atomic operations */ -#ifdef SDL_HAS_64BIT_TYPE - -SDL_bool -SDL_AtomicTestThenSet64(volatile Uint64 * ptr) -{ -#ifdef nativeTestThenSet64 - return 0 == __sync_lock_test_and_set(ptr, 1); -#else - SDL_bool result = SDL_FALSE; - - privateWaitLock(ptr); - result = (*ptr == 0); - if (result) - { - *ptr = 1; - } - privateUnlock(ptr); - - return result; -#endif -} - -void -SDL_AtomicClear64(volatile Uint64 * ptr) -{ -#ifdef nativeClear64 - __sync_lock_test_and_set(ptr, 0); - return; -#else - privateWaitLock(ptr); - *ptr = 0; - privateUnlock(ptr); - - return; -#endif -} - -Uint64 -SDL_AtomicFetchThenIncrement64(volatile Uint64 * ptr) -{ -#ifdef nativeFetchThenIncrement64 - return __sync_fetch_and_add(ptr, 1); -#else - Uint64 tmp = 0; - - privateWaitLock(ptr); - tmp = *ptr; - (*ptr)+= 1; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint64 -SDL_AtomicFetchThenDecrement64(volatile Uint64 * ptr) -{ -#ifdef nativeFetchThenDecrement64 - return __sync_fetch_and_sub(ptr, 1); -#else - Uint64 tmp = 0; - - privateWaitLock(ptr); - tmp = *ptr; - (*ptr) -= 1; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint64 -SDL_AtomicFetchThenAdd64(volatile Uint64 * ptr, Uint64 value) -{ -#ifdef nativeFetchThenAdd64 - return __sync_fetch_and_add(ptr, value); -#else - Uint64 tmp = 0; - - privateWaitLock(ptr); - tmp = *ptr; - (*ptr)+= value; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint64 -SDL_AtomicFetchThenSubtract64(volatile Uint64 * ptr, Uint64 value) -{ -#ifdef nativeFetchThenSubtract64 - return __sync_fetch_and_sub(ptr, value); -#else - Uint64 tmp = 0; - - privateWaitLock(ptr); - tmp = *ptr; - (*ptr)-= value; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint64 -SDL_AtomicIncrementThenFetch64(volatile Uint64 * ptr) -{ -#ifdef nativeIncrementThenFetch64 - return __sync_add_and_fetch(ptr, 1); -#else - Uint64 tmp = 0; - - privateWaitLock(ptr); - (*ptr)+= 1; - tmp = *ptr; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint64 -SDL_AtomicDecrementThenFetch64(volatile Uint64 * ptr) -{ -#ifdef nativeDecrementThenFetch64 - return __sync_sub_and_fetch(ptr, 1); -#else - Uint64 tmp = 0; - - privateWaitLock(ptr); - (*ptr)-= 1; - tmp = *ptr; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint64 -SDL_AtomicAddThenFetch64(volatile Uint64 * ptr, Uint64 value) -{ -#ifdef nativeAddThenFetch64 - return __sync_add_and_fetch(ptr, value); -#else - Uint64 tmp = 0; - - privateWaitLock(ptr); - (*ptr)+= value; - tmp = *ptr; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint64 -SDL_AtomicSubtractThenFetch64(volatile Uint64 * ptr, Uint64 value) -{ -#ifdef nativeSubtractThenFetch64 - return __sync_sub_and_fetch(ptr, value); -#else - Uint64 tmp = 0; - - privateWaitLock(ptr); - (*ptr)-= value; - tmp = *ptr; - privateUnlock(ptr); - - return tmp; -#endif -} - -#endif /* SDL_HAS_64BIT_TYPE */ diff --git a/src/atomic/macosx/SDL_atomic.c b/src/atomic/macosx/SDL_atomic.c deleted file mode 100644 index c4ee7701b..000000000 --- a/src/atomic/macosx/SDL_atomic.c +++ /dev/null @@ -1,469 +0,0 @@ -/* - SDL - Simple DirectMedia Layer - Copyright (C) 1997-2010 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 - - Contributed by Bob Pendleton, bob@pendleton.com -*/ - -#include "SDL_stdinc.h" -#include "SDL_atomic.h" - -#include "SDL_error.h" - -/* - This file provides 32, and 64 bit atomic operations. If the - operations are provided by the native hardware and operating system - they are used. If they are not then the operations are emulated - using the SDL spin lock operations. If spin lock can not be - implemented then these functions must fail. -*/ - -/* - DUMMY VERSION. - - This version of the code assumes there is no support for atomic - operations. Therefore, every function sets the SDL error - message. Oddly enough, if you only have one thread then this - version actuallys works. -*/ - -/* - Native spinlock routines. Because this is the dummy implementation - these will always call SDL_SetError() and do nothing. -*/ - -void -SDL_AtomicLock(SDL_SpinLock *lock) -{ - SDL_SetError("SDL_atomic.c: is not implemented on this platform"); -} - -void -SDL_AtomicUnlock(SDL_SpinLock *lock) -{ - SDL_SetError("SDL_atomic.c: is not implemented on this platform"); -} - -/* - Note that platform specific versions can be built from this version - by changing the #undefs to #defines and adding platform specific - code. -*/ - -#undef nativeTestThenSet32 -#undef nativeClear32 -#undef nativeFetchThenIncrement32 -#undef nativeFetchThenDecrement32 -#undef nativeFetchThenAdd32 -#undef nativeFetchThenSubtract32 -#undef nativeIncrementThenFetch32 -#undef nativeDecrementThenFetch32 -#undef nativeAddThenFetch32 -#undef nativeSubtractThenFetch32 - -#undef nativeTestThenSet64 -#undef nativeClear64 -#undef nativeFetchThenIncrement64 -#undef nativeFetchThenDecrement64 -#undef nativeFetchThenAdd64 -#undef nativeFetchThenSubtract64 -#undef nativeIncrementThenFetch64 -#undef nativeDecrementThenFetch64 -#undef nativeAddThenFetch64 -#undef nativeSubtractThenFetch64 - -/* - If any of the operations are not provided then we must emulate some - of them. That means we need a nice implementation of spin locks - that avoids the "one big lock" problem. We use a vector of spin - locks and pick which one to use based on the address of the operand - of the function. - - To generate the index of the lock we first shift by 3 bits to get - rid on the zero bits that result from 32 and 64 bit allignment of - data. We then mask off all but 5 bits and use those 5 bits as an - index into the table. - - Picking the lock this way insures that accesses to the same data at - the same time will go to the same lock. OTOH, accesses to different - data have only a 1/32 chance of hitting the same lock. That should - pretty much eliminate the chances of several atomic operations on - different data from waiting on the same "big lock". If it isn't - then the table of locks can be expanded to a new size so long as - the new size is a power of two. -*/ - -static SDL_SpinLock locks[32] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; - -static __inline__ void -privateWaitLock(volatile void *ptr) -{ -#if SIZEOF_VOIDP == 4 - Uint32 index = ((((Uint32)ptr) >> 3) & 0x1f); -#elif SIZEOF_VOIDP == 8 - Uint64 index = ((((Uint64)ptr) >> 3) & 0x1f); -#endif - - SDL_AtomicLock(&locks[index]); -} - -static __inline__ void -privateUnlock(volatile void *ptr) -{ -#if SIZEOF_VOIDP == 4 - Uint32 index = ((((Uint32)ptr) >> 3) & 0x1f); -#elif SIZEOF_VOIDP == 8 - Uint64 index = ((((Uint64)ptr) >> 3) & 0x1f); -#endif - - SDL_AtomicUnlock(&locks[index]); -} - -/* 32 bit atomic operations */ - -SDL_bool -SDL_AtomicTestThenSet32(volatile Uint32 * ptr) -{ -#ifdef nativeTestThenSet32 -#else - SDL_bool result = SDL_FALSE; - - privateWaitLock(ptr); - result = (*ptr == 0); - if (result) - { - *ptr = 1; - } - privateUnlock(ptr); - - return result; -#endif -} - -void -SDL_AtomicClear32(volatile Uint32 * ptr) -{ -#ifdef nativeClear32 -#else - privateWaitLock(ptr); - *ptr = 0; - privateUnlock(ptr); - - return; -#endif -} - -Uint32 -SDL_AtomicFetchThenIncrement32(volatile Uint32 * ptr) -{ -#ifdef nativeFetchThenIncrement32 -#else - Uint32 tmp = 0; - - privateWaitLock(ptr); - tmp = *ptr; - (*ptr)+= 1; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint32 -SDL_AtomicFetchThenDecrement32(volatile Uint32 * ptr) -{ -#ifdef nativeFetchThenDecrement32 -#else - Uint32 tmp = 0; - - privateWaitLock(ptr); - tmp = *ptr; - (*ptr) -= 1; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint32 -SDL_AtomicFetchThenAdd32(volatile Uint32 * ptr, Uint32 value) -{ -#ifdef nativeFetchThenAdd32 -#else - Uint32 tmp = 0; - - privateWaitLock(ptr); - tmp = *ptr; - (*ptr)+= value; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint32 -SDL_AtomicFetchThenSubtract32(volatile Uint32 * ptr, Uint32 value) -{ -#ifdef nativeFetchThenSubtract32 -#else - Uint32 tmp = 0; - - privateWaitLock(ptr); - tmp = *ptr; - (*ptr)-= value; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint32 -SDL_AtomicIncrementThenFetch32(volatile Uint32 * ptr) -{ -#ifdef nativeIncrementThenFetch32 -#else - Uint32 tmp = 0; - - privateWaitLock(ptr); - (*ptr)+= 1; - tmp = *ptr; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint32 -SDL_AtomicDecrementThenFetch32(volatile Uint32 * ptr) -{ -#ifdef nativeDecrementThenFetch32 -#else - Uint32 tmp = 0; - - privateWaitLock(ptr); - (*ptr)-= 1; - tmp = *ptr; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint32 -SDL_AtomicAddThenFetch32(volatile Uint32 * ptr, Uint32 value) -{ -#ifdef nativeAddThenFetch32 -#else - Uint32 tmp = 0; - - privateWaitLock(ptr); - (*ptr)+= value; - tmp = *ptr; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint32 -SDL_AtomicSubtractThenFetch32(volatile Uint32 * ptr, Uint32 value) -{ -#ifdef nativeSubtractThenFetch32 -#else - Uint32 tmp = 0; - - privateWaitLock(ptr); - (*ptr)-= value; - tmp = *ptr; - privateUnlock(ptr); - - return tmp; -#endif -} - -/* 64 bit atomic operations */ -#ifdef SDL_HAS_64BIT_TYPE - -SDL_bool -SDL_AtomicTestThenSet64(volatile Uint64 * ptr) -{ -#ifdef nativeTestThenSet64 -#else - SDL_bool result = SDL_FALSE; - - privateWaitLock(ptr); - result = (*ptr == 0); - if (result) - { - *ptr = 1; - } - privateUnlock(ptr); - - return result; -#endif -} - -void -SDL_AtomicClear64(volatile Uint64 * ptr) -{ -#ifdef nativeClear64 -#else - privateWaitLock(ptr); - *ptr = 0; - privateUnlock(ptr); - - return; -#endif -} - -Uint64 -SDL_AtomicFetchThenIncrement64(volatile Uint64 * ptr) -{ -#ifdef nativeFetchThenIncrement64 -#else - Uint64 tmp = 0; - - privateWaitLock(ptr); - tmp = *ptr; - (*ptr)+= 1; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint64 -SDL_AtomicFetchThenDecrement64(volatile Uint64 * ptr) -{ -#ifdef nativeFetchThenDecrement64 -#else - Uint64 tmp = 0; - - privateWaitLock(ptr); - tmp = *ptr; - (*ptr) -= 1; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint64 -SDL_AtomicFetchThenAdd64(volatile Uint64 * ptr, Uint64 value) -{ -#ifdef nativeFetchThenAdd64 -#else - Uint64 tmp = 0; - - privateWaitLock(ptr); - tmp = *ptr; - (*ptr)+= value; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint64 -SDL_AtomicFetchThenSubtract64(volatile Uint64 * ptr, Uint64 value) -{ -#ifdef nativeFetchThenSubtract64 -#else - Uint64 tmp = 0; - - privateWaitLock(ptr); - tmp = *ptr; - (*ptr)-= value; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint64 -SDL_AtomicIncrementThenFetch64(volatile Uint64 * ptr) -{ -#ifdef nativeIncrementThenFetch64 -#else - Uint64 tmp = 0; - - privateWaitLock(ptr); - (*ptr)+= 1; - tmp = *ptr; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint64 -SDL_AtomicDecrementThenFetch64(volatile Uint64 * ptr) -{ -#ifdef nativeDecrementThenFetch64 -#else - Uint64 tmp = 0; - - privateWaitLock(ptr); - (*ptr)-= 1; - tmp = *ptr; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint64 -SDL_AtomicAddThenFetch64(volatile Uint64 * ptr, Uint64 value) -{ -#ifdef nativeAddThenFetch64 -#else - Uint64 tmp = 0; - - privateWaitLock(ptr); - (*ptr)+= value; - tmp = *ptr; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint64 -SDL_AtomicSubtractThenFetch64(volatile Uint64 * ptr, Uint64 value) -{ -#ifdef nativeSubtractThenFetch64 -#else - Uint64 tmp = 0; - - privateWaitLock(ptr); - (*ptr)-= value; - tmp = *ptr; - privateUnlock(ptr); - - return tmp; -#endif -} -#endif - diff --git a/src/atomic/qnx/SDL_atomic.c b/src/atomic/qnx/SDL_atomic.c deleted file mode 100644 index d9f51df9a..000000000 --- a/src/atomic/qnx/SDL_atomic.c +++ /dev/null @@ -1,505 +0,0 @@ -/* - SDL - Simple DirectMedia Layer - Copyright (C) 1997-2010 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 - - QNX native atomic operations - Copyright (C) 2009 Mike Gorchak - (mike@malva.ua, lestat@i.com.ua) -*/ - -#include "SDL_stdinc.h" -#include "SDL_atomic.h" -#include "SDL_error.h" - -#include - -/* SMP Exchange for PPC platform */ -#ifdef __PPC__ -#include -#endif /* __PPC__ */ - -/* SMP Exchange for ARM platform */ -#ifdef __ARM__ -#include -#endif /* __ARM__ */ - -/* SMP Exchange for MIPS platform */ -#if defined (__MIPSEB__) || defined(__MIPSEL__) -#include -#endif /* __MIPSEB__ || __MIPSEL__ */ - -/* SMP Exchange for SH platform */ -#ifdef __SH__ -#include -#endif /* __SH__ */ - -/* SMP Exchange for x86 platform */ -#ifdef __X86__ -#include -#endif /* __X86__ */ - -/* - This file provides 32, and 64 bit atomic operations. If the - operations are provided by the native hardware and operating system - they are used. If they are not then the operations are emulated - using the SDL spin lock operations. If spin lock can not be - implemented then these functions must fail. -*/ - -void -SDL_AtomicLock(SDL_SpinLock *lock) -{ - unsigned volatile* l = (unsigned volatile*)lock; - Uint32 oldval = 0; - Uint32 newval = 1; - - oldval = _smp_xchg(l, newval); - while(1 == oldval) - { - oldval = _smp_xchg(l, newval); - } -} - -void -SDL_AtomicUnlock(SDL_SpinLock *lock) -{ - unsigned volatile* l = (unsigned volatile*)lock; - Uint32 newval = 0; - - _smp_xchg(l, newval); -} - -/* - QNX 6.4.1 supports only 32 bit atomic access -*/ - -#undef nativeTestThenSet32 -#define nativeClear32 -#define nativeFetchThenIncrement32 -#define nativeFetchThenDecrement32 -#define nativeFetchThenAdd32 -#define nativeFetchThenSubtract32 -#define nativeIncrementThenFetch32 -#define nativeDecrementThenFetch32 -#define nativeAddThenFetch32 -#define nativeSubtractThenFetch32 - -#undef nativeTestThenSet64 -#undef nativeClear64 -#undef nativeFetchThenIncrement64 -#undef nativeFetchThenDecrement64 -#undef nativeFetchThenAdd64 -#undef nativeFetchThenSubtract64 -#undef nativeIncrementThenFetch64 -#undef nativeDecrementThenFetch64 -#undef nativeAddThenFetch64 -#undef nativeSubtractThenFetch64 - -/* - If any of the operations are not provided then we must emulate some - of them. That means we need a nice implementation of spin locks - that avoids the "one big lock" problem. We use a vector of spin - locks and pick which one to use based on the address of the operand - of the function. - - To generate the index of the lock we first shift by 3 bits to get - rid on the zero bits that result from 32 and 64 bit allignment of - data. We then mask off all but 5 bits and use those 5 bits as an - index into the table. - - Picking the lock this way insures that accesses to the same data at - the same time will go to the same lock. OTOH, accesses to different - data have only a 1/32 chance of hitting the same lock. That should - pretty much eliminate the chances of several atomic operations on - different data from waiting on the same "big lock". If it isn't - then the table of locks can be expanded to a new size so long as - the new size is a power of two. -*/ - -static SDL_SpinLock locks[32] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; - -static __inline__ void -privateWaitLock(volatile void *ptr) -{ -#if SIZEOF_VOIDP == 4 - Uint32 index = ((((Uint32)ptr) >> 3) & 0x1f); -#elif SIZEOF_VOIDP == 8 - Uint64 index = ((((Uint64)ptr) >> 3) & 0x1f); -#endif /* SIZEOF_VOIDP */ - - SDL_AtomicLock(&locks[index]); -} - -static __inline__ void -privateUnlock(volatile void *ptr) -{ -#if SIZEOF_VOIDP == 4 - Uint32 index = ((((Uint32)ptr) >> 3) & 0x1f); -#elif SIZEOF_VOIDP == 8 - Uint64 index = ((((Uint64)ptr) >> 3) & 0x1f); -#endif /* SIZEOF_VOIDP */ - - SDL_AtomicUnlock(&locks[index]); -} - -/* 32 bit atomic operations */ - -SDL_bool -SDL_AtomicTestThenSet32(volatile Uint32 * ptr) -{ -#ifdef nativeTestThenSet32 -#else - SDL_bool result = SDL_FALSE; - - privateWaitLock(ptr); - result = (*ptr == 0); - if (result) - { - *ptr = 1; - } - privateUnlock(ptr); - - return result; -#endif /* nativeTestThenSet32 */ -} - -void -SDL_AtomicClear32(volatile Uint32 * ptr) -{ -#ifdef nativeClear32 - atomic_clr(ptr, 0xFFFFFFFF); -#else - privateWaitLock(ptr); - *ptr = 0; - privateUnlock(ptr); - - return; -#endif /* nativeClear32 */ -} - -Uint32 -SDL_AtomicFetchThenIncrement32(volatile Uint32 * ptr) -{ -#ifdef nativeFetchThenIncrement32 - return atomic_add_value(ptr, 0x00000001); -#else - Uint32 tmp = 0; - - privateWaitLock(ptr); - tmp = *ptr; - (*ptr)+= 1; - privateUnlock(ptr); - - return tmp; -#endif /* nativeFetchThenIncrement32 */ -} - -Uint32 -SDL_AtomicFetchThenDecrement32(volatile Uint32 * ptr) -{ -#ifdef nativeFetchThenDecrement32 - return atomic_sub_value(ptr, 0x00000001); -#else - Uint32 tmp = 0; - - privateWaitLock(ptr); - tmp = *ptr; - (*ptr) -= 1; - privateUnlock(ptr); - - return tmp; -#endif /* nativeFetchThenDecrement32 */ -} - -Uint32 -SDL_AtomicFetchThenAdd32(volatile Uint32 * ptr, Uint32 value) -{ -#ifdef nativeFetchThenAdd32 - return atomic_add_value(ptr, value); -#else - Uint32 tmp = 0; - - privateWaitLock(ptr); - tmp = *ptr; - (*ptr)+= value; - privateUnlock(ptr); - - return tmp; -#endif /* nativeFetchThenAdd32 */ -} - -Uint32 -SDL_AtomicFetchThenSubtract32(volatile Uint32 * ptr, Uint32 value) -{ -#ifdef nativeFetchThenSubtract32 - return atomic_sub_value(ptr, value); -#else - Uint32 tmp = 0; - - privateWaitLock(ptr); - tmp = *ptr; - (*ptr)-= value; - privateUnlock(ptr); - - return tmp; -#endif /* nativeFetchThenSubtract32 */ -} - -Uint32 -SDL_AtomicIncrementThenFetch32(volatile Uint32 * ptr) -{ -#ifdef nativeIncrementThenFetch32 - atomic_add(ptr, 0x00000001); - return atomic_add_value(ptr, 0x00000000); -#else - Uint32 tmp = 0; - - privateWaitLock(ptr); - (*ptr)+= 1; - tmp = *ptr; - privateUnlock(ptr); - - return tmp; -#endif /* nativeIncrementThenFetch32 */ -} - -Uint32 -SDL_AtomicDecrementThenFetch32(volatile Uint32 * ptr) -{ -#ifdef nativeDecrementThenFetch32 - atomic_sub(ptr, 0x00000001); - return atomic_sub_value(ptr, 0x00000000); -#else - Uint32 tmp = 0; - - privateWaitLock(ptr); - (*ptr)-= 1; - tmp = *ptr; - privateUnlock(ptr); - - return tmp; -#endif /* nativeDecrementThenFetch32 */ -} - -Uint32 -SDL_AtomicAddThenFetch32(volatile Uint32 * ptr, Uint32 value) -{ -#ifdef nativeAddThenFetch32 - atomic_add(ptr, value); - return atomic_add_value(ptr, 0x00000000); -#else - Uint32 tmp = 0; - - privateWaitLock(ptr); - (*ptr)+= value; - tmp = *ptr; - privateUnlock(ptr); - - return tmp; -#endif /* nativeAddThenFetch32 */ -} - -Uint32 -SDL_AtomicSubtractThenFetch32(volatile Uint32 * ptr, Uint32 value) -{ -#ifdef nativeSubtractThenFetch32 - atomic_sub(ptr, value); - return atomic_sub_value(ptr, 0x00000000); -#else - Uint32 tmp = 0; - - privateWaitLock(ptr); - (*ptr)-= value; - tmp = *ptr; - privateUnlock(ptr); - - return tmp; -#endif /* nativeSubtractThenFetch32 */ -} - -/* 64 bit atomic operations */ -#ifdef SDL_HAS_64BIT_TYPE - -SDL_bool -SDL_AtomicTestThenSet64(volatile Uint64 * ptr) -{ -#ifdef nativeTestThenSet64 -#else - SDL_bool result = SDL_FALSE; - - privateWaitLock(ptr); - result = (*ptr == 0); - if (result) - { - *ptr = 1; - } - privateUnlock(ptr); - - return result; -#endif /* nativeTestThenSet64 */ -} - -void -SDL_AtomicClear64(volatile Uint64 * ptr) -{ -#ifdef nativeClear64 -#else - privateWaitLock(ptr); - *ptr = 0; - privateUnlock(ptr); - - return; -#endif /* nativeClear64 */ -} - -Uint64 -SDL_AtomicFetchThenIncrement64(volatile Uint64 * ptr) -{ -#ifdef nativeFetchThenIncrement64 -#else - Uint64 tmp = 0; - - privateWaitLock(ptr); - tmp = *ptr; - (*ptr)+= 1; - privateUnlock(ptr); - - return tmp; -#endif /* nativeFetchThenIncrement64 */ -} - -Uint64 -SDL_AtomicFetchThenDecrement64(volatile Uint64 * ptr) -{ -#ifdef nativeFetchThenDecrement64 -#else - Uint64 tmp = 0; - - privateWaitLock(ptr); - tmp = *ptr; - (*ptr) -= 1; - privateUnlock(ptr); - - return tmp; -#endif /* nativeFetchThenDecrement64 */ -} - -Uint64 -SDL_AtomicFetchThenAdd64(volatile Uint64 * ptr, Uint64 value) -{ -#ifdef nativeFetchThenAdd64 -#else - Uint64 tmp = 0; - - privateWaitLock(ptr); - tmp = *ptr; - (*ptr)+= value; - privateUnlock(ptr); - - return tmp; -#endif /* nativeFetchThenAdd64 */ -} - -Uint64 -SDL_AtomicFetchThenSubtract64(volatile Uint64 * ptr, Uint64 value) -{ -#ifdef nativeFetchThenSubtract64 -#else - Uint64 tmp = 0; - - privateWaitLock(ptr); - tmp = *ptr; - (*ptr)-= value; - privateUnlock(ptr); - - return tmp; -#endif /* nativeFetchThenSubtract64 */ -} - -Uint64 -SDL_AtomicIncrementThenFetch64(volatile Uint64 * ptr) -{ -#ifdef nativeIncrementThenFetch64 -#else - Uint64 tmp = 0; - - privateWaitLock(ptr); - (*ptr)+= 1; - tmp = *ptr; - privateUnlock(ptr); - - return tmp; -#endif /* nativeIncrementThenFetch64 */ -} - -Uint64 -SDL_AtomicDecrementThenFetch64(volatile Uint64 * ptr) -{ -#ifdef nativeDecrementThenFetch64 -#else - Uint64 tmp = 0; - - privateWaitLock(ptr); - (*ptr)-= 1; - tmp = *ptr; - privateUnlock(ptr); - - return tmp; -#endif /* nativeDecrementThenFetch64 */ -} - -Uint64 -SDL_AtomicAddThenFetch64(volatile Uint64 * ptr, Uint64 value) -{ -#ifdef nativeAddThenFetch64 -#else - Uint64 tmp = 0; - - privateWaitLock(ptr); - (*ptr)+= value; - tmp = *ptr; - privateUnlock(ptr); - - return tmp; -#endif /* nativeAddThenFetch64 */ -} - -Uint64 -SDL_AtomicSubtractThenFetch64(volatile Uint64 * ptr, Uint64 value) -{ -#ifdef nativeSubtractThenFetch64 -#else - Uint64 tmp = 0; - - privateWaitLock(ptr); - (*ptr)-= value; - tmp = *ptr; - privateUnlock(ptr); - - return tmp; -#endif /* nativeSubtractThenFetch64 */ -} - -#endif /* SDL_HAS_64BIT_TYPE */ diff --git a/src/atomic/win32/SDL_atomic.c b/src/atomic/win32/SDL_atomic.c deleted file mode 100644 index e009fd0d2..000000000 --- a/src/atomic/win32/SDL_atomic.c +++ /dev/null @@ -1,512 +0,0 @@ -/* - SDL - Simple DirectMedia Layer - Copyright (C) 1997-2010 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 - - Contributed by Bob Pendleton, bob@pendleton.com -*/ - -#include "SDL_stdinc.h" -#include "SDL_atomic.h" - -#define WIN32_LEAN_AND_MEAN -#include - -#include "SDL_error.h" - -/* - This file provides 32, and 64 bit atomic operations. If the - operations are provided by the native hardware and operating system - they are used. If they are not then the operations are emulated - using the SDL spin lock operations. If spin lock can not be - implemented then these functions must fail. -*/ - -/* - WIN32 VERSION. - - This makes use of native Windows atomic operations. -*/ - -/* - Native spinlock routines. Because this is the dummy implementation - these will always call SDL_SetError() and do nothing. -*/ - -void -SDL_AtomicLock(SDL_SpinLock *lock) -{ - long volatile * l = (long volatile *)lock; - Uint32 old = 0; - Uint32 new = 1; - - old = InterlockedExchange(l, new); - while(1 == old) - { - old = InterlockedExchange(l, new); - } -} - -void -SDL_AtomicUnlock(SDL_SpinLock *lock) -{ - long volatile * l = (long volatile *)lock; - Uint32 new = 0; - - InterlockedExchange(l, new); -} - -/* - Note that platform specific versions can be built from this version - by changing the #undefs to #defines and adding platform specific - code. -*/ - -#define nativeTestThenSet32 -#define nativeClear32 -#define nativeFetchThenIncrement32 -#define nativeFetchThenDecrement32 -#define nativeFetchThenAdd32 -#define nativeFetchThenSubtract32 -#define nativeIncrementThenFetch32 -#define nativeDecrementThenFetch32 -#define nativeAddThenFetch32 -#define nativeSubtractThenFetch32 - -#undef nativeTestThenSet64 -#undef nativeClear64 -#undef nativeFetchThenIncrement64 -#undef nativeFetchThenDecrement64 -#undef nativeFetchThenAdd64 -#undef nativeFetchThenSubtract64 -#undef nativeIncrementThenFetch64 -#undef nativeDecrementThenFetch64 -#undef nativeAddThenFetch64 -#undef nativeSubtractThenFetch64 - -/* - If any of the operations are not provided then we must emulate some - of them. That means we need a nice implementation of spin locks - that avoids the "one big lock" problem. We use a vector of spin - locks and pick which one to use based on the address of the operand - of the function. - - To generate the index of the lock we first shift by 3 bits to get - rid on the zero bits that result from 32 and 64 bit allignment of - data. We then mask off all but 5 bits and use those 5 bits as an - index into the table. - - Picking the lock this way insures that accesses to the same data at - the same time will go to the same lock. OTOH, accesses to different - data have only a 1/32 chance of hitting the same lock. That should - pretty much eliminate the chances of several atomic operations on - different data from waiting on the same "big lock". If it isn't - then the table of locks can be expanded to a new size so long as - the new size is a power of two. -*/ - -static SDL_SpinLock locks[32] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; - -static __inline__ void -privateWaitLock(volatile void *ptr) -{ -#if SIZEOF_VOIDP == 4 - Uint32 index = ((((Uint32)ptr) >> 3) & 0x1f); -#elif SIZEOF_VOIDP == 8 - Uint64 index = ((((Uint64)ptr) >> 3) & 0x1f); -#endif - - SDL_AtomicLock(&locks[index]); -} - -static __inline__ void -privateUnlock(volatile void *ptr) -{ -#if SIZEOF_VOIDP == 4 - Uint32 index = ((((Uint32)ptr) >> 3) & 0x1f); -#elif SIZEOF_VOIDP == 8 - Uint64 index = ((((Uint64)ptr) >> 3) & 0x1f); -#endif - - SDL_AtomicUnlock(&locks[index]); -} - -/* 32 bit atomic operations */ - -SDL_bool -SDL_AtomicTestThenSet32(volatile Uint32 * ptr) -{ -#ifdef nativeTestThenSet32 - long volatile * p = (long volatile *)ptr; - Uint32 new = 1; - - return 0 == InterlockedExchange(p, new); -#else - SDL_bool result = SDL_FALSE; - - privateWaitLock(ptr); - result = (*ptr == 0); - if (result) - { - *ptr = 1; - } - privateUnlock(ptr); - - return result; -#endif -} - -void -SDL_AtomicClear32(volatile Uint32 * ptr) -{ -#ifdef nativeClear32 - long volatile * p = (long volatile *)ptr; - Uint32 new = 0; - - InterlockedExchange(p, new); -#else - privateWaitLock(ptr); - *ptr = 0; - privateUnlock(ptr); - - return; -#endif -} - -Uint32 -SDL_AtomicFetchThenIncrement32(volatile Uint32 * ptr) -{ -#ifdef nativeFetchThenIncrement32 - long volatile * p = (long volatile *)ptr; - - return InterlockedExchangeAdd(p, 1); -#else - Uint32 tmp = 0; - - privateWaitLock(ptr); - tmp = *ptr; - (*ptr)+= 1; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint32 -SDL_AtomicFetchThenDecrement32(volatile Uint32 * ptr) -{ -#ifdef nativeFetchThenDecrement32 - long volatile * p = (long volatile *)ptr; - - return InterlockedExchangeAdd(p, -1); -#else - Uint32 tmp = 0; - - privateWaitLock(ptr); - tmp = *ptr; - (*ptr) -= 1; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint32 -SDL_AtomicFetchThenAdd32(volatile Uint32 * ptr, Uint32 value) -{ -#ifdef nativeFetchThenAdd32 - long volatile * p = (long volatile *)ptr; - - return InterlockedExchangeAdd(p, value); -#else - Uint32 tmp = 0; - - privateWaitLock(ptr); - tmp = *ptr; - (*ptr)+= value; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint32 -SDL_AtomicFetchThenSubtract32(volatile Uint32 * ptr, Uint32 value) -{ -#ifdef nativeFetchThenSubtract32 - long volatile * p = (long volatile *)ptr; - - return InterlockedExchangeAdd(p, (0 - value)); -#else - Uint32 tmp = 0; - - privateWaitLock(ptr); - tmp = *ptr; - (*ptr)-= value; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint32 -SDL_AtomicIncrementThenFetch32(volatile Uint32 * ptr) -{ -#ifdef nativeIncrementThenFetch32 - long volatile * p = (LONG volatile *)ptr; - - return InterlockedIncrement(p); -#else - Uint32 tmp = 0; - - privateWaitLock(ptr); - (*ptr)+= 1; - tmp = *ptr; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint32 -SDL_AtomicDecrementThenFetch32(volatile Uint32 * ptr) -{ -#ifdef nativeDecrementThenFetch32 - long volatile * p = (LONG volatile *)ptr; - - return InterlockedDecrement(p); -#else - Uint32 tmp = 0; - - privateWaitLock(ptr); - (*ptr)-= 1; - tmp = *ptr; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint32 -SDL_AtomicAddThenFetch32(volatile Uint32 * ptr, Uint32 value) -{ -#ifdef nativeAddThenFetch32 - long volatile * p = (long volatile *)ptr; - - return InterlockedExchangeAdd(p, value) + value; -#else - Uint32 tmp = 0; - - privateWaitLock(ptr); - (*ptr)+= value; - tmp = *ptr; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint32 -SDL_AtomicSubtractThenFetch32(volatile Uint32 * ptr, Uint32 value) -{ -#ifdef nativeSubtractThenFetch32 - long volatile * p = (long volatile *)ptr; - - return InterlockedExchangeAdd(p, (0 - value)) - value; -#else - Uint32 tmp = 0; - - privateWaitLock(ptr); - (*ptr)-= value; - tmp = *ptr; - privateUnlock(ptr); - - return tmp; -#endif -} - -/* 64 bit atomic operations */ -#ifdef SDL_HAS_64BIT_TYPE - -SDL_bool -SDL_AtomicTestThenSet64(volatile Uint64 * ptr) -{ -#ifdef nativeTestThenSet64 -#else - SDL_bool result = SDL_FALSE; - - privateWaitLock(ptr); - result = (*ptr == 0); - if (result) - { - *ptr = 1; - } - privateUnlock(ptr); - - return result; -#endif -} - -void -SDL_AtomicClear64(volatile Uint64 * ptr) -{ -#ifdef nativeClear64 -#else - privateWaitLock(ptr); - *ptr = 0; - privateUnlock(ptr); - - return; -#endif -} - -Uint64 -SDL_AtomicFetchThenIncrement64(volatile Uint64 * ptr) -{ -#ifdef nativeFetchThenIncrement64 -#else - Uint64 tmp = 0; - - privateWaitLock(ptr); - tmp = *ptr; - (*ptr)+= 1; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint64 -SDL_AtomicFetchThenDecrement64(volatile Uint64 * ptr) -{ -#ifdef nativeFetchThenDecrement64 -#else - Uint64 tmp = 0; - - privateWaitLock(ptr); - tmp = *ptr; - (*ptr) -= 1; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint64 -SDL_AtomicFetchThenAdd64(volatile Uint64 * ptr, Uint64 value) -{ -#ifdef nativeFetchThenAdd64 -#else - Uint64 tmp = 0; - - privateWaitLock(ptr); - tmp = *ptr; - (*ptr)+= value; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint64 -SDL_AtomicFetchThenSubtract64(volatile Uint64 * ptr, Uint64 value) -{ -#ifdef nativeFetchThenSubtract64 -#else - Uint64 tmp = 0; - - privateWaitLock(ptr); - tmp = *ptr; - (*ptr)-= value; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint64 -SDL_AtomicIncrementThenFetch64(volatile Uint64 * ptr) -{ -#ifdef nativeIncrementThenFetch64 -#else - Uint64 tmp = 0; - - privateWaitLock(ptr); - (*ptr)+= 1; - tmp = *ptr; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint64 -SDL_AtomicDecrementThenFetch64(volatile Uint64 * ptr) -{ -#ifdef nativeDecrementThenFetch64 -#else - Uint64 tmp = 0; - - privateWaitLock(ptr); - (*ptr)-= 1; - tmp = *ptr; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint64 -SDL_AtomicAddThenFetch64(volatile Uint64 * ptr, Uint64 value) -{ -#ifdef nativeAddThenFetch64 -#else - Uint64 tmp = 0; - - privateWaitLock(ptr); - (*ptr)+= value; - tmp = *ptr; - privateUnlock(ptr); - - return tmp; -#endif -} - -Uint64 -SDL_AtomicSubtractThenFetch64(volatile Uint64 * ptr, Uint64 value) -{ -#ifdef nativeSubtractThenFetch64 -#else - Uint64 tmp = 0; - - privateWaitLock(ptr); - (*ptr)-= value; - tmp = *ptr; - privateUnlock(ptr); - - return tmp; -#endif -} -#endif - diff --git a/test/testatomic.c b/test/testatomic.c index bd9873408..85f7b567e 100644 --- a/test/testatomic.c +++ b/test/testatomic.c @@ -1,18 +1,6 @@ #include #include "SDL.h" -/* Make sure we have good macros for printing 32 and 64 bit values */ -#ifndef PRIu32 -#define PRIu32 "u" -#endif -#ifndef PRIu64 -#ifdef __WIN32__ -#define PRIu64 "I64u" -#else -#define PRIu64 "llu" -#endif -#endif - /* Absolutely basic tests just to see if we get the expected value after calling each function. @@ -21,109 +9,60 @@ char * tf(SDL_bool tf) { - static char *t = "true"; - static char *f = "false"; + static char *t = "TRUE"; + static char *f = "FALSE"; - if (tf) - { - return t; - } + if (tf) + { + return t; + } - return f; + return f; } int main(int argc, char *argv[]) { - - volatile Uint32 val32 = 0; - Uint32 ret32 = 0; - - volatile Uint64 val64 = 0; - Uint64 ret64 = 0; - - SDL_SpinLock lock = 0; - - SDL_bool tfret = SDL_FALSE; - - printf("\nspin lock---------------------------------------\n\n"); - - SDL_AtomicLock(&lock); - printf("AtomicLock lock=%d\n", lock); - SDL_AtomicUnlock(&lock); - printf("AtomicUnlock lock=%d\n", lock); - - printf("\n32 bit -----------------------------------------\n\n"); - - val32 = 0; - tfret = SDL_AtomicTestThenSet32(&val32); - printf("TestThenSet32 tfret=%s val=%"PRIu32"\n", tf(tfret), val32); - tfret = SDL_AtomicTestThenSet32(&val32); - printf("TestThenSet32 tfret=%s val=%"PRIu32"\n", tf(tfret), val32); - - SDL_AtomicClear32(&val32); - printf("Clear32 val=%"PRIu32"\n", val32); - - ret32 = SDL_AtomicFetchThenIncrement32(&val32); - printf("FetchThenIncrement32 ret=%"PRIu32" val=%"PRIu32"\n", ret32, val32); - - ret32 = SDL_AtomicFetchThenDecrement32(&val32); - printf("FetchThenDecrement32 ret=%"PRIu32" val=%"PRIu32"\n", ret32, val32); - - ret32 = SDL_AtomicFetchThenAdd32(&val32, 10); - printf("FetchThenAdd32 ret=%"PRIu32" val=%"PRIu32"\n", ret32, val32); - - ret32 = SDL_AtomicFetchThenSubtract32(&val32, 10); - printf("FetchThenSubtract32 ret=%"PRIu32" val=%"PRIu32"\n", ret32, val32); - - ret32 = SDL_AtomicIncrementThenFetch32(&val32); - printf("IncrementThenFetch32 ret=%"PRIu32" val=%"PRIu32"\n", ret32, val32); - - ret32 = SDL_AtomicDecrementThenFetch32(&val32); - printf("DecrementThenFetch32 ret=%"PRIu32" val=%"PRIu32"\n", ret32, val32); - - ret32 = SDL_AtomicAddThenFetch32(&val32, 10); - printf("AddThenFetch32 ret=%"PRIu32" val=%"PRIu32"\n", ret32, val32); - - ret32 = SDL_AtomicSubtractThenFetch32(&val32, 10); - printf("SubtractThenFetch32 ret=%"PRIu32" val=%"PRIu32"\n", ret32, val32); - -#ifdef SDL_HAS_64BIT_TYPE - printf("\n64 bit -----------------------------------------\n\n"); - - val64 = 0; - tfret = SDL_AtomicTestThenSet64(&val64); - printf("TestThenSet64 tfret=%s val=%"PRIu64"\n", tf(tfret), val64); - tfret = SDL_AtomicTestThenSet64(&val64); - printf("TestThenSet64 tfret=%s val=%"PRIu64"\n", tf(tfret), val64); - - SDL_AtomicClear64(&val64); - printf("Clear64 val=%"PRIu64"\n", val64); - - ret64 = SDL_AtomicFetchThenIncrement64(&val64); - printf("FetchThenIncrement64 ret=%"PRIu64" val=%"PRIu64"\n", ret64, val64); - - ret64 = SDL_AtomicFetchThenDecrement64(&val64); - printf("FetchThenDecrement64 ret=%"PRIu64" val=%"PRIu64"\n", ret64, val64); - - ret64 = SDL_AtomicFetchThenAdd64(&val64, 10); - printf("FetchThenAdd64 ret=%"PRIu64" val=%"PRIu64"\n", ret64, val64); - - ret64 = SDL_AtomicFetchThenSubtract64(&val64, 10); - printf("FetchThenSubtract64 ret=%"PRIu64" val=%"PRIu64"\n", ret64, val64); - - ret64 = SDL_AtomicIncrementThenFetch64(&val64); - printf("IncrementThenFetch64 ret=%"PRIu64" val=%"PRIu64"\n", ret64, val64); - - ret64 = SDL_AtomicDecrementThenFetch64(&val64); - printf("DecrementThenFetch64 ret=%"PRIu64" val=%"PRIu64"\n", ret64, val64); - - ret64 = SDL_AtomicAddThenFetch64(&val64, 10); - printf("AddThenFetch64 ret=%"PRIu64" val=%"PRIu64"\n", ret64, val64); - - ret64 = SDL_AtomicSubtractThenFetch64(&val64, 10); - printf("SubtractThenFetch64 ret=%"PRIu64" val=%"PRIu64"\n", ret64, val64); -#endif - - return 0; - } + int value; + SDL_SpinLock lock = 0; + + SDL_bool tfret = SDL_FALSE; + + printf("\nspin lock---------------------------------------\n\n"); + + SDL_AtomicLock(&lock); + printf("AtomicLock lock=%d\n", lock); + SDL_AtomicUnlock(&lock); + printf("AtomicUnlock lock=%d\n", lock); + + printf("\natomic -----------------------------------------\n\n"); + + SDL_atomic_t v; + + SDL_AtomicSet(&v, 0); + tfret = SDL_AtomicSet(&v, 10) == 0; + printf("AtomicSet(10) tfret=%s val=%"PRIu32"\n", tf(tfret), SDL_AtomicGet(&v)); + tfret = SDL_AtomicAdd(&v, 10) == 10; + printf("AtomicAdd(10) tfret=%s val=%"PRIu32"\n", tf(tfret), SDL_AtomicGet(&v)); + + SDL_AtomicSet(&v, 0); + SDL_AtomicIncRef(&v); + tfret = (SDL_AtomicGet(&v) == 1); + printf("AtomicIncRef() tfret=%s val=%"PRIu32"\n", tf(tfret), SDL_AtomicGet(&v)); + SDL_AtomicIncRef(&v); + tfret = (SDL_AtomicGet(&v) == 2); + printf("AtomicIncRef() tfret=%s val=%"PRIu32"\n", tf(tfret), SDL_AtomicGet(&v)); + tfret = (SDL_AtomicDecRef(&v) == SDL_FALSE); + printf("AtomicDecRef() tfret=%s val=%"PRIu32"\n", tf(tfret), SDL_AtomicGet(&v)); + tfret = (SDL_AtomicDecRef(&v) == SDL_TRUE); + printf("AtomicDecRef() tfret=%s val=%"PRIu32"\n", tf(tfret), SDL_AtomicGet(&v)); + + SDL_AtomicSet(&v, 10); + tfret = (SDL_AtomicCAS(&v, 0, 20) != 0); + printf("AtomicCAS() tfret=%s val=%"PRIu32"\n", tf(tfret), SDL_AtomicGet(&v)); + value = SDL_AtomicGet(&v); + tfret = (SDL_AtomicCAS(&v, value, 20) == value); + printf("AtomicCAS() tfret=%s val=%"PRIu32"\n", tf(tfret), SDL_AtomicGet(&v)); + + return 0; +}