Commit 1bc8fe69 authored by Sam Lantinga's avatar Sam Lantinga

Updated the atomic API for better use cases

parent 40844381
......@@ -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))
......
......@@ -644,7 +644,11 @@
>
</File>
<File
RelativePath="..\..\src\atomic\win32\SDL_atomic.c"
RelativePath="..\..\src\atomic\SDL_atomic.c"
>
</File>
<File
RelativePath="..\..\src\atomic\SDL_spinlock.c"
>
</File>
<File
......
......@@ -631,7 +631,11 @@
>
</File>
<File
RelativePath="..\..\src\atomic\win32\SDL_atomic.c"
RelativePath="..\..\src\atomic\SDL_atomic.c"
>
</File>
<File
RelativePath="..\..\src\atomic\SDL_spinlock.c"
>
</File>
<File
......
......@@ -365,7 +365,8 @@ echo #define SDL_REVISION 0 &gt;"$(ProjectDir)\..\..\include\SDL_revision.h"
<ClCompile Include="..\..\src\SDL.c" />
<ClCompile Include="..\..\src\video\SDL_alphamult.c" />
<ClCompile Include="..\..\src\SDL_assert.c" />
<ClCompile Include="..\..\src\atomic\win32\SDL_atomic.c" />
<ClCompile Include="..\..\src\atomic\SDL_atomic.c" />
<ClCompile Include="..\..\src\atomic\SDL_spinlock.c" />
<ClCompile Include="..\..\src\audio\SDL_audio.c" />
<ClCompile Include="..\..\src\audio\SDL_audiocvt.c" />
<ClCompile Include="..\..\src\audio\SDL_audiodev.c" />
......@@ -457,4 +458,4 @@ echo #define SDL_REVISION 0 &gt;"$(ProjectDir)\..\..\include\SDL_revision.h"
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
\ No newline at end of file
</Project>
......@@ -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 = "<group>"; };
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 = "<group>"; };
04BA9D6011EF474A00B60E01 /* SDL_gesture.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_gesture.c; sourceTree = "<group>"; };
......@@ -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 = "<group>"; };
04FFAB8A12E23B8D00BA343D /* SDL_spinlock.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_spinlock.c; sourceTree = "<group>"; };
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 = "<group>"; };
......@@ -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 = "<group>";
};
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;
};
......
......@@ -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 = "<group>"; };
00CFA6B0106B46E500758660 /* SDL_audio_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_audio_c.h; sourceTree = "<group>"; };
00CFA6B1106B46E500758660 /* SDL_audiodev_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_audiodev_c.h; sourceTree = "<group>"; };
00CFA6B2106B46E500758660 /* SDL_audiomem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_audiomem.h; sourceTree = "<group>"; };
......@@ -861,6 +862,8 @@
04DEA57811E600A600386CAC /* SDL_cocoaclipboard.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDL_cocoaclipboard.m; sourceTree = "<group>"; };
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 = "<group>"; };
04FB7D4B12E2350700A522C6 /* SDL_spinlock.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_spinlock.c; sourceTree = "<group>"; };
083E489D006D88D97F000001 /* SDL_joystick.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = SDL_joystick.c; sourceTree = "<group>"; };
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 = "<group>";
};
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;
};
......
......@@ -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
......
......@@ -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
......
/*
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: */
/*
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 <windows.h>
#elif defined(__MACOSX__)
#include <libkern/OSAtomic.h>
#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: */
/*
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
/*
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 */
/*
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
/*
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 <atomic.h>
/* SMP Exchange for PPC platform */
#ifdef __PPC__
#include <ppc/smpxchg.h>
#endif /* __PPC__ */
/* SMP Exchange for ARM platform */
#ifdef __ARM__
#include <arm/smpxchg.h>
#endif /* __ARM__ */
/* SMP Exchange for MIPS platform */
#if defined (__MIPSEB__) || defined(__MIPSEL__)
#include <mips/smpxchg.h>
#endif /* __MIPSEB__ || __MIPSEL__ */
/* SMP Exchange for SH platform */
#ifdef __SH__
#include <sh/smpxchg.h>
#endif /* __SH__ */
/* SMP Exchange for x86 platform */
#ifdef __X86__
#include <x86/smpxchg.h>
#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 */
/*
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 <windows.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.
*/
/*
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
#include <stdio.h>
#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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment