1 /****************************************************************************
2 * Copyright (C) 2017 Intel Corporation. All Rights Reserved.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 ****************************************************************************/
24 #include "common/os.h"
32 #if defined(__APPLE__) || defined(FORCE_LINUX) || defined(__linux__) || defined(__gnu_linux__)
39 static const DWORD MS_VC_EXCEPTION
= 0x406D1388;
42 typedef struct tagTHREADNAME_INFO
44 DWORD dwType
; // Must be 0x1000.
45 LPCSTR szName
; // Pointer to name (in user addr space).
46 DWORD dwThreadID
; // Thread ID (-1=caller thread).
47 DWORD dwFlags
; // Reserved for future use, must be zero.
51 void LegacySetThreadName(const char* pThreadName
)
55 info
.szName
= pThreadName
;
56 info
.dwThreadID
= GetCurrentThreadId();
59 if (!IsDebuggerPresent())
61 // No debugger attached to interpret exception, no need to actually do it
66 #pragma warning(disable: 6320 6322)
68 RaiseException(MS_VC_EXCEPTION
, 0, sizeof(info
) / sizeof(ULONG_PTR
), (ULONG_PTR
*)&info
);
70 __except (EXCEPTION_EXECUTE_HANDLER
) {
76 void SWR_API
SetCurrentThreadName(const char* pThreadName
)
79 // The SetThreadDescription API was brought in version 1607 of Windows 10.
80 typedef HRESULT(WINAPI
* PFNSetThreadDescription
)(HANDLE hThread
, PCWSTR lpThreadDescription
);
81 // The SetThreadDescription API works even if no debugger is attached.
82 auto pfnSetThreadDescription
=
83 reinterpret_cast<PFNSetThreadDescription
>(
84 GetProcAddress(GetModuleHandleA("Kernel32.dll"), "SetThreadDescription"));
86 if (!pfnSetThreadDescription
)
89 pfnSetThreadDescription
=
90 reinterpret_cast<PFNSetThreadDescription
>(
91 GetProcAddress(GetModuleHandleA("KernelBase.dll"), "SetThreadDescription"));
94 if (pfnSetThreadDescription
)
96 std::string utf8Name
= pThreadName
;
97 std::wstring wideName
;
98 wideName
.resize(utf8Name
.size() + 1);
99 swprintf_s(&(wideName
.front()), wideName
.size(), L
"%S", utf8Name
.c_str());
100 HRESULT hr
= pfnSetThreadDescription(GetCurrentThread(), wideName
.c_str());
101 SWR_ASSERT(SUCCEEDED(hr
), "Failed to set thread name to %s", pThreadName
);
103 // Fall through - it seems like some debuggers only recognize the exception
106 // Fall back to exception based hack
107 LegacySetThreadName(pThreadName
);
110 #if defined(FORCE_LINUX) || defined(__linux__) || defined(__gnu_linux__)
111 pthread_setname_np(pthread_self(), pThreadName
);
115 static void SplitString(std::vector
<std::string
>& out_segments
, const std::string
& input
, char splitToken
)
117 out_segments
.clear();
119 std::istringstream
f(input
);
121 while (std::getline(f
, s
, splitToken
))
125 out_segments
.push_back(s
);
130 void SWR_API
CreateDirectoryPath(const std::string
& path
)
133 SHCreateDirectoryExA(nullptr, path
.c_str(), nullptr);
136 #if defined(__APPLE__) || defined(FORCE_LINUX) || defined(__linux__) || defined(__gnu_linux__)
137 std::vector
<std::string
> pathSegments
;
138 SplitString(pathSegments
, path
, '/');
141 for (auto const& segment
: pathSegments
)
143 tmpPath
.push_back('/');
146 int result
= mkdir(tmpPath
.c_str(), 0777);
147 if (result
== -1 && errno
!= EEXIST
)