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