Change PerThreadFileSystem solution to still require explicit Setup

- Added AutoCleanupPerThreadFileSystem for calling cleanup on scope exit,
  useful for command line users.
- Use global singleton and ensure cleanup on exit if not called
- Put setup/cleanup in VerifierTest.cpp where the TestModule[Setup|Cleanup]
  methods live.
- Remove GlobalPerThreadSys from FileCheckForTest, since this has to happen
  at the module level instead.
- Added Setup/Cleanup to all the appropriate places
This commit is contained in:
Tex Riddell 2018-04-19 18:42:52 -07:00
Родитель 3bc4206b8c
Коммит 283b71ca16
12 изменённых файлов: 53 добавлений и 37 удалений

Просмотреть файл

@ -53,12 +53,11 @@ namespace fs {
class MSFileSystem;
typedef _Inout_ MSFileSystem* MSFileSystemRef;
std::error_code GetFileSystemTlsError() throw();
std::error_code GetFileSystemTlsStatus() throw();
// Setup/Cleanup are no longer necessary, but SetupPerThreadFileSystem will
// return GetFileSystemTlsError();
std::error_code SetupPerThreadFileSystem() throw();
void CleanupPerThreadFileSystem() throw();
struct AutoCleanupPerThreadFileSystem { ~AutoCleanupPerThreadFileSystem() { CleanupPerThreadFileSystem(); } };
/// <summary>Gets a reference to the file system installed for the current thread (possibly NULL).</summary>
/// <remarks>In practice, consumers of the library should always install a file system.</remarks>

Просмотреть файл

@ -58,18 +58,28 @@ class ThreadLocalStorage {
DWORD m_Tls;
DWORD m_dwError;
public:
ThreadLocalStorage() : m_Tls(TlsAlloc()), m_dwError(0) {
if (m_Tls == TLS_OUT_OF_INDEXES)
m_dwError = ::GetLastError();
ThreadLocalStorage() : m_Tls(TLS_OUT_OF_INDEXES), m_dwError(ERROR_NOT_READY) {}
DWORD Setup() {
if (m_Tls == TLS_OUT_OF_INDEXES) {
m_Tls = TlsAlloc();
m_dwError = (m_Tls == TLS_OUT_OF_INDEXES) ? ::GetLastError() : 0;
}
return m_dwError;
}
~ThreadLocalStorage() { TlsFree(m_Tls); }
_T GetValue() throw() {
void Cleanup() {
if (m_Tls != TLS_OUT_OF_INDEXES)
TlsFree(m_Tls);
m_Tls = TLS_OUT_OF_INDEXES;
m_dwError = ERROR_NOT_READY;
}
~ThreadLocalStorage() { Cleanup(); }
_T GetValue() const {
if (m_Tls != TLS_OUT_OF_INDEXES)
return (_T)TlsGetValue(m_Tls);
else
return nullptr;
}
bool SetValue(_T value) throw() {
bool SetValue(_T value) {
if (m_Tls != TLS_OUT_OF_INDEXES) {
return TlsSetValue(m_Tls, (void*)value);
} else {
@ -81,11 +91,14 @@ public:
DWORD GetError() const {
return m_dwError;
}
operator bool() const { return m_Tls != TLS_OUT_OF_INDEXES; }
};
static ThreadLocalStorage<MSFileSystemRef> g_PerThreadSystem;
}
error_code GetFileSystemTlsError() throw() {
error_code GetFileSystemTlsStatus() throw() {
DWORD dwError = g_PerThreadSystem.GetError();
if (dwError)
return error_code(dwError, system_category());
@ -93,19 +106,25 @@ error_code GetFileSystemTlsError() throw() {
return error_code();
}
// No longer necessary to call, but returns error code if TlsAlloc() failed.
error_code SetupPerThreadFileSystem() throw() {
return GetFileSystemTlsError();
assert(!g_PerThreadSystem && g_PerThreadSystem.GetError() == ERROR_NOT_READY &&
"otherwise, PerThreadSystem already set up.");
if (g_PerThreadSystem.Setup())
return GetFileSystemTlsStatus();
return error_code();
}
void CleanupPerThreadFileSystem() throw() {
g_PerThreadSystem.Cleanup();
}
void CleanupPerThreadFileSystem() throw() {}
MSFileSystemRef GetCurrentThreadFileSystem() throw()
{
MSFileSystemRef GetCurrentThreadFileSystem() throw() {
assert(g_PerThreadSystem && "otherwise, TLS not initialized");
return g_PerThreadSystem.GetValue();
}
error_code SetCurrentThreadFileSystem(MSFileSystemRef value) throw()
{
assert(g_PerThreadSystem && "otherwise, TLS not initialized");
// For now, disallow reentrancy in APIs (i.e., replace the current instance with another one).
if (value != nullptr)
{

Просмотреть файл

@ -373,6 +373,9 @@ static int ExecuteCC1Tool(ArrayRef<const char *> argv, StringRef Tool) {
// HLSL Change: changed calling convention to __cdecl
int __cdecl main(int argc_, const char **argv_) {
// HLSL Change Starts
if (llvm::sys::fs::SetupPerThreadFileSystem())
return 1;
llvm::sys::fs::AutoCleanupPerThreadFileSystem auto_cleanup_fs;
llvm::sys::fs::MSFileSystem* msfPtr;
HRESULT hr;
if (!SUCCEEDED(hr = CreateMSFileSystemForDisk(&msfPtr)))

Просмотреть файл

@ -120,6 +120,9 @@ using namespace hlsl::options;
int __cdecl main(int argc, _In_reads_z_(argc) char **argv) {
const char *pStage = "Operation";
int retVal = 0;
if (llvm::sys::fs::SetupPerThreadFileSystem())
return 1;
llvm::sys::fs::AutoCleanupPerThreadFileSystem auto_cleanup_fs;
if (FAILED(DxcInitThreadMalloc())) return 1;
DxcSetThreadMallocOrDefault(nullptr);
try {

Просмотреть файл

@ -27,6 +27,8 @@
#include <iostream>
#include <limits>
#include "llvm/Support/FileSystem.h"
inline bool wcseq(LPCWSTR a, LPCWSTR b) {
return (a == nullptr && b == nullptr) || (a != nullptr && b != nullptr && wcscmp(a, b) == 0);
}
@ -211,6 +213,9 @@ static void PrintHelp() {
int __cdecl wmain(int argc, const wchar_t **argv_) {
const char *pStage = "Operation";
int retVal = 0;
if (llvm::sys::fs::SetupPerThreadFileSystem())
return 1;
llvm::sys::fs::AutoCleanupPerThreadFileSystem auto_cleanup_fs;
try {
// Parse command line options.
pStage = "Argument processing";

Просмотреть файл

@ -1750,8 +1750,6 @@ bool CompilerTest::InitSupport() {
if (!m_dllSupport.IsEnabled()) {
VERIFY_SUCCEEDED(m_dllSupport.Initialize());
m_ver.Initialize(m_dllSupport);
if (llvm::sys::fs::GetFileSystemTlsResult())
return false;
}
return true;
}

Просмотреть файл

@ -64,8 +64,6 @@ bool DxilModuleTest::InitSupport() {
if (!m_dllSupport.IsEnabled()) {
VERIFY_SUCCEEDED(m_dllSupport.Initialize());
}
if (llvm::sys::fs::GetFileSystemTlsResult())
return false;
return true;
}

Просмотреть файл

@ -1298,26 +1298,8 @@ bool ReadCheckFile(SourceMgr &SM,
return false;
}
// This would typically be done in DLL load.
struct GlobalPerThreadSys {
bool success;
GlobalPerThreadSys() {
success = ::llvm::sys::fs::SetupPerThreadFileSystem() ? false : true;
}
~GlobalPerThreadSys() {
if (success)
::llvm::sys::fs::CleanupPerThreadFileSystem();
}
};
int run_main() {
// HLSL Change Starts
GlobalPerThreadSys gpts;
if (!gpts.success) {
return 1;
}
llvm::sys::fs::MSFileSystem* msfPtr;
HRESULT hr;
if (!SUCCEEDED(hr = CreateMSFileSystemForDisk(&msfPtr)))

Просмотреть файл

@ -15,6 +15,7 @@
#include "HLSLTestData.h"
#include "llvm/Support/ManagedStatic.h"
#include "dxc/Support/HLSLOptions.h"
#include "llvm/Support/FileSystem.h"
#include <fstream>
@ -131,6 +132,8 @@ public:
};
bool TestModuleSetup() {
if (llvm::sys::fs::SetupPerThreadFileSystem())
return false;
// Use this module-level function to set up LLVM dependencies.
if (hlsl::options::initHlslOptTable()) {
return false;
@ -143,6 +146,7 @@ bool TestModuleCleanup() {
// In particular, clean up managed static allocations used by
// parsing options with the LLVM library.
::hlsl::options::cleanupHlslOptTable();
llvm::sys::fs::CleanupPerThreadFileSystem();
::llvm::llvm_shutdown();
return true;
}

Просмотреть файл

@ -832,6 +832,9 @@ int DxcBatchContext::BatchCompile(bool bMultiThread, bool bLibLink) {
int __cdecl wmain(int argc, const wchar_t **argv_) {
const char *pStage = "Initialization";
int retVal = 0;
if (llvm::sys::fs::SetupPerThreadFileSystem())
return 1;
llvm::sys::fs::AutoCleanupPerThreadFileSystem auto_cleanup_fs;
try {
auto t_start = std::chrono::high_resolution_clock::now();

Просмотреть файл

@ -252,6 +252,7 @@ int main(int argc, char **argv) {
HRESULT hr;
if (std::error_code ec = llvm::sys::fs::SetupPerThreadFileSystem())
return 1;
llvm::sys::fs::AutoCleanupPerThreadFileSystem auto_cleanup_fs;
if (!SUCCEEDED(hr = CreateMSFileSystemForDisk(&msfPtr)))
return 1;
std::unique_ptr<llvm::sys::fs::MSFileSystem> msf(msfPtr);

Просмотреть файл

@ -182,6 +182,7 @@ int main(int argc, char **argv) {
// HLSL Change Starts
if (std::error_code ec = llvm::sys::fs::SetupPerThreadFileSystem())
return 1;
llvm::sys::fs::AutoCleanupPerThreadFileSystem auto_cleanup_fs;
llvm::sys::fs::MSFileSystem* msfPtr;
HRESULT hr;
if (!SUCCEEDED(hr = CreateMSFileSystemForDisk(&msfPtr)))