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