1 /****************************************************************************** 2 * Copyright (c) 2011, Duane Merrill. All rights reserved. 3 * Copyright (c) 2011-2018, NVIDIA CORPORATION. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * * Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * * Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * * Neither the name of the NVIDIA CORPORATION nor the 13 * names of its contributors may be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY 20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 * 27 ******************************************************************************/ 28 29 /** 30 * \file 31 * Simple portable mutex 32 */ 33 34 35 #pragma once 36 37 #if (__cplusplus > 199711L) || (defined(_MSC_VER) && _MSC_VER >= 1800) 38 #include <mutex> 39 #else 40 #if defined(_WIN32) || defined(_WIN64) 41 #include <intrin.h> 42 43 #define WIN32_LEAN_AND_MEAN 44 #define NOMINMAX 45 #include <windows.h> 46 #undef WIN32_LEAN_AND_MEAN 47 #undef NOMINMAX 48 49 /** 50 * Compiler read/write barrier 51 */ 52 #pragma intrinsic(_ReadWriteBarrier) 53 54 #endif 55 #endif 56 57 #include "../util_namespace.cuh" 58 59 60 /// Optional outer namespace(s) 61 THRUST_CUB_NS_PREFIX 62 63 /// CUB namespace 64 namespace cub { 65 66 67 /** 68 * Simple portable mutex 69 * - Wraps std::mutex when compiled with C++11 or newer (supported on all platforms) 70 * - Uses GNU/Windows spinlock mechanisms for pre C++11 (supported on x86/x64 when compiled with cl.exe or g++) 71 */ 72 struct Mutex 73 { 74 #if (__cplusplus > 199711L) || (defined(_MSC_VER) && _MSC_VER >= 1800) 75 76 std::mutex mtx; 77 Lockcub::Mutex78 void Lock() 79 { 80 mtx.lock(); 81 } 82 Unlockcub::Mutex83 void Unlock() 84 { 85 mtx.unlock(); 86 } 87 TryLockcub::Mutex88 void TryLock() 89 { 90 mtx.try_lock(); 91 } 92 93 #else //__cplusplus > 199711L 94 95 #if defined(_MSC_VER) 96 97 // Microsoft VC++ 98 typedef long Spinlock; 99 100 #else 101 102 // GNU g++ 103 typedef int Spinlock; 104 105 /** 106 * Compiler read/write barrier 107 */ 108 __forceinline__ void _ReadWriteBarrier() 109 { 110 __sync_synchronize(); 111 } 112 113 /** 114 * Atomic exchange 115 */ 116 __forceinline__ long _InterlockedExchange(volatile int * const Target, const int Value) 117 { 118 // NOTE: __sync_lock_test_and_set would be an acquire barrier, so we force a full barrier 119 _ReadWriteBarrier(); 120 return __sync_lock_test_and_set(Target, Value); 121 } 122 123 /** 124 * Pause instruction to prevent excess processor bus usage 125 */ 126 __forceinline__ void YieldProcessor() 127 { 128 } 129 130 #endif // defined(_MSC_VER) 131 132 /// Lock member 133 volatile Spinlock lock; 134 135 /** 136 * Constructor 137 */ 138 Mutex() : lock(0) {} 139 140 /** 141 * Return when the specified spinlock has been acquired 142 */ 143 __forceinline__ void Lock() 144 { 145 while (1) 146 { 147 if (!_InterlockedExchange(&lock, 1)) return; 148 while (lock) YieldProcessor(); 149 } 150 } 151 152 153 /** 154 * Release the specified spinlock 155 */ 156 __forceinline__ void Unlock() 157 { 158 _ReadWriteBarrier(); 159 lock = 0; 160 } 161 162 #endif // __cplusplus > 199711L 163 164 }; 165 166 167 168 169 } // CUB namespace 170 THRUST_CUB_NS_POSTFIX // Optional outer namespace(s) 171 172