summaryrefslogtreecommitdiffstats
path: root/xpcom/base/nsMacUtilsImpl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'xpcom/base/nsMacUtilsImpl.cpp')
-rw-r--r--xpcom/base/nsMacUtilsImpl.cpp65
1 files changed, 65 insertions, 0 deletions
diff --git a/xpcom/base/nsMacUtilsImpl.cpp b/xpcom/base/nsMacUtilsImpl.cpp
index 7666728..dc49c0c 100644
--- a/xpcom/base/nsMacUtilsImpl.cpp
+++ b/xpcom/base/nsMacUtilsImpl.cpp
@@ -7,9 +7,17 @@
#include "nsMacUtilsImpl.h"
#include <CoreFoundation/CoreFoundation.h>
+#include <sys/sysctl.h>
+
+#include "mozilla/Unused.h"
NS_IMPL_ISUPPORTS(nsMacUtilsImpl, nsIMacUtils)
+using mozilla::Unused;
+
+// Initialize with Unknown until we've checked if TCSM is available to set
+Atomic<nsMacUtilsImpl::TCSMStatus> nsMacUtilsImpl::sTCSMStatus(TCSM_Unknown);
+
nsresult nsMacUtilsImpl::GetArchString(nsAString& aArchString) {
if (!mBinaryArchs.IsEmpty()) {
aArchString.Assign(mBinaryArchs);
@@ -138,3 +146,60 @@ nsMacUtilsImpl::GetIsTranslated(bool* aIsTranslated) {
return NS_OK;
}
+
+/* static */
+bool nsMacUtilsImpl::IsTCSMAvailable() {
+ if (sTCSMStatus == TCSM_Unknown) {
+ uint32_t oldVal = 0;
+ size_t oldValSize = sizeof(oldVal);
+ int rv = sysctlbyname("kern.tcsm_available", &oldVal, &oldValSize, NULL, 0);
+ TCSMStatus newStatus;
+ if (rv < 0 || oldVal == 0) {
+ newStatus = TCSM_Unavailable;
+ } else {
+ newStatus = TCSM_Available;
+ }
+ // The value of sysctl kern.tcsm_available is the same for all
+ // threads within the same process. If another thread raced with us
+ // and initialized sTCSMStatus first (changing it from
+ // TCSM_Unknown), we can continue without needing to update it
+ // again. Hence, we ignore compareExchange's return value.
+ Unused << sTCSMStatus.compareExchange(TCSM_Unknown, newStatus);
+ }
+ return (sTCSMStatus == TCSM_Available);
+}
+
+/* static */
+nsresult nsMacUtilsImpl::EnableTCSM() {
+ uint32_t newVal = 1;
+ int rv = sysctlbyname("kern.tcsm_enable", NULL, 0, &newVal, sizeof(newVal));
+ if (rv < 0) {
+ return NS_ERROR_UNEXPECTED;
+ }
+ return NS_OK;
+}
+
+/*
+ * Intentionally return void so that failures will be ignored in non-debug
+ * builds. This method uses new sysctls which may not be as thoroughly tested
+ * and we don't want to cause crashes handling the failure due to an OS bug.
+ */
+/* static */
+void nsMacUtilsImpl::EnableTCSMIfAvailable() {
+ if (IsTCSMAvailable()) {
+ if (NS_FAILED(EnableTCSM())) {
+ NS_WARNING("Failed to enable TCSM");
+ }
+ MOZ_ASSERT(IsTCSMEnabled());
+ }
+}
+
+#if defined(DEBUG)
+/* static */
+bool nsMacUtilsImpl::IsTCSMEnabled() {
+ uint32_t oldVal = 0;
+ size_t oldValSize = sizeof(oldVal);
+ int rv = sysctlbyname("kern.tcsm_enable", &oldVal, &oldValSize, NULL, 0);
+ return (rv == 0) && (oldVal != 0);
+}
+#endif