1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2018 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.cpp: Implementation of common functions
8*8975f5c5SAndroid Build Coastguard Worker
9*8975f5c5SAndroid Build Coastguard Worker #include "common/system_utils.h"
10*8975f5c5SAndroid Build Coastguard Worker #include "common/debug.h"
11*8975f5c5SAndroid Build Coastguard Worker
12*8975f5c5SAndroid Build Coastguard Worker #include <stdlib.h>
13*8975f5c5SAndroid Build Coastguard Worker #include <atomic>
14*8975f5c5SAndroid Build Coastguard Worker
15*8975f5c5SAndroid Build Coastguard Worker #if defined(ANGLE_PLATFORM_ANDROID)
16*8975f5c5SAndroid Build Coastguard Worker # include <sys/system_properties.h>
17*8975f5c5SAndroid Build Coastguard Worker #endif
18*8975f5c5SAndroid Build Coastguard Worker
19*8975f5c5SAndroid Build Coastguard Worker #if defined(ANGLE_PLATFORM_APPLE)
20*8975f5c5SAndroid Build Coastguard Worker # include <dispatch/dispatch.h>
21*8975f5c5SAndroid Build Coastguard Worker # include <pthread.h>
22*8975f5c5SAndroid Build Coastguard Worker #endif
23*8975f5c5SAndroid Build Coastguard Worker
24*8975f5c5SAndroid Build Coastguard Worker namespace angle
25*8975f5c5SAndroid Build Coastguard Worker {
GetExecutableName()26*8975f5c5SAndroid Build Coastguard Worker std::string GetExecutableName()
27*8975f5c5SAndroid Build Coastguard Worker {
28*8975f5c5SAndroid Build Coastguard Worker #if defined(ANGLE_PLATFORM_ANDROID) && __ANDROID_API__ >= 21
29*8975f5c5SAndroid Build Coastguard Worker // Support for "getprogname" function in bionic was introduced in L (API level 21)
30*8975f5c5SAndroid Build Coastguard Worker const char *executableName = getprogname();
31*8975f5c5SAndroid Build Coastguard Worker return (executableName) ? std::string(executableName) : "ANGLE";
32*8975f5c5SAndroid Build Coastguard Worker #else
33*8975f5c5SAndroid Build Coastguard Worker std::string executableName = GetExecutablePath();
34*8975f5c5SAndroid Build Coastguard Worker size_t lastPathSepLoc = executableName.find_last_of(GetPathSeparator());
35*8975f5c5SAndroid Build Coastguard Worker return (lastPathSepLoc > 0 ? executableName.substr(lastPathSepLoc + 1, executableName.length())
36*8975f5c5SAndroid Build Coastguard Worker : "ANGLE");
37*8975f5c5SAndroid Build Coastguard Worker #endif // ANGLE_PLATFORM_ANDROID
38*8975f5c5SAndroid Build Coastguard Worker }
39*8975f5c5SAndroid Build Coastguard Worker
40*8975f5c5SAndroid Build Coastguard Worker // On Android return value cached in the process environment, if none, call
41*8975f5c5SAndroid Build Coastguard Worker // GetEnvironmentVarOrUnCachedAndroidProperty if not in environment.
GetEnvironmentVarOrAndroidProperty(const char * variableName,const char * propertyName)42*8975f5c5SAndroid Build Coastguard Worker std::string GetEnvironmentVarOrAndroidProperty(const char *variableName, const char *propertyName)
43*8975f5c5SAndroid Build Coastguard Worker {
44*8975f5c5SAndroid Build Coastguard Worker #if defined(ANGLE_PLATFORM_ANDROID) && __ANDROID_API__ >= 21
45*8975f5c5SAndroid Build Coastguard Worker // Can't use GetEnvironmentVar here because that won't allow us to distinguish between the
46*8975f5c5SAndroid Build Coastguard Worker // environment being set to an empty string vs. not set at all.
47*8975f5c5SAndroid Build Coastguard Worker const char *variableValue = getenv(variableName);
48*8975f5c5SAndroid Build Coastguard Worker if (variableValue != nullptr)
49*8975f5c5SAndroid Build Coastguard Worker {
50*8975f5c5SAndroid Build Coastguard Worker std::string value(variableValue);
51*8975f5c5SAndroid Build Coastguard Worker return value;
52*8975f5c5SAndroid Build Coastguard Worker }
53*8975f5c5SAndroid Build Coastguard Worker #endif
54*8975f5c5SAndroid Build Coastguard Worker return GetEnvironmentVarOrUnCachedAndroidProperty(variableName, propertyName);
55*8975f5c5SAndroid Build Coastguard Worker }
56*8975f5c5SAndroid Build Coastguard Worker
57*8975f5c5SAndroid Build Coastguard Worker // On Android call out to 'getprop' on a shell to get an Android property. On desktop, return
58*8975f5c5SAndroid Build Coastguard Worker // the value of the environment variable.
GetEnvironmentVarOrUnCachedAndroidProperty(const char * variableName,const char * propertyName)59*8975f5c5SAndroid Build Coastguard Worker std::string GetEnvironmentVarOrUnCachedAndroidProperty(const char *variableName,
60*8975f5c5SAndroid Build Coastguard Worker const char *propertyName)
61*8975f5c5SAndroid Build Coastguard Worker {
62*8975f5c5SAndroid Build Coastguard Worker #if defined(ANGLE_PLATFORM_ANDROID) && __ANDROID_API__ >= 26
63*8975f5c5SAndroid Build Coastguard Worker std::string propertyValue;
64*8975f5c5SAndroid Build Coastguard Worker
65*8975f5c5SAndroid Build Coastguard Worker const prop_info *propertyInfo = __system_property_find(propertyName);
66*8975f5c5SAndroid Build Coastguard Worker if (propertyInfo != nullptr)
67*8975f5c5SAndroid Build Coastguard Worker {
68*8975f5c5SAndroid Build Coastguard Worker __system_property_read_callback(
69*8975f5c5SAndroid Build Coastguard Worker propertyInfo,
70*8975f5c5SAndroid Build Coastguard Worker [](void *cookie, const char *, const char *value, unsigned) {
71*8975f5c5SAndroid Build Coastguard Worker auto propertyValue = reinterpret_cast<std::string *>(cookie);
72*8975f5c5SAndroid Build Coastguard Worker *propertyValue = value;
73*8975f5c5SAndroid Build Coastguard Worker },
74*8975f5c5SAndroid Build Coastguard Worker &propertyValue);
75*8975f5c5SAndroid Build Coastguard Worker }
76*8975f5c5SAndroid Build Coastguard Worker
77*8975f5c5SAndroid Build Coastguard Worker return propertyValue;
78*8975f5c5SAndroid Build Coastguard Worker #else
79*8975f5c5SAndroid Build Coastguard Worker // Return the environment variable's value.
80*8975f5c5SAndroid Build Coastguard Worker return GetEnvironmentVar(variableName);
81*8975f5c5SAndroid Build Coastguard Worker #endif // ANGLE_PLATFORM_ANDROID
82*8975f5c5SAndroid Build Coastguard Worker }
83*8975f5c5SAndroid Build Coastguard Worker
84*8975f5c5SAndroid Build Coastguard Worker // Look up a property and add it to the application's environment.
85*8975f5c5SAndroid Build Coastguard Worker // Adding to the env is a performance optimization, as getting properties is expensive.
86*8975f5c5SAndroid Build Coastguard Worker // This should only be used in non-Release paths, i.e. when using FrameCapture or DebugUtils.
87*8975f5c5SAndroid Build Coastguard Worker // It can cause race conditions in stress testing. See http://anglebug.com/42265318
GetAndSetEnvironmentVarOrUnCachedAndroidProperty(const char * variableName,const char * propertyName)88*8975f5c5SAndroid Build Coastguard Worker std::string GetAndSetEnvironmentVarOrUnCachedAndroidProperty(const char *variableName,
89*8975f5c5SAndroid Build Coastguard Worker const char *propertyName)
90*8975f5c5SAndroid Build Coastguard Worker {
91*8975f5c5SAndroid Build Coastguard Worker std::string value = GetEnvironmentVarOrUnCachedAndroidProperty(variableName, propertyName);
92*8975f5c5SAndroid Build Coastguard Worker
93*8975f5c5SAndroid Build Coastguard Worker #if defined(ANGLE_PLATFORM_ANDROID)
94*8975f5c5SAndroid Build Coastguard Worker if (!value.empty())
95*8975f5c5SAndroid Build Coastguard Worker {
96*8975f5c5SAndroid Build Coastguard Worker // Set the environment variable with the value to improve future lookups (avoids
97*8975f5c5SAndroid Build Coastguard Worker SetEnvironmentVar(variableName, value.c_str());
98*8975f5c5SAndroid Build Coastguard Worker }
99*8975f5c5SAndroid Build Coastguard Worker #endif
100*8975f5c5SAndroid Build Coastguard Worker
101*8975f5c5SAndroid Build Coastguard Worker return value;
102*8975f5c5SAndroid Build Coastguard Worker }
103*8975f5c5SAndroid Build Coastguard Worker
GetBoolEnvironmentVar(const char * variableName)104*8975f5c5SAndroid Build Coastguard Worker bool GetBoolEnvironmentVar(const char *variableName)
105*8975f5c5SAndroid Build Coastguard Worker {
106*8975f5c5SAndroid Build Coastguard Worker std::string envVarString = GetEnvironmentVar(variableName);
107*8975f5c5SAndroid Build Coastguard Worker return (!envVarString.empty() && envVarString == "1");
108*8975f5c5SAndroid Build Coastguard Worker }
109*8975f5c5SAndroid Build Coastguard Worker
PrependPathToEnvironmentVar(const char * variableName,const char * path)110*8975f5c5SAndroid Build Coastguard Worker bool PrependPathToEnvironmentVar(const char *variableName, const char *path)
111*8975f5c5SAndroid Build Coastguard Worker {
112*8975f5c5SAndroid Build Coastguard Worker std::string oldValue = GetEnvironmentVar(variableName);
113*8975f5c5SAndroid Build Coastguard Worker const char *newValue = nullptr;
114*8975f5c5SAndroid Build Coastguard Worker std::string buf;
115*8975f5c5SAndroid Build Coastguard Worker if (oldValue.empty())
116*8975f5c5SAndroid Build Coastguard Worker {
117*8975f5c5SAndroid Build Coastguard Worker newValue = path;
118*8975f5c5SAndroid Build Coastguard Worker }
119*8975f5c5SAndroid Build Coastguard Worker else
120*8975f5c5SAndroid Build Coastguard Worker {
121*8975f5c5SAndroid Build Coastguard Worker buf = path;
122*8975f5c5SAndroid Build Coastguard Worker buf += GetPathSeparatorForEnvironmentVar();
123*8975f5c5SAndroid Build Coastguard Worker buf += oldValue;
124*8975f5c5SAndroid Build Coastguard Worker newValue = buf.c_str();
125*8975f5c5SAndroid Build Coastguard Worker }
126*8975f5c5SAndroid Build Coastguard Worker return SetEnvironmentVar(variableName, newValue);
127*8975f5c5SAndroid Build Coastguard Worker }
128*8975f5c5SAndroid Build Coastguard Worker
IsFullPath(std::string dirName)129*8975f5c5SAndroid Build Coastguard Worker bool IsFullPath(std::string dirName)
130*8975f5c5SAndroid Build Coastguard Worker {
131*8975f5c5SAndroid Build Coastguard Worker if (dirName.find(GetRootDirectory()) == 0)
132*8975f5c5SAndroid Build Coastguard Worker {
133*8975f5c5SAndroid Build Coastguard Worker return true;
134*8975f5c5SAndroid Build Coastguard Worker }
135*8975f5c5SAndroid Build Coastguard Worker return false;
136*8975f5c5SAndroid Build Coastguard Worker }
137*8975f5c5SAndroid Build Coastguard Worker
ConcatenatePath(std::string first,std::string second)138*8975f5c5SAndroid Build Coastguard Worker std::string ConcatenatePath(std::string first, std::string second)
139*8975f5c5SAndroid Build Coastguard Worker {
140*8975f5c5SAndroid Build Coastguard Worker if (first.empty())
141*8975f5c5SAndroid Build Coastguard Worker {
142*8975f5c5SAndroid Build Coastguard Worker return second;
143*8975f5c5SAndroid Build Coastguard Worker }
144*8975f5c5SAndroid Build Coastguard Worker if (second.empty())
145*8975f5c5SAndroid Build Coastguard Worker {
146*8975f5c5SAndroid Build Coastguard Worker return first;
147*8975f5c5SAndroid Build Coastguard Worker }
148*8975f5c5SAndroid Build Coastguard Worker if (IsFullPath(second))
149*8975f5c5SAndroid Build Coastguard Worker {
150*8975f5c5SAndroid Build Coastguard Worker return second;
151*8975f5c5SAndroid Build Coastguard Worker }
152*8975f5c5SAndroid Build Coastguard Worker bool firstRedundantPathSeparator = first.find_last_of(GetPathSeparator()) == first.length() - 1;
153*8975f5c5SAndroid Build Coastguard Worker bool secondRedundantPathSeparator = second.find(GetPathSeparator()) == 0;
154*8975f5c5SAndroid Build Coastguard Worker if (firstRedundantPathSeparator && secondRedundantPathSeparator)
155*8975f5c5SAndroid Build Coastguard Worker {
156*8975f5c5SAndroid Build Coastguard Worker return first + second.substr(1);
157*8975f5c5SAndroid Build Coastguard Worker }
158*8975f5c5SAndroid Build Coastguard Worker else if (firstRedundantPathSeparator || secondRedundantPathSeparator)
159*8975f5c5SAndroid Build Coastguard Worker {
160*8975f5c5SAndroid Build Coastguard Worker return first + second;
161*8975f5c5SAndroid Build Coastguard Worker }
162*8975f5c5SAndroid Build Coastguard Worker return first + GetPathSeparator() + second;
163*8975f5c5SAndroid Build Coastguard Worker }
164*8975f5c5SAndroid Build Coastguard Worker
CreateTemporaryFile()165*8975f5c5SAndroid Build Coastguard Worker Optional<std::string> CreateTemporaryFile()
166*8975f5c5SAndroid Build Coastguard Worker {
167*8975f5c5SAndroid Build Coastguard Worker const Optional<std::string> tempDir = GetTempDirectory();
168*8975f5c5SAndroid Build Coastguard Worker if (!tempDir.valid())
169*8975f5c5SAndroid Build Coastguard Worker return Optional<std::string>::Invalid();
170*8975f5c5SAndroid Build Coastguard Worker
171*8975f5c5SAndroid Build Coastguard Worker return CreateTemporaryFileInDirectory(tempDir.value());
172*8975f5c5SAndroid Build Coastguard Worker }
173*8975f5c5SAndroid Build Coastguard Worker
PageFaultHandler(PageFaultCallback callback)174*8975f5c5SAndroid Build Coastguard Worker PageFaultHandler::PageFaultHandler(PageFaultCallback callback) : mCallback(callback) {}
~PageFaultHandler()175*8975f5c5SAndroid Build Coastguard Worker PageFaultHandler::~PageFaultHandler() {}
176*8975f5c5SAndroid Build Coastguard Worker
OpenSharedLibrary(const char * libraryName,SearchType searchType)177*8975f5c5SAndroid Build Coastguard Worker Library *OpenSharedLibrary(const char *libraryName, SearchType searchType)
178*8975f5c5SAndroid Build Coastguard Worker {
179*8975f5c5SAndroid Build Coastguard Worker void *libraryHandle = OpenSystemLibraryAndGetError(libraryName, searchType, nullptr);
180*8975f5c5SAndroid Build Coastguard Worker return new Library(libraryHandle);
181*8975f5c5SAndroid Build Coastguard Worker }
182*8975f5c5SAndroid Build Coastguard Worker
OpenSharedLibraryWithExtension(const char * libraryName,SearchType searchType)183*8975f5c5SAndroid Build Coastguard Worker Library *OpenSharedLibraryWithExtension(const char *libraryName, SearchType searchType)
184*8975f5c5SAndroid Build Coastguard Worker {
185*8975f5c5SAndroid Build Coastguard Worker void *libraryHandle =
186*8975f5c5SAndroid Build Coastguard Worker OpenSystemLibraryWithExtensionAndGetError(libraryName, searchType, nullptr);
187*8975f5c5SAndroid Build Coastguard Worker return new Library(libraryHandle);
188*8975f5c5SAndroid Build Coastguard Worker }
189*8975f5c5SAndroid Build Coastguard Worker
OpenSharedLibraryAndGetError(const char * libraryName,SearchType searchType,std::string * errorOut)190*8975f5c5SAndroid Build Coastguard Worker Library *OpenSharedLibraryAndGetError(const char *libraryName,
191*8975f5c5SAndroid Build Coastguard Worker SearchType searchType,
192*8975f5c5SAndroid Build Coastguard Worker std::string *errorOut)
193*8975f5c5SAndroid Build Coastguard Worker {
194*8975f5c5SAndroid Build Coastguard Worker void *libraryHandle = OpenSystemLibraryAndGetError(libraryName, searchType, errorOut);
195*8975f5c5SAndroid Build Coastguard Worker return new Library(libraryHandle);
196*8975f5c5SAndroid Build Coastguard Worker }
197*8975f5c5SAndroid Build Coastguard Worker
OpenSharedLibraryWithExtensionAndGetError(const char * libraryName,SearchType searchType,std::string * errorOut)198*8975f5c5SAndroid Build Coastguard Worker Library *OpenSharedLibraryWithExtensionAndGetError(const char *libraryName,
199*8975f5c5SAndroid Build Coastguard Worker SearchType searchType,
200*8975f5c5SAndroid Build Coastguard Worker std::string *errorOut)
201*8975f5c5SAndroid Build Coastguard Worker {
202*8975f5c5SAndroid Build Coastguard Worker void *libraryHandle =
203*8975f5c5SAndroid Build Coastguard Worker OpenSystemLibraryWithExtensionAndGetError(libraryName, searchType, errorOut);
204*8975f5c5SAndroid Build Coastguard Worker return new Library(libraryHandle);
205*8975f5c5SAndroid Build Coastguard Worker }
206*8975f5c5SAndroid Build Coastguard Worker
OpenSystemLibrary(const char * libraryName,SearchType searchType)207*8975f5c5SAndroid Build Coastguard Worker void *OpenSystemLibrary(const char *libraryName, SearchType searchType)
208*8975f5c5SAndroid Build Coastguard Worker {
209*8975f5c5SAndroid Build Coastguard Worker return OpenSystemLibraryAndGetError(libraryName, searchType, nullptr);
210*8975f5c5SAndroid Build Coastguard Worker }
211*8975f5c5SAndroid Build Coastguard Worker
OpenSystemLibraryWithExtension(const char * libraryName,SearchType searchType)212*8975f5c5SAndroid Build Coastguard Worker void *OpenSystemLibraryWithExtension(const char *libraryName, SearchType searchType)
213*8975f5c5SAndroid Build Coastguard Worker {
214*8975f5c5SAndroid Build Coastguard Worker return OpenSystemLibraryWithExtensionAndGetError(libraryName, searchType, nullptr);
215*8975f5c5SAndroid Build Coastguard Worker }
216*8975f5c5SAndroid Build Coastguard Worker
OpenSystemLibraryAndGetError(const char * libraryName,SearchType searchType,std::string * errorOut)217*8975f5c5SAndroid Build Coastguard Worker void *OpenSystemLibraryAndGetError(const char *libraryName,
218*8975f5c5SAndroid Build Coastguard Worker SearchType searchType,
219*8975f5c5SAndroid Build Coastguard Worker std::string *errorOut)
220*8975f5c5SAndroid Build Coastguard Worker {
221*8975f5c5SAndroid Build Coastguard Worker std::string libraryWithExtension = std::string(libraryName);
222*8975f5c5SAndroid Build Coastguard Worker std::string dotExtension = std::string(".") + GetSharedLibraryExtension();
223*8975f5c5SAndroid Build Coastguard Worker // Only append the extension if it's not already present. This enables building libEGL.so.1
224*8975f5c5SAndroid Build Coastguard Worker // and libGLESv2.so.2 by setting these as ANGLE_EGL_LIBRARY_NAME and ANGLE_GLESV2_LIBRARY_NAME.
225*8975f5c5SAndroid Build Coastguard Worker if (libraryWithExtension.find(dotExtension) == std::string::npos)
226*8975f5c5SAndroid Build Coastguard Worker {
227*8975f5c5SAndroid Build Coastguard Worker libraryWithExtension += dotExtension;
228*8975f5c5SAndroid Build Coastguard Worker }
229*8975f5c5SAndroid Build Coastguard Worker #if ANGLE_PLATFORM_IOS_FAMILY
230*8975f5c5SAndroid Build Coastguard Worker // On iOS, libraryWithExtension is a directory in which the library resides.
231*8975f5c5SAndroid Build Coastguard Worker // The actual library name doesn't have an extension at all.
232*8975f5c5SAndroid Build Coastguard Worker // E.g. "libEGL.framework/libEGL"
233*8975f5c5SAndroid Build Coastguard Worker libraryWithExtension = libraryWithExtension + "/" + libraryName;
234*8975f5c5SAndroid Build Coastguard Worker #endif
235*8975f5c5SAndroid Build Coastguard Worker return OpenSystemLibraryWithExtensionAndGetError(libraryWithExtension.c_str(), searchType,
236*8975f5c5SAndroid Build Coastguard Worker errorOut);
237*8975f5c5SAndroid Build Coastguard Worker }
238*8975f5c5SAndroid Build Coastguard Worker
StripFilenameFromPath(const std::string & path)239*8975f5c5SAndroid Build Coastguard Worker std::string StripFilenameFromPath(const std::string &path)
240*8975f5c5SAndroid Build Coastguard Worker {
241*8975f5c5SAndroid Build Coastguard Worker size_t lastPathSepLoc = path.find_last_of("\\/");
242*8975f5c5SAndroid Build Coastguard Worker return (lastPathSepLoc != std::string::npos) ? path.substr(0, lastPathSepLoc) : "";
243*8975f5c5SAndroid Build Coastguard Worker }
244*8975f5c5SAndroid Build Coastguard Worker
245*8975f5c5SAndroid Build Coastguard Worker #if defined(ANGLE_PLATFORM_APPLE)
246*8975f5c5SAndroid Build Coastguard Worker // https://anglebug.com/42264979, similar to egl::GetCurrentThread() in libGLESv2/global_state.cpp
GetCurrentThreadUniqueId()247*8975f5c5SAndroid Build Coastguard Worker uint64_t GetCurrentThreadUniqueId()
248*8975f5c5SAndroid Build Coastguard Worker {
249*8975f5c5SAndroid Build Coastguard Worker static std::atomic<uint64_t> globalThreadSerial;
250*8975f5c5SAndroid Build Coastguard Worker static pthread_key_t tlsIndex;
251*8975f5c5SAndroid Build Coastguard Worker static dispatch_once_t once;
252*8975f5c5SAndroid Build Coastguard Worker dispatch_once(&once, ^{
253*8975f5c5SAndroid Build Coastguard Worker auto result = pthread_key_create(&tlsIndex, nullptr);
254*8975f5c5SAndroid Build Coastguard Worker ASSERT(result == 0);
255*8975f5c5SAndroid Build Coastguard Worker });
256*8975f5c5SAndroid Build Coastguard Worker void *tlsValue = pthread_getspecific(tlsIndex);
257*8975f5c5SAndroid Build Coastguard Worker if (ANGLE_UNLIKELY(tlsValue == nullptr))
258*8975f5c5SAndroid Build Coastguard Worker {
259*8975f5c5SAndroid Build Coastguard Worker uint64_t threadId = ++globalThreadSerial;
260*8975f5c5SAndroid Build Coastguard Worker auto result = pthread_setspecific(tlsIndex, reinterpret_cast<void *>(threadId));
261*8975f5c5SAndroid Build Coastguard Worker ASSERT(result == 0);
262*8975f5c5SAndroid Build Coastguard Worker return threadId;
263*8975f5c5SAndroid Build Coastguard Worker }
264*8975f5c5SAndroid Build Coastguard Worker return reinterpret_cast<uint64_t>(tlsValue);
265*8975f5c5SAndroid Build Coastguard Worker }
266*8975f5c5SAndroid Build Coastguard Worker #else
GetCurrentThreadUniqueId()267*8975f5c5SAndroid Build Coastguard Worker uint64_t GetCurrentThreadUniqueId()
268*8975f5c5SAndroid Build Coastguard Worker {
269*8975f5c5SAndroid Build Coastguard Worker static std::atomic<uint64_t> globalThreadSerial;
270*8975f5c5SAndroid Build Coastguard Worker thread_local uint64_t threadId(++globalThreadSerial);
271*8975f5c5SAndroid Build Coastguard Worker return threadId;
272*8975f5c5SAndroid Build Coastguard Worker }
273*8975f5c5SAndroid Build Coastguard Worker #endif
274*8975f5c5SAndroid Build Coastguard Worker
275*8975f5c5SAndroid Build Coastguard Worker } // namespace angle
276