1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright 2014 ADVANCED MICRO DEVICES, INC.
4 //
5 // AMD is granting you permission to use this software and documentation(if any)
6 // (collectively, the "Materials") pursuant to the terms and conditions of the
7 // Software License Agreement included with the Materials.If you do not have a
8 // copy of the Software License Agreement, contact your AMD representative for a
9 // copy.
10 //
11 // WARRANTY DISCLAIMER : THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF
12 // ANY KIND.AMD DISCLAIMS ALL WARRANTIES, EXPRESS, IMPLIED, OR STATUTORY,
13 // INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY,
14 // FITNESS FOR A PARTICULAR PURPOSE, TITLE, NON - INFRINGEMENT, THAT THE
15 // SOFTWARE WILL RUN UNINTERRUPTED OR ERROR - FREE OR WARRANTIES ARISING FROM
16 // CUSTOM OF TRADE OR COURSE OF USAGE.THE ENTIRE RISK ASSOCIATED WITH THE USE OF
17 // THE SOFTWARE IS ASSUMED BY YOU.Some jurisdictions do not allow the exclusion
18 // of implied warranties, so the above exclusion may not apply to You.
19 //
20 // LIMITATION OF LIABILITY AND INDEMNIFICATION : AMD AND ITS LICENSORS WILL NOT,
21 // UNDER ANY CIRCUMSTANCES BE LIABLE TO YOU FOR ANY PUNITIVE, DIRECT,
22 // INCIDENTAL, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING FROM USE OF
23 // THE SOFTWARE OR THIS AGREEMENT EVEN IF AMD AND ITS LICENSORS HAVE BEEN
24 // ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.In no event shall AMD's total
25 // liability to You for all damages, losses, and causes of action (whether in
26 // contract, tort (including negligence) or otherwise) exceed the amount of $100
27 // USD. You agree to defend, indemnify and hold harmless AMD and its licensors,
28 // and any of their directors, officers, employees, affiliates or agents from
29 // and against any and all loss, damage, liability and other expenses (including
30 // reasonable attorneys' fees), resulting from Your use of the Software or
31 // violation of the terms and conditions of this Agreement.
32 //
33 // U.S.GOVERNMENT RESTRICTED RIGHTS : The Materials are provided with
34 // "RESTRICTED RIGHTS." Use, duplication, or disclosure by the Government is
35 // subject to the restrictions as set forth in FAR 52.227 - 14 and DFAR252.227 -
36 // 7013, et seq., or its successor.Use of the Materials by the Government
37 // constitutes acknowledgement of AMD's proprietary rights in them.
38 //
39 // EXPORT RESTRICTIONS: The Materials may be subject to export restrictions as
40 // stated in the Software License Agreement.
41 //
42 ////////////////////////////////////////////////////////////////////////////////
43
44 #ifdef _WIN32 // Are we compiling for windows?
45 #define NOMINMAX
46
47 #include "core/util/os.h"
48
49 #include <algorithm>
50 #include <process.h>
51 #include <string>
52 #include <windows.h>
53
54 #include <emmintrin.h>
55 #include <pmmintrin.h>
56 #include <xmmintrin.h>
57
58 #undef Yield
59 #undef CreateMutex
60
61 namespace os {
62
63 static_assert(sizeof(LibHandle) == sizeof(HMODULE),
64 "OS abstraction size mismatch");
65 static_assert(sizeof(LibHandle) == sizeof(::HANDLE),
66 "OS abstraction size mismatch");
67 static_assert(sizeof(Mutex) == sizeof(::HANDLE),
68 "OS abstraction size mismatch");
69 static_assert(sizeof(Thread) == sizeof(::HANDLE),
70 "OS abstraction size mismatch");
71 static_assert(sizeof(EventHandle) == sizeof(::HANDLE),
72 "OS abstraction size mismatch");
73
LoadLib(std::string filename)74 LibHandle LoadLib(std::string filename) {
75 HMODULE ret = LoadLibrary(filename.c_str());
76 return *(LibHandle*)&ret;
77 }
78
GetExportAddress(LibHandle lib,std::string export_name)79 void* GetExportAddress(LibHandle lib, std::string export_name) {
80 return GetProcAddress(*(HMODULE*)&lib, export_name.c_str());
81 }
82
CloseLib(LibHandle lib)83 void CloseLib(LibHandle lib) { FreeLibrary(*(::HMODULE*)&lib); }
84
CreateMutex()85 Mutex CreateMutex() { return CreateEvent(NULL, false, true, NULL); }
86
TryAcquireMutex(Mutex lock)87 bool TryAcquireMutex(Mutex lock) {
88 return WaitForSingleObject(*(::HANDLE*)&lock, 0) == WAIT_OBJECT_0;
89 }
90
AcquireMutex(Mutex lock)91 bool AcquireMutex(Mutex lock) {
92 return WaitForSingleObject(*(::HANDLE*)&lock, INFINITE) == WAIT_OBJECT_0;
93 }
94
ReleaseMutex(Mutex lock)95 void ReleaseMutex(Mutex lock) { SetEvent(*(::HANDLE*)&lock); }
96
DestroyMutex(Mutex lock)97 void DestroyMutex(Mutex lock) { CloseHandle(*(::HANDLE*)&lock); }
98
Sleep(int delay_in_millisecond)99 void Sleep(int delay_in_millisecond) { ::Sleep(delay_in_millisecond); }
100
uSleep(int delayInUs)101 void uSleep(int delayInUs) { ::Sleep(delayInUs / 1000); }
102
YieldThread()103 void YieldThread() { ::Sleep(0); }
104
105 struct ThreadArgs {
106 void* entry_args;
107 ThreadEntry entry_function;
108 };
109
ThreadTrampoline(void * arg)110 unsigned __stdcall ThreadTrampoline(void* arg) {
111 ThreadArgs* thread_args = (ThreadArgs*)arg;
112 ThreadEntry entry = thread_args->entry_function;
113 void* data = thread_args->entry_args;
114 delete thread_args;
115 entry(data);
116 _endthreadex(0);
117 return 0;
118 }
119
CreateThread(ThreadEntry entry_function,void * entry_argument,uint stack_size)120 Thread CreateThread(ThreadEntry entry_function, void* entry_argument,
121 uint stack_size) {
122 ThreadArgs* thread_args = new ThreadArgs();
123 thread_args->entry_args = entry_argument;
124 thread_args->entry_function = entry_function;
125 uintptr_t ret =
126 _beginthreadex(NULL, stack_size, ThreadTrampoline, thread_args, 0, NULL);
127 return *(Thread*)&ret;
128 }
129
CloseThread(Thread thread)130 void CloseThread(Thread thread) { CloseHandle(*(::HANDLE*)&thread); }
131
WaitForThread(Thread thread)132 bool WaitForThread(Thread thread) {
133 return WaitForSingleObject(*(::HANDLE*)&thread, INFINITE) == WAIT_OBJECT_0;
134 }
135
WaitForAllThreads(Thread * threads,uint thread_count)136 bool WaitForAllThreads(Thread* threads, uint thread_count) {
137 return WaitForMultipleObjects(thread_count, threads, TRUE, INFINITE) ==
138 WAIT_OBJECT_0;
139 }
140
SetEnvVar(std::string env_var_name,std::string env_var_value)141 void SetEnvVar(std::string env_var_name, std::string env_var_value) {
142 SetEnvironmentVariable(env_var_name.c_str(), env_var_value.c_str());
143 }
144
GetEnvVar(std::string env_var_name)145 std::string GetEnvVar(std::string env_var_name) {
146 char* buff;
147 DWORD char_count = GetEnvironmentVariable(env_var_name.c_str(), NULL, 0);
148 if (char_count == 0) return "";
149 buff = (char*)alloca(sizeof(char) * char_count);
150 GetEnvironmentVariable(env_var_name.c_str(), buff, char_count);
151 buff[char_count - 1] = '\0';
152 std::string ret = buff;
153 return ret;
154 }
155
GetUserModeVirtualMemorySize()156 size_t GetUserModeVirtualMemorySize() {
157 SYSTEM_INFO system_info = {0};
158 GetSystemInfo(&system_info);
159 return ((size_t)system_info.lpMaximumApplicationAddress + 1);
160 }
161
GetUsablePhysicalHostMemorySize()162 size_t GetUsablePhysicalHostMemorySize() {
163 MEMORYSTATUSEX memory_status = {0};
164 memory_status.dwLength = sizeof(memory_status);
165 if (GlobalMemoryStatusEx(&memory_status) == 0) {
166 return 0;
167 }
168
169 const size_t physical_size = static_cast<size_t>(memory_status.ullTotalPhys);
170 return std::min(GetUserModeVirtualMemorySize(), physical_size);
171 }
172
GetUserModeVirtualMemoryBase()173 uintptr_t GetUserModeVirtualMemoryBase() { return (uintptr_t)0; }
174
175 // Os event wrappers
CreateOsEvent(bool auto_reset,bool init_state)176 EventHandle CreateOsEvent(bool auto_reset, bool init_state) {
177 EventHandle evt = reinterpret_cast<EventHandle>(
178 CreateEvent(NULL, (BOOL)(!auto_reset), (BOOL)init_state, NULL));
179 return evt;
180 }
181
DestroyOsEvent(EventHandle event)182 int DestroyOsEvent(EventHandle event) {
183 if (event == NULL) {
184 return -1;
185 }
186 return CloseHandle(reinterpret_cast<::HANDLE>(event));
187 }
188
WaitForOsEvent(EventHandle event,unsigned int milli_seconds)189 int WaitForOsEvent(EventHandle event, unsigned int milli_seconds) {
190 if (event == NULL) {
191 return -1;
192 }
193
194 int ret_code =
195 WaitForSingleObject(reinterpret_cast<::HANDLE>(event), milli_seconds);
196 if (ret_code == WAIT_TIMEOUT) {
197 ret_code = 0x14003; // 0x14003 indicates timeout
198 }
199 return ret_code;
200 }
201
SetOsEvent(EventHandle event)202 int SetOsEvent(EventHandle event) {
203 if (event == NULL) {
204 return -1;
205 }
206 return SetEvent(reinterpret_cast<::HANDLE>(event));
207 }
208
ResetOsEvent(EventHandle event)209 int ResetOsEvent(EventHandle event) {
210 if (event == NULL) {
211 return -1;
212 }
213 return ResetEvent(reinterpret_cast<::HANDLE>(event));
214 }
215
ReadAccurateClock()216 uint64_t ReadAccurateClock() {
217 uint64_t ret;
218 QueryPerformanceCounter((LARGE_INTEGER*)&ret);
219 return ret;
220 }
221
AccurateClockFrequency()222 uint64_t AccurateClockFrequency() {
223 uint64_t ret;
224 QueryPerformanceFrequency((LARGE_INTEGER*)&ret);
225 return ret;
226 }
227 }
228
229 #endif
230