P4 to Git Change 1398097 by lmoriche@lmoriche_opencl_dev2 on 2017/04/13 13:01:56

SWDEV-102733 - [OCL-LC-ROCm] Cmake build Write CMakeLists.txt to enable building with and without the DK environment
	- Change the coding convention of the runtime files. Use Google's Style (https://google.github.io/styleguide/cppguide.html).

Affected files ...

... //depot/stg/opencl/drivers/opencl/.clang-format#1 add
... //depot/stg/opencl/drivers/opencl/api/opencl/amdocl/cl_agent_amd.h#2 edit
... //depot/stg/opencl/drivers/opencl/api/opencl/amdocl/cl_command.cpp#13 edit
... //depot/stg/opencl/drivers/opencl/api/opencl/amdocl/cl_context.cpp#53 edit
... //depot/stg/opencl/drivers/opencl/api/opencl/amdocl/cl_counter.cpp#2 edit
... //depot/stg/opencl/drivers/opencl/api/opencl/amdocl/cl_d3d10.cpp#15 edit
... //depot/stg/opencl/drivers/opencl/api/opencl/amdocl/cl_d3d11.cpp#22 edit
... //depot/stg/opencl/drivers/opencl/api/opencl/amdocl/cl_d3d9.cpp#32 edit
... //depot/stg/opencl/drivers/opencl/api/opencl/amdocl/cl_debugger_amd.cpp#8 edit
... //depot/stg/opencl/drivers/opencl/api/opencl/amdocl/cl_debugger_amd.h#7 edit
... //depot/stg/opencl/drivers/opencl/api/opencl/amdocl/cl_device.cpp#61 edit
... //depot/stg/opencl/drivers/opencl/api/opencl/amdocl/cl_event.cpp#10 edit
... //depot/stg/opencl/drivers/opencl/api/opencl/amdocl/cl_execute.cpp#23 edit
... //depot/stg/opencl/drivers/opencl/api/opencl/amdocl/cl_gl.cpp#53 edit
... //depot/stg/opencl/drivers/opencl/api/opencl/amdocl/cl_icd.cpp#27 edit
... //depot/stg/opencl/drivers/opencl/api/opencl/amdocl/cl_icd_amd.h#18 edit
... //depot/stg/opencl/drivers/opencl/api/opencl/amdocl/cl_kernel.h#24 edit
... //depot/stg/opencl/drivers/opencl/api/opencl/amdocl/cl_kernel_info_amd.cpp#3 edit
... //depot/stg/opencl/drivers/opencl/api/opencl/amdocl/cl_kernel_info_amd.h#4 edit
... //depot/stg/opencl/drivers/opencl/api/opencl/amdocl/cl_lqdflash_amd.cpp#17 edit
... //depot/stg/opencl/drivers/opencl/api/opencl/amdocl/cl_lqdflash_amd.h#6 edit
... //depot/stg/opencl/drivers/opencl/api/opencl/amdocl/cl_memobj.cpp#81 edit
... //depot/stg/opencl/drivers/opencl/api/opencl/amdocl/cl_object.cpp#3 edit
... //depot/stg/opencl/drivers/opencl/api/opencl/amdocl/cl_pipe.cpp#6 edit
... //depot/stg/opencl/drivers/opencl/api/opencl/amdocl/cl_platform_amd.cpp#2 edit
... //depot/stg/opencl/drivers/opencl/api/opencl/amdocl/cl_platform_amd.h#2 edit
... //depot/stg/opencl/drivers/opencl/api/opencl/amdocl/cl_profile_amd.cpp#3 edit
... //depot/stg/opencl/drivers/opencl/api/opencl/amdocl/cl_profile_amd.h#2 edit
... //depot/stg/opencl/drivers/opencl/api/opencl/amdocl/cl_program.cpp#41 edit
... //depot/stg/opencl/drivers/opencl/api/opencl/amdocl/cl_sampler.cpp#6 edit
... //depot/stg/opencl/drivers/opencl/api/opencl/amdocl/cl_sdi_amd.cpp#3 edit
... //depot/stg/opencl/drivers/opencl/api/opencl/amdocl/cl_sdi_amd.h#2 edit
... //depot/stg/opencl/drivers/opencl/api/opencl/amdocl/cl_semaphore_amd.h#3 edit
... //depot/stg/opencl/drivers/opencl/api/opencl/amdocl/cl_svm.cpp#20 edit
... //depot/stg/opencl/drivers/opencl/api/opencl/amdocl/cl_thread_trace_amd.cpp#8 edit
... //depot/stg/opencl/drivers/opencl/api/opencl/amdocl/cl_thread_trace_amd.h#4 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/appprofile.cpp#17 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/appprofile.hpp#12 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/blit.cpp#4 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/blit.hpp#4 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/blitcl.cpp#11 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/cpu/cpubinary.cpp#11 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/cpu/cpubinary.hpp#4 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/cpu/cpubuiltins.cpp#13 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/cpu/cpubuiltins.hpp#4 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/cpu/cpucommand.cpp#66 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/cpu/cpucommand.hpp#40 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/cpu/cpudevice.cpp#280 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/cpu/cpudevice.hpp#96 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/cpu/cpufeat.hpp#3 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/cpu/cpukernel.hpp#8 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/cpu/cpumapping.cpp#6 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/cpu/cpumapping.hpp#4 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/cpu/cpuprogram.cpp#70 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/cpu/cpuprogram.hpp#14 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/cpu/cpusettings.cpp#33 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/cpu/cpusettings.hpp#2 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/cpu/cputables.hpp#5 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/cpu/cpuvirtual.cpp#26 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/cpu/cpuvirtual.hpp#13 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/device.cpp#209 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/device.hpp#284 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpuappprofile.cpp#12 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpuappprofile.hpp#7 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpubinary.cpp#58 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpubinary.hpp#27 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpublit.cpp#126 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpublit.hpp#41 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpucompiler.cpp#156 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpuconstbuf.cpp#10 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpuconstbuf.hpp#7 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpucounters.cpp#12 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpucounters.hpp#9 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpudebugger.hpp#7 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpudebugmanager.cpp#10 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpudebugmanager.hpp#6 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpudefs.hpp#147 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpudevice.cpp#567 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpudevice.hpp#163 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpukernel.cpp#318 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpukernel.hpp#126 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpumemory.cpp#131 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpumemory.hpp#50 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpuprintf.cpp#44 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpuprintf.hpp#15 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpuprogram.cpp#232 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpuprogram.hpp#69 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpuresource.cpp#238 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpuresource.hpp#87 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpusched.hpp#19 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpuschedcl.cpp#35 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpuscsi.cpp#37 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpusettings.cpp#350 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpusettings.hpp#98 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gputhreadtrace.cpp#9 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gputhreadtrace.hpp#7 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gputimestamp.cpp#27 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gputimestamp.hpp#16 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gputrap.hpp#4 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpuvirtual.cpp#410 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpuvirtual.hpp#140 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpuwavelimiter.cpp#13 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpuwavelimiter.hpp#9 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/hwdebug.cpp#7 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/hwdebug.hpp#8 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/palappprofile.cpp#2 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/palappprofile.hpp#3 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/palbinary.cpp#2 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/palbinary.hpp#3 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/palblit.cpp#13 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/palblit.hpp#5 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/palcompiler.cpp#15 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/palconstbuf.cpp#2 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/palconstbuf.hpp#3 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/palcounters.cpp#11 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/palcounters.hpp#9 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/paldebugger.hpp#3 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/paldebugmanager.cpp#2 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/paldebugmanager.hpp#3 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/paldefs.hpp#16 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/paldevice.cpp#45 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/paldevice.hpp#16 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/paldeviced3d10.cpp#2 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/paldeviced3d11.cpp#2 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/paldeviced3d9.cpp#2 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/paldevicegl.cpp#4 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/palkernel.cpp#34 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/palkernel.hpp#11 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/palmemory.cpp#13 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/palmemory.hpp#3 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/palprintf.cpp#5 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/palprintf.hpp#3 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/palprogram.cpp#39 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/palprogram.hpp#17 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/palresource.cpp#28 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/palresource.hpp#12 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/palsched.hpp#3 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/palschedcl.cpp#4 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/palsettings.cpp#24 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/palsettings.hpp#10 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/palthreadtrace.cpp#3 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/palthreadtrace.hpp#5 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/paltimestamp.cpp#2 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/paltimestamp.hpp#3 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/paltrap.hpp#2 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/palvirtual.cpp#48 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/palvirtual.hpp#21 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/palwavelimiter.cpp#3 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/palwavelimiter.hpp#4 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/rocm/mesa_glinterop.h#4 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/rocm/rocappprofile.cpp#6 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/rocm/rocappprofile.hpp#4 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/rocm/rocbinary.hpp#4 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/rocm/rocblit.cpp#17 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/rocm/rocblit.hpp#8 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/rocm/roccompiler.cpp#32 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/rocm/roccompilerlib.cpp#6 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/rocm/roccompilerlib.hpp#5 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/rocm/rocdefs.hpp#10 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/rocm/rocdevice.cpp#48 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/rocm/rocdevice.hpp#20 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/rocm/rocglinterop.cpp#4 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/rocm/rocglinterop.hpp#4 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/rocm/rockernel.cpp#22 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/rocm/rockernel.hpp#16 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/rocm/rocmemory.cpp#15 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/rocm/rocmemory.hpp#8 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/rocm/rocprintf.cpp#7 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/rocm/rocprintf.hpp#5 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/rocm/rocprogram.cpp#64 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/rocm/rocprogram.hpp#23 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/rocm/rocregisters.hpp#4 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/rocm/rocsettings.cpp#17 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/rocm/rocsettings.hpp#8 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/rocm/rocvirtual.cpp#34 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/rocm/rocvirtual.hpp#10 edit
... //depot/stg/opencl/drivers/opencl/runtime/os/alloc.cpp#7 edit
... //depot/stg/opencl/drivers/opencl/runtime/os/alloc.hpp#4 edit
... //depot/stg/opencl/drivers/opencl/runtime/os/os.cpp#8 edit
... //depot/stg/opencl/drivers/opencl/runtime/os/os.hpp#30 edit
... //depot/stg/opencl/drivers/opencl/runtime/os/os_posix.cpp#42 edit
... //depot/stg/opencl/drivers/opencl/runtime/os/os_win32.cpp#47 edit
... //depot/stg/opencl/drivers/opencl/runtime/platform/agent.cpp#8 edit
... //depot/stg/opencl/drivers/opencl/runtime/platform/agent.hpp#6 edit
... //depot/stg/opencl/drivers/opencl/runtime/platform/command.cpp#78 edit
... //depot/stg/opencl/drivers/opencl/runtime/platform/command.hpp#83 edit
... //depot/stg/opencl/drivers/opencl/runtime/platform/commandqueue.cpp#23 edit
... //depot/stg/opencl/drivers/opencl/runtime/platform/commandqueue.hpp#18 edit
... //depot/stg/opencl/drivers/opencl/runtime/platform/context.cpp#42 edit
... //depot/stg/opencl/drivers/opencl/runtime/platform/context.hpp#26 edit
... //depot/stg/opencl/drivers/opencl/runtime/platform/counter.hpp#4 edit
... //depot/stg/opencl/drivers/opencl/runtime/platform/interop.hpp#12 edit
... //depot/stg/opencl/drivers/opencl/runtime/platform/kernel.cpp#23 edit
... //depot/stg/opencl/drivers/opencl/runtime/platform/kernel.hpp#18 edit
... //depot/stg/opencl/drivers/opencl/runtime/platform/memory.cpp#127 edit
... //depot/stg/opencl/drivers/opencl/runtime/platform/memory.hpp#100 edit
... //depot/stg/opencl/drivers/opencl/runtime/platform/ndrange.cpp#8 edit
... //depot/stg/opencl/drivers/opencl/runtime/platform/ndrange.hpp#9 edit
... //depot/stg/opencl/drivers/opencl/runtime/platform/object.cpp#2 edit
... //depot/stg/opencl/drivers/opencl/runtime/platform/object.hpp#17 edit
... //depot/stg/opencl/drivers/opencl/runtime/platform/perfctr.hpp#5 edit
... //depot/stg/opencl/drivers/opencl/runtime/platform/program.cpp#86 edit
... //depot/stg/opencl/drivers/opencl/runtime/platform/program.hpp#41 edit
... //depot/stg/opencl/drivers/opencl/runtime/platform/runtime.cpp#35 edit
... //depot/stg/opencl/drivers/opencl/runtime/platform/runtime.hpp#4 edit
... //depot/stg/opencl/drivers/opencl/runtime/platform/sampler.hpp#8 edit
... //depot/stg/opencl/drivers/opencl/runtime/platform/threadtrace.hpp#6 edit
... //depot/stg/opencl/drivers/opencl/runtime/thread/atomic.hpp#7 edit
... //depot/stg/opencl/drivers/opencl/runtime/thread/monitor.cpp#7 edit
... //depot/stg/opencl/drivers/opencl/runtime/thread/monitor.hpp#8 edit
... //depot/stg/opencl/drivers/opencl/runtime/thread/semaphore.cpp#10 edit
... //depot/stg/opencl/drivers/opencl/runtime/thread/semaphore.hpp#7 edit
... //depot/stg/opencl/drivers/opencl/runtime/thread/thread.cpp#14 edit
... //depot/stg/opencl/drivers/opencl/runtime/thread/thread.hpp#15 edit
... //depot/stg/opencl/drivers/opencl/runtime/top.hpp#26 edit
... //depot/stg/opencl/drivers/opencl/runtime/utils/concurrent.hpp#8 edit
... //depot/stg/opencl/drivers/opencl/runtime/utils/debug.cpp#5 edit
... //depot/stg/opencl/drivers/opencl/runtime/utils/debug.hpp#7 edit
... //depot/stg/opencl/drivers/opencl/runtime/utils/flags.cpp#16 edit
... //depot/stg/opencl/drivers/opencl/runtime/utils/flags.hpp#271 edit
... //depot/stg/opencl/drivers/opencl/runtime/utils/macros.hpp#8 edit
... //depot/stg/opencl/drivers/opencl/runtime/utils/util.hpp#12 edit
... //depot/stg/opencl/drivers/opencl/runtime/utils/versions.hpp#2150 edit


[ROCm/clr commit: 465c1c0287]
Tento commit je obsažen v:
foreman
2017-04-13 13:56:38 -04:00
rodič 211ca254bf
revize 3a8d567489
188 změnil soubory, kde provedl 68133 přidání a 78048 odebrání
+252 -359
Zobrazit soubor
@@ -17,11 +17,11 @@
#include <type_traits>
#ifdef _WIN32
# include <intrin.h>
#include <intrin.h>
#elif defined(ATI_ARCH_X86)
# include <emmintrin.h>
# include <xmmintrin.h>
#endif // !_WIN32
#include <emmintrin.h>
#include <xmmintrin.h>
#endif // !_WIN32
#include <atomic>
#include <utility>
@@ -37,135 +37,111 @@ namespace amd {
/*! \brief Static functions for atomic operations.
*/
class AtomicOperation : AllStatic
{
private:
//! Template to specialize atomic intrinsics on register size.
template <int N>
struct Intrinsics {
/*! \brief %Atomic add.
*
* Atomically add \a inc to \a *dest and return the prior value.
*/
template <typename T>
static inline T add(T increment, volatile T* dest);
/*! \brief %Atomic exchange.
*
* Atomically exchange value with *dest and return the prior value.
*/
template <typename T>
static inline T swap(T value, volatile T* dest);
/*! \brief %Atomic compare and exchange.
*
* Atomically compare and xchge value with *dest if *dest == compare.
* Return the prior value.
*/
template <typename T>
static inline T compareAndSwap(T compare, volatile T* dest, T value);
/*! \brief %Atomic increment.
*
* Atomically increment *dest and return the prior value.
*/
template <typename T>
static inline T increment(volatile T* dest);
/*! \brief %Atomic exchange.
*
* Atomically decrement *dest and return the prior value.
*/
template <typename T>
static inline T decrement(volatile T* dest);
/*! \brief %Atomic or.
*
* Atomically or \a mask to \a *dest and return the prior value.
*/
template <typename T>
static inline T _or(T mask, volatile T* dest);
/*! \brief %Atomic and.
*
* Atomically and \a mask to \a *dest and return the prior value.
*/
template <typename T>
static inline T _and(T mask, volatile T* dest);
};
public:
class AtomicOperation : AllStatic {
private:
//! Template to specialize atomic intrinsics on register size.
template <int N> struct Intrinsics {
/*! \brief %Atomic add.
*
* Atomically add \a inc to \a *dest and return the prior value.
*/
template <typename T>
static T add(T inc, volatile T* dest)
{
return Intrinsics<sizeof(T)>::add((T) inc, dest);
}
template <typename T> static inline T add(T increment, volatile T* dest);
/*! \brief %Atomic exchange.
*
* Atomically exchange value with *dest and return the prior value.
*/
template <typename T>
static T swap(T value, volatile T* dest)
{
return Intrinsics<sizeof(T)>::swap(value, dest);
}
template <typename T> static inline T swap(T value, volatile T* dest);
/*! \brief %Atomic compare and exchange.
*
* Atomically compare and exchange value with *dest if *dest == compare.
* Atomically compare and xchge value with *dest if *dest == compare.
* Return the prior value.
*/
template <typename T>
static T compareAndSwap(T compare, volatile T* dest, T value)
{
return Intrinsics<sizeof(T)>::compareAndSwap(compare, dest, value);
}
template <typename T> static inline T compareAndSwap(T compare, volatile T* dest, T value);
/*! \brief %Atomic increment.
*
* Atomically increment *dest and return the prior value.
*/
template <typename T>
static T increment(volatile T* dest)
{
return Intrinsics<sizeof(T)>::increment(dest);
}
template <typename T> static inline T increment(volatile T* dest);
/*! \brief %Atomic decrement.
/*! \brief %Atomic exchange.
*
* Atomically decrement *dest and return the prior value.
*/
template <typename T>
static T decrement(volatile T* dest)
{
return Intrinsics<sizeof(T)>::decrement(dest);
}
template <typename T> static inline T decrement(volatile T* dest);
/*! \brief %Atomic or.
*
* Atomically or \a mask to \a *dest and return the prior value.
*/
template <typename T>
static T _or(T mask, volatile T* dest)
{
return Intrinsics<sizeof(T)>::_or((T) mask, dest);
}
template <typename T> static inline T _or(T mask, volatile T* dest);
/*! \brief %Atomic and.
*
* Atomically or \a mask to \a *dest and return the prior value.
* Atomically and \a mask to \a *dest and return the prior value.
*/
template <typename T>
static T _and(T mask, volatile T* dest)
{
return Intrinsics<sizeof(T)>::_and((T) mask, dest);
}
template <typename T> static inline T _and(T mask, volatile T* dest);
};
public:
/*! \brief %Atomic add.
*
* Atomically add \a inc to \a *dest and return the prior value.
*/
template <typename T> static T add(T inc, volatile T* dest) {
return Intrinsics<sizeof(T)>::add((T)inc, dest);
}
/*! \brief %Atomic exchange.
*
* Atomically exchange value with *dest and return the prior value.
*/
template <typename T> static T swap(T value, volatile T* dest) {
return Intrinsics<sizeof(T)>::swap(value, dest);
}
/*! \brief %Atomic compare and exchange.
*
* Atomically compare and exchange value with *dest if *dest == compare.
* Return the prior value.
*/
template <typename T> static T compareAndSwap(T compare, volatile T* dest, T value) {
return Intrinsics<sizeof(T)>::compareAndSwap(compare, dest, value);
}
/*! \brief %Atomic increment.
*
* Atomically increment *dest and return the prior value.
*/
template <typename T> static T increment(volatile T* dest) {
return Intrinsics<sizeof(T)>::increment(dest);
}
/*! \brief %Atomic decrement.
*
* Atomically decrement *dest and return the prior value.
*/
template <typename T> static T decrement(volatile T* dest) {
return Intrinsics<sizeof(T)>::decrement(dest);
}
/*! \brief %Atomic or.
*
* Atomically or \a mask to \a *dest and return the prior value.
*/
template <typename T> static T _or(T mask, volatile T* dest) {
return Intrinsics<sizeof(T)>::_or((T)mask, dest);
}
/*! \brief %Atomic and.
*
* Atomically or \a mask to \a *dest and return the prior value.
*/
template <typename T> static T _and(T mask, volatile T* dest) {
return Intrinsics<sizeof(T)>::_and((T)mask, dest);
}
};
/*@}*/
@@ -174,193 +150,139 @@ public:
template <>
template <typename T>
inline T
AtomicOperation::Intrinsics<4>::add(T increment, volatile T* dest)
{
return (T)_InterlockedExchangeAdd(
(volatile long*)dest, (long)increment);
inline T AtomicOperation::Intrinsics<4>::add(T increment, volatile T* dest) {
return (T)_InterlockedExchangeAdd((volatile long*)dest, (long)increment);
}
template <>
template <typename T>
inline T
AtomicOperation::Intrinsics<4>::swap(T value, volatile T* dest)
{
return (T)_InterlockedExchange(
(volatile long*)dest, (long)value);
inline T AtomicOperation::Intrinsics<4>::swap(T value, volatile T* dest) {
return (T)_InterlockedExchange((volatile long*)dest, (long)value);
}
template <>
template <typename T>
inline T
AtomicOperation::Intrinsics<4>::compareAndSwap(
T compare, volatile T* dest, T value)
{
return (T)_InterlockedCompareExchange(
(volatile long*)dest, (long)value, (long)compare);
inline T AtomicOperation::Intrinsics<4>::compareAndSwap(T compare, volatile T* dest, T value) {
return (T)_InterlockedCompareExchange((volatile long*)dest, (long)value, (long)compare);
}
template <>
template <typename T>
inline T
AtomicOperation::Intrinsics<4>::increment(volatile T* dest)
{
return (T)(_InterlockedIncrement((volatile long*)dest) - 1L);
inline T AtomicOperation::Intrinsics<4>::increment(volatile T* dest) {
return (T)(_InterlockedIncrement((volatile long*)dest) - 1L);
}
template <>
template <typename T>
inline T
AtomicOperation::Intrinsics<4>::decrement(volatile T* dest)
{
return (T)(_InterlockedDecrement((volatile long*)dest) + 1L);
inline T AtomicOperation::Intrinsics<4>::decrement(volatile T* dest) {
return (T)(_InterlockedDecrement((volatile long*)dest) + 1L);
}
template <>
template <typename T>
inline T
AtomicOperation::Intrinsics<4>::_or(T mask, volatile T* dest)
{
return (T)_InterlockedOr(
(volatile long*)dest, (long)mask);
inline T AtomicOperation::Intrinsics<4>::_or(T mask, volatile T* dest) {
return (T)_InterlockedOr((volatile long*)dest, (long)mask);
}
template <>
template <typename T>
inline T
AtomicOperation::Intrinsics<4>::_and(T mask, volatile T* dest)
{
return (T)_InterlockedAnd(
(volatile long*)dest, (long)mask);
inline T AtomicOperation::Intrinsics<4>::_and(T mask, volatile T* dest) {
return (T)_InterlockedAnd((volatile long*)dest, (long)mask);
}
#ifdef _WIN64
template <>
template <typename T>
inline T
AtomicOperation::Intrinsics<8>::add(T increment, volatile T* dest)
{
return (T)_InterlockedExchangeAdd64(
(volatile __int64*)dest, (__int64)increment);
inline T AtomicOperation::Intrinsics<8>::add(T increment, volatile T* dest) {
return (T)_InterlockedExchangeAdd64((volatile __int64*)dest, (__int64)increment);
}
template <>
template <typename T>
inline T
AtomicOperation::Intrinsics<8>::swap(T value, volatile T* dest)
{
return (T)_InterlockedExchange64(
(volatile __int64*)dest, (__int64)value);
inline T AtomicOperation::Intrinsics<8>::swap(T value, volatile T* dest) {
return (T)_InterlockedExchange64((volatile __int64*)dest, (__int64)value);
}
template <>
template <typename T>
inline T
AtomicOperation::Intrinsics<8>::compareAndSwap(
T compare, volatile T* dest, T value)
{
return (T)_InterlockedCompareExchange64(
(volatile __int64*)dest, (__int64)value, (__int64)compare);
inline T AtomicOperation::Intrinsics<8>::compareAndSwap(T compare, volatile T* dest, T value) {
return (T)_InterlockedCompareExchange64((volatile __int64*)dest, (__int64)value,
(__int64)compare);
}
template <>
template <typename T>
inline T
AtomicOperation::Intrinsics<8>::increment(volatile T* dest)
{
return (T)(_InterlockedIncrement64((volatile __int64*)dest) - 1LL);
inline T AtomicOperation::Intrinsics<8>::increment(volatile T* dest) {
return (T)(_InterlockedIncrement64((volatile __int64*)dest) - 1LL);
}
template <>
template <typename T>
inline T
AtomicOperation::Intrinsics<8>::decrement(volatile T* dest)
{
return (T)(_InterlockedDecrement64((volatile __int64*)dest) + 1LL);
inline T AtomicOperation::Intrinsics<8>::decrement(volatile T* dest) {
return (T)(_InterlockedDecrement64((volatile __int64*)dest) + 1LL);
}
template <>
template <typename T>
inline T
AtomicOperation::Intrinsics<8>::_or(T mask, volatile T* dest)
{
return (T)_InterlockedOr64(
(volatile long*)dest, (long)mask);
inline T AtomicOperation::Intrinsics<8>::_or(T mask, volatile T* dest) {
return (T)_InterlockedOr64((volatile long*)dest, (long)mask);
}
template <>
template <typename T>
inline T
AtomicOperation::Intrinsics<8>::_and(T mask, volatile T* dest)
{
return (T)_InterlockedAnd64(
(volatile long*)dest, (long)mask);
inline T AtomicOperation::Intrinsics<8>::_and(T mask, volatile T* dest) {
return (T)_InterlockedAnd64((volatile long*)dest, (long)mask);
}
#endif // _LP64
#endif // _LP64
#elif defined(__GNUC__)
template <int N>
template <typename T>
inline T
AtomicOperation::Intrinsics<N>::add(T inc, volatile T* dest)
{
return __sync_fetch_and_add(dest, inc);
}
template<int N>
template <typename T>
inline T
AtomicOperation::Intrinsics<N>::swap(T value, volatile T* dest)
{
return __sync_lock_test_and_set(dest, value);
inline T AtomicOperation::Intrinsics<N>::add(T inc, volatile T* dest) {
return __sync_fetch_and_add(dest, inc);
}
template <int N>
template <typename T>
inline T
AtomicOperation::Intrinsics<N>::compareAndSwap(
T compare, volatile T* dest, T value)
{
return __sync_val_compare_and_swap(dest, compare, value);
}
template<int N>
template <typename T>
inline T
AtomicOperation::Intrinsics<N>::increment(volatile T* dest)
{
return add(T(1), dest);
}
template<int N>
template <typename T>
inline T
AtomicOperation::Intrinsics<N>::decrement(volatile T* dest)
{
return add(T(-1), dest);
inline T AtomicOperation::Intrinsics<N>::swap(T value, volatile T* dest) {
return __sync_lock_test_and_set(dest, value);
}
template <int N>
template <typename T>
inline T
AtomicOperation::Intrinsics<N>::_or(T mask, volatile T* dest)
{
return __sync_fetch_and_or(dest, mask);
inline T AtomicOperation::Intrinsics<N>::compareAndSwap(T compare, volatile T* dest, T value) {
return __sync_val_compare_and_swap(dest, compare, value);
}
template <int N>
template <typename T>
inline T
AtomicOperation::Intrinsics<N>::_and(T mask, volatile T* dest)
{
return __sync_fetch_and_and(dest, mask);
inline T AtomicOperation::Intrinsics<N>::increment(volatile T* dest) {
return add(T(1), dest);
}
template <int N>
template <typename T>
inline T AtomicOperation::Intrinsics<N>::decrement(volatile T* dest) {
return add(T(-1), dest);
}
template <int N>
template <typename T>
inline T AtomicOperation::Intrinsics<N>::_or(T mask, volatile T* dest) {
return __sync_fetch_and_or(dest, mask);
}
template <int N>
template <typename T>
inline T AtomicOperation::Intrinsics<N>::_and(T mask, volatile T* dest) {
return __sync_fetch_and_and(dest, mask);
}
#else
# error Unimplemented
#error Unimplemented
#endif
/*! \addtogroup Atomic Atomic Operations
@@ -369,180 +291,151 @@ AtomicOperation::Intrinsics<N>::_and(T mask, volatile T* dest)
/*! \brief A variable of type T with atomic properties.
*/
template <typename T>
class Atomic
{
private:
template <typename T> class Atomic {
private:
typedef typename std::remove_volatile<
typename std::remove_pointer<typename std::remove_reference<T>::type>::type>::type value_type;
typename std::add_volatile<T>::type value_; //!< \brief The variable.
typedef typename std::remove_volatile<typename std::remove_pointer<
typename std::remove_reference<T>::type>::type>::type value_type;
typename std::add_volatile<T>::type value_; //!< \brief The variable.
public:
//! Construct a new %Atomic variable of type T.
Atomic() : value_(T(0)) {}
//! Construct a new %Atomic variable of type T from \a value.
Atomic(T value) : value_(value) {}
//! Construct a new %Atomic variable of type T from another %Atomic.
Atomic(const Atomic<T>& atomic) : value_(atomic.value_) {}
//! Copy value into this %Atomic variable.
Atomic<T>& operator=(T value) {
value_ = value;
return *this;
}
public:
//! Construct a new %Atomic variable of type T.
Atomic() : value_(T(0)) {}
//! Construct a new %Atomic variable of type T from \a value.
Atomic(T value) : value_(value) {}
//! Construct a new %Atomic variable of type T from another %Atomic.
Atomic(const Atomic<T>& atomic) : value_(atomic.value_) { }
//! Copy value into this %Atomic variable.
Atomic<T>& operator = (T value)
{
value_ = value;
return *this;
//! Return the %Atomic variable value.
operator T() const { return T(value_); }
//! Return the %Atomic variable value.
T operator->() const { return T(value_); }
//! Return the %Atomic variable's address.
typename std::add_pointer<typename std::add_volatile<value_type>::type>::type operator&() {
return &value_;
}
//! Atomically add \a inc to this variable.
Atomic<T>& operator+=(value_type inc) {
if (std::is_pointer<T>::value) {
inc *= sizeof(typename std::remove_pointer<T>::type);
}
AtomicOperation::add(inc, &value_);
return *this;
}
//! Return the %Atomic variable value.
operator T () const { return T(value_); }
//! Return the %Atomic variable value.
T operator ->() const { return T(value_); }
//! Return the %Atomic variable's address.
typename std::add_pointer<typename std::add_volatile<value_type>::type>::
type operator &() { return &value_; }
//! Atomically add \a inc to this variable.
Atomic<T>& operator += (value_type inc)
{
if (std::is_pointer<T>::value) {
inc *= sizeof(typename std::remove_pointer<T>::type);
}
AtomicOperation::add(inc, &value_);
return *this;
//! Atomically subtract \a inc to this variable.
Atomic<T>& operator-=(value_type inc) {
value_type modifier = 0;
if (std::is_pointer<T>::value) {
inc *= sizeof(typename std::remove_pointer<T>::type);
}
AtomicOperation::add(modifier - inc, &value_);
return *this;
}
//! Atomically subtract \a inc to this variable.
Atomic<T>& operator -= (value_type inc)
{
value_type modifier = 0;
if (std::is_pointer<T>::value) {
inc *= sizeof(typename std::remove_pointer<T>::type);
}
AtomicOperation::add(modifier - inc, &value_);
return *this;
}
//! Atomically OR \a value to this variable.
Atomic<T>& operator|=(value_type mask) {
AtomicOperation::_or(mask, &value_);
return *this;
}
//! Atomically OR \a value to this variable.
Atomic<T>& operator |= (value_type mask)
{
AtomicOperation::_or(mask, &value_);
return *this;
}
//! Atomically AND \a value to this variable.
Atomic<T>& operator&=(value_type mask) {
AtomicOperation::_and(mask, &value_);
return *this;
}
//! Atomically AND \a value to this variable.
Atomic<T>& operator &= (value_type mask)
{
AtomicOperation::_and(mask, &value_);
return *this;
//! Atomically increment this variable and return its new value.
typename std::remove_reference<T>::type operator++() {
if (std::is_pointer<T>::value) {
value_type inc = static_cast<value_type>(sizeof(typename std::remove_pointer<T>::type));
return AtomicOperation::add(inc, &value_) + 1;
} else {
return AtomicOperation::increment(&value_) + 1;
}
}
//! Atomically increment this variable and return its new value.
typename std::remove_reference<T>::type operator ++ ()
{
if (std::is_pointer<T>::value) {
value_type inc = static_cast<value_type>(
sizeof(typename std::remove_pointer<T>::type));
return AtomicOperation::add(inc, &value_) + 1;
}
else {
return AtomicOperation::increment(&value_) + 1;
}
//! Atomically decrement this variable and return its new value.
typename std::remove_reference<T>::type operator--() {
if (std::is_pointer<T>::value) {
value_type inc =
static_cast<value_type>(-static_cast<typename std::make_signed<value_type>::type>(
sizeof(typename std::remove_pointer<T>::type)));
return AtomicOperation::add(inc, &value_) - 1;
} else {
return AtomicOperation::decrement(&value_) - 1;
}
}
//! Atomically decrement this variable and return its new value.
typename std::remove_reference<T>::type operator -- ()
{
if (std::is_pointer<T>::value) {
value_type inc = static_cast<value_type>(-
static_cast<typename std::make_signed<value_type>::type>(
sizeof(typename std::remove_pointer<T>::type)));
return AtomicOperation::add(inc, &value_) - 1;
}
else {
return AtomicOperation::decrement(&value_) - 1;
}
//! Atomically increment this variable and return its previous value.
typename std::remove_reference<T>::type operator++(int) {
if (std::is_pointer<T>::value) {
value_type inc = static_cast<value_type>(sizeof(typename std::remove_pointer<T>::type));
return AtomicOperation::add(inc, &value_);
} else {
return AtomicOperation::increment(&value_);
}
}
//! Atomically increment this variable and return its previous value.
typename std::remove_reference<T>::type operator ++ (int)
{
if (std::is_pointer<T>::value) {
value_type inc = static_cast<value_type>(
sizeof(typename std::remove_pointer<T>::type));
return AtomicOperation::add(inc, &value_);
}
else {
return AtomicOperation::increment(&value_);
}
//! Atomically decrement this variable and return its previous value.
T operator--(int) {
if (std::is_pointer<T>::value) {
value_type inc =
static_cast<value_type>(-static_cast<typename std::make_signed<value_type>::type>(
sizeof(typename std::remove_pointer<T>::type)));
return AtomicOperation::add(inc, &value_);
} else {
return AtomicOperation::decrement(&value_);
}
}
//! Atomically decrement this variable and return its previous value.
T operator -- (int)
{
if (std::is_pointer<T>::value) {
value_type inc = static_cast<value_type>(-
static_cast<typename std::make_signed<value_type>::type>(
sizeof(typename std::remove_pointer<T>::type)));
return AtomicOperation::add(inc, &value_);
}
else {
return AtomicOperation::decrement(&value_);
}
}
/*! \brief Atomically compare this variable with \a compare and set
* to value if equals
*/
bool compareAndSet(T compare, T value) {
return compare == AtomicOperation::compareAndSwap(compare, &value_, value);
}
/*! \brief Atomically compare this variable with \a compare and set
* to value if equals
*/
bool compareAndSet(T compare, T value)
{
return compare == AtomicOperation::compareAndSwap(
compare, &value_, value);
}
//! Atomically set this variable to \a value and return its previous value.
T swap(T value) { return AtomicOperation::swap(value, &value_); }
//! Atomically set this variable to \a value and return its previous value.
T swap(T value)
{
return AtomicOperation::swap(value, &value_);
}
/*! \brief Execute a stores fence followed by a store to this variable.
*
* This storeRelease operation ensures that all store to memory operations
* preceding this function will be globally visible before the update to
* this variable's value.
*/
void storeRelease(T value) {
std::atomic_thread_fence(std::memory_order_release);
value_ = value;
}
/*! \brief Execute a stores fence followed by a store to this variable.
*
* This storeRelease operation ensures that all store to memory operations
* preceding this function will be globally visible before the update to
* this variable's value.
*/
void storeRelease(T value)
{
std::atomic_thread_fence(std::memory_order_release);
value_ = value;
}
/*! \brief Execute a load from this variable followed by a loads fence.
*
* This loadAcquire operation ensures that all load from memory operations
* following this function will be globally visible after the read from
* this variable's value.
*/
T loadAcquire() const
{
T value = value_;
std::atomic_thread_fence(std::memory_order_acquire);
return value;
}
/*! \brief Execute a load from this variable followed by a loads fence.
*
* This loadAcquire operation ensures that all load from memory operations
* following this function will be globally visible after the read from
* this variable's value.
*/
T loadAcquire() const {
T value = value_;
std::atomic_thread_fence(std::memory_order_acquire);
return value;
}
};
//! Helper function to tie an Atomic<T&> to a variable of type T.
template <typename T>
inline Atomic<T&>
make_atomic(T& t)
{
return Atomic<T&>(t);
}
template <typename T> inline Atomic<T&> make_atomic(T& t) { return Atomic<T&>(t); }
/*! @}
* @}
*/
} // namespace amd
} // namespace amd
#endif /*ATOMIC_HPP_*/
+240 -261
Zobrazit soubor
@@ -14,308 +14,287 @@
namespace amd {
Monitor::Monitor(const char* name, bool recursive) :
contendersList_(0), onDeck_(0), waitersList_(NULL),
owner_(NULL), recursive_(recursive)
{
const size_t maxNameLen = sizeof(name_);
if (name == NULL) {
const char* unknownName = "@unknown@";
assert(sizeof(unknownName) < maxNameLen && "just checking");
strcpy(name_, unknownName);
Monitor::Monitor(const char* name, bool recursive)
: contendersList_(0), onDeck_(0), waitersList_(NULL), owner_(NULL), recursive_(recursive) {
const size_t maxNameLen = sizeof(name_);
if (name == NULL) {
const char* unknownName = "@unknown@";
assert(sizeof(unknownName) < maxNameLen && "just checking");
strcpy(name_, unknownName);
} else {
strncpy(name_, name, maxNameLen - 1);
name_[maxNameLen - 1] = '\0';
}
}
bool Monitor::trySpinLock() {
if (tryLock()) {
return true;
}
for (int s = kMaxSpinIter; s > 0; --s) {
// First, be SMT friendly
if (s >= (kMaxSpinIter - kMaxReadSpinIter)) {
Os::spinPause();
}
// and then SMP friendly
else {
strncpy(name_, name, maxNameLen - 1);
name_[maxNameLen - 1] = '\0';
Thread::yield();
}
if (!isLocked()) {
return tryLock();
}
}
// We could not acquire the lock in the spin loop.
return false;
}
bool
Monitor::trySpinLock()
{
void Monitor::finishLock() {
Thread* thread = Thread::current();
assert(thread != NULL && "cannot lock() from (null)");
if (trySpinLock()) {
return; // We succeeded, we are done.
}
/* The lock is contended. Push the thread's semaphore onto
* the contention list.
*/
Semaphore& semaphore = thread->lockSemaphore();
semaphore.reset();
LinkedNode newHead;
newHead.setItem(&semaphore);
intptr_t head = contendersList_.load(std::memory_order_acquire);
for (;;) {
// The assumption is that lockWord is locked. Make sure we do not
// continue unless the lock bit is set.
if ((head & kLockBit) == 0) {
if (tryLock()) {
return;
}
continue;
}
// Set the new contention list head if lockWord is unchanged.
newHead.setNext(reinterpret_cast<LinkedNode*>(head & ~kLockBit));
if (contendersList_.compare_exchange_weak(head, reinterpret_cast<intptr_t>(&newHead) | kLockBit,
std::memory_order_acq_rel,
std::memory_order_acquire)) {
break;
}
// We failed the CAS. yield/pause before trying again.
Thread::yield();
}
int32_t spinCount = 0;
// Go to sleep until we become the on-deck thread.
while ((onDeck_ & ~kLockBit) != reinterpret_cast<intptr_t>(&semaphore)) {
// First, be SMT friendly
if (spinCount < kMaxReadSpinIter) {
Os::spinPause();
}
// and then SMP friendly
else if (spinCount < kMaxSpinIter) {
Thread::yield();
}
// now go to sleep
else {
semaphore.wait();
}
spinCount++;
}
spinCount = 0;
//
// From now-on, we are the on-deck thread. It will stay that way until
// we successfuly acquire the lock.
//
for (;;) {
assert((onDeck_ & ~kLockBit) == reinterpret_cast<intptr_t>(&semaphore) && "just checking");
if (tryLock()) {
return true;
break;
}
for (int s = kMaxSpinIter; s > 0; --s) {
// First, be SMT friendly
if (s >= (kMaxSpinIter - kMaxReadSpinIter)) {
Os::spinPause();
}
// and then SMP friendly
else {
Thread::yield();
}
if (!isLocked()) {
return tryLock();
}
// Somebody beat us to it. Since we are on-deck, we can just go
// back to sleep.
// First, be SMT friendly
if (spinCount < kMaxReadSpinIter) {
Os::spinPause();
}
// and then SMP friendly
else if (spinCount < kMaxSpinIter) {
Thread::yield();
}
// now go to sleep
else {
semaphore.wait();
}
spinCount++;
}
// We could not acquire the lock in the spin loop.
return false;
assert(newHead.next() == NULL && "Should not be linked");
onDeck_ = 0;
}
void
Monitor::finishLock()
{
Thread* thread = Thread::current();
assert(thread != NULL && "cannot lock() from (null)");
void Monitor::finishUnlock() {
// If we get here, it means that there might be a thread in the contention
// list waiting to acquire the lock. We need to select a successor and
// place it on-deck.
if (trySpinLock()) {
return; // We succeeded, we are done.
for (;;) {
// Grab the onDeck_ microlock to protect the next loop (make sure only
// one semaphore is removed from the contention list).
//
intptr_t ptr = 0;
if (!onDeck_.compare_exchange_strong(ptr, ptr | kLockBit, std::memory_order_acq_rel,
std::memory_order_acquire)) {
return; // Somebody else has the microlock, let him select onDeck_
}
/* The lock is contended. Push the thread's semaphore onto
* the contention list.
*/
Semaphore& semaphore = thread->lockSemaphore();
semaphore.reset();
LinkedNode newHead;
newHead.setItem(&semaphore);
intptr_t head = contendersList_.load(std::memory_order_acquire);
for (;;) {
// The assumption is that lockWord is locked. Make sure we do not
// continue unless the lock bit is set.
if ((head & kLockBit) == 0) {
if (tryLock()) {
return;
}
continue;
}
if (head == 0) {
break; // There's nothing else to do.
}
// Set the new contention list head if lockWord is unchanged.
newHead.setNext(reinterpret_cast<LinkedNode*>(head & ~kLockBit));
if (contendersList_.compare_exchange_weak(head,
reinterpret_cast<intptr_t>(&newHead) | kLockBit,
std::memory_order_acq_rel, std::memory_order_acquire)) {
break;
}
if ((head & kLockBit) != 0) {
// Somebody could have acquired then released the lock
// and failed to grab the onDeck_ microlock.
head = 0;
break;
}
// We failed the CAS. yield/pause before trying again.
Thread::yield();
if (contendersList_.compare_exchange_weak(
head, reinterpret_cast<intptr_t>(reinterpret_cast<LinkedNode*>(head)->next()),
std::memory_order_acq_rel, std::memory_order_acquire)) {
#ifdef ASSERT
reinterpret_cast<LinkedNode*>(head)->setNext(NULL);
#endif // ASSERT
break;
}
}
int32_t spinCount = 0;
// Go to sleep until we become the on-deck thread.
while ((onDeck_ & ~kLockBit) != reinterpret_cast<intptr_t>(&semaphore)) {
// First, be SMT friendly
if (spinCount < kMaxReadSpinIter) {
Os::spinPause();
}
// and then SMP friendly
else if (spinCount < kMaxSpinIter) {
Thread::yield();
}
// now go to sleep
else {
semaphore.wait();
}
spinCount++;
}
Semaphore* semaphore = (head != 0) ? reinterpret_cast<LinkedNode*>(head)->item() : NULL;
spinCount = 0;
onDeck_.store(reinterpret_cast<intptr_t>(semaphore), std::memory_order_release);
//
// From now-on, we are the on-deck thread. It will stay that way until
// we successfuly acquire the lock.
//
for (;;) {
assert((onDeck_ & ~kLockBit) == reinterpret_cast<intptr_t>(&semaphore)
&& "just checking");
if (tryLock()) {
break;
}
// Release the onDeck_ microlock (end of critical region);
// Somebody beat us to it. Since we are on-deck, we can just go
// back to sleep.
// First, be SMT friendly
if (spinCount < kMaxReadSpinIter) {
Os::spinPause();
}
// and then SMP friendly
else if (spinCount < kMaxSpinIter) {
Thread::yield();
}
// now go to sleep
else {
semaphore.wait();
}
spinCount++;
if (semaphore != NULL) {
semaphore->post();
return;
}
assert(newHead.next() == NULL && "Should not be linked");
onDeck_ = 0;
// We do not have an on-deck thread (semaphore == NULL). Return if
// the contention list is empty or if the lock got acquired again.
head = contendersList_;
if (head == 0 || (head & kLockBit) != 0) {
return;
}
}
}
void
Monitor::finishUnlock()
{
// If we get here, it means that there might be a thread in the contention
// list waiting to acquire the lock. We need to select a successor and
// place it on-deck.
void Monitor::wait() {
Thread* thread = Thread::current();
assert(isLocked() && owner_ == thread && "just checking");
for (;;) {
// Grab the onDeck_ microlock to protect the next loop (make sure only
// one semaphore is removed from the contention list).
//
intptr_t ptr = 0;
if (!onDeck_.compare_exchange_strong(ptr, ptr | kLockBit,
std::memory_order_acq_rel, std::memory_order_acquire)) {
return; // Somebody else has the microlock, let him select onDeck_
}
// Add the thread's resume semaphore to the list.
Semaphore& suspend = thread->suspendSemaphore();
suspend.reset();
intptr_t head = contendersList_.load(std::memory_order_acquire);
for (;;) {
if (head == 0) {
break; // There's nothing else to do.
}
LinkedNode newHead;
newHead.setItem(&suspend);
newHead.setNext(waitersList_);
waitersList_ = &newHead;
if ((head & kLockBit) != 0) {
// Somebody could have acquired then released the lock
// and failed to grab the onDeck_ microlock.
head = 0;
break;
}
// Preserve the lock count (for recursive mutexes)
uint32_t lockCount = lockCount_;
lockCount_ = 1;
if (contendersList_.compare_exchange_weak(
head, reinterpret_cast<intptr_t>(
reinterpret_cast<LinkedNode*>(head)->next()),
std::memory_order_acq_rel, std::memory_order_acquire)) {
#ifdef ASSERT
reinterpret_cast<LinkedNode*>(head)->setNext(NULL);
#endif // ASSERT
break;
}
}
// Release the lock and go to sleep.
unlock();
Semaphore* semaphore = (head != 0)
? reinterpret_cast<LinkedNode*>(head)->item()
: NULL;
onDeck_.store(reinterpret_cast<intptr_t>(semaphore),
std::memory_order_release);
//
// Release the onDeck_ microlock (end of critical region);
if (semaphore != NULL) {
semaphore->post();
return;
}
// We do not have an on-deck thread (semaphore == NULL). Return if
// the contention list is empty or if the lock got acquired again.
head = contendersList_;
if (head == 0 || (head & kLockBit) != 0) {
return;
}
// Go to sleep until we become the on-deck thread.
int32_t spinCount = 0;
while ((onDeck_ & ~kLockBit) != reinterpret_cast<intptr_t>(&suspend)) {
// First, be SMT friendly
if (spinCount < kMaxReadSpinIter) {
Os::spinPause();
}
// and then SMP friendly
else if (spinCount < kMaxSpinIter) {
Thread::yield();
}
// now go to sleep
else {
suspend.wait();
}
spinCount++;
}
spinCount = 0;
for (;;) {
assert((onDeck_ & ~kLockBit) == reinterpret_cast<intptr_t>(&suspend) && "just checking");
if (trySpinLock()) {
break;
}
// Somebody beat us to it. Since we are on-deck, we can just go
// back to sleep.
// First, be SMT friendly
if (spinCount < kMaxReadSpinIter) {
Os::spinPause();
}
// and then SMP friendly
else if (spinCount < kMaxSpinIter) {
Thread::yield();
}
// now go to sleep
else {
suspend.wait();
}
spinCount++;
}
// Restore the lock count (for recursive mutexes)
lockCount_ = lockCount;
onDeck_.store(0, std::memory_order_release);
}
void
Monitor::wait()
{
Thread* thread = Thread::current();
assert(isLocked() && owner_ == thread && "just checking");
void Monitor::notify() {
assert(isLocked() && owner_ == Thread::current() && "just checking");
// Add the thread's resume semaphore to the list.
Semaphore& suspend = thread->suspendSemaphore();
suspend.reset();
LinkedNode* waiter = waitersList_;
if (waiter == NULL) {
return;
}
LinkedNode newHead;
newHead.setItem(&suspend);
newHead.setNext(waitersList_);
waitersList_ = &newHead;
// Dequeue a waiter from the wait list and add it to the contention list.
waitersList_ = waiter->next();
// Preserve the lock count (for recursive mutexes)
uint32_t lockCount = lockCount_;
lockCount_ = 1;
// Release the lock and go to sleep.
unlock();
// Go to sleep until we become the on-deck thread.
int32_t spinCount = 0;
while ((onDeck_ & ~kLockBit) != reinterpret_cast<intptr_t>(&suspend)) {
// First, be SMT friendly
if (spinCount < kMaxReadSpinIter) {
Os::spinPause();
}
// and then SMP friendly
else if (spinCount < kMaxSpinIter) {
Thread::yield();
}
// now go to sleep
else {
suspend.wait();
}
spinCount++;
intptr_t node = contendersList_.load(std::memory_order_acquire);
for (;;) {
waiter->setNext(reinterpret_cast<LinkedNode*>(node & ~kLockBit));
if (contendersList_.compare_exchange_weak(node, reinterpret_cast<intptr_t>(waiter) | kLockBit,
std::memory_order_acq_rel,
std::memory_order_acquire)) {
break;
}
spinCount = 0;
for (;;) {
assert((onDeck_ & ~kLockBit) == reinterpret_cast<intptr_t>(&suspend)
&& "just checking");
if (trySpinLock()) {
break;
}
// Somebody beat us to it. Since we are on-deck, we can just go
// back to sleep.
// First, be SMT friendly
if (spinCount < kMaxReadSpinIter) {
Os::spinPause();
}
// and then SMP friendly
else if (spinCount < kMaxSpinIter) {
Thread::yield();
}
// now go to sleep
else {
suspend.wait();
}
spinCount++;
}
// Restore the lock count (for recursive mutexes)
lockCount_ = lockCount;
onDeck_.store(0, std::memory_order_release);
}
}
void
Monitor::notify()
{
assert(isLocked() && owner_ == Thread::current() && "just checking");
LinkedNode* waiter = waitersList_;
if (waiter == NULL) {
return;
}
// Dequeue a waiter from the wait list and add it to the contention list.
waitersList_ = waiter->next();
intptr_t node = contendersList_.load(std::memory_order_acquire);
for (;;) {
waiter->setNext(reinterpret_cast<LinkedNode*>(node & ~kLockBit));
if (contendersList_.compare_exchange_weak(node,
reinterpret_cast<intptr_t>(waiter) | kLockBit,
std::memory_order_acq_rel, std::memory_order_acquire)) {
break;
}
}
void Monitor::notifyAll() {
// NOTE: We could CAS the whole list in 1 shot but this is
// not critical code. Optimize this if it becomes hot.
while (waitersList_ != NULL) {
notify();
}
}
void
Monitor::notifyAll()
{
// NOTE: We could CAS the whole list in 1 shot but this is
// not critical code. Optimize this if it becomes hot.
while (waitersList_ != NULL) {
notify();
}
}
} // namespace amd
} // namespace amd
+163 -181
Zobrazit soubor
@@ -25,239 +25,221 @@ namespace amd {
namespace details {
template <class T, class AllocClass = HeapObject>
struct SimplyLinkedNode : public AllocClass
{
typedef SimplyLinkedNode<T, AllocClass> Node;
template <class T, class AllocClass = HeapObject> struct SimplyLinkedNode : public AllocClass {
typedef SimplyLinkedNode<T, AllocClass> Node;
protected:
std::atomic<Node*> next_; /*!< \brief The next element. */
T volatile item_;
protected:
std::atomic<Node*> next_; /*!< \brief The next element. */
T volatile item_;
public:
//! \brief Return the next element in the linked-list.
Node* next() const { return next_; }
//! \brief Return the item.
T item() const { return item_; }
public:
//! \brief Return the next element in the linked-list.
Node* next() const { return next_; }
//! \brief Return the item.
T item() const { return item_; }
//! \brief Set the next element pointer.
void setNext(Node* next) { next_ = next; }
//! \brief Set the item.
void setItem(T item) { item_ = item; }
//! \brief Set the next element pointer.
void setNext(Node* next) { next_ = next; }
//! \brief Set the item.
void setItem(T item) { item_ = item; }
//! \brief Swap the next element pointer.
Node* swapNext(Node* next) { return next_.swap(next); }
//! \brief Swap the next element pointer.
Node* swapNext(Node* next) { return next_.swap(next); }
//! \brief Compare and set the next element pointer.
bool compareAndSetNext(Node* compare, Node* next)
{
return next_.compare_exchange_strong(compare, next);
}
//! \brief Compare and set the next element pointer.
bool compareAndSetNext(Node* compare, Node* next) {
return next_.compare_exchange_strong(compare, next);
}
};
} // namespace details
} // namespace details
class Monitor : public HeapObject
{
typedef details::SimplyLinkedNode<Semaphore*,StackObject> LinkedNode;
class Monitor : public HeapObject {
typedef details::SimplyLinkedNode<Semaphore*, StackObject> LinkedNode;
private:
static const intptr_t kLockBit = 0x1;
private:
static const intptr_t kLockBit = 0x1;
static const int kMaxSpinIter = 55; //!< Total number of spin iterations.
static const int kMaxReadSpinIter = 50; //!< Read iterations before yielding
static const int kMaxSpinIter = 55; //!< Total number of spin iterations.
static const int kMaxReadSpinIter = 50; //!< Read iterations before yielding
/*! Linked list of semaphores the contending threads are waiting on
* and main lock.
*/
std::atomic_intptr_t contendersList_;
//! The Mutex's name
char name_[64];
/*! Linked list of semaphores the contending threads are waiting on
* and main lock.
*/
std::atomic_intptr_t contendersList_;
//! The Mutex's name
char name_[64];
//! Semaphore of the next thread to contend for the lock.
std::atomic_intptr_t onDeck_;
//! Linked list of the suspended threads resume semaphores.
LinkedNode* volatile waitersList_;
//! Semaphore of the next thread to contend for the lock.
std::atomic_intptr_t onDeck_;
//! Linked list of the suspended threads resume semaphores.
LinkedNode* volatile waitersList_;
//! Thread owning this monitor.
Thread* volatile owner_;
//! The amount of times this monitor was acquired by the owner.
uint32_t lockCount_;
//! True if this is a recursive mutex, false otherwise.
const bool recursive_;
//! Thread owning this monitor.
Thread* volatile owner_;
//! The amount of times this monitor was acquired by the owner.
uint32_t lockCount_;
//! True if this is a recursive mutex, false otherwise.
const bool recursive_;
private:
//! Finish locking the mutex (contented case).
void finishLock();
//! Finish unlocking the mutex (contented case).
void finishUnlock();
private:
//! Finish locking the mutex (contented case).
void finishLock();
//! Finish unlocking the mutex (contented case).
void finishUnlock();
protected:
//! Try to spin-acquire the lock, return true if successful.
bool trySpinLock();
protected:
//! Try to spin-acquire the lock, return true if successful.
bool trySpinLock();
/*! \brief Return true if the lock is owned.
*
* \note The user is responsible for the memory ordering.
*/
bool isLocked() const { return (contendersList_ & kLockBit) != 0; }
/*! \brief Return true if the lock is owned.
*
* \note The user is responsible for the memory ordering.
*/
bool isLocked() const { return (contendersList_ & kLockBit) != 0; }
//! Return this monitor's owner thread (NULL if unlocked).
Thread* owner() const { return owner_; }
//! Return this monitor's owner thread (NULL if unlocked).
Thread* owner() const { return owner_; }
//! Set the owner.
void setOwner(Thread* thread) { owner_ = thread; }
//! Set the owner.
void setOwner(Thread* thread) { owner_ = thread; }
public:
explicit Monitor(const char* name = NULL, bool recursive = false);
~Monitor() {}
public:
explicit Monitor(const char* name = NULL, bool recursive = false);
~Monitor() {}
//! Try to acquire the lock, return true if successful.
inline bool tryLock();
//! Try to acquire the lock, return true if successful.
inline bool tryLock();
//! Acquire the lock or suspend the calling thread.
inline void lock();
//! Acquire the lock or suspend the calling thread.
inline void lock();
//! Release the lock and wake a single waiting thread if any.
inline void unlock();
//! Release the lock and wake a single waiting thread if any.
inline void unlock();
/*! \brief Give up the lock and go to sleep.
*
* Calling wait() causes the current thread to go to sleep until
* another thread calls notify()/notifyAll().
*
* \note The monitor must be owned before calling wait().
*/
void wait();
/*! \brief Wake up a single thread waiting on this monitor.
*
* \note The monitor must be owned before calling notify().
*/
void notify();
/*! \brief Wake up all threads that are waiting on this monitor.
*
* \note The monitor must be owned before calling notifyAll().
*/
void notifyAll();
/*! \brief Give up the lock and go to sleep.
*
* Calling wait() causes the current thread to go to sleep until
* another thread calls notify()/notifyAll().
*
* \note The monitor must be owned before calling wait().
*/
void wait();
/*! \brief Wake up a single thread waiting on this monitor.
*
* \note The monitor must be owned before calling notify().
*/
void notify();
/*! \brief Wake up all threads that are waiting on this monitor.
*
* \note The monitor must be owned before calling notifyAll().
*/
void notifyAll();
//! Return this lock's name.
const char* name() const { return name_; }
//! Return this lock's name.
const char* name() const { return name_; }
};
class ScopedLock : StackObject
{
private:
Monitor* lock_;
class ScopedLock : StackObject {
private:
Monitor* lock_;
public:
ScopedLock(Monitor& lock)
: lock_(&lock)
{
lock_->lock();
}
public:
ScopedLock(Monitor& lock) : lock_(&lock) { lock_->lock(); }
ScopedLock(Monitor* lock)
: lock_(lock)
{
if (lock_) lock_->lock();
}
ScopedLock(Monitor* lock) : lock_(lock) {
if (lock_) lock_->lock();
}
~ScopedLock()
{
if (lock_) lock_->unlock();
}
~ScopedLock() {
if (lock_) lock_->unlock();
}
};
/*! @}
* @}
*/
inline bool
Monitor::tryLock()
{
Thread* thread = Thread::current();
assert(thread != NULL && "cannot lock() from (null)");
inline bool Monitor::tryLock() {
Thread* thread = Thread::current();
assert(thread != NULL && "cannot lock() from (null)");
intptr_t ptr = contendersList_.load(std::memory_order_acquire);
intptr_t ptr = contendersList_.load(std::memory_order_acquire);
if (unlikely((ptr & kLockBit) != 0)) {
if (recursive_ && thread == owner_) {
// Recursive lock: increment the lock count and return.
++lockCount_;
return true;
}
return false; // Already locked!
if (unlikely((ptr & kLockBit) != 0)) {
if (recursive_ && thread == owner_) {
// Recursive lock: increment the lock count and return.
++lockCount_;
return true;
}
return false; // Already locked!
}
if (unlikely(!contendersList_.compare_exchange_weak(ptr, ptr | kLockBit,
std::memory_order_acq_rel, std::memory_order_acquire))) {
return false; // We failed the CAS from unlocked to locked.
}
if (unlikely(!contendersList_.compare_exchange_weak(
ptr, ptr | kLockBit, std::memory_order_acq_rel, std::memory_order_acquire))) {
return false; // We failed the CAS from unlocked to locked.
}
setOwner(thread); // cannot move above the CAS.
lockCount_ = 1;
setOwner(thread); // cannot move above the CAS.
lockCount_ = 1;
return true;
return true;
}
inline void
Monitor::lock()
{
if (unlikely(!tryLock())) {
// The lock is contented.
finishLock();
}
inline void Monitor::lock() {
if (unlikely(!tryLock())) {
// The lock is contented.
finishLock();
}
// This is the beginning of the critical region. From now-on, everything
// executes single-threaded!
//
// This is the beginning of the critical region. From now-on, everything
// executes single-threaded!
//
}
inline void
Monitor::unlock()
{
assert(isLocked() && owner_ == Thread::current() && "invariant");
inline void Monitor::unlock() {
assert(isLocked() && owner_ == Thread::current() && "invariant");
if (recursive_ && --lockCount_ > 0) {
// was a recursive lock case, simply return.
return;
if (recursive_ && --lockCount_ > 0) {
// was a recursive lock case, simply return.
return;
}
setOwner(NULL);
// Clear the lock bit.
intptr_t ptr = contendersList_.load(std::memory_order_acquire);
while (!contendersList_.compare_exchange_weak(ptr, ptr & ~kLockBit, std::memory_order_acq_rel,
std::memory_order_acquire))
;
//
// We succeeded the CAS from locked to unlocked.
// This is the end of the critical region.
// Check if we have an on-deck thread that needs signaling.
intptr_t onDeck = onDeck_;
if (onDeck != 0) {
if ((onDeck & kLockBit) == 0) {
// Only signal if it is unmarked.
reinterpret_cast<Semaphore*>(onDeck)->post();
}
return; // We are done.
}
setOwner(NULL);
// We do not have an on-deck thread yet, we might have to walk the list in
// order to select the next onDeck_. Only one thread needs to fill onDeck_,
// so return if the list is empty or if the lock got acquired again (it's
// somebody else's problem now!)
// Clear the lock bit.
intptr_t ptr = contendersList_.load(std::memory_order_acquire);
while (!contendersList_.compare_exchange_weak(ptr, ptr & ~kLockBit,
std::memory_order_acq_rel, std::memory_order_acquire))
;
//
// We succeeded the CAS from locked to unlocked.
// This is the end of the critical region.
intptr_t head = contendersList_;
if (head == 0 || (head & kLockBit) != 0) {
return;
}
// Check if we have an on-deck thread that needs signaling.
intptr_t onDeck = onDeck_;
if (onDeck != 0) {
if ((onDeck & kLockBit) == 0) {
// Only signal if it is unmarked.
reinterpret_cast<Semaphore*>(onDeck)->post();
}
return; // We are done.
}
// We do not have an on-deck thread yet, we might have to walk the list in
// order to select the next onDeck_. Only one thread needs to fill onDeck_,
// so return if the list is empty or if the lock got acquired again (it's
// somebody else's problem now!)
intptr_t head = contendersList_;
if (head == 0 || (head & kLockBit) != 0) {
return;
}
// Finish the unlock operation: find a thread to wake up.
finishUnlock();
// Finish the unlock operation: find a thread to wake up.
finishUnlock();
}
} // namespace amd
} // namespace amd
#endif /*MONITOR_HPP_*/
+65 -73
Zobrazit soubor
@@ -6,90 +6,82 @@
#include "thread/thread.hpp"
#if defined(_WIN32) || defined(__CYGWIN__)
# include <windows.h>
#else // !_WIN32
# include <semaphore.h>
# include <errno.h>
#endif // !_WIN32
#include <windows.h>
#else // !_WIN32
#include <semaphore.h>
#include <errno.h>
#endif // !_WIN32
namespace amd {
Semaphore::Semaphore()
: state_(0)
{
Semaphore::Semaphore() : state_(0) {
#ifdef _WIN32
handle_ = static_cast<void*>(CreateSemaphore(NULL, 0, LONG_MAX, NULL));
assert(handle_ != NULL && "CreateSemaphore failed");
#else // !_WIN32
if (sem_init(&sem_, 0, 0) != 0) {
fatal("sem_init() failed");
}
#endif // !_WIN32
handle_ = static_cast<void*>(CreateSemaphore(NULL, 0, LONG_MAX, NULL));
assert(handle_ != NULL && "CreateSemaphore failed");
#else // !_WIN32
if (sem_init(&sem_, 0, 0) != 0) {
fatal("sem_init() failed");
}
#endif // !_WIN32
}
Semaphore::~Semaphore()
{
Semaphore::~Semaphore() {
#ifdef _WIN32
if (!CloseHandle(static_cast<HANDLE>(handle_))) {
fatal("CloseHandle() failed");
}
#else // !_WIN32
if (sem_destroy(&sem_) != 0) {
fatal("sem_destroy() failed");
}
#endif // !WIN32
if (!CloseHandle(static_cast<HANDLE>(handle_))) {
fatal("CloseHandle() failed");
}
#else // !_WIN32
if (sem_destroy(&sem_) != 0) {
fatal("sem_destroy() failed");
}
#endif // !WIN32
}
void
Semaphore::post()
{
int state = state_.load(std::memory_order_relaxed);
for (;;) {
if (state > 0) {
int newstate = state_.load(std::memory_order_acquire);
if (state == newstate) {
return;
}
state = newstate;
continue;
}
if (state_.compare_exchange_weak(state, state+1,
std::memory_order_acq_rel, std::memory_order_acquire)) {
break;
}
}
if (state < 0) {
// We have threads waiting on this event.
#ifdef _WIN32
ReleaseSemaphore(static_cast<HANDLE>(handle_), 1, NULL);
#else // !_WIN32
if (0 != sem_post(&sem_)) {
fatal("sem_post() failed");
}
#endif // !_WIN32
}
}
void
Semaphore::wait()
{
if (state_-- > 0) {
void Semaphore::post() {
int state = state_.load(std::memory_order_relaxed);
for (;;) {
if (state > 0) {
int newstate = state_.load(std::memory_order_acquire);
if (state == newstate) {
return;
}
#ifdef _WIN32
if (WAIT_OBJECT_0 != WaitForSingleObject(
static_cast<HANDLE>(handle_), INFINITE)) {
fatal("WaitForSingleObject failed");
}
#else // !_WIN32
while (0 != sem_wait(&sem_)) {
if (EINTR != errno) {
fatal("sem_wait() failed");
}
state = newstate;
continue;
}
#endif // !_WIN32
if (state_.compare_exchange_weak(state, state + 1, std::memory_order_acq_rel,
std::memory_order_acquire)) {
break;
}
}
if (state < 0) {
// We have threads waiting on this event.
#ifdef _WIN32
ReleaseSemaphore(static_cast<HANDLE>(handle_), 1, NULL);
#else // !_WIN32
if (0 != sem_post(&sem_)) {
fatal("sem_post() failed");
}
#endif // !_WIN32
}
}
} // namespace amd
void Semaphore::wait() {
if (state_-- > 0) {
return;
}
#ifdef _WIN32
if (WAIT_OBJECT_0 != WaitForSingleObject(static_cast<HANDLE>(handle_), INFINITE)) {
fatal("WaitForSingleObject failed");
}
#else // !_WIN32
while (0 != sem_wait(&sem_)) {
if (EINTR != errno) {
fatal("sem_wait() failed");
}
}
#endif // !_WIN32
}
} // namespace amd
+19 -23
Zobrazit soubor
@@ -10,7 +10,7 @@
#include <atomic>
#if defined(__linux__)
# include <semaphore.h>
#include <semaphore.h>
#endif /*linux*/
@@ -26,40 +26,36 @@ namespace amd {
class Thread;
//! \brief Counting semaphore
class Semaphore : public HeapObject
{
private:
std::atomic_int state_; //!< This semaphore's value.
class Semaphore : public HeapObject {
private:
std::atomic_int state_; //!< This semaphore's value.
#ifdef _WIN32
void* handle_; //!< The semaphore object's handle.
char padding_[64-sizeof(void*)-sizeof(std::atomic_int)];
#else // !_WIN32
sem_t sem_; //!< The semaphore object's identifier.
char padding_[64-sizeof(sem_t)-sizeof(std::atomic_int)];
void* handle_; //!< The semaphore object's handle.
char padding_[64 - sizeof(void*) - sizeof(std::atomic_int)];
#else // !_WIN32
sem_t sem_; //!< The semaphore object's identifier.
char padding_[64 - sizeof(sem_t) - sizeof(std::atomic_int)];
#endif /*!_WIN32*/
public:
Semaphore();
~Semaphore();
public:
Semaphore();
~Semaphore();
//! \brief Decrement this semaphore
void wait();
//! \brief Decrement this semaphore
void wait();
//! \brief Increment this semaphore
void post();
//! \brief Increment this semaphore
void post();
//! \brief Reset this semaphore.
void reset()
{
state_.store(0, std::memory_order_release);
}
//! \brief Reset this semaphore.
void reset() { state_.store(0, std::memory_order_release); }
};
/*! @}
* @}
*/
} // namespace amd
} // namespace amd
#endif /*SEMAPHORE_HPP_*/
+96 -122
Zobrazit soubor
@@ -8,109 +8,97 @@
#include "os/os.hpp"
#if defined(_WIN32) || defined(__CYGWIN__)
# include <windows.h>
#endif // _WIN32
#include <windows.h>
#endif // _WIN32
namespace amd {
HostThread::HostThread()
: Thread("HostThread", 0, false)
{
setCurrent();
Os::currentStackInfo(&stackBase_, &stackSize_);
setState(RUNNABLE);
HostThread::HostThread() : Thread("HostThread", 0, false) {
setCurrent();
Os::currentStackInfo(&stackBase_, &stackSize_);
setState(RUNNABLE);
}
void
Thread::create()
{
created_ = new Semaphore();
lock_ = new Semaphore();
suspend_ = new Semaphore();
void Thread::create() {
created_ = new Semaphore();
lock_ = new Semaphore();
suspend_ = new Semaphore();
selfSuspendLock_ = new Monitor();
selfSuspendLock_ = new Monitor();
data_ = NULL;
handle_ = NULL;
setState(CREATED);
data_ = NULL;
handle_ = NULL;
setState(CREATED);
}
Thread::Thread(const std::string& name, size_t stackSize, bool spawn)
: handle_(NULL), name_(name), stackSize_(stackSize)
{
create();
: handle_(NULL), name_(name), stackSize_(stackSize) {
create();
if (!spawn) return;
if (!spawn) return;
if ((handle_ = Os::createOsThread(this))) {
// Now we need to wait for Thread::main to report back.
while (state() != Thread::INITIALIZED) {
created_->wait();
}
if ((handle_ = Os::createOsThread(this))) {
// Now we need to wait for Thread::main to report back.
while (state() != Thread::INITIALIZED) {
created_->wait();
}
}
}
Thread::~Thread()
{
Thread::~Thread() {
#if defined(_WIN32)
if (handle_ != NULL) {
::CloseHandle((HANDLE) handle_);
}
if (handle_ != NULL) {
::CloseHandle((HANDLE)handle_);
}
#endif
delete created_;
delete lock_;
delete suspend_;
delete created_;
delete lock_;
delete suspend_;
delete selfSuspendLock_;
delete selfSuspendLock_;
}
void*
Thread::main()
{
void* Thread::main() {
#ifdef DEBUG
Os::setCurrentThreadName(name().c_str());
#endif // DEBUG
Os::currentStackInfo(&stackBase_, &stackSize_);
setCurrent();
Os::setCurrentThreadName(name().c_str());
#endif // DEBUG
Os::currentStackInfo(&stackBase_, &stackSize_);
setCurrent();
// Notify the parent thread that we are up and running.
{
ScopedLock sl(selfSuspendLock_);
setState(INITIALIZED);
created_->post();
selfSuspendLock_->wait();
}
if (state() == RUNNABLE) {
run(data_);
}
setState(FINISHED);
return NULL;
}
bool
Thread::start(void* data)
{
if (state() != INITIALIZED) {
return false;
}
data_ = data;
{
ScopedLock sl(selfSuspendLock_);
setState(RUNNABLE);
selfSuspendLock_->notify();
}
return true;
}
void
Thread::resume()
{
// Notify the parent thread that we are up and running.
{
ScopedLock sl(selfSuspendLock_);
setState(INITIALIZED);
created_->post();
selfSuspendLock_->wait();
}
if (state() == RUNNABLE) {
run(data_);
}
setState(FINISHED);
return NULL;
}
bool Thread::start(void* data) {
if (state() != INITIALIZED) {
return false;
}
data_ = data;
{
ScopedLock sl(selfSuspendLock_);
setState(RUNNABLE);
selfSuspendLock_->notify();
}
return true;
}
void Thread::resume() {
ScopedLock sl(selfSuspendLock_);
selfSuspendLock_->notify();
}
#if defined(__linux__)
@@ -119,19 +107,13 @@ namespace details {
__thread Thread* thread_ __attribute__((tls_model("initial-exec")));
} // namespace details
} // namespace details
void
Thread::registerStack(address base, address top)
{
// Nothing to do.
void Thread::registerStack(address base, address top) {
// Nothing to do.
}
void
Thread::setCurrent()
{
details::thread_ = this;
}
void Thread::setCurrent() { details::thread_ = this; }
#elif defined(_WIN32)
@@ -139,53 +121,45 @@ namespace details {
#if defined(USE_DECLSPEC_THREAD)
__declspec(thread) Thread* thread_;
#else // !USE_DECLSPEC_THREAD
#else // !USE_DECLSPEC_THREAD
DWORD threadIndex_ = TlsAlloc();
#endif // !USE_DECLSPEC_THREAD
#endif // !USE_DECLSPEC_THREAD
} // namespace details
} // namespace details
void
Thread::registerStack(address base, address top)
{
// Nothing to do.
void Thread::registerStack(address base, address top) {
// Nothing to do.
}
void
Thread::setCurrent()
{
void Thread::setCurrent() {
#if defined(USE_DECLSPEC_THREAD)
details::thread_ = this;
#else // !USE_DECLSPEC_THREAD
TlsSetValue(details::threadIndex_, this);
#endif // !USE_DECLSPEC_THREAD
details::thread_ = this;
#else // !USE_DECLSPEC_THREAD
TlsSetValue(details::threadIndex_, this);
#endif // !USE_DECLSPEC_THREAD
}
#endif
bool
Thread::init()
{
static bool initialized_ = false;
bool Thread::init() {
static bool initialized_ = false;
// We could use InitOnceExecuteOnce/pthread_once here:
if (initialized_) {
return true;
}
initialized_ = true;
// We could use InitOnceExecuteOnce/pthread_once here:
if (initialized_) {
return true;
}
initialized_ = true;
// Register the main thread
return NULL != new HostThread();
// Register the main thread
return NULL != new HostThread();
}
void
Thread::tearDown()
{
void Thread::tearDown() {
#if defined(_WIN32) && !defined(USE_DECLSPEC_THREAD)
if (details::threadIndex_ != TLS_OUT_OF_INDEXES) {
TlsFree(threadIndex_);
}
#endif // _WIN32 && !USE_DECLSPEC_THREAD
if (details::threadIndex_ != TLS_OUT_OF_INDEXES) {
TlsFree(threadIndex_);
}
#endif // _WIN32 && !USE_DECLSPEC_THREAD
}
} // namespace amd
} // namespace amd
+114 -144
Zobrazit soubor
@@ -12,10 +12,10 @@
#include <string>
#if defined(_WIN32)
# define USE_DECLSPEC_THREAD 1
# if !defined(USE_DECLSPEC_THREAD)
# include <windows.h>
# endif /*!USE_DECLSPEC_THREAD*/
#define USE_DECLSPEC_THREAD 1
#if !defined(USE_DECLSPEC_THREAD)
#include <windows.h>
#endif /*!USE_DECLSPEC_THREAD*/
#endif /*_WIN32*/
namespace amd {
@@ -29,157 +29,137 @@ namespace amd {
class Monitor;
class Thread : public HeapObject
{
friend const void* Os::createOsThread(Thread*);
class Thread : public HeapObject {
friend const void* Os::createOsThread(Thread*);
public:
enum ThreadState
{
CREATED,
INITIALIZED,
RUNNABLE,
SUSPENDED,
FINISHED,
FAILED
};
public:
enum ThreadState { CREATED, INITIALIZED, RUNNABLE, SUSPENDED, FINISHED, FAILED };
private:
//! System thread handle.
const void* handle_;
//! The thread's name.
const std::string name_;
//! Current running state.
volatile ThreadState state_;
//! The argument passed to run()
void* data_;
private:
//! System thread handle.
const void* handle_;
//! The thread's name.
const std::string name_;
//! Current running state.
volatile ThreadState state_;
//! The argument passed to run()
void* data_;
//! \cond ignore
Semaphore* created_; //!< To notify the parent thread.
Semaphore* lock_; //!< For mutex support (during contention).
Semaphore* suspend_; //!< For wait/suspend support.
//! \endcond
//! \cond ignore
Semaphore* created_; //!< To notify the parent thread.
Semaphore* lock_; //!< For mutex support (during contention).
Semaphore* suspend_; //!< For wait/suspend support.
//! \endcond
Monitor* selfSuspendLock_; //!< For self suspend/resume.
Monitor* selfSuspendLock_; //!< For self suspend/resume.
protected:
address stackBase_; //!< Main stack base.
size_t stackSize_; //!< Main stack size.
protected:
address stackBase_; //!< Main stack base.
size_t stackSize_; //!< Main stack size.
private:
private:
/*! \brief The start wrapper for all newly create threads.
* This is called from the pthread_create start_thread.
*/
static void* entry(Thread* thread);
/*! \brief The start wrapper for all newly create threads.
* This is called from the pthread_create start_thread.
*/
static void* entry(Thread* thread);
/*! \brief Thread main (called from the main function).
* Setup the thread for running and wait for the semaphore to be signaled.
*/
void* main();
/*! \brief Thread main (called from the main function).
* Setup the thread for running and wait for the semaphore to be signaled.
*/
void* main();
//! The entry point for this thread.
virtual void run(void* data) = 0;
//! The entry point for this thread.
virtual void run(void* data) = 0;
protected:
//! Bring this thread to the created state.
void create();
protected:
//! Bring this thread to the created state.
void create();
//! Set the current thread state.
void setState(ThreadState state) { state_ = state; }
//! Set the current thread state.
void setState(ThreadState state) { state_ = state; }
//! Set the thread-local _thread variable (used by current()).
void setCurrent();
//! Set the thread-local _thread variable (used by current()).
void setCurrent();
//! Register the given memory region as a valid stack.
void registerStack(address base, address top);
//! Register the given memory region as a valid stack.
void registerStack(address base, address top);
/*! \brief Construct a new thread.
* If \a spawn is false, do not create a new OS thread, instead,
* bind to the currently running on.
*/
explicit Thread(const std::string& name, size_t stackSize = 0 /*use system default*/,
bool spawn = true /* create a new Os::thread */);
/*! \brief Construct a new thread.
* If \a spawn is false, do not create a new OS thread, instead,
* bind to the currently running on.
*/
explicit Thread(
const std::string& name,
size_t stackSize = 0 /*use system default*/,
bool spawn = true /* create a new Os::thread */);
public:
//! Return the currently running thread instance.
static inline Thread* current();
public:
//! Return the currently running thread instance.
static inline Thread* current();
//! Initialize the OsThread package.
static bool init();
//! Initialize the OsThread package.
static bool init();
//! Tear down the OsThread package.
static void tearDown();
//! Tear down the OsThread package.
static void tearDown();
//! Destroy this thread.
virtual ~Thread();
//! Destroy this thread.
virtual ~Thread();
//! Return the thread's name
const std::string& name() const { return name_; }
//! Return the thread's name
const std::string& name() const { return name_; }
//! Get the system thread handle.
const void* handle() const { return handle_; }
//! Get the system thread handle.
const void* handle() const { return handle_; }
//! Start the thread execution
bool start(void* data = NULL);
//! Start the thread execution
bool start(void *data = NULL);
//! Resume the thread
void resume();
//! Resume the thread
void resume();
//! Return true is this is the host thread.
virtual bool isHostThread() const { return false; }
//! Return true is this is the host thread.
virtual bool isHostThread() const { return false; }
//! Return true if this is a worker thread.
virtual bool isWorkerThread() const { return false; }
//! Return true if this is a worker thread.
virtual bool isWorkerThread() const { return false; }
//! Get the current thread state.
ThreadState state() const { return state_; }
//! Get the current thread state.
ThreadState state() const { return state_; }
//! Return this thread's stack base.
address stackBase() const { return stackBase_; }
//! Return this thread's stack size.
size_t stackSize() const { return stackSize_; }
//! Return this thread's stack bottom.
address stackBottom() const { return stackBase() - stackSize(); }
//! Return this thread's stack base.
address stackBase() const { return stackBase_; }
//! Return this thread's stack size.
size_t stackSize() const { return stackSize_; }
//! Return this thread's stack bottom.
address stackBottom() const { return stackBase() - stackSize(); }
//! Return this thread's contend semaphore.
Semaphore& lockSemaphore() const { return *lock_; }
//! Return this thread's resume semaphore.
Semaphore& suspendSemaphore() const { return *suspend_; }
//! Return this thread's contend semaphore.
Semaphore& lockSemaphore() const { return *lock_; }
//! Return this thread's resume semaphore.
Semaphore& suspendSemaphore() const { return *suspend_; }
//! Set this thread's affinity to the given cpu.
void setAffinity(uint cpu_id) const { Os::setThreadAffinity(handle_, cpu_id); }
//! Set this thread's affinity to the given cpu.
void setAffinity(uint cpu_id) const
{
Os::setThreadAffinity(handle_, cpu_id);
}
//! Set this thread's affinity to the given cpu mask.
void setAffinity(const Os::ThreadAffinityMask& mask) const {
Os::setThreadAffinity(handle_, mask);
}
//! Set this thread's affinity to the given cpu mask.
void setAffinity(const Os::ThreadAffinityMask& mask) const
{
Os::setThreadAffinity(handle_, mask);
}
//! Yield to threads of the same priority of higher
static void yield()
{
Os::yield();
}
//! Yield to threads of the same priority of higher
static void yield() { Os::yield(); }
};
class HostThread : public Thread
{
private:
//! A HostThread does not have a run function
virtual void run(void* data) { ShouldNotCallThis(); }
class HostThread : public Thread {
private:
//! A HostThread does not have a run function
virtual void run(void* data) { ShouldNotCallThis(); }
public:
//! Construct a new HostThread
HostThread();
public:
//! Construct a new HostThread
HostThread();
//! Return true is this is the host thread.
bool isHostThread() const { return true; };
//! Return true is this is the host thread.
bool isHostThread() const { return true; };
};
/*! @}
@@ -192,40 +172,30 @@ namespace details {
extern __thread Thread* thread_ __attribute__((tls_model("initial-exec")));
static inline Thread*
currentThread()
{
return thread_;
}
static inline Thread* currentThread() { return thread_; }
#elif defined(_WIN32)
#if defined(USE_DECLSPEC_THREAD)
extern __declspec(thread) Thread* thread_;
#else // !USE_DECLSPEC_THREAD
#else // !USE_DECLSPEC_THREAD
extern DWORD threadIndex_;
#endif // !USE_DECLSPEC_THREAD
#endif // !USE_DECLSPEC_THREAD
static inline Thread*
currentThread()
{
static inline Thread* currentThread() {
#if defined(USE_DECLSPEC_THREAD)
return thread_;
#else // !USE_DECLSPEC_THREAD
return (Thread*) TlsGetValue(threadIndex_);
#endif // !USE_DECLSPEC_THREAD
return thread_;
#else // !USE_DECLSPEC_THREAD
return (Thread*)TlsGetValue(threadIndex_);
#endif // !USE_DECLSPEC_THREAD
}
#endif // _WIN32
#endif // _WIN32
} // namespace details
} // namespace details
inline Thread*
Thread::current()
{
return details::currentThread();
}
inline Thread* Thread::current() { return details::currentThread(); }
} // namespace amd
} // namespace amd
#endif /*THREAD_HPP_*/