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