Make Reactor build stand-alone.
This is accomplished by duplicating files from the Common directory
that Reactor (both with LLVM and Subzero back-end) depended on. They
will be minimized in the next change.
Bug b/115344057
Bug swiftshader:16
Change-Id: I2dc087e91b761cc4402ed8594022551e9246b855
Reviewed-on: https://swiftshader-review.googlesource.com/c/20108
Tested-by: Nicolas Capens <nicolascapens@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
diff --git a/src/Android.mk b/src/Android.mk
index b25ef91..d418b35 100644
--- a/src/Android.mk
+++ b/src/Android.mk
@@ -60,17 +60,22 @@
Main/FrameBufferAndroid.cpp \
Main/SwiftConfig.cpp
+COMMON_SRC_FILES += \
+ Reactor/Routine.cpp \
+ Reactor/Debug.cpp \
+ Reactor/DebugAndroid.cpp \
+ Reactor/Memory.cpp
+
ifdef SWIFTSHADER_USE_SUBZERO
COMMON_SRC_FILES += \
Reactor/SubzeroReactor.cpp \
- Reactor/Routine.cpp \
Reactor/Optimizer.cpp
else
COMMON_SRC_FILES += \
Reactor/LLVMReactor.cpp \
- Reactor/Routine.cpp \
Reactor/LLVMRoutine.cpp \
- Reactor/LLVMRoutineManager.cpp
+ Reactor/LLVMRoutineManager.cpp \
+ Reactor/CPUID.cpp
endif
COMMON_SRC_FILES += \
diff --git a/src/Common/Version.h b/src/Common/Version.h
index 72bd15d..bf1701e 100644
--- a/src/Common/Version.h
+++ b/src/Common/Version.h
@@ -15,7 +15,7 @@
#define MAJOR_VERSION 4
#define MINOR_VERSION 1
#define BUILD_VERSION 0
-#define BUILD_REVISION 2
+#define BUILD_REVISION 3
#define STRINGIFY(x) #x
#define MACRO_STRINGIFY(x) STRINGIFY(x)
diff --git a/src/Reactor/BUILD.gn b/src/Reactor/BUILD.gn
index 1084f27..c63e359 100644
--- a/src/Reactor/BUILD.gn
+++ b/src/Reactor/BUILD.gn
@@ -267,6 +267,8 @@
sources = [
"Routine.cpp",
+ "Debug.cpp",
+ "Memory.cpp",
]
if (use_swiftshader_with_subzero) {
@@ -283,7 +285,6 @@
]
include_dirs = [
- "..",
]
} else {
deps += [ "../../third_party/LLVM:swiftshader_llvm" ]
@@ -292,13 +293,12 @@
"LLVMReactor.cpp",
"LLVMRoutine.cpp",
"LLVMRoutineManager.cpp",
+ "CPUID.cpp",
]
configs = [ ":swiftshader_reactor_private_config" ]
include_dirs = [
- "..",
- "../Common",
"../../third_party/LLVM/include/",
]
}
diff --git a/src/Reactor/CPUID.cpp b/src/Reactor/CPUID.cpp
new file mode 100644
index 0000000..58ef009
--- /dev/null
+++ b/src/Reactor/CPUID.cpp
@@ -0,0 +1,227 @@
+// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "CPUID.hpp"
+
+#if defined(_WIN32)
+ #ifndef WIN32_LEAN_AND_MEAN
+ #define WIN32_LEAN_AND_MEAN
+ #endif
+ #include <windows.h>
+ #include <intrin.h>
+ #include <float.h>
+#else
+ #include <unistd.h>
+ #include <sched.h>
+ #include <sys/types.h>
+#endif
+
+namespace rr
+{
+ bool CPUID::MMX = detectMMX();
+ bool CPUID::CMOV = detectCMOV();
+ bool CPUID::SSE = detectSSE();
+ bool CPUID::SSE2 = detectSSE2();
+ bool CPUID::SSE3 = detectSSE3();
+ bool CPUID::SSSE3 = detectSSSE3();
+ bool CPUID::SSE4_1 = detectSSE4_1();
+
+ bool CPUID::enableMMX = true;
+ bool CPUID::enableCMOV = true;
+ bool CPUID::enableSSE = true;
+ bool CPUID::enableSSE2 = true;
+ bool CPUID::enableSSE3 = true;
+ bool CPUID::enableSSSE3 = true;
+ bool CPUID::enableSSE4_1 = true;
+
+ void CPUID::setEnableMMX(bool enable)
+ {
+ enableMMX = enable;
+
+ if(!enableMMX)
+ {
+ enableSSE = false;
+ enableSSE2 = false;
+ enableSSE3 = false;
+ enableSSSE3 = false;
+ enableSSE4_1 = false;
+ }
+ }
+
+ void CPUID::setEnableCMOV(bool enable)
+ {
+ enableCMOV = enable;
+
+ if(!CMOV)
+ {
+ enableSSE = false;
+ enableSSE2 = false;
+ enableSSE3 = false;
+ enableSSSE3 = false;
+ enableSSE4_1 = false;
+ }
+ }
+
+ void CPUID::setEnableSSE(bool enable)
+ {
+ enableSSE = enable;
+
+ if(enableSSE)
+ {
+ enableMMX = true;
+ enableCMOV = true;
+ }
+ else
+ {
+ enableSSE2 = false;
+ enableSSE3 = false;
+ enableSSSE3 = false;
+ enableSSE4_1 = false;
+ }
+ }
+
+ void CPUID::setEnableSSE2(bool enable)
+ {
+ enableSSE2 = enable;
+
+ if(enableSSE2)
+ {
+ enableMMX = true;
+ enableCMOV = true;
+ enableSSE = true;
+ }
+ else
+ {
+ enableSSE3 = false;
+ enableSSSE3 = false;
+ enableSSE4_1 = false;
+ }
+ }
+
+ void CPUID::setEnableSSE3(bool enable)
+ {
+ enableSSE3 = enable;
+
+ if(enableSSE3)
+ {
+ enableMMX = true;
+ enableCMOV = true;
+ enableSSE = true;
+ enableSSE2 = true;
+ }
+ else
+ {
+ enableSSSE3 = false;
+ enableSSE4_1 = false;
+ }
+ }
+
+ void CPUID::setEnableSSSE3(bool enable)
+ {
+ enableSSSE3 = enable;
+
+ if(enableSSSE3)
+ {
+ enableMMX = true;
+ enableCMOV = true;
+ enableSSE = true;
+ enableSSE2 = true;
+ enableSSE3 = true;
+ }
+ else
+ {
+ enableSSE4_1 = false;
+ }
+ }
+
+ void CPUID::setEnableSSE4_1(bool enable)
+ {
+ enableSSE4_1 = enable;
+
+ if(enableSSE4_1)
+ {
+ enableMMX = true;
+ enableCMOV = true;
+ enableSSE = true;
+ enableSSE2 = true;
+ enableSSE3 = true;
+ enableSSSE3 = true;
+ }
+ }
+
+ static void cpuid(int registers[4], int info)
+ {
+ #if defined(__i386__) || defined(__x86_64__)
+ #if defined(_WIN32)
+ __cpuid(registers, info);
+ #else
+ __asm volatile("cpuid": "=a" (registers[0]), "=b" (registers[1]), "=c" (registers[2]), "=d" (registers[3]): "a" (info));
+ #endif
+ #else
+ registers[0] = 0;
+ registers[1] = 0;
+ registers[2] = 0;
+ registers[3] = 0;
+ #endif
+ }
+
+ bool CPUID::detectMMX()
+ {
+ int registers[4];
+ cpuid(registers, 1);
+ return MMX = (registers[3] & 0x00800000) != 0;
+ }
+
+ bool CPUID::detectCMOV()
+ {
+ int registers[4];
+ cpuid(registers, 1);
+ return CMOV = (registers[3] & 0x00008000) != 0;
+ }
+
+ bool CPUID::detectSSE()
+ {
+ int registers[4];
+ cpuid(registers, 1);
+ return SSE = (registers[3] & 0x02000000) != 0;
+ }
+
+ bool CPUID::detectSSE2()
+ {
+ int registers[4];
+ cpuid(registers, 1);
+ return SSE2 = (registers[3] & 0x04000000) != 0;
+ }
+
+ bool CPUID::detectSSE3()
+ {
+ int registers[4];
+ cpuid(registers, 1);
+ return SSE3 = (registers[2] & 0x00000001) != 0;
+ }
+
+ bool CPUID::detectSSSE3()
+ {
+ int registers[4];
+ cpuid(registers, 1);
+ return SSSE3 = (registers[2] & 0x00000200) != 0;
+ }
+
+ bool CPUID::detectSSE4_1()
+ {
+ int registers[4];
+ cpuid(registers, 1);
+ return SSE4_1 = (registers[2] & 0x00080000) != 0;
+ }
+}
diff --git a/src/Reactor/CPUID.hpp b/src/Reactor/CPUID.hpp
new file mode 100644
index 0000000..108d4a7
--- /dev/null
+++ b/src/Reactor/CPUID.hpp
@@ -0,0 +1,118 @@
+// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef rr_CPUID_hpp
+#define rr_CPUID_hpp
+
+namespace rr
+{
+ #if !defined(__i386__) && defined(_M_IX86)
+ #define __i386__ 1
+ #endif
+
+ #if !defined(__x86_64__) && (defined(_M_AMD64) || defined (_M_X64))
+ #define __x86_64__ 1
+ #endif
+
+ class CPUID
+ {
+ public:
+ static bool supportsMMX();
+ static bool supportsCMOV();
+ static bool supportsMMX2(); // MMX instructions added by SSE: pshufw, pmulhuw, pmovmskb, pavgw/b, pextrw, pinsrw, pmaxsw/ub, etc.
+ static bool supportsSSE();
+ static bool supportsSSE2();
+ static bool supportsSSE3();
+ static bool supportsSSSE3();
+ static bool supportsSSE4_1();
+
+ static void setEnableMMX(bool enable);
+ static void setEnableCMOV(bool enable);
+ static void setEnableSSE(bool enable);
+ static void setEnableSSE2(bool enable);
+ static void setEnableSSE3(bool enable);
+ static void setEnableSSSE3(bool enable);
+ static void setEnableSSE4_1(bool enable);
+
+ private:
+ static bool MMX;
+ static bool CMOV;
+ static bool SSE;
+ static bool SSE2;
+ static bool SSE3;
+ static bool SSSE3;
+ static bool SSE4_1;
+
+ static bool enableMMX;
+ static bool enableCMOV;
+ static bool enableSSE;
+ static bool enableSSE2;
+ static bool enableSSE3;
+ static bool enableSSSE3;
+ static bool enableSSE4_1;
+
+ static bool detectMMX();
+ static bool detectCMOV();
+ static bool detectSSE();
+ static bool detectSSE2();
+ static bool detectSSE3();
+ static bool detectSSSE3();
+ static bool detectSSE4_1();
+ };
+}
+
+namespace rr
+{
+ inline bool CPUID::supportsMMX()
+ {
+ return MMX && enableMMX;
+ }
+
+ inline bool CPUID::supportsCMOV()
+ {
+ return CMOV && enableCMOV;
+ }
+
+ inline bool CPUID::supportsMMX2()
+ {
+ return supportsSSE(); // Coincides with 64-bit integer vector instructions supported by SSE
+ }
+
+ inline bool CPUID::supportsSSE()
+ {
+ return SSE && enableSSE;
+ }
+
+ inline bool CPUID::supportsSSE2()
+ {
+ return SSE2 && enableSSE2;
+ }
+
+ inline bool CPUID::supportsSSE3()
+ {
+ return SSE3 && enableSSE3;
+ }
+
+ inline bool CPUID::supportsSSSE3()
+ {
+ return SSSE3 && enableSSSE3;
+ }
+
+ inline bool CPUID::supportsSSE4_1()
+ {
+ return SSE4_1 && enableSSE4_1;
+ }
+}
+
+#endif // rr_CPUID_hpp
diff --git a/src/Reactor/Debug.cpp b/src/Reactor/Debug.cpp
new file mode 100644
index 0000000..adfcabd
--- /dev/null
+++ b/src/Reactor/Debug.cpp
@@ -0,0 +1,39 @@
+// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "Debug.hpp"
+
+#include <stdio.h>
+#include <stdarg.h>
+
+namespace rr
+{
+void trace(const char *format, ...)
+{
+ if(false)
+ {
+ FILE *file = fopen("debug.txt", "a");
+
+ if(file)
+ {
+ va_list vararg;
+ va_start(vararg, format);
+ vfprintf(file, format, vararg);
+ va_end(vararg);
+
+ fclose(file);
+ }
+ }
+}
+}
\ No newline at end of file
diff --git a/src/Reactor/Debug.hpp b/src/Reactor/Debug.hpp
new file mode 100644
index 0000000..720b38a
--- /dev/null
+++ b/src/Reactor/Debug.hpp
@@ -0,0 +1,52 @@
+// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef Debug_hpp
+#define Debug_hpp
+
+#ifdef __ANDROID__
+#include "DebugAndroid.hpp"
+#else
+
+#include <assert.h>
+#include <stdio.h>
+
+#undef min
+#undef max
+
+namespace rr
+{
+void trace(const char *format, ...);
+
+#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
+ #define TRACE(format, ...) trace("[0x%0.8X]%s(" format ")\n", this, __FUNCTION__, ##__VA_ARGS__)
+#else
+ #define TRACE(...) ((void)0)
+#endif
+
+#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
+ #define UNIMPLEMENTED() {trace("\t! Unimplemented: %s(%d)\n", __FUNCTION__, __LINE__); ASSERT(false);}
+#else
+ #define UNIMPLEMENTED() ((void)0)
+#endif
+
+#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
+ #define ASSERT(expression) {if(!(expression)) trace("\t! Assert failed in %s(%d): " #expression "\n", __FUNCTION__, __LINE__); assert(expression);}
+#else
+ #define ASSERT assert
+#endif
+}
+
+#endif // __ANDROID__
+#endif // Debug_hpp
diff --git a/src/Reactor/DebugAndroid.cpp b/src/Reactor/DebugAndroid.cpp
new file mode 100644
index 0000000..c511fc3
--- /dev/null
+++ b/src/Reactor/DebugAndroid.cpp
@@ -0,0 +1,53 @@
+// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "DebugAndroid.hpp"
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <cutils/properties.h>
+
+void AndroidEnterDebugger()
+{
+ ALOGE(__FUNCTION__);
+#ifndef NDEBUG
+ static volatile int * const makefault = nullptr;
+ char value[PROPERTY_VALUE_MAX];
+ property_get("debug.db.uid", value, "-1");
+ int debug_uid = atoi(value);
+ if((debug_uid >= 0) && (geteuid() < static_cast<uid_t>(debug_uid)))
+ {
+ ALOGE("Waiting for debugger: gdbserver :${PORT} --attach %u. Look for thread %u", getpid(), gettid());
+ volatile int waiting = 1;
+ while (waiting) {
+ sleep(1);
+ }
+ }
+ else
+ {
+ ALOGE("No debugger");
+ }
+#endif
+}
+
+void trace(const char *format, ...)
+{
+#ifndef NDEBUG
+ va_list vararg;
+ va_start(vararg, format);
+ android_vprintLog(ANDROID_LOG_VERBOSE, NULL, LOG_TAG, format, vararg);
+ va_end(vararg);
+#endif
+}
diff --git a/src/Reactor/DebugAndroid.hpp b/src/Reactor/DebugAndroid.hpp
new file mode 100644
index 0000000..eced194
--- /dev/null
+++ b/src/Reactor/DebugAndroid.hpp
@@ -0,0 +1,99 @@
+// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef DebugAndroid_hpp
+#define DebugAndroid_hpp
+
+#if ANDROID_PLATFORM_SDK_VERSION < 27
+#include <cutils/log.h>
+#elif ANDROID_PLATFORM_SDK_VERSION >= 27
+#include <log/log.h>
+#else
+#error "ANDROID_PLATFORM_SDK_VERSION is not defined"
+#endif
+
+#include <cassert>
+
+// On Android Virtual Devices we heavily depend on logging, even in
+// production builds. We do this because AVDs are components of larger
+// systems, and may be configured in ways that are difficult to
+// reproduce locally. For example some system run tests against
+// third-party code that we cannot access. Aborting (cf. assert) on
+// unimplemented functionality creates two problems. First, it produces
+// a service failure where none is needed. Second, it puts the
+// customer on the critical path for notifying us of a problem.
+// The alternative, skipping unimplemented functionality silently, is
+// arguably worse: neither the service provider nor the customer will
+// learn that unimplemented functionality may have compromised the test
+// results.
+// Logging invocations of unimplemented functionality is useful to both
+// service provider and the customer. The service provider can learn
+// that the functionality is needed. The customer learns that the test
+// results may be compromised.
+
+/**
+ * Enter the debugger with a memory fault iff debuggerd is set to capture this
+ * process. Otherwise return.
+ */
+void AndroidEnterDebugger();
+
+#define ASSERT(E) do { \
+ if (!(E)) { \
+ ALOGE("badness: assertion_failed %s in %s at %s:%d", #E, \
+ __FUNCTION__, __FILE__, __LINE__); \
+ AndroidEnterDebugger(); \
+ } \
+ } while(0)
+
+#undef assert
+#define assert(E) ASSERT(E)
+
+#define ERR(format, ...) \
+ do { \
+ ALOGE("badness: err %s %s:%d (" format ")", __FUNCTION__, __FILE__, \
+ __LINE__, ##__VA_ARGS__); \
+ AndroidEnterDebugger(); \
+ } while(0)
+
+#define FIXME(format, ...) \
+ do { \
+ ALOGE("badness: fixme %s %s:%d (" format ")", __FUNCTION__, __FILE__, \
+ __LINE__, ##__VA_ARGS__); \
+ AndroidEnterDebugger(); \
+ } while(0)
+
+// TODO: Handle __VA_ARGS__ (can be empty)
+#define UNIMPLEMENTED(...) do { \
+ ALOGE("badness: unimplemented: %s %s:%d", \
+ __FUNCTION__, __FILE__, __LINE__); \
+ AndroidEnterDebugger(); \
+ } while(0)
+
+#define UNREACHABLE(value) do { \
+ ALOGE("badness: unreachable case reached: %s %s:%d. %s: %d", \
+ __FUNCTION__, __FILE__, __LINE__, #value, value); \
+ AndroidEnterDebugger(); \
+ } while(0)
+
+#ifndef NDEBUG
+ #define TRACE(format, ...) \
+ ALOGV("%s %s:%d (" format ")", __FUNCTION__, __FILE__, \
+ __LINE__, ##__VA_ARGS__)
+#else
+ #define TRACE(...) ((void)0)
+#endif
+
+void trace(const char *format, ...);
+
+#endif // DebugAndroid_hpp
diff --git a/src/Reactor/LLVMReactor.cpp b/src/Reactor/LLVMReactor.cpp
index b702ec9..0f3b3da 100644
--- a/src/Reactor/LLVMReactor.cpp
+++ b/src/Reactor/LLVMReactor.cpp
@@ -14,6 +14,15 @@
#include "Reactor.hpp"
+#include "x86.hpp"
+#include "CPUID.hpp"
+#include "Thread.hpp"
+#include "Memory.hpp"
+#include "MutexLock.hpp"
+
+#undef min
+#undef max
+
#if SWIFTSHADER_LLVM_VERSION < 7
#include "llvm/Analysis/LoopPass.h"
#include "llvm/Constants.h"
@@ -69,12 +78,6 @@
#include <unordered_map>
#endif
-#include "x86.hpp"
-#include "Common/CPUID.hpp"
-#include "Common/Thread.hpp"
-#include "Common/Memory.hpp"
-#include "Common/MutexLock.hpp"
-
#include <numeric>
#include <fstream>
@@ -120,7 +123,7 @@
llvm::Module *module = nullptr;
llvm::Function *function = nullptr;
- sw::MutexLock codegenMutex;
+ rr::MutexLock codegenMutex;
#if SWIFTSHADER_LLVM_VERSION >= 7
llvm::Value *lowerPAVG(llvm::Value *x, llvm::Value *y)
@@ -443,8 +446,6 @@
namespace rr
{
- using namespace sw;
-
#if SWIFTSHADER_LLVM_VERSION < 7
class LLVMReactorJIT
{
diff --git a/src/Reactor/LLVMRoutine.cpp b/src/Reactor/LLVMRoutine.cpp
index 8dbfe07..6b37fa6 100644
--- a/src/Reactor/LLVMRoutine.cpp
+++ b/src/Reactor/LLVMRoutine.cpp
@@ -14,16 +14,16 @@
#include "LLVMRoutine.hpp"
-#include "Common/Memory.hpp"
-#include "Common/Thread.hpp"
-#include "Common/Types.hpp"
+#include "Memory.hpp"
+#include "Thread.hpp"
+#include "Types.hpp"
namespace rr
{
#if SWIFTSHADER_LLVM_VERSION < 7
LLVMRoutine::LLVMRoutine(int bufferSize) : bufferSize(bufferSize)
{
- void *memory = sw::allocateExecutable(bufferSize);
+ void *memory = allocateExecutable(bufferSize);
buffer = memory;
entry = memory;
@@ -32,7 +32,7 @@
LLVMRoutine::~LLVMRoutine()
{
- sw::deallocateExecutable(buffer, bufferSize);
+ deallocateExecutable(buffer, bufferSize);
}
const void *LLVMRoutine::getEntry()
diff --git a/src/Reactor/LLVMRoutineManager.cpp b/src/Reactor/LLVMRoutineManager.cpp
index 8af37f3..276bdd9 100644
--- a/src/Reactor/LLVMRoutineManager.cpp
+++ b/src/Reactor/LLVMRoutineManager.cpp
@@ -18,9 +18,9 @@
#include "LLVMRoutine.hpp"
#include "llvm/Function.h"
-#include "Common/Memory.hpp"
-#include "Common/Thread.hpp"
-#include "Common/Debug.hpp"
+#include "Memory.hpp"
+#include "Thread.hpp"
+#include "Debug.hpp"
namespace rr
{
@@ -63,11 +63,11 @@
}
else // Estimate was too low
{
- sw::atomicIncrement(&averageInstructionSize);
+ atomicIncrement(&averageInstructionSize);
}
// Round up to the next page size
- size_t pageSize = sw::memoryPageSize();
+ size_t pageSize = memoryPageSize();
actualSize = (actualSize + pageSize - 1) & ~(pageSize - 1);
delete routine;
@@ -130,7 +130,7 @@
void LLVMRoutineManager::setMemoryExecutable()
{
- sw::markExecutable(routine->buffer, routine->bufferSize);
+ markExecutable(routine->buffer, routine->bufferSize);
}
void LLVMRoutineManager::setPoisonMemory(bool poison)
diff --git a/src/Reactor/Memory.cpp b/src/Reactor/Memory.cpp
new file mode 100644
index 0000000..c7c3d6d
--- /dev/null
+++ b/src/Reactor/Memory.cpp
@@ -0,0 +1,262 @@
+// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "Memory.hpp"
+
+#include "Types.hpp"
+#include "Debug.hpp"
+
+#if defined(_WIN32)
+ #ifndef WIN32_LEAN_AND_MEAN
+ #define WIN32_LEAN_AND_MEAN
+ #endif
+ #include <windows.h>
+ #include <intrin.h>
+#else
+ #include <errno.h>
+ #include <sys/mman.h>
+ #include <stdlib.h>
+ #include <unistd.h>
+#endif
+
+#include <memory.h>
+
+#undef allocate
+#undef deallocate
+
+#if (defined(__i386__) || defined(_M_IX86) || defined(__x86_64__) || defined (_M_X64)) && !defined(__x86__)
+#define __x86__
+#endif
+
+namespace rr
+{
+namespace
+{
+struct Allocation
+{
+// size_t bytes;
+ unsigned char *block;
+};
+
+void *allocateRaw(size_t bytes, size_t alignment)
+{
+ ASSERT((alignment & (alignment - 1)) == 0); // Power of 2 alignment.
+
+ #if defined(LINUX_ENABLE_NAMED_MMAP)
+ void *allocation;
+ int result = posix_memalign(&allocation, alignment, bytes);
+ if(result != 0)
+ {
+ errno = result;
+ allocation = nullptr;
+ }
+ return allocation;
+ #else
+ unsigned char *block = new unsigned char[bytes + sizeof(Allocation) + alignment];
+ unsigned char *aligned = nullptr;
+
+ if(block)
+ {
+ aligned = (unsigned char*)((uintptr_t)(block + sizeof(Allocation) + alignment - 1) & -(intptr_t)alignment);
+ Allocation *allocation = (Allocation*)(aligned - sizeof(Allocation));
+
+ // allocation->bytes = bytes;
+ allocation->block = block;
+ }
+
+ return aligned;
+ #endif
+}
+
+#if defined(LINUX_ENABLE_NAMED_MMAP)
+// Create a file descriptor for anonymous memory with the given
+// name. Returns -1 on failure.
+// TODO: remove once libc wrapper exists.
+int memfd_create(const char* name, unsigned int flags)
+{
+ #if __aarch64__
+ #define __NR_memfd_create 279
+ #elif __arm__
+ #define __NR_memfd_create 279
+ #elif __powerpc64__
+ #define __NR_memfd_create 360
+ #elif __i386__
+ #define __NR_memfd_create 356
+ #elif __x86_64__
+ #define __NR_memfd_create 319
+ #endif /* __NR_memfd_create__ */
+ #ifdef __NR_memfd_create
+ // In the event of no system call this returns -1 with errno set
+ // as ENOSYS.
+ return syscall(__NR_memfd_create, name, flags);
+ #else
+ return -1;
+ #endif
+}
+
+// Returns a file descriptor for use with an anonymous mmap, if
+// memfd_create fails, -1 is returned. Note, the mappings should be
+// MAP_PRIVATE so that underlying pages aren't shared.
+int anonymousFd()
+{
+ static int fd = memfd_create("SwiftShader JIT", 0);
+ return fd;
+}
+
+// Ensure there is enough space in the "anonymous" fd for length.
+void ensureAnonFileSize(int anonFd, size_t length)
+{
+ static size_t fileSize = 0;
+ if(length > fileSize)
+ {
+ ftruncate(anonFd, length);
+ fileSize = length;
+ }
+}
+#endif // defined(LINUX_ENABLE_NAMED_MMAP)
+
+} // anonymous namespace
+
+size_t memoryPageSize()
+{
+ static int pageSize = 0;
+
+ if(pageSize == 0)
+ {
+ #if defined(_WIN32)
+ SYSTEM_INFO systemInfo;
+ GetSystemInfo(&systemInfo);
+ pageSize = systemInfo.dwPageSize;
+ #else
+ pageSize = sysconf(_SC_PAGESIZE);
+ #endif
+ }
+
+ return pageSize;
+}
+
+void *allocate(size_t bytes, size_t alignment)
+{
+ void *memory = allocateRaw(bytes, alignment);
+
+ if(memory)
+ {
+ memset(memory, 0, bytes);
+ }
+
+ return memory;
+}
+
+void deallocate(void *memory)
+{
+ #if defined(LINUX_ENABLE_NAMED_MMAP)
+ free(memory);
+ #else
+ if(memory)
+ {
+ unsigned char *aligned = (unsigned char*)memory;
+ Allocation *allocation = (Allocation*)(aligned - sizeof(Allocation));
+
+ delete[] allocation->block;
+ }
+ #endif
+}
+
+void *allocateExecutable(size_t bytes)
+{
+ size_t pageSize = memoryPageSize();
+ size_t length = (bytes + pageSize - 1) & ~(pageSize - 1);
+ void *mapping;
+
+ #if defined(LINUX_ENABLE_NAMED_MMAP)
+ // Try to name the memory region for the executable code,
+ // to aid profilers.
+ int anonFd = anonymousFd();
+ if(anonFd == -1)
+ {
+ mapping = mmap(nullptr, length, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ }
+ else
+ {
+ ensureAnonFileSize(anonFd, length);
+ mapping = mmap(nullptr, length, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE, anonFd, 0);
+ }
+
+ if(mapping == MAP_FAILED)
+ {
+ mapping = nullptr;
+ }
+ #else
+ mapping = allocate(length, pageSize);
+ #endif
+
+ return mapping;
+}
+
+void markExecutable(void *memory, size_t bytes)
+{
+ #if defined(_WIN32)
+ unsigned long oldProtection;
+ VirtualProtect(memory, bytes, PAGE_EXECUTE_READ, &oldProtection);
+ #else
+ mprotect(memory, bytes, PROT_READ | PROT_EXEC);
+ #endif
+}
+
+void deallocateExecutable(void *memory, size_t bytes)
+{
+ #if defined(_WIN32)
+ unsigned long oldProtection;
+ VirtualProtect(memory, bytes, PAGE_READWRITE, &oldProtection);
+ deallocate(memory);
+ #elif defined(LINUX_ENABLE_NAMED_MMAP)
+ size_t pageSize = memoryPageSize();
+ size_t length = (bytes + pageSize - 1) & ~(pageSize - 1);
+ munmap(memory, length);
+ #else
+ mprotect(memory, bytes, PROT_READ | PROT_WRITE);
+ deallocate(memory);
+ #endif
+}
+
+void clear(uint16_t *memory, uint16_t element, size_t count)
+{
+ #if defined(_MSC_VER) && defined(__x86__) && !defined(MEMORY_SANITIZER)
+ __stosw(memory, element, count);
+ #elif defined(__GNUC__) && defined(__x86__) && !defined(MEMORY_SANITIZER)
+ __asm__("rep stosw" : : "D"(memory), "a"(element), "c"(count));
+ #else
+ for(size_t i = 0; i < count; i++)
+ {
+ memory[i] = element;
+ }
+ #endif
+}
+
+void clear(uint32_t *memory, uint32_t element, size_t count)
+{
+ #if defined(_MSC_VER) && defined(__x86__) && !defined(MEMORY_SANITIZER)
+ __stosd((unsigned long*)memory, element, count);
+ #elif defined(__GNUC__) && defined(__x86__) && !defined(MEMORY_SANITIZER)
+ __asm__("rep stosl" : : "D"(memory), "a"(element), "c"(count));
+ #else
+ for(size_t i = 0; i < count; i++)
+ {
+ memory[i] = element;
+ }
+ #endif
+}
+}
diff --git a/src/Reactor/Memory.hpp b/src/Reactor/Memory.hpp
new file mode 100644
index 0000000..3517f3c
--- /dev/null
+++ b/src/Reactor/Memory.hpp
@@ -0,0 +1,36 @@
+// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef rr_Memory_hpp
+#define rr_Memory_hpp
+
+#include <stddef.h>
+#include <stdint.h>
+
+namespace rr
+{
+size_t memoryPageSize();
+
+void *allocate(size_t bytes, size_t alignment = 16);
+void deallocate(void *memory);
+
+void *allocateExecutable(size_t bytes); // Allocates memory that can be made executable using markExecutable()
+void markExecutable(void *memory, size_t bytes);
+void deallocateExecutable(void *memory, size_t bytes);
+
+void clear(uint16_t *memory, uint16_t element, size_t count);
+void clear(uint32_t *memory, uint32_t element, size_t count);
+}
+
+#endif // rr_Memory_hpp
diff --git a/src/Reactor/MutexLock.hpp b/src/Reactor/MutexLock.hpp
new file mode 100644
index 0000000..c2d00eb
--- /dev/null
+++ b/src/Reactor/MutexLock.hpp
@@ -0,0 +1,177 @@
+// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef rr_MutexLock_hpp
+#define rr_MutexLock_hpp
+
+#include "Thread.hpp"
+
+#if defined(__linux__)
+// Use a pthread mutex on Linux. Since many processes may use SwiftShader
+// at the same time it's best to just have the scheduler overhead.
+#include <pthread.h>
+
+namespace rr
+{
+ class MutexLock
+ {
+ public:
+ MutexLock()
+ {
+ pthread_mutex_init(&mutex, NULL);
+ }
+
+ ~MutexLock()
+ {
+ pthread_mutex_destroy(&mutex);
+ }
+
+ bool attemptLock()
+ {
+ return pthread_mutex_trylock(&mutex) == 0;
+ }
+
+ void lock()
+ {
+ pthread_mutex_lock(&mutex);
+ }
+
+ void unlock()
+ {
+ pthread_mutex_unlock(&mutex);
+ }
+
+ private:
+ pthread_mutex_t mutex;
+ };
+}
+
+#else // !__linux__
+
+#include <atomic>
+
+namespace rr
+{
+ class BackoffLock
+ {
+ public:
+ BackoffLock()
+ {
+ mutex = 0;
+ }
+
+ bool attemptLock()
+ {
+ if(!isLocked())
+ {
+ if(mutex.exchange(true) == false)
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ void lock()
+ {
+ int backoff = 1;
+
+ while(!attemptLock())
+ {
+ if(backoff <= 64)
+ {
+ for(int i = 0; i < backoff; i++)
+ {
+ nop();
+ nop();
+ nop();
+ nop();
+ nop();
+
+ nop();
+ nop();
+ nop();
+ nop();
+ nop();
+
+ nop();
+ nop();
+ nop();
+ nop();
+ nop();
+
+ nop();
+ nop();
+ nop();
+ nop();
+ nop();
+
+ nop();
+ nop();
+ nop();
+ nop();
+ nop();
+
+ nop();
+ nop();
+ nop();
+ nop();
+ nop();
+
+ nop();
+ nop();
+ nop();
+ nop();
+ nop();
+ }
+
+ backoff *= 2;
+ }
+ else
+ {
+ Thread::yield();
+
+ backoff = 1;
+ }
+ };
+ }
+
+ void unlock()
+ {
+ mutex.store(false, std::memory_order_release);
+ }
+
+ bool isLocked()
+ {
+ return mutex.load(std::memory_order_acquire);
+ }
+
+ private:
+ struct
+ {
+ // Ensure that the mutex variable is on its own 64-byte cache line to avoid false sharing
+ // Padding must be public to avoid compiler warnings
+ volatile int padding1[16];
+ std::atomic<bool> mutex;
+ volatile int padding2[15];
+ };
+ };
+
+ using MutexLock = BackoffLock;
+}
+
+#endif // !__linux__
+
+#endif // rr_MutexLock_hpp
diff --git a/src/Reactor/Reactor.vcxproj b/src/Reactor/Reactor.vcxproj
index 788de64..dbf7b5f 100644
--- a/src/Reactor/Reactor.vcxproj
+++ b/src/Reactor/Reactor.vcxproj
@@ -277,17 +277,27 @@
</ProjectReference>
</ItemDefinitionGroup>
<ItemGroup>
+ <ClCompile Include="CPUID.cpp" />
+ <ClCompile Include="Debug.cpp" />
<ClCompile Include="LLVMRoutine.cpp" />
<ClCompile Include="LLVMRoutineManager.cpp" />
<ClCompile Include="LLVMReactor.cpp" />
+ <ClCompile Include="Memory.cpp" />
<ClCompile Include="Routine.cpp" />
+ <ClCompile Include="Thread.cpp" />
</ItemGroup>
<ItemGroup>
+ <ClInclude Include="CPUID.hpp" />
+ <ClInclude Include="Debug.hpp" />
<ClInclude Include="LLVMRoutine.hpp" />
<ClInclude Include="LLVMRoutineManager.hpp" />
+ <ClInclude Include="Memory.hpp" />
+ <ClInclude Include="MutexLock.hpp" />
<ClInclude Include="Nucleus.hpp" />
<ClInclude Include="Reactor.hpp" />
<ClInclude Include="Routine.hpp" />
+ <ClInclude Include="Thread.hpp" />
+ <ClInclude Include="Types.hpp" />
<ClInclude Include="x86.hpp" />
</ItemGroup>
<ItemGroup>
diff --git a/src/Reactor/Reactor.vcxproj.filters b/src/Reactor/Reactor.vcxproj.filters
index 2aebff5..34bb0f1 100644
--- a/src/Reactor/Reactor.vcxproj.filters
+++ b/src/Reactor/Reactor.vcxproj.filters
@@ -27,6 +27,18 @@
<ClCompile Include="LLVMReactor.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="CPUID.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="Debug.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="Memory.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="Thread.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Nucleus.hpp">
@@ -47,5 +59,23 @@
<ClInclude Include="LLVMRoutine.hpp">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="CPUID.hpp">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="Debug.hpp">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="Memory.hpp">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="MutexLock.hpp">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="Thread.hpp">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="Types.hpp">
+ <Filter>Header Files</Filter>
+ </ClInclude>
</ItemGroup>
</Project>
\ No newline at end of file
diff --git a/src/Reactor/Main.cpp b/src/Reactor/ReactorUnitTests.cpp
similarity index 97%
rename from src/Reactor/Main.cpp
rename to src/Reactor/ReactorUnitTests.cpp
index 2bc9f7e..f6484f4 100644
--- a/src/Reactor/Main.cpp
+++ b/src/Reactor/ReactorUnitTests.cpp
@@ -33,7 +33,7 @@
return sum;
}
-TEST(SubzeroReactorTest, Sample)
+TEST(ReactorUnitTests, Sample)
{
Routine *routine = nullptr;
@@ -73,7 +73,7 @@
delete routine;
}
-TEST(SubzeroReactorTest, Uninitialized)
+TEST(ReactorUnitTests, Uninitialized)
{
Routine *routine = nullptr;
@@ -110,7 +110,7 @@
delete routine;
}
-TEST(SubzeroReactorTest, SubVectorLoadStore)
+TEST(ReactorUnitTests, SubVectorLoadStore)
{
Routine *routine = nullptr;
@@ -170,7 +170,7 @@
delete routine;
}
-TEST(SubzeroReactorTest, VectorConstant)
+TEST(ReactorUnitTests, VectorConstant)
{
Routine *routine = nullptr;
@@ -219,7 +219,7 @@
delete routine;
}
-TEST(SubzeroReactorTest, Concatenate)
+TEST(ReactorUnitTests, Concatenate)
{
Routine *routine = nullptr;
@@ -262,7 +262,7 @@
delete routine;
}
-TEST(SubzeroReactorTest, Swizzle)
+TEST(ReactorUnitTests, Swizzle)
{
Routine *routine = nullptr;
@@ -389,7 +389,7 @@
delete routine;
}
-TEST(SubzeroReactorTest, Branching)
+TEST(ReactorUnitTests, Branching)
{
Routine *routine = nullptr;
@@ -454,7 +454,7 @@
delete routine;
}
-TEST(SubzeroReactorTest, MinMax)
+TEST(ReactorUnitTests, MinMax)
{
Routine *routine = nullptr;
@@ -545,7 +545,7 @@
delete routine;
}
-TEST(SubzeroReactorTest, NotNeg)
+TEST(ReactorUnitTests, NotNeg)
{
Routine *routine = nullptr;
@@ -630,7 +630,7 @@
delete routine;
}
-TEST(SubzeroReactorTest, VectorCompare)
+TEST(ReactorUnitTests, VectorCompare)
{
Routine *routine = nullptr;
@@ -692,7 +692,7 @@
delete routine;
}
-TEST(SubzeroReactorTest, SaturatedAddAndSubtract)
+TEST(ReactorUnitTests, SaturatedAddAndSubtract)
{
Routine *routine = nullptr;
@@ -805,7 +805,7 @@
delete routine;
}
-TEST(SubzeroReactorTest, Unpack)
+TEST(ReactorUnitTests, Unpack)
{
Routine *routine = nullptr;
@@ -852,7 +852,7 @@
delete routine;
}
-TEST(SubzeroReactorTest, Pack)
+TEST(ReactorUnitTests, Pack)
{
Routine *routine = nullptr;
@@ -914,7 +914,7 @@
delete routine;
}
-TEST(SubzeroReactorTest, MulHigh)
+TEST(ReactorUnitTests, MulHigh)
{
Routine *routine = nullptr;
@@ -956,7 +956,7 @@
delete routine;
}
-TEST(SubzeroReactorTest, MulAdd)
+TEST(ReactorUnitTests, MulAdd)
{
Routine *routine = nullptr;
diff --git a/src/Reactor/SubzeroTest.vcxproj b/src/Reactor/ReactorUnitTests.vcxproj
similarity index 73%
rename from src/Reactor/SubzeroTest.vcxproj
rename to src/Reactor/ReactorUnitTests.vcxproj
index 218073b..0471ba6 100644
--- a/src/Reactor/SubzeroTest.vcxproj
+++ b/src/Reactor/ReactorUnitTests.vcxproj
@@ -21,7 +21,7 @@
<PropertyGroup Label="Globals">
<ProjectGuid>{4EC107AB-89E8-4A0B-8366-B3E81085AE07}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
- <RootNamespace>SubzeroTest</RootNamespace>
+ <RootNamespace>ReactorUnitTests</RootNamespace>
<WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
@@ -170,67 +170,14 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
+ <ClCompile Include="..\..\third_party\googletest\googletest\src\gtest-all.cc" />
+ <ClCompile Include="ReactorUnitTests.cpp" />
+ </ItemGroup>
+ <ItemGroup>
<ProjectReference Include="Subzero.vcxproj">
<Project>{0eb31aec-b020-46ab-ba05-730f6d01c29b}</Project>
- <UseLibraryDependencyInputs>false</UseLibraryDependencyInputs>
- <LinkLibraryDependencies>true</LinkLibraryDependencies>
- <CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
</ProjectReference>
</ItemGroup>
- <ItemGroup>
- <ClCompile Include="..\..\third_party\googletest\googletest\src\gtest-all.cc" />
- <ClCompile Include="..\..\third_party\subzero\unittest\AssemblerX8632\ControlFlow.cpp">
- <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
- <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
- </ClCompile>
- <ClCompile Include="..\..\third_party\subzero\unittest\AssemblerX8632\DataMov.cpp">
- <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
- <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
- </ClCompile>
- <ClCompile Include="..\..\third_party\subzero\unittest\AssemblerX8632\LowLevel.cpp">
- <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
- <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
- </ClCompile>
- <ClCompile Include="..\..\third_party\subzero\unittest\AssemblerX8632\Other.cpp">
- <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
- <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
- </ClCompile>
- <ClCompile Include="..\..\third_party\subzero\unittest\AssemblerX8632\XmmArith.cpp">
- <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
- <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
- </ClCompile>
- <ClCompile Include="..\..\third_party\subzero\unittest\AssemblerX8664\ControlFlow.cpp">
- <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
- <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
- </ClCompile>
- <ClCompile Include="..\..\third_party\subzero\unittest\AssemblerX8664\DataMov.cpp">
- <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
- <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
- </ClCompile>
- <ClCompile Include="..\..\third_party\subzero\unittest\AssemblerX8664\LowLevel.cpp">
- <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
- <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
- </ClCompile>
- <ClCompile Include="..\..\third_party\subzero\unittest\AssemblerX8664\Other.cpp">
- <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
- <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
- </ClCompile>
- <ClCompile Include="..\..\third_party\subzero\unittest\AssemblerX8664\XmmArith.cpp">
- <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
- <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
- </ClCompile>
- <ClCompile Include="Main.cpp" />
- </ItemGroup>
- <ItemGroup>
- <ClInclude Include="..\..\third_party\subzero\unittest\AssemblerX8632\TestUtil.h">
- <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
- <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
- </ClInclude>
- <ClInclude Include="..\..\third_party\subzero\unittest\AssemblerX8664\TestUtil.h">
- <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
- <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
- </ClInclude>
- </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
diff --git a/src/Reactor/ReactorUnitTests.vcxproj.filters b/src/Reactor/ReactorUnitTests.vcxproj.filters
new file mode 100644
index 0000000..721fc57
--- /dev/null
+++ b/src/Reactor/ReactorUnitTests.vcxproj.filters
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\third_party\googletest\googletest\src\gtest-all.cc">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="ReactorUnitTests.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/src/Reactor/Routine.cpp b/src/Reactor/Routine.cpp
index 5899c58..23cf929 100644
--- a/src/Reactor/Routine.cpp
+++ b/src/Reactor/Routine.cpp
@@ -14,7 +14,7 @@
#include "Routine.hpp"
-#include "Common/Thread.hpp"
+#include "Thread.hpp"
#include <cassert>
@@ -27,12 +27,12 @@
void Routine::bind()
{
- sw::atomicIncrement(&bindCount);
+ atomicIncrement(&bindCount);
}
void Routine::unbind()
{
- long count = sw::atomicDecrement(&bindCount);
+ long count = atomicDecrement(&bindCount);
if(count == 0)
{
diff --git a/src/Reactor/Subzero.vcxproj b/src/Reactor/Subzero.vcxproj
index 7f7525e..3aaf7b4 100644
--- a/src/Reactor/Subzero.vcxproj
+++ b/src/Reactor/Subzero.vcxproj
@@ -95,7 +95,7 @@
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>SZTARGET=X8632;ALLOW_DUMP=0;ALLOW_TIMERS=0;ALLOW_LLVM_CL=0;ALLOW_LLVM_IR=0;ALLOW_LLVM_IR_AS_INPUT=0;ALLOW_MINIMAL_BUILD=0;ALLOW_WASM=0;ICE_THREAD_LOCAL_HACK=0;SUBZERO_USE_MICROSOFT_ABI;WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalUsingDirectories>%(AdditionalUsingDirectories)</AdditionalUsingDirectories>
- <AdditionalIncludeDirectories>$(SolutionDir)third_party\subzero;$(SolutionDir)third_party\llvm-subzero\include;$(SolutionDir)third_party\llvm-subzero\build\Windows\include;$(SolutionDir)third_party\subzero\pnacl-llvm\include;$(SolutionDir)src\</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>$(SolutionDir)third_party\subzero;$(SolutionDir)third_party\llvm-subzero\include;$(SolutionDir)third_party\llvm-subzero\build\Windows\include;$(SolutionDir)third_party\subzero\pnacl-llvm\include</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<ForcedIncludeFiles>src/IceTypes.h</ForcedIncludeFiles>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
@@ -114,7 +114,7 @@
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>SZTARGET=X8664;ALLOW_DUMP=0;ALLOW_TIMERS=0;ALLOW_LLVM_CL=0;ALLOW_LLVM_IR=0;ALLOW_LLVM_IR_AS_INPUT=0;ALLOW_MINIMAL_BUILD=0;ALLOW_WASM=0;ICE_THREAD_LOCAL_HACK=0;SUBZERO_USE_MICROSOFT_ABI;WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalUsingDirectories>%(AdditionalUsingDirectories)</AdditionalUsingDirectories>
- <AdditionalIncludeDirectories>$(SolutionDir)third_party\subzero;$(SolutionDir)third_party\llvm-subzero\include;$(SolutionDir)third_party\llvm-subzero\build\Windows\include;$(SolutionDir)third_party\subzero\pnacl-llvm\include;$(SolutionDir)src\</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>$(SolutionDir)third_party\subzero;$(SolutionDir)third_party\llvm-subzero\include;$(SolutionDir)third_party\llvm-subzero\build\Windows\include;$(SolutionDir)third_party\subzero\pnacl-llvm\include</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<ForcedIncludeFiles>src/IceTypes.h</ForcedIncludeFiles>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
@@ -135,7 +135,7 @@
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>SZTARGET=X8632;ALLOW_DUMP=0;ALLOW_TIMERS=0;ALLOW_LLVM_CL=0;ALLOW_LLVM_IR=0;ALLOW_LLVM_IR_AS_INPUT=0;ALLOW_MINIMAL_BUILD=0;ALLOW_WASM=0;ICE_THREAD_LOCAL_HACK=0;SUBZERO_USE_MICROSOFT_ABI;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalUsingDirectories>%(AdditionalUsingDirectories)</AdditionalUsingDirectories>
- <AdditionalIncludeDirectories>$(SolutionDir)third_party\subzero;$(SolutionDir)third_party\llvm-subzero\include;$(SolutionDir)third_party\llvm-subzero\build\Windows\include;$(SolutionDir)third_party\subzero\pnacl-llvm\include;$(SolutionDir)src\</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>$(SolutionDir)third_party\subzero;$(SolutionDir)third_party\llvm-subzero\include;$(SolutionDir)third_party\llvm-subzero\build\Windows\include;$(SolutionDir)third_party\subzero\pnacl-llvm\include</AdditionalIncludeDirectories>
<ForcedIncludeFiles>src/IceTypes.h</ForcedIncludeFiles>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
@@ -158,7 +158,7 @@
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>SZTARGET=X8664;ALLOW_DUMP=0;ALLOW_TIMERS=0;ALLOW_LLVM_CL=0;ALLOW_LLVM_IR=0;ALLOW_LLVM_IR_AS_INPUT=0;ALLOW_MINIMAL_BUILD=0;ALLOW_WASM=0;ICE_THREAD_LOCAL_HACK=0;SUBZERO_USE_MICROSOFT_ABI;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalUsingDirectories>%(AdditionalUsingDirectories)</AdditionalUsingDirectories>
- <AdditionalIncludeDirectories>$(SolutionDir)third_party\subzero;$(SolutionDir)third_party\llvm-subzero\include;$(SolutionDir)third_party\llvm-subzero\build\Windows\include;$(SolutionDir)third_party\subzero\pnacl-llvm\include;$(SolutionDir)src\</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>$(SolutionDir)third_party\subzero;$(SolutionDir)third_party\llvm-subzero\include;$(SolutionDir)third_party\llvm-subzero\build\Windows\include;$(SolutionDir)third_party\subzero\pnacl-llvm\include</AdditionalIncludeDirectories>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<OmitFramePointers>true</OmitFramePointers>
<EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
@@ -216,8 +216,9 @@
<ClCompile Include="$(SolutionDir)third_party\subzero\src\IceTimerTree.cpp" />
<ClCompile Include="$(SolutionDir)third_party\subzero\src\IceTypes.cpp" />
<ClCompile Include="$(SolutionDir)third_party\subzero\src\IceVariableSplitting.cpp" />
- <ClCompile Include="..\Common\Debug.cpp" />
- <ClCompile Include="..\Common\Memory.cpp" />
+ <ClCompile Include="CPUID.cpp" />
+ <ClCompile Include="Debug.cpp" />
+ <ClCompile Include="Memory.cpp" />
<ClCompile Include="Optimizer.cpp" />
<ClCompile Include="Routine.cpp" />
<ClCompile Include="SubzeroReactor.cpp" />
@@ -279,6 +280,8 @@
<ClInclude Include="$(SolutionDir)third_party\subzero\src\IceConditionCodesX8664.h" />
<ClInclude Include="$(SolutionDir)third_party\subzero\src\IceInstX8664.h" />
<ClInclude Include="$(SolutionDir)third_party\subzero\src\IceRegistersX8664.h" />
+ <ClInclude Include="CPUID.hpp" />
+ <ClInclude Include="Debug.hpp" />
<ClInclude Include="Optimizer.hpp" />
</ItemGroup>
<ItemGroup>
@@ -296,6 +299,8 @@
<ItemGroup>
<ProjectReference Include="SubzeroLLVMDependencies.vcxproj">
<Project>{e3bbd7da-45c1-43ef-9c87-3f411031bde4}</Project>
+ <LinkLibraryDependencies>false</LinkLibraryDependencies>
+ <UseLibraryDependencyInputs>false</UseLibraryDependencyInputs>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
diff --git a/src/Reactor/Subzero.vcxproj.filters b/src/Reactor/Subzero.vcxproj.filters
index 68cb2e8..42f0bda 100644
--- a/src/Reactor/Subzero.vcxproj.filters
+++ b/src/Reactor/Subzero.vcxproj.filters
@@ -120,10 +120,13 @@
<ClCompile Include="Optimizer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="..\Common\Memory.cpp">
+ <ClCompile Include="CPUID.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="..\Common\Debug.cpp">
+ <ClCompile Include="Memory.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="Debug.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
@@ -299,6 +302,12 @@
<ClInclude Include="Optimizer.hpp">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="CPUID.hpp">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="Debug.hpp">
+ <Filter>Header Files</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="$(SolutionDir)third_party\subzero\src\IceClFlags.def">
diff --git a/src/Reactor/SubzeroReactor.cpp b/src/Reactor/SubzeroReactor.cpp
index b92005c..a691037 100644
--- a/src/Reactor/SubzeroReactor.cpp
+++ b/src/Reactor/SubzeroReactor.cpp
@@ -15,8 +15,7 @@
#include "Reactor.hpp"
#include "Optimizer.hpp"
-
-#include "Common/Memory.hpp"
+#include "Memory.hpp"
#include "src/IceTypes.h"
#include "src/IceCfg.h"
@@ -49,7 +48,7 @@
#endif
#endif
-//#include <mutex>
+#include <mutex>
#include <limits>
#include <iostream>
#include <cassert>
@@ -427,12 +426,12 @@
T *allocate(size_type n)
{
- return (T*)sw::allocateExecutable(sizeof(T) * n);
+ return (T*)allocateExecutable(sizeof(T) * n);
}
void deallocate(T *p, size_type n)
{
- sw::deallocateExecutable(p, sizeof(T) * n);
+ deallocateExecutable(p, sizeof(T) * n);
}
};
diff --git a/src/Reactor/SubzeroTest.vcxproj.filters b/src/Reactor/SubzeroTest.vcxproj.filters
deleted file mode 100644
index 4fc3643..0000000
--- a/src/Reactor/SubzeroTest.vcxproj.filters
+++ /dev/null
@@ -1,63 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <ItemGroup>
- <Filter Include="Source Files">
- <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
- <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
- </Filter>
- <Filter Include="Header Files">
- <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
- <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
- </Filter>
- <Filter Include="Resource Files">
- <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
- <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
- </Filter>
- </ItemGroup>
- <ItemGroup>
- <ClCompile Include="Main.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="..\..\third_party\googletest\googletest\src\gtest-all.cc">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="..\..\third_party\subzero\unittest\AssemblerX8632\XmmArith.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="..\..\third_party\subzero\unittest\AssemblerX8664\XmmArith.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="..\..\third_party\subzero\unittest\AssemblerX8664\DataMov.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="..\..\third_party\subzero\unittest\AssemblerX8632\DataMov.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="..\..\third_party\subzero\unittest\AssemblerX8664\ControlFlow.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="..\..\third_party\subzero\unittest\AssemblerX8632\ControlFlow.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="..\..\third_party\subzero\unittest\AssemblerX8664\LowLevel.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="..\..\third_party\subzero\unittest\AssemblerX8664\Other.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="..\..\third_party\subzero\unittest\AssemblerX8632\LowLevel.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="..\..\third_party\subzero\unittest\AssemblerX8632\Other.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- </ItemGroup>
- <ItemGroup>
- <ClInclude Include="..\..\third_party\subzero\unittest\AssemblerX8632\TestUtil.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="..\..\third_party\subzero\unittest\AssemblerX8664\TestUtil.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- </ItemGroup>
-</Project>
\ No newline at end of file
diff --git a/src/Reactor/Thread.cpp b/src/Reactor/Thread.cpp
new file mode 100644
index 0000000..7a9b07d
--- /dev/null
+++ b/src/Reactor/Thread.cpp
@@ -0,0 +1,91 @@
+// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "Thread.hpp"
+
+namespace rr
+{
+ Thread::Thread(void (*threadFunction)(void *parameters), void *parameters)
+ {
+ Event init;
+ Entry entry = {threadFunction, parameters, &init};
+
+ #if defined(_WIN32)
+ handle = CreateThread(NULL, 1024 * 1024, startFunction, &entry, 0, NULL);
+ #else
+ pthread_create(&handle, NULL, startFunction, &entry);
+ #endif
+
+ init.wait();
+ }
+
+ Thread::~Thread()
+ {
+ join(); // Make threads exit before deleting them to not block here
+ }
+
+ void Thread::join()
+ {
+ if(!hasJoined)
+ {
+ #if defined(_WIN32)
+ WaitForSingleObject(handle, INFINITE);
+ CloseHandle(handle);
+ #else
+ pthread_join(handle, NULL);
+ #endif
+
+ hasJoined = true;
+ }
+ }
+
+ #if defined(_WIN32)
+ unsigned long __stdcall Thread::startFunction(void *parameters)
+ {
+ Entry entry = *(Entry*)parameters;
+ entry.init->signal();
+ entry.threadFunction(entry.threadParameters);
+ return 0;
+ }
+ #else
+ void *Thread::startFunction(void *parameters)
+ {
+ Entry entry = *(Entry*)parameters;
+ entry.init->signal();
+ entry.threadFunction(entry.threadParameters);
+ return nullptr;
+ }
+ #endif
+
+ Event::Event()
+ {
+ #if defined(_WIN32)
+ handle = CreateEvent(NULL, FALSE, FALSE, NULL);
+ #else
+ pthread_cond_init(&handle, NULL);
+ pthread_mutex_init(&mutex, NULL);
+ signaled = false;
+ #endif
+ }
+
+ Event::~Event()
+ {
+ #if defined(_WIN32)
+ CloseHandle(handle);
+ #else
+ pthread_cond_destroy(&handle);
+ pthread_mutex_destroy(&mutex);
+ #endif
+ }
+}
diff --git a/src/Reactor/Thread.hpp b/src/Reactor/Thread.hpp
new file mode 100644
index 0000000..7f8be13
--- /dev/null
+++ b/src/Reactor/Thread.hpp
@@ -0,0 +1,338 @@
+// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef rr_Thread_hpp
+#define rr_Thread_hpp
+
+#if defined(_WIN32)
+ #ifndef WIN32_LEAN_AND_MEAN
+ #define WIN32_LEAN_AND_MEAN
+ #endif
+ #include <windows.h>
+ #include <intrin.h>
+#else
+ #include <pthread.h>
+ #include <sched.h>
+ #include <unistd.h>
+ #define TLS_OUT_OF_INDEXES (pthread_key_t)(~0)
+#endif
+
+#include <stdlib.h>
+
+#if defined(__clang__)
+#if __has_include(<atomic>) // clang has an explicit check for the availability of atomic
+#define USE_STD_ATOMIC 1
+#endif
+// atomic is available in C++11 or newer, and in Visual Studio 2012 or newer
+#elif (defined(_MSC_VER) && (_MSC_VER >= 1700)) || (__cplusplus >= 201103L)
+#define USE_STD_ATOMIC 1
+#endif
+
+#if USE_STD_ATOMIC
+#include <atomic>
+#endif
+
+namespace rr
+{
+ class Event;
+
+ class Thread
+ {
+ public:
+ Thread(void (*threadFunction)(void *parameters), void *parameters);
+
+ ~Thread();
+
+ void join();
+
+ static void yield();
+ static void sleep(int milliseconds);
+
+ #if defined(_WIN32)
+ typedef DWORD LocalStorageKey;
+ #else
+ typedef pthread_key_t LocalStorageKey;
+ #endif
+
+ static LocalStorageKey allocateLocalStorageKey(void (*destructor)(void *storage) = free);
+ static void freeLocalStorageKey(LocalStorageKey key);
+ static void *allocateLocalStorage(LocalStorageKey key, size_t size);
+ static void *getLocalStorage(LocalStorageKey key);
+ static void freeLocalStorage(LocalStorageKey key);
+
+ private:
+ struct Entry
+ {
+ void (*const threadFunction)(void *parameters);
+ void *threadParameters;
+ Event *init;
+ };
+
+ #if defined(_WIN32)
+ static unsigned long __stdcall startFunction(void *parameters);
+ HANDLE handle;
+ #else
+ static void *startFunction(void *parameters);
+ pthread_t handle;
+ #endif
+
+ bool hasJoined = false;
+ };
+
+ class Event
+ {
+ friend class Thread;
+
+ public:
+ Event();
+
+ ~Event();
+
+ void signal();
+ void wait();
+
+ private:
+ #if defined(_WIN32)
+ HANDLE handle;
+ #else
+ pthread_cond_t handle;
+ pthread_mutex_t mutex;
+ volatile bool signaled;
+ #endif
+ };
+
+ #if PERF_PROFILE
+ int64_t atomicExchange(int64_t volatile *target, int64_t value);
+ #endif
+
+ int atomicExchange(int volatile *target, int value);
+ int atomicIncrement(int volatile *value);
+ int atomicDecrement(int volatile *value);
+ int atomicAdd(int volatile *target, int value);
+ void nop();
+}
+
+namespace rr
+{
+ inline void Thread::yield()
+ {
+ #if defined(_WIN32)
+ Sleep(0);
+ #elif defined(__APPLE__)
+ pthread_yield_np();
+ #else
+ sched_yield();
+ #endif
+ }
+
+ inline void Thread::sleep(int milliseconds)
+ {
+ #if defined(_WIN32)
+ Sleep(milliseconds);
+ #else
+ usleep(1000 * milliseconds);
+ #endif
+ }
+
+ inline Thread::LocalStorageKey Thread::allocateLocalStorageKey(void (*destructor)(void *storage))
+ {
+ #if defined(_WIN32)
+ return TlsAlloc();
+ #else
+ LocalStorageKey key;
+ pthread_key_create(&key, destructor);
+ return key;
+ #endif
+ }
+
+ inline void Thread::freeLocalStorageKey(LocalStorageKey key)
+ {
+ #if defined(_WIN32)
+ TlsFree(key);
+ #else
+ pthread_key_delete(key); // Using an invalid key is an error but not undefined behavior.
+ #endif
+ }
+
+ inline void *Thread::allocateLocalStorage(LocalStorageKey key, size_t size)
+ {
+ if(key == TLS_OUT_OF_INDEXES)
+ {
+ return nullptr;
+ }
+
+ freeLocalStorage(key);
+
+ void *storage = malloc(size);
+
+ #if defined(_WIN32)
+ TlsSetValue(key, storage);
+ #else
+ pthread_setspecific(key, storage);
+ #endif
+
+ return storage;
+ }
+
+ inline void *Thread::getLocalStorage(LocalStorageKey key)
+ {
+ #if defined(_WIN32)
+ return TlsGetValue(key);
+ #else
+ if(key == TLS_OUT_OF_INDEXES) // Avoid undefined behavior.
+ {
+ return nullptr;
+ }
+
+ return pthread_getspecific(key);
+ #endif
+ }
+
+ inline void Thread::freeLocalStorage(LocalStorageKey key)
+ {
+ free(getLocalStorage(key));
+
+ #if defined(_WIN32)
+ TlsSetValue(key, nullptr);
+ #else
+ pthread_setspecific(key, nullptr);
+ #endif
+ }
+
+ inline void Event::signal()
+ {
+ #if defined(_WIN32)
+ SetEvent(handle);
+ #else
+ pthread_mutex_lock(&mutex);
+ signaled = true;
+ pthread_cond_signal(&handle);
+ pthread_mutex_unlock(&mutex);
+ #endif
+ }
+
+ inline void Event::wait()
+ {
+ #if defined(_WIN32)
+ WaitForSingleObject(handle, INFINITE);
+ #else
+ pthread_mutex_lock(&mutex);
+ while(!signaled) pthread_cond_wait(&handle, &mutex);
+ signaled = false;
+ pthread_mutex_unlock(&mutex);
+ #endif
+ }
+
+ #if PERF_PROFILE
+ inline int64_t atomicExchange(volatile int64_t *target, int64_t value)
+ {
+ #if defined(_WIN32)
+ return InterlockedExchange64(target, value);
+ #else
+ int ret;
+ __asm__ __volatile__("lock; xchg8 %0,(%1)" : "=r" (ret) :"r" (target), "0" (value) : "memory" );
+ return ret;
+ #endif
+ }
+ #endif
+
+ inline int atomicExchange(volatile int *target, int value)
+ {
+ #if defined(_WIN32)
+ return InterlockedExchange((volatile long*)target, (long)value);
+ #else
+ int ret;
+ __asm__ __volatile__("lock; xchgl %0,(%1)" : "=r" (ret) :"r" (target), "0" (value) : "memory" );
+ return ret;
+ #endif
+ }
+
+ inline int atomicIncrement(volatile int *value)
+ {
+ #if defined(_WIN32)
+ return InterlockedIncrement((volatile long*)value);
+ #else
+ return __sync_add_and_fetch(value, 1);
+ #endif
+ }
+
+ inline int atomicDecrement(volatile int *value)
+ {
+ #if defined(_WIN32)
+ return InterlockedDecrement((volatile long*)value);
+ #else
+ return __sync_sub_and_fetch(value, 1);
+ #endif
+ }
+
+ inline int atomicAdd(volatile int* target, int value)
+ {
+ #if defined(_WIN32)
+ return InterlockedExchangeAdd((volatile long*)target, value) + value;
+ #else
+ return __sync_add_and_fetch(target, value);
+ #endif
+ }
+
+ inline void nop()
+ {
+ #if defined(_WIN32)
+ __nop();
+ #else
+ __asm__ __volatile__ ("nop");
+ #endif
+ }
+
+ #if USE_STD_ATOMIC
+ class AtomicInt
+ {
+ public:
+ AtomicInt() : ai() {}
+ AtomicInt(int i) : ai(i) {}
+
+ inline operator int() const { return ai.load(std::memory_order_acquire); }
+ inline void operator=(const AtomicInt& i) { ai.store(i.ai.load(std::memory_order_acquire), std::memory_order_release); }
+ inline void operator=(int i) { ai.store(i, std::memory_order_release); }
+ inline void operator--() { ai.fetch_sub(1, std::memory_order_acq_rel); }
+ inline void operator++() { ai.fetch_add(1, std::memory_order_acq_rel); }
+ inline int operator--(int) { return ai.fetch_sub(1, std::memory_order_acq_rel) - 1; }
+ inline int operator++(int) { return ai.fetch_add(1, std::memory_order_acq_rel) + 1; }
+ inline void operator-=(int i) { ai.fetch_sub(i, std::memory_order_acq_rel); }
+ inline void operator+=(int i) { ai.fetch_add(i, std::memory_order_acq_rel); }
+ private:
+ std::atomic<int> ai;
+ };
+ #else
+ class AtomicInt
+ {
+ public:
+ AtomicInt() {}
+ AtomicInt(int i) : vi(i) {}
+
+ inline operator int() const { return vi; } // Note: this isn't a guaranteed atomic operation
+ inline void operator=(const AtomicInt& i) { atomicExchange(&vi, i.vi); }
+ inline void operator=(int i) { atomicExchange(&vi, i); }
+ inline void operator--() { atomicDecrement(&vi); }
+ inline void operator++() { atomicIncrement(&vi); }
+ inline int operator--(int) { return atomicDecrement(&vi); }
+ inline int operator++(int) { return atomicIncrement(&vi); }
+ inline void operator-=(int i) { atomicAdd(&vi, -i); }
+ inline void operator+=(int i) { atomicAdd(&vi, i); }
+ private:
+ volatile int vi;
+ };
+ #endif
+}
+
+#endif // rr_Thread_hpp
diff --git a/src/Reactor/Types.hpp b/src/Reactor/Types.hpp
new file mode 100644
index 0000000..428da51
--- /dev/null
+++ b/src/Reactor/Types.hpp
@@ -0,0 +1,157 @@
+// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef r3_Types_hpp
+#define r3_Types_hpp
+
+#include <limits>
+#include <type_traits>
+
+// GCC warns against bitfields not fitting the entire range of an enum with a fixed underlying type of unsigned int, which gets promoted to an error with -Werror and cannot be suppressed.
+// However, GCC already defaults to using unsigned int as the underlying type of an unscoped enum without a fixed underlying type. So we can just omit it.
+#if defined(__GNUC__) && !defined(__clang__)
+namespace {enum E {}; static_assert(!std::numeric_limits<std::underlying_type<E>::type>::is_signed, "expected unscoped enum whose underlying type is not fixed to be unsigned");}
+#define ENUM_UNDERLYING_TYPE_UNSIGNED_INT
+#else
+#define ENUM_UNDERLYING_TYPE_UNSIGNED_INT : unsigned int
+#endif
+
+#if defined(_MSC_VER)
+ typedef signed __int8 int8_t;
+ typedef signed __int16 int16_t;
+ typedef signed __int32 int32_t;
+ typedef signed __int64 int64_t;
+ typedef unsigned __int8 uint8_t;
+ typedef unsigned __int16 uint16_t;
+ typedef unsigned __int32 uint32_t;
+ typedef unsigned __int64 uint64_t;
+ #define ALIGN(bytes, type) __declspec(align(bytes)) type
+#else
+ #include <stdint.h>
+ #define ALIGN(bytes, type) type __attribute__((aligned(bytes)))
+#endif
+
+namespace rr
+{
+ typedef ALIGN(1, uint8_t) byte;
+ typedef ALIGN(2, uint16_t) word;
+ typedef ALIGN(4, uint32_t) dword;
+ typedef ALIGN(8, uint64_t) qword;
+ typedef ALIGN(16, uint64_t) qword2[2];
+ typedef ALIGN(4, uint8_t) byte4[4];
+ typedef ALIGN(8, uint8_t) byte8[8];
+ typedef ALIGN(16, uint8_t) byte16[16];
+ typedef ALIGN(8, uint16_t) word4[4];
+ typedef ALIGN(8, uint32_t) dword2[2];
+ typedef ALIGN(16, uint32_t) dword4[4];
+ typedef ALIGN(16, uint64_t) xword[2];
+
+ typedef ALIGN(1, int8_t) sbyte;
+ typedef ALIGN(4, int8_t) sbyte4[4];
+ typedef ALIGN(8, int8_t) sbyte8[8];
+ typedef ALIGN(16, int8_t) sbyte16[16];
+ typedef ALIGN(8, short) short4[4];
+ typedef ALIGN(8, unsigned short) ushort4[4];
+ typedef ALIGN(16, short) short8[8];
+ typedef ALIGN(16, unsigned short) ushort8[8];
+ typedef ALIGN(8, int) int2[2];
+ typedef ALIGN(8, unsigned int) uint2[2];
+ typedef ALIGN(16, unsigned int) uint4[4];
+
+ typedef ALIGN(8, float) float2[2];
+
+ ALIGN(16, struct int4
+ {
+ int x;
+ int y;
+ int z;
+ int w;
+
+ int &operator[](int i)
+ {
+ return (&x)[i];
+ }
+
+ const int &operator[](int i) const
+ {
+ return (&x)[i];
+ }
+
+ bool operator!=(const int4 &rhs)
+ {
+ return x != rhs.x || y != rhs.y || z != rhs.z || w != rhs.w;
+ }
+
+ bool operator==(const int4 &rhs)
+ {
+ return x == rhs.x && y == rhs.y && z == rhs.z && w == rhs.w;
+ }
+ });
+
+ ALIGN(16, struct float4
+ {
+ float x;
+ float y;
+ float z;
+ float w;
+
+ float &operator[](int i)
+ {
+ return (&x)[i];
+ }
+
+ const float &operator[](int i) const
+ {
+ return (&x)[i];
+ }
+
+ bool operator!=(const float4 &rhs)
+ {
+ return x != rhs.x || y != rhs.y || z != rhs.z || w != rhs.w;
+ }
+
+ bool operator==(const float4 &rhs)
+ {
+ return x == rhs.x && y == rhs.y && z == rhs.z && w == rhs.w;
+ }
+ });
+
+ inline float4 vector(float x, float y, float z, float w)
+ {
+ float4 v;
+
+ v.x = x;
+ v.y = y;
+ v.z = z;
+ v.w = w;
+
+ return v;
+ }
+
+ inline float4 replicate(float f)
+ {
+ float4 v;
+
+ v.x = f;
+ v.y = f;
+ v.z = f;
+ v.w = f;
+
+ return v;
+ }
+
+ #define OFFSET(s,m) (int)(size_t)&reinterpret_cast<const volatile char&>((((s*)0)->m))
+}
+
+#endif // r3_Types_hpp