├── CMakeLists.txt ├── LICENSE ├── README.md ├── generate-xcode-iphone.py ├── iOS.cmake ├── main.cpp ├── randomdelay.cpp └── randomdelay.h /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 2.8.8) 2 | set(CMAKE_CONFIGURATION_TYPES "Release") 3 | 4 | set(CMAKE_XCODE_EFFECTIVE_PLATFORMS "-iphoneos;-iphonesimulator") 5 | 6 | project (AcquireRelease) 7 | set(MACOSX_BUNDLE_GUI_IDENTIFIER "com.mycompany.\${PRODUCT_NAME:identifier}") 8 | file(GLOB SOURCES *.cpp) 9 | add_executable(AcquireRelease MACOSX_BUNDLE ${SOURCES}) 10 | 11 | set_target_properties(AcquireRelease PROPERTIES XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "iPhone Developer") 12 | set_target_properties(AcquireRelease PROPERTIES XCODE_ATTRIBUTE_GCC_OPTIMIZATION_LEVEL "s") 13 | set_target_properties(AcquireRelease PROPERTIES XCODE_ATTRIBUTE_CLANG_CXX_LANGUAGE_STANDARD "c++0x") 14 | set_target_properties(AcquireRelease PROPERTIES XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++") 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The contents of this repository, except iOS.cmake, are released to the public 2 | domain. 3 | 4 | The original iOS.cmake file is the copyright of its authors and seems to be 5 | released under the New BSD License (except without an actual license 6 | notice). See http://code.google.com/p/ios-cmake/ for more information. 7 | 8 | Redistribution and use in source and binary forms of iOS.cmake, with or 9 | without modification, are permitted provided that the following conditions 10 | are met: 11 | 12 | * Redistributions of source code must retain the above copyright notice, this 13 | list of conditions and the following disclaimer. 14 | * Redistributions in binary form must reproduce the above copyright notice, 15 | this list of conditions and the following disclaimer in the documentation 16 | and/or other materials provided with the distribution. 17 | * Neither the name of the organization nor the names of its contributors may 18 | be used to endorse or promote products derived from this software without 19 | specific prior written permission. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 25 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | POSSIBILITY OF SUCH DAMAGE. 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AcquireRelease 2 | 3 | AcquireRelease is a sample application which complements the blog post, [This Is Why They Call It a Weakly-Ordered CPU](http://preshing.com/20121019/this-is-why-they-call-it-a-weakly-ordered-cpu). 4 | 5 | It demonstrates the kind of memory reordering which only happens on weakly-ordered CPUs, assuming no compiler reordering takes place. 6 | 7 | ## Requirements 8 | 9 | [CMake](http://www.cmake.org/cmake/resources/software.html) 2.8.9 or later. It might work using earlier versions of CMake if you edit `CMakeLists.txt`, but I didn't test this. The CMake executable must be available in your path. 10 | 11 | A compiler toolchain which supports C++11 threads and atomics. I tested it using Xcode 4.5.1 on OSX Mountain Lion 10.8.2, and Visual Studio 2012 on Windows 7. 12 | 13 | If you're targeting iOS, your device must be running iOS 5.0 or later. You must also have your developer certificate and provisioning profiles already set up. If you're able to build and run sample applications, you should be good to go. 14 | 15 | ## How to Build and Run on iOS Devices 16 | 17 | Run `generate-xcode-iphone.py`. 18 | 19 | Open `build/AcquireRelease.xcodeproj`. 20 | 21 | Select **AcquireRelease** as the target scheme using the drop-down list available by clicking the **Scheme** box. 22 | 23 | Click **Run**. 24 | 25 | Notes: 26 | 27 | * The Xcode project is generated using a slightly modified version of [this CMake toolchain file](http://code.google.com/p/ios-cmake/). Specifically, I modified it to additionally search for the iOS Developer folder under `/Applications/Xcode.app/Contents/`, which is where it was for me after installing Xcode via the App Store on Mountain Lion. 28 | * When using the resulting generated Xcode project, you won't be able to set source-level breakpoints. Assembly-level breakpoints still work, though. 29 | 30 | ## How to Build on Other Platforms 31 | 32 | Make a `build` subdirectory, run `cmake -G "" ..` in that subdirectory, then use the resulting solution, project or makefile. To see a list of available generators, run `cmake` by itself. For example, for Visual Studio 2012, I used the following command line: 33 | 34 | ``` 35 | cmake -G "Visual Studio 11" .. 36 | ``` 37 | -------------------------------------------------------------------------------- /generate-xcode-iphone.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | import os 3 | import sys 4 | 5 | # Change working directory to the one containing this script 6 | os.chdir(os.path.split(sys.argv[0])[0]) 7 | 8 | # Create build subfolder and chdir into it 9 | if not os.path.isdir("build"): 10 | os.mkdir("build") 11 | os.chdir("build") 12 | 13 | # Run cmake with the correct arguments 14 | os.system("cmake -DCMAKE_TOOLCHAIN_FILE=../iOS.cmake -GXcode ..") 15 | -------------------------------------------------------------------------------- /iOS.cmake: -------------------------------------------------------------------------------- 1 | # This file is based off of the Platform/Darwin.cmake and Platform/UnixPaths.cmake 2 | # files which are included with CMake 2.8.4 3 | # It has been altered for iOS development 4 | 5 | # Options: 6 | # 7 | # IOS_PLATFORM = OS (default) or SIMULATOR 8 | # This decides if SDKS will be selected from the iPhoneOS.platform or iPhoneSimulator.platform folders 9 | # OS - the default, used to build for iPhone and iPad physical devices, which have an arm arch. 10 | # SIMULATOR - used to build for the Simulator platforms, which have an x86 arch. 11 | # 12 | # CMAKE_IOS_DEVELOPER_ROOT = automatic(default) or /path/to/platform/Developer folder 13 | # By default this location is automatcially chosen based on the IOS_PLATFORM value above. 14 | # If set manually, it will override the default location and force the user of a particular Developer Platform 15 | # 16 | # CMAKE_IOS_SDK_ROOT = automatic(default) or /path/to/platform/Developer/SDKs/SDK folder 17 | # By default this location is automatcially chosen based on the CMAKE_IOS_DEVELOPER_ROOT value. 18 | # In this case it will always be the most up-to-date SDK found in the CMAKE_IOS_DEVELOPER_ROOT path. 19 | # If set manually, this will force the use of a specific SDK version 20 | 21 | # Standard settings 22 | set (CMAKE_SYSTEM_NAME Darwin) 23 | set (CMAKE_SYSTEM_VERSION 1 ) 24 | set (UNIX True) 25 | set (APPLE True) 26 | set (IOS True) 27 | 28 | # Force the compilers to gcc for iOS 29 | include (CMakeForceCompiler) 30 | CMAKE_FORCE_C_COMPILER (gcc gcc) 31 | CMAKE_FORCE_CXX_COMPILER (g++ g++) 32 | 33 | # Skip the platform compiler checks for cross compiling 34 | set (CMAKE_CXX_COMPILER_WORKS TRUE) 35 | set (CMAKE_C_COMPILER_WORKS TRUE) 36 | 37 | # All iOS/Darwin specific settings - some may be redundant 38 | set (CMAKE_SHARED_LIBRARY_PREFIX "lib") 39 | set (CMAKE_SHARED_LIBRARY_SUFFIX ".dylib") 40 | set (CMAKE_SHARED_MODULE_PREFIX "lib") 41 | set (CMAKE_SHARED_MODULE_SUFFIX ".so") 42 | set (CMAKE_MODULE_EXISTS 1) 43 | set (CMAKE_DL_LIBS "") 44 | 45 | set (CMAKE_C_OSX_COMPATIBILITY_VERSION_FLAG "-compatibility_version ") 46 | set (CMAKE_C_OSX_CURRENT_VERSION_FLAG "-current_version ") 47 | set (CMAKE_CXX_OSX_COMPATIBILITY_VERSION_FLAG "${CMAKE_C_OSX_COMPATIBILITY_VERSION_FLAG}") 48 | set (CMAKE_CXX_OSX_CURRENT_VERSION_FLAG "${CMAKE_C_OSX_CURRENT_VERSION_FLAG}") 49 | 50 | # Hidden visibilty is required for cxx on iOS 51 | set (CMAKE_C_FLAGS "") 52 | set (CMAKE_CXX_FLAGS "-headerpad_max_install_names -fvisibility=hidden -fvisibility-inlines-hidden") 53 | 54 | set (CMAKE_C_LINK_FLAGS "-Wl,-search_paths_first ${CMAKE_C_LINK_FLAGS}") 55 | set (CMAKE_CXX_LINK_FLAGS "-Wl,-search_paths_first ${CMAKE_CXX_LINK_FLAGS}") 56 | 57 | set (CMAKE_PLATFORM_HAS_INSTALLNAME 1) 58 | set (CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "-dynamiclib -headerpad_max_install_names") 59 | set (CMAKE_SHARED_MODULE_CREATE_C_FLAGS "-bundle -headerpad_max_install_names") 60 | set (CMAKE_SHARED_MODULE_LOADER_C_FLAG "-Wl,-bundle_loader,") 61 | set (CMAKE_SHARED_MODULE_LOADER_CXX_FLAG "-Wl,-bundle_loader,") 62 | set (CMAKE_FIND_LIBRARY_SUFFIXES ".dylib" ".so" ".a") 63 | 64 | # hack: if a new cmake (which uses CMAKE_INSTALL_NAME_TOOL) runs on an old build tree 65 | # (where install_name_tool was hardcoded) and where CMAKE_INSTALL_NAME_TOOL isn't in the cache 66 | # and still cmake didn't fail in CMakeFindBinUtils.cmake (because it isn't rerun) 67 | # hardcode CMAKE_INSTALL_NAME_TOOL here to install_name_tool, so it behaves as it did before, Alex 68 | if (NOT DEFINED CMAKE_INSTALL_NAME_TOOL) 69 | find_program(CMAKE_INSTALL_NAME_TOOL install_name_tool) 70 | endif (NOT DEFINED CMAKE_INSTALL_NAME_TOOL) 71 | 72 | # Setup iOS platform 73 | if (NOT DEFINED IOS_PLATFORM) 74 | set (IOS_PLATFORM "OS") 75 | endif (NOT DEFINED IOS_PLATFORM) 76 | set (IOS_PLATFORM ${IOS_PLATFORM} CACHE STRING "Type of iOS Platform") 77 | 78 | # Check the platform selection and setup for developer root 79 | if (${IOS_PLATFORM} STREQUAL "OS") 80 | set (IOS_PLATFORM_LOCATION "iPhoneOS.platform") 81 | elseif (${IOS_PLATFORM} STREQUAL "SIMULATOR") 82 | set (IOS_PLATFORM_LOCATION "iPhoneSimulator.platform") 83 | else (${IOS_PLATFORM} STREQUAL "OS") 84 | message (FATAL_ERROR "Unsupported IOS_PLATFORM value selected. Please choose OS or SIMULATOR") 85 | endif (${IOS_PLATFORM} STREQUAL "OS") 86 | 87 | # Setup iOS developer location 88 | if (NOT DEFINED CMAKE_IOS_DEVELOPER_ROOT) 89 | set (CMAKE_IOS_DEVELOPER_ROOT "/Developer/Platforms/${IOS_PLATFORM_LOCATION}/Developer") 90 | if (NOT EXISTS "${CMAKE_IOS_DEVELOPER_ROOT}") 91 | set (CMAKE_IOS_DEVELOPER_ROOT "/Applications/Xcode.app/Contents/Developer/Platforms/${IOS_PLATFORM_LOCATION}/Developer") 92 | endif (NOT EXISTS "${CMAKE_IOS_DEVELOPER_ROOT}") 93 | endif (NOT DEFINED CMAKE_IOS_DEVELOPER_ROOT) 94 | set (CMAKE_IOS_DEVELOPER_ROOT ${CMAKE_IOS_DEVELOPER_ROOT} CACHE PATH "Location of iOS Platform") 95 | 96 | # Find and use the most recent iOS sdk 97 | if (NOT DEFINED CMAKE_IOS_SDK_ROOT) 98 | file (GLOB _CMAKE_IOS_SDKS "${CMAKE_IOS_DEVELOPER_ROOT}/SDKs/*") 99 | if (_CMAKE_IOS_SDKS) 100 | list (SORT _CMAKE_IOS_SDKS) 101 | list (REVERSE _CMAKE_IOS_SDKS) 102 | list (GET _CMAKE_IOS_SDKS 0 CMAKE_IOS_SDK_ROOT) 103 | else (_CMAKE_IOS_SDKS) 104 | message (FATAL_ERROR "No iOS SDK's found in default seach path ${CMAKE_IOS_DEVELOPER_ROOT}. Manually set CMAKE_IOS_SDK_ROOT or install the iOS SDK.") 105 | endif (_CMAKE_IOS_SDKS) 106 | message (STATUS "Toolchain using default iOS SDK: ${CMAKE_IOS_SDK_ROOT}") 107 | endif (NOT DEFINED CMAKE_IOS_SDK_ROOT) 108 | set (CMAKE_IOS_SDK_ROOT ${CMAKE_IOS_SDK_ROOT} CACHE PATH "Location of the selected iOS SDK") 109 | 110 | # Set the sysroot default to the most recent SDK 111 | set (CMAKE_OSX_SYSROOT ${CMAKE_IOS_SDK_ROOT} CACHE PATH "Sysroot used for iOS support") 112 | 113 | # set the architecture for iOS - using ARCHS_STANDARD_32_BIT sets armv6,armv7 and appears to be XCode's standard. 114 | # The other value that works is ARCHS_UNIVERSAL_IPHONE_OS but that sets armv7 only 115 | set (CMAKE_OSX_ARCHITECTURES "$(ARCHS_STANDARD_32_BIT)" CACHE string "Build architecture for iOS") 116 | 117 | # Set the find root to the iOS developer roots and to user defined paths 118 | set (CMAKE_FIND_ROOT_PATH ${CMAKE_IOS_DEVELOPER_ROOT} ${CMAKE_IOS_SDK_ROOT} ${CMAKE_PREFIX_PATH} CACHE string "iOS find search path root") 119 | 120 | # default to searching for frameworks first 121 | set (CMAKE_FIND_FRAMEWORK FIRST) 122 | 123 | # set up the default search directories for frameworks 124 | set (CMAKE_SYSTEM_FRAMEWORK_PATH 125 | ${CMAKE_IOS_SDK_ROOT}/System/Library/Frameworks 126 | ${CMAKE_IOS_SDK_ROOT}/System/Library/PrivateFrameworks 127 | ${CMAKE_IOS_SDK_ROOT}/Developer/Library/Frameworks 128 | ) 129 | 130 | # only search the iOS sdks, not the remainder of the host filesystem 131 | set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY) 132 | set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) 133 | set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) 134 | 135 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "randomdelay.h" 5 | 6 | using namespace std; 7 | 8 | atomic flag; 9 | int sharedValue = 0; 10 | 11 | RandomDelay randomDelay1(1, 60101); 12 | RandomDelay randomDelay2(2, 65535); 13 | 14 | void IncrementSharedValue10000000Times(RandomDelay& randomDelay) 15 | { 16 | int count = 0; 17 | while (count < 10000000) 18 | { 19 | randomDelay.doBusyWork(); 20 | int expected = 0; 21 | if (flag.compare_exchange_strong(expected, 1, memory_order_relaxed)) 22 | { 23 | // Lock was successful 24 | sharedValue++; 25 | flag.store(0, memory_order_relaxed); 26 | count++; 27 | } 28 | } 29 | } 30 | 31 | void Thread2Func() 32 | { 33 | IncrementSharedValue10000000Times(randomDelay2); 34 | } 35 | 36 | int main(int argc, char* argv[]) 37 | { 38 | RandomDelay::Initialize(); 39 | 40 | printf("is_lock_free: %s\n", flag.is_lock_free() ? "true" : "false"); 41 | 42 | for (;;) { 43 | sharedValue = 0; 44 | thread thread2(Thread2Func); 45 | IncrementSharedValue10000000Times(randomDelay1); 46 | thread2.join(); 47 | printf("sharedValue=%d\n", sharedValue); 48 | } 49 | 50 | return 0; 51 | } 52 | 53 | -------------------------------------------------------------------------------- /randomdelay.cpp: -------------------------------------------------------------------------------- 1 | #include "randomdelay.h" 2 | #include 3 | #include 4 | 5 | int RandomDelay::g_randomValues[65536]; 6 | 7 | void RandomDelay::Initialize() 8 | { 9 | for (int i = 0; i < 65536; i++) 10 | g_randomValues[i] = rand(); 11 | } 12 | 13 | RandomDelay::RandomDelay(int step, int wrap) : m_pos(0), m_step(step), m_wrap(wrap) 14 | { 15 | assert(step < kArraySize); 16 | assert(wrap < kArraySize); 17 | } 18 | 19 | void RandomDelay::doBusyWork() 20 | { 21 | int i; 22 | do 23 | { 24 | i = g_randomValues[m_pos]; 25 | m_pos += m_step; 26 | if (m_pos >= m_wrap) 27 | m_pos -= m_wrap; 28 | } 29 | while (i & 7); 30 | } 31 | 32 | -------------------------------------------------------------------------------- /randomdelay.h: -------------------------------------------------------------------------------- 1 | #ifndef __RANDOM_DELAY_H__ 2 | #define __RANDOM_DELAY_H__ 3 | 4 | 5 | //------------------------------------- 6 | // RandomDelay 7 | //------------------------------------- 8 | class RandomDelay 9 | { 10 | private: 11 | static const int kArraySize = 65536; 12 | static int g_randomValues[kArraySize]; 13 | 14 | unsigned int m_pos; 15 | unsigned int m_step; 16 | unsigned int m_wrap; 17 | 18 | public: 19 | static void Initialize(); 20 | 21 | RandomDelay(int step, int wrap); 22 | void doBusyWork(); 23 | }; 24 | 25 | 26 | #endif // __RANDOM_DELAY_H__ 27 | --------------------------------------------------------------------------------