summaryrefslogtreecommitdiffstats
path: root/gfx/angle/checkout/src/common/system_utils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/angle/checkout/src/common/system_utils.cpp')
-rw-r--r--gfx/angle/checkout/src/common/system_utils.cpp267
1 files changed, 267 insertions, 0 deletions
diff --git a/gfx/angle/checkout/src/common/system_utils.cpp b/gfx/angle/checkout/src/common/system_utils.cpp
new file mode 100644
index 0000000000..89b632bc17
--- /dev/null
+++ b/gfx/angle/checkout/src/common/system_utils.cpp
@@ -0,0 +1,267 @@
+//
+// Copyright 2018 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// system_utils.cpp: Implementation of common functions
+
+#include "common/system_utils.h"
+#include "common/debug.h"
+
+#include <stdlib.h>
+#include <atomic>
+
+#if defined(ANGLE_PLATFORM_ANDROID)
+# include <sys/system_properties.h>
+#endif
+
+#if defined(ANGLE_PLATFORM_APPLE)
+# include <dispatch/dispatch.h>
+# include <pthread.h>
+#endif
+
+namespace angle
+{
+std::string GetExecutableName()
+{
+#if defined(ANGLE_PLATFORM_ANDROID) && __ANDROID_API__ >= 21
+ // Support for "getprogname" function in bionic was introduced in L (API level 21)
+ const char *executableName = getprogname();
+ return (executableName) ? std::string(executableName) : "ANGLE";
+#else
+ std::string executableName = GetExecutablePath();
+ size_t lastPathSepLoc = executableName.find_last_of(GetPathSeparator());
+ return (lastPathSepLoc > 0 ? executableName.substr(lastPathSepLoc + 1, executableName.length())
+ : "ANGLE");
+#endif // ANGLE_PLATFORM_ANDROID
+}
+
+// On Android return value cached in the process environment, if none, call
+// GetEnvironmentVarOrUnCachedAndroidProperty if not in environment.
+std::string GetEnvironmentVarOrAndroidProperty(const char *variableName, const char *propertyName)
+{
+#if defined(ANGLE_PLATFORM_ANDROID) && __ANDROID_API__ >= 21
+ // Can't use GetEnvironmentVar here because that won't allow us to distinguish between the
+ // environment being set to an empty string vs. not set at all.
+ const char *variableValue = getenv(variableName);
+ if (variableValue != nullptr)
+ {
+ std::string value(variableValue);
+ return value;
+ }
+#endif
+ return GetEnvironmentVarOrUnCachedAndroidProperty(variableName, propertyName);
+}
+
+// On Android call out to 'getprop' on a shell to get an Android property. On desktop, return
+// the value of the environment variable.
+std::string GetEnvironmentVarOrUnCachedAndroidProperty(const char *variableName,
+ const char *propertyName)
+{
+#if defined(ANGLE_PLATFORM_ANDROID) && __ANDROID_API__ >= 26
+ std::string propertyValue;
+
+ const prop_info *propertyInfo = __system_property_find(propertyName);
+ if (propertyInfo != nullptr)
+ {
+ __system_property_read_callback(
+ propertyInfo,
+ [](void *cookie, const char *, const char *value, unsigned) {
+ auto propertyValue = reinterpret_cast<std::string *>(cookie);
+ *propertyValue = value;
+ },
+ &propertyValue);
+ }
+
+ return propertyValue;
+#else
+ // Return the environment variable's value.
+ return GetEnvironmentVar(variableName);
+#endif // ANGLE_PLATFORM_ANDROID
+}
+
+// Look up a property and add it to the application's environment.
+// Adding to the env is a performance optimization, as getting properties is expensive.
+// This should only be used in non-Release paths, i.e. when using FrameCapture or DebugUtils.
+// It can cause race conditions in stress testing. See http://anglebug.com/6822
+std::string GetAndSetEnvironmentVarOrUnCachedAndroidProperty(const char *variableName,
+ const char *propertyName)
+{
+ std::string value = GetEnvironmentVarOrUnCachedAndroidProperty(variableName, propertyName);
+
+#if defined(ANGLE_PLATFORM_ANDROID)
+ if (!value.empty())
+ {
+ // Set the environment variable with the value to improve future lookups (avoids
+ SetEnvironmentVar(variableName, value.c_str());
+ }
+#endif
+
+ return value;
+}
+
+bool GetBoolEnvironmentVar(const char *variableName)
+{
+ std::string envVarString = GetEnvironmentVar(variableName);
+ return (!envVarString.empty() && envVarString == "1");
+}
+
+bool PrependPathToEnvironmentVar(const char *variableName, const char *path)
+{
+ std::string oldValue = GetEnvironmentVar(variableName);
+ const char *newValue = nullptr;
+ std::string buf;
+ if (oldValue.empty())
+ {
+ newValue = path;
+ }
+ else
+ {
+ buf = path;
+ buf += GetPathSeparatorForEnvironmentVar();
+ buf += oldValue;
+ newValue = buf.c_str();
+ }
+ return SetEnvironmentVar(variableName, newValue);
+}
+
+bool IsFullPath(std::string dirName)
+{
+ if (dirName.find(GetRootDirectory()) == 0)
+ {
+ return true;
+ }
+ return false;
+}
+
+std::string ConcatenatePath(std::string first, std::string second)
+{
+ if (first.empty())
+ {
+ return second;
+ }
+ if (second.empty())
+ {
+ return first;
+ }
+ if (IsFullPath(second))
+ {
+ return second;
+ }
+ bool firstRedundantPathSeparator = first.find_last_of(GetPathSeparator()) == first.length() - 1;
+ bool secondRedundantPathSeparator = second.find(GetPathSeparator()) == 0;
+ if (firstRedundantPathSeparator && secondRedundantPathSeparator)
+ {
+ return first + second.substr(1);
+ }
+ else if (firstRedundantPathSeparator || secondRedundantPathSeparator)
+ {
+ return first + second;
+ }
+ return first + GetPathSeparator() + second;
+}
+
+Optional<std::string> CreateTemporaryFile()
+{
+ const Optional<std::string> tempDir = GetTempDirectory();
+ if (!tempDir.valid())
+ return Optional<std::string>::Invalid();
+
+ return CreateTemporaryFileInDirectory(tempDir.value());
+}
+
+PageFaultHandler::PageFaultHandler(PageFaultCallback callback) : mCallback(callback) {}
+PageFaultHandler::~PageFaultHandler() {}
+
+Library *OpenSharedLibrary(const char *libraryName, SearchType searchType)
+{
+ void *libraryHandle = OpenSystemLibraryAndGetError(libraryName, searchType, nullptr);
+ return new Library(libraryHandle);
+}
+
+Library *OpenSharedLibraryWithExtension(const char *libraryName, SearchType searchType)
+{
+ void *libraryHandle =
+ OpenSystemLibraryWithExtensionAndGetError(libraryName, searchType, nullptr);
+ return new Library(libraryHandle);
+}
+
+Library *OpenSharedLibraryAndGetError(const char *libraryName,
+ SearchType searchType,
+ std::string *errorOut)
+{
+ void *libraryHandle = OpenSystemLibraryAndGetError(libraryName, searchType, errorOut);
+ return new Library(libraryHandle);
+}
+
+Library *OpenSharedLibraryWithExtensionAndGetError(const char *libraryName,
+ SearchType searchType,
+ std::string *errorOut)
+{
+ void *libraryHandle =
+ OpenSystemLibraryWithExtensionAndGetError(libraryName, searchType, errorOut);
+ return new Library(libraryHandle);
+}
+
+void *OpenSystemLibrary(const char *libraryName, SearchType searchType)
+{
+ return OpenSystemLibraryAndGetError(libraryName, searchType, nullptr);
+}
+
+void *OpenSystemLibraryWithExtension(const char *libraryName, SearchType searchType)
+{
+ return OpenSystemLibraryWithExtensionAndGetError(libraryName, searchType, nullptr);
+}
+
+void *OpenSystemLibraryAndGetError(const char *libraryName,
+ SearchType searchType,
+ std::string *errorOut)
+{
+ std::string libraryWithExtension = std::string(libraryName) + "." + GetSharedLibraryExtension();
+#if ANGLE_PLATFORM_IOS
+ // On iOS, libraryWithExtension is a directory in which the library resides.
+ // The actual library name doesn't have an extension at all.
+ // E.g. "libEGL.framework/libEGL"
+ libraryWithExtension = libraryWithExtension + "/" + libraryName;
+#endif
+ return OpenSystemLibraryWithExtensionAndGetError(libraryWithExtension.c_str(), searchType,
+ errorOut);
+}
+
+std::string StripFilenameFromPath(const std::string &path)
+{
+ size_t lastPathSepLoc = path.find_last_of("\\/");
+ return (lastPathSepLoc != std::string::npos) ? path.substr(0, lastPathSepLoc) : "";
+}
+
+static std::atomic<uint64_t> globalThreadSerial(1);
+
+#if defined(ANGLE_PLATFORM_APPLE)
+// https://anglebug.com/6479, similar to egl::GetCurrentThread() in libGLESv2/global_state.cpp
+uint64_t GetCurrentThreadUniqueId()
+{
+ static pthread_key_t tlsIndex;
+ static dispatch_once_t once;
+ dispatch_once(&once, ^{
+ ASSERT(pthread_key_create(&tlsIndex, nullptr) == 0);
+ });
+
+ void *tlsValue = pthread_getspecific(tlsIndex);
+ if (tlsValue == nullptr)
+ {
+ uint64_t threadId = globalThreadSerial++;
+ ASSERT(pthread_setspecific(tlsIndex, reinterpret_cast<void *>(threadId)) == 0);
+ return threadId;
+ }
+ return reinterpret_cast<uint64_t>(tlsValue);
+}
+#else
+uint64_t GetCurrentThreadUniqueId()
+{
+ thread_local uint64_t threadId(globalThreadSerial++);
+ return threadId;
+}
+#endif
+
+} // namespace angle