• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2014 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 // system_utils.h: declaration of OS-specific utility functions
8 
9 #ifndef COMMON_SYSTEM_UTILS_H_
10 #define COMMON_SYSTEM_UTILS_H_
11 
12 #include "common/Optional.h"
13 #include "common/angleutils.h"
14 
15 #include <functional>
16 #include <string>
17 #include <string_view>
18 
19 namespace angle
20 {
21 std::string GetExecutableName();
22 std::string GetExecutablePath();
23 std::string GetExecutableDirectory();
24 std::string GetModuleDirectory();
25 const char *GetSharedLibraryExtension();
26 const char *GetExecutableExtension();
27 char GetPathSeparator();
28 Optional<std::string> GetCWD();
29 bool SetCWD(const char *dirName);
30 bool SetEnvironmentVar(const char *variableName, const char *value);
31 bool UnsetEnvironmentVar(const char *variableName);
32 bool GetBoolEnvironmentVar(const char *variableName);
33 std::string GetEnvironmentVar(const char *variableName);
34 std::string GetEnvironmentVarOrUnCachedAndroidProperty(const char *variableName,
35                                                        const char *propertyName);
36 std::string GetAndSetEnvironmentVarOrUnCachedAndroidProperty(const char *variableName,
37                                                              const char *propertyName);
38 std::string GetEnvironmentVarOrAndroidProperty(const char *variableName, const char *propertyName);
39 const char *GetPathSeparatorForEnvironmentVar();
40 bool PrependPathToEnvironmentVar(const char *variableName, const char *path);
41 bool IsDirectory(const char *filename);
42 bool IsFullPath(std::string dirName);
43 std::string GetRootDirectory();
44 std::string ConcatenatePath(std::string first, std::string second);
45 
46 Optional<std::string> GetTempDirectory();
47 Optional<std::string> CreateTemporaryFileInDirectory(const std::string &directory);
48 Optional<std::string> CreateTemporaryFile();
49 
50 #if defined(ANGLE_PLATFORM_POSIX)
51 // Same as CreateTemporaryFileInDirectory(), but allows for supplying an extension.
52 Optional<std::string> CreateTemporaryFileInDirectoryWithExtension(const std::string &directory,
53                                                                   const std::string &extension);
54 #endif
55 
56 // Get absolute time in seconds.  Use this function to get an absolute time with an unknown origin.
57 double GetCurrentSystemTime();
58 // Get CPU time for current process in seconds.
59 double GetCurrentProcessCpuTime();
60 
61 // Unique thread id (std::this_thread::get_id() gets recycled!)
62 uint64_t GetCurrentThreadUniqueId();
63 // Fast function to get thread id when performance is critical (may be recycled).
64 // On Android 7-8x faster than GetCurrentThreadUniqueId().
65 ThreadId GetCurrentThreadId();
66 // Returns id that does not represent a thread.
67 ThreadId InvalidThreadId();
68 
69 // Run an application and get the output.  Gets a nullptr-terminated set of args to execute the
70 // application with, and returns the stdout and stderr outputs as well as the exit code.
71 //
72 // Pass nullptr for stdoutOut/stderrOut if you don't need to capture. exitCodeOut is required.
73 //
74 // Returns false if it fails to actually execute the application.
75 bool RunApp(const std::vector<const char *> &args,
76             std::string *stdoutOut,
77             std::string *stderrOut,
78             int *exitCodeOut);
79 
80 // Use SYSTEM_DIR to bypass loading ANGLE libraries with the same name as system DLLS
81 // (e.g. opengl32.dll)
82 enum class SearchType
83 {
84     // Try to find the library in the same directory as the current module
85     ModuleDir,
86     // Load the library from the system directories
87     SystemDir,
88     // Get a reference to an already loaded shared library.
89     AlreadyLoaded,
90 };
91 
92 void *OpenSystemLibrary(const char *libraryName, SearchType searchType);
93 void *OpenSystemLibraryWithExtension(const char *libraryName, SearchType searchType);
94 void *OpenSystemLibraryAndGetError(const char *libraryName,
95                                    SearchType searchType,
96                                    std::string *errorOut);
97 void *OpenSystemLibraryWithExtensionAndGetError(const char *libraryName,
98                                                 SearchType searchType,
99                                                 std::string *errorOut);
100 
101 void *GetLibrarySymbol(void *libraryHandle, const char *symbolName);
102 std::string GetLibraryPath(void *libraryHandle);
103 void CloseSystemLibrary(void *libraryHandle);
104 
105 class Library : angle::NonCopyable
106 {
107   public:
Library()108     Library() {}
Library(void * libraryHandle)109     Library(void *libraryHandle) : mLibraryHandle(libraryHandle) {}
~Library()110     ~Library() { close(); }
111 
open(const char * libraryName,SearchType searchType)112     [[nodiscard]] bool open(const char *libraryName, SearchType searchType)
113     {
114         close();
115         mLibraryHandle = OpenSystemLibrary(libraryName, searchType);
116         return mLibraryHandle != nullptr;
117     }
118 
openWithExtension(const char * libraryName,SearchType searchType)119     [[nodiscard]] bool openWithExtension(const char *libraryName, SearchType searchType)
120     {
121         close();
122         mLibraryHandle = OpenSystemLibraryWithExtension(libraryName, searchType);
123         return mLibraryHandle != nullptr;
124     }
125 
openAndGetError(const char * libraryName,SearchType searchType,std::string * errorOut)126     [[nodiscard]] bool openAndGetError(const char *libraryName,
127                                        SearchType searchType,
128                                        std::string *errorOut)
129     {
130         close();
131         mLibraryHandle = OpenSystemLibraryAndGetError(libraryName, searchType, errorOut);
132         return mLibraryHandle != nullptr;
133     }
134 
openWithExtensionAndGetError(const char * libraryName,SearchType searchType,std::string * errorOut)135     [[nodiscard]] bool openWithExtensionAndGetError(const char *libraryName,
136                                                     SearchType searchType,
137                                                     std::string *errorOut)
138     {
139         close();
140         mLibraryHandle =
141             OpenSystemLibraryWithExtensionAndGetError(libraryName, searchType, errorOut);
142         return mLibraryHandle != nullptr;
143     }
144 
close()145     void close()
146     {
147         if (mLibraryHandle)
148         {
149             CloseSystemLibrary(mLibraryHandle);
150             mLibraryHandle = nullptr;
151         }
152     }
153 
getSymbol(const char * symbolName)154     void *getSymbol(const char *symbolName) { return GetLibrarySymbol(mLibraryHandle, symbolName); }
155 
getNative()156     void *getNative() const { return mLibraryHandle; }
157 
getPath()158     std::string getPath() const { return GetLibraryPath(mLibraryHandle); }
159 
160     template <typename FuncT>
getAs(const char * symbolName,FuncT * funcOut)161     void getAs(const char *symbolName, FuncT *funcOut)
162     {
163         *funcOut = reinterpret_cast<FuncT>(getSymbol(symbolName));
164     }
165 
166   private:
167     void *mLibraryHandle = nullptr;
168 };
169 
170 Library *OpenSharedLibrary(const char *libraryName, SearchType searchType);
171 Library *OpenSharedLibraryWithExtension(const char *libraryName, SearchType searchType);
172 Library *OpenSharedLibraryAndGetError(const char *libraryName,
173                                       SearchType searchType,
174                                       std::string *errorOut);
175 Library *OpenSharedLibraryWithExtensionAndGetError(const char *libraryName,
176                                                    SearchType searchType,
177                                                    std::string *errorOut);
178 
179 // Returns true if the process is currently being debugged.
180 bool IsDebuggerAttached();
181 
182 // Calls system APIs to break into the debugger.
183 void BreakDebugger();
184 
185 uint64_t GetProcessMemoryUsageKB();
186 
187 bool ProtectMemory(uintptr_t start, size_t size);
188 bool UnprotectMemory(uintptr_t start, size_t size);
189 
190 size_t GetPageSize();
191 
192 // Return type of the PageFaultCallback
193 enum class PageFaultHandlerRangeType
194 {
195     // The memory address was known by the page fault handler
196     InRange,
197     // The memory address was not in the page fault handler's range
198     // and the signal will be forwarded to the default page handler.
199     OutOfRange,
200 };
201 
202 using PageFaultCallback = std::function<PageFaultHandlerRangeType(uintptr_t)>;
203 
204 class PageFaultHandler : angle::NonCopyable
205 {
206   public:
207     PageFaultHandler(PageFaultCallback callback);
208     virtual ~PageFaultHandler();
209 
210     // Registers OS level page fault handler for memory protection signals
211     // and enables reception on PageFaultCallback
212     virtual bool enable() = 0;
213 
214     // Unregisters OS level page fault handler and deactivates PageFaultCallback
215     virtual bool disable() = 0;
216 
217   protected:
218     PageFaultCallback mCallback;
219 };
220 
221 // Creates single instance page fault handler
222 PageFaultHandler *CreatePageFaultHandler(PageFaultCallback callback);
223 
224 #ifdef ANGLE_PLATFORM_WINDOWS
225 // Convert an UTF-16 wstring to an UTF-8 string.
226 std::string Narrow(const std::wstring_view &utf16);
227 
228 // Convert an UTF-8 string to an UTF-16 wstring.
229 std::wstring Widen(const std::string_view &utf8);
230 #endif
231 
232 std::string StripFilenameFromPath(const std::string &path);
233 
234 #if defined(ANGLE_PLATFORM_LINUX) || defined(ANGLE_PLATFORM_WINDOWS)
235 // Use C++ thread_local which is about 2x faster than std::this_thread::get_id()
GetCurrentThreadId()236 ANGLE_INLINE ThreadId GetCurrentThreadId()
237 {
238     thread_local int tls;
239     return static_cast<ThreadId>(reinterpret_cast<uintptr_t>(&tls));
240 }
InvalidThreadId()241 ANGLE_INLINE ThreadId InvalidThreadId()
242 {
243     return -1;
244 }
245 #else
246 // Default. Fastest on Android (about the same as `pthread_self` and a bit faster then `gettid`).
GetCurrentThreadId()247 ANGLE_INLINE ThreadId GetCurrentThreadId()
248 {
249     return std::this_thread::get_id();
250 }
InvalidThreadId()251 ANGLE_INLINE ThreadId InvalidThreadId()
252 {
253     return ThreadId();
254 }
255 #endif
256 }  // namespace angle
257 
258 #endif  // COMMON_SYSTEM_UTILS_H_
259