summaryrefslogtreecommitdiffstats
path: root/src/VBox/Runtime/r3/darwin
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 14:19:18 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 14:19:18 +0000
commit4035b1bfb1e5843a539a8b624d21952b756974d1 (patch)
treef1e9cd5bf548cbc57ff2fddfb2b4aa9ae95587e2 /src/VBox/Runtime/r3/darwin
parentInitial commit. (diff)
downloadvirtualbox-4035b1bfb1e5843a539a8b624d21952b756974d1.tar.xz
virtualbox-4035b1bfb1e5843a539a8b624d21952b756974d1.zip
Adding upstream version 6.1.22-dfsg.upstream/6.1.22-dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/VBox/Runtime/r3/darwin')
-rw-r--r--src/VBox/Runtime/r3/darwin/Makefile.kup0
-rw-r--r--src/VBox/Runtime/r3/darwin/RTCrStoreCreateSnapshotById-darwin.cpp248
-rw-r--r--src/VBox/Runtime/r3/darwin/RTPathUserDocuments-darwin.cpp99
-rw-r--r--src/VBox/Runtime/r3/darwin/RTSystemQueryDmiString-darwin.cpp153
-rw-r--r--src/VBox/Runtime/r3/darwin/filelock-darwin.cpp168
-rw-r--r--src/VBox/Runtime/r3/darwin/krnlmod-darwin.cpp391
-rw-r--r--src/VBox/Runtime/r3/darwin/mp-darwin.cpp256
-rw-r--r--src/VBox/Runtime/r3/darwin/pathhost-darwin.cpp107
-rw-r--r--src/VBox/Runtime/r3/darwin/rtProcInitExePath-darwin.cpp66
-rw-r--r--src/VBox/Runtime/r3/darwin/sched-darwin.cpp353
-rw-r--r--src/VBox/Runtime/r3/darwin/systemmem-darwin.cpp86
-rw-r--r--src/VBox/Runtime/r3/darwin/time-darwin.cpp115
12 files changed, 2042 insertions, 0 deletions
diff --git a/src/VBox/Runtime/r3/darwin/Makefile.kup b/src/VBox/Runtime/r3/darwin/Makefile.kup
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/VBox/Runtime/r3/darwin/Makefile.kup
diff --git a/src/VBox/Runtime/r3/darwin/RTCrStoreCreateSnapshotById-darwin.cpp b/src/VBox/Runtime/r3/darwin/RTCrStoreCreateSnapshotById-darwin.cpp
new file mode 100644
index 00000000..6b67ec9d
--- /dev/null
+++ b/src/VBox/Runtime/r3/darwin/RTCrStoreCreateSnapshotById-darwin.cpp
@@ -0,0 +1,248 @@
+/* $Id: RTCrStoreCreateSnapshotById-darwin.cpp $ */
+/** @file
+ * IPRT - RTCrStoreCreateSnapshotById, Darwin.
+ */
+
+/*
+ * Copyright (C) 2006-2020 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#include <iprt/crypto/store.h>
+#include "internal/iprt.h"
+
+#include <iprt/assert.h>
+#include <iprt/err.h>
+#include <iprt/file.h>
+
+/* HACK ALERT! Shut up those deprecated messages on SecKeychainSearchCreateFromAttributes and SecKeychainSearchCopyNext. */
+#include <CoreFoundation/CoreFoundation.h>
+#undef DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
+#define DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
+
+#include <Security/Security.h>
+
+
+/**
+ * Checks the trust settings of the certificate.
+ *
+ * @returns true if not out-right distructed, otherwise false.
+ * @param hCert The certificate.
+ * @param enmTrustDomain The trust settings domain to check relative to.
+ */
+static bool rtCrStoreIsDarwinCertTrustworthy(SecCertificateRef hCert, SecTrustSettingsDomain enmTrustDomain)
+{
+ bool fResult = true;
+ CFArrayRef hTrustSettings;
+ OSStatus orc = SecTrustSettingsCopyTrustSettings(hCert, enmTrustDomain, &hTrustSettings);
+ if (orc == noErr)
+ {
+ CFIndex const cTrustSettings = CFArrayGetCount(hTrustSettings);
+ for (CFIndex i = 0; i < cTrustSettings; i++)
+ {
+ CFDictionaryRef hDict = (CFDictionaryRef)CFArrayGetValueAtIndex(hTrustSettings, i);
+ AssertContinue(CFGetTypeID(hDict) == CFDictionaryGetTypeID());
+
+ CFNumberRef hNum = (CFNumberRef)CFDictionaryGetValue(hDict, kSecTrustSettingsResult);
+ if (hNum)
+ {
+ AssertContinue(CFGetTypeID(hNum) == CFNumberGetTypeID());
+ SInt32 iNum;
+ if (CFNumberGetValue(hNum, kCFNumberSInt32Type, &iNum))
+ {
+ if (iNum == kSecTrustSettingsResultDeny)
+ {
+ fResult = false;
+ break;
+ }
+ }
+ /* No need to release hNum (get rule). */
+ }
+ /* No need to release hDict (get rule). */
+ }
+ CFRelease(hTrustSettings);
+ }
+ else if (orc != errSecItemNotFound)
+ {
+ AssertFailed();
+ fResult = false;
+ }
+ return fResult;
+}
+
+
+static int rtCrStoreAddCertsFromNativeKeychain(RTCRSTORE hStore, SecKeychainRef hKeychain, SecTrustSettingsDomain enmTrustDomain,
+ int rc, PRTERRINFO pErrInfo)
+{
+ /*
+ * Enumerate the certificates in the keychain.
+ */
+ SecKeychainSearchRef hSearch;
+ OSStatus orc = SecKeychainSearchCreateFromAttributes(hKeychain, kSecCertificateItemClass, NULL, &hSearch);
+ if (orc == noErr)
+ {
+ SecKeychainItemRef hItem;
+ while ((orc = SecKeychainSearchCopyNext(hSearch, &hItem)) == noErr)
+ {
+ Assert(CFGetTypeID(hItem) == SecCertificateGetTypeID());
+ SecCertificateRef hCert = (SecCertificateRef)hItem;
+
+ /*
+ * Check if the current certificate is at all trusted, skip it if it's isn't.
+ */
+ if (rtCrStoreIsDarwinCertTrustworthy(hCert, enmTrustDomain))
+ {
+ /*
+ * Get the certificate data.
+ */
+ CFDataRef hEncodedCert = SecCertificateCopyData(hCert);
+ Assert(hEncodedCert);
+ if (hEncodedCert)
+ {
+ CFIndex cbEncoded = CFDataGetLength(hEncodedCert);
+ const uint8_t *pbEncoded = CFDataGetBytePtr(hEncodedCert);
+
+ RTERRINFOSTATIC StaticErrInfo;
+ int rc2 = RTCrStoreCertAddEncoded(hStore, RTCRCERTCTX_F_ENC_X509_DER | RTCRCERTCTX_F_ADD_IF_NOT_FOUND,
+ pbEncoded, cbEncoded, RTErrInfoInitStatic(&StaticErrInfo));
+ if (RT_FAILURE(rc2))
+ {
+ if (RTErrInfoIsSet(&StaticErrInfo.Core))
+ RTErrInfoAddF(pErrInfo, -rc2, " %s", StaticErrInfo.Core.pszMsg);
+ else
+ RTErrInfoAddF(pErrInfo, -rc2, " %Rrc adding cert", rc2);
+ rc = -rc2;
+ }
+
+ CFRelease(hEncodedCert);
+ }
+ }
+
+ CFRelease(hItem);
+ }
+ if (orc != errSecItemNotFound)
+ rc = RTErrInfoAddF(pErrInfo, -VERR_SEARCH_ERROR,
+ " SecKeychainSearchCopyNext failed with %#x", orc);
+ CFRelease(hSearch);
+ }
+ else
+ rc = RTErrInfoAddF(pErrInfo, -VERR_SEARCH_ERROR,
+ " SecKeychainSearchCreateFromAttributes failed with %#x", orc);
+ return rc;
+}
+
+
+static int rtCrStoreAddCertsFromNativeKeychainFile(RTCRSTORE hStore, const char *pszKeychain,
+ SecTrustSettingsDomain enmTrustDomain,
+ int rc, PRTERRINFO pErrInfo)
+{
+ /*
+ * Open the keychain and call common worker to do the job.
+ */
+ SecKeychainRef hKeychain;
+ OSStatus orc = SecKeychainOpen(pszKeychain, &hKeychain);
+ if (orc == noErr)
+ {
+ rc = rtCrStoreAddCertsFromNativeKeychain(hStore, hKeychain, enmTrustDomain, rc, pErrInfo);
+
+ CFRelease(hKeychain);
+ }
+ else if (RTFileExists(pszKeychain))
+ rc = RTErrInfoAddF(pErrInfo, -VERR_OPEN_FAILED, " SecKeychainOpen failed with %#x on '%s'", orc, pszKeychain);
+ return rc;
+}
+
+
+static int rtCrStoreAddCertsFromNativeKeystoreDomain(RTCRSTORE hStore, SecPreferencesDomain enmDomain,
+ SecTrustSettingsDomain enmTrustDomain,
+ int rc, PRTERRINFO pErrInfo)
+{
+ /*
+ * Get a list of keystores for this domain and call common worker on each.
+ */
+ CFArrayRef hKeychains;
+ OSStatus orc = SecKeychainCopyDomainSearchList(enmDomain, &hKeychains);
+ if (orc == noErr)
+ {
+ CFIndex const cEntries = CFArrayGetCount(hKeychains);
+ for (CFIndex i = 0; i < cEntries; i++)
+ {
+ SecKeychainRef hKeychain = (SecKeychainRef)CFArrayGetValueAtIndex(hKeychains, i);
+ Assert(CFGetTypeID(hKeychain) == SecKeychainGetTypeID());
+ CFRetain(hKeychain);
+
+ rc = rtCrStoreAddCertsFromNativeKeychain(hStore, hKeychain, enmTrustDomain, rc, pErrInfo);
+
+ CFRelease(hKeychain);
+ }
+
+ CFRelease(hKeychains);
+ }
+ else
+ rc = RTErrInfoAddF(pErrInfo, -VERR_SEARCH_ERROR,
+ " SecKeychainCopyDomainSearchList failed with %#x on %d", orc, enmDomain);
+ return rc;
+}
+
+
+RTDECL(int) RTCrStoreCreateSnapshotById(PRTCRSTORE phStore, RTCRSTOREID enmStoreId, PRTERRINFO pErrInfo)
+{
+ AssertReturn(enmStoreId > RTCRSTOREID_INVALID && enmStoreId < RTCRSTOREID_END, VERR_INVALID_PARAMETER);
+
+ /*
+ * Create an empty in-memory store.
+ */
+ RTCRSTORE hStore;
+ int rc = RTCrStoreCreateInMem(&hStore, 128);
+ if (RT_SUCCESS(rc))
+ {
+ *phStore = hStore;
+
+ /*
+ * Load the certificates corresponding to the given virtual store ID.
+ */
+ switch (enmStoreId)
+ {
+ case RTCRSTOREID_USER_TRUSTED_CAS_AND_CERTIFICATES:
+ rc = rtCrStoreAddCertsFromNativeKeystoreDomain(hStore, kSecPreferencesDomainUser,
+ kSecTrustSettingsDomainUser, rc, pErrInfo);
+ break;
+
+ case RTCRSTOREID_SYSTEM_TRUSTED_CAS_AND_CERTIFICATES:
+ rc = rtCrStoreAddCertsFromNativeKeystoreDomain(hStore, kSecPreferencesDomainSystem,
+ kSecTrustSettingsDomainSystem, rc, pErrInfo);
+ rc = rtCrStoreAddCertsFromNativeKeychainFile(hStore,
+ "/System/Library/Keychains/SystemRootCertificates.keychain",
+ kSecTrustSettingsDomainSystem, rc, pErrInfo);
+ break;
+
+ default:
+ AssertFailed(); /* implement me */
+ }
+ }
+ else
+ RTErrInfoSet(pErrInfo, rc, "RTCrStoreCreateInMem failed");
+ return rc;
+}
+RT_EXPORT_SYMBOL(RTCrStoreCreateSnapshotById);
+
diff --git a/src/VBox/Runtime/r3/darwin/RTPathUserDocuments-darwin.cpp b/src/VBox/Runtime/r3/darwin/RTPathUserDocuments-darwin.cpp
new file mode 100644
index 00000000..44695df6
--- /dev/null
+++ b/src/VBox/Runtime/r3/darwin/RTPathUserDocuments-darwin.cpp
@@ -0,0 +1,99 @@
+/* $Id: RTPathUserDocuments-darwin.cpp $ */
+/** @file
+ * IPRT - RTPathUserDocuments, darwin ring-3.
+ */
+
+/*
+ * Copyright (C) 2011-2020 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#include <iprt/path.h>
+#include "internal/iprt.h"
+
+#include <iprt/assert.h>
+#include <iprt/string.h>
+#include <iprt/err.h>
+
+#include <NSSystemDirectories.h>
+#include <sys/syslimits.h>
+#ifdef IPRT_USE_CORE_SERVICE_FOR_USER_DOCUMENTS
+# include <CoreServices/CoreServices.h>
+#endif
+
+
+RTDECL(int) RTPathUserDocuments(char *pszPath, size_t cchPath)
+{
+ /*
+ * Validate input
+ */
+ AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
+ AssertReturn(cchPath, VERR_INVALID_PARAMETER);
+
+ /*
+ * Try NSSystemDirectories first since that works for directories that doesn't exist.
+ */
+ int rc = VERR_PATH_NOT_FOUND;
+ NSSearchPathEnumerationState EnmState = NSStartSearchPathEnumeration(NSDocumentDirectory, NSUserDomainMask);
+ if (EnmState != 0)
+ {
+ char szTmp[PATH_MAX];
+ szTmp[0] = szTmp[PATH_MAX - 1] = '\0';
+ EnmState = NSGetNextSearchPathEnumeration(EnmState, szTmp);
+ if (EnmState != 0)
+ {
+ size_t cchTmp = strlen(szTmp);
+ if (cchTmp >= cchPath)
+ return VERR_BUFFER_OVERFLOW;
+
+ if (szTmp[0] == '~' && szTmp[1] == '/')
+ {
+ /* Expand tilde. */
+ rc = RTPathUserHome(pszPath, cchPath - cchTmp + 2);
+ if (RT_FAILURE(rc))
+ return rc;
+ rc = RTPathAppend(pszPath, cchPath, &szTmp[2]);
+ }
+ else
+ rc = RTStrCopy(pszPath, cchPath, szTmp);
+ return rc;
+ }
+ }
+
+#ifdef IPRT_USE_CORE_SERVICE_FOR_USER_DOCUMENTS
+ /*
+ * Fall back on FSFindFolder in case the above should fail...
+ */
+ FSRef ref;
+ OSErr err = FSFindFolder(kOnAppropriateDisk, kDocumentsFolderType, false /* createFolder */, &ref);
+ if (err == noErr)
+ {
+ err = FSRefMakePath(&ref, (UInt8*)pszPath, cchPath);
+ if (err == noErr)
+ return VINF_SUCCESS;
+ }
+#endif
+ Assert(RT_FAILURE_NP(rc));
+ return rc;
+}
+
diff --git a/src/VBox/Runtime/r3/darwin/RTSystemQueryDmiString-darwin.cpp b/src/VBox/Runtime/r3/darwin/RTSystemQueryDmiString-darwin.cpp
new file mode 100644
index 00000000..f8d0a71f
--- /dev/null
+++ b/src/VBox/Runtime/r3/darwin/RTSystemQueryDmiString-darwin.cpp
@@ -0,0 +1,153 @@
+/* $Id: RTSystemQueryDmiString-darwin.cpp $ */
+/** @file
+ * IPRT - RTSystemQueryDmiString, darwin ring-3.
+ */
+
+/*
+ * Copyright (C) 2010-2020 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#include <iprt/system.h>
+#include "internal/iprt.h"
+
+#include <iprt/assert.h>
+#include <iprt/err.h>
+#include <iprt/mem.h>
+#include <iprt/string.h>
+
+#include <mach/mach_port.h>
+#include <IOKit/IOKitLib.h>
+
+
+/*********************************************************************************************************************************
+* Defined Constants And Macros *
+*********************************************************************************************************************************/
+#define IOCLASS_PLATFORMEXPERTDEVICE "IOPlatformExpertDevice"
+#define PROP_PRODUCT_NAME "product-name"
+#define PROP_PRODUCT_VERSION "version"
+#define PROP_PRODUCT_SERIAL "IOPlatformSerialNumber"
+#define PROP_PRODUCT_UUID "IOPlatformUUID"
+#define PROP_MANUFACTURER "manufacturer"
+
+
+RTDECL(int) RTSystemQueryDmiString(RTSYSDMISTR enmString, char *pszBuf, size_t cbBuf)
+{
+ AssertPtrReturn(pszBuf, VERR_INVALID_POINTER);
+ AssertReturn(cbBuf > 0, VERR_INVALID_PARAMETER);
+ *pszBuf = '\0';
+ AssertReturn(enmString > RTSYSDMISTR_INVALID && enmString < RTSYSDMISTR_END, VERR_INVALID_PARAMETER);
+
+ CFStringRef PropStringRef = NULL;
+ switch (enmString)
+ {
+ case RTSYSDMISTR_PRODUCT_NAME: PropStringRef = CFSTR(PROP_PRODUCT_NAME); break;
+ case RTSYSDMISTR_PRODUCT_VERSION: PropStringRef = CFSTR(PROP_PRODUCT_VERSION); break;
+ case RTSYSDMISTR_PRODUCT_SERIAL: PropStringRef = CFSTR(PROP_PRODUCT_SERIAL); break;
+ case RTSYSDMISTR_PRODUCT_UUID: PropStringRef = CFSTR(PROP_PRODUCT_UUID); break;
+ case RTSYSDMISTR_MANUFACTURER: PropStringRef = CFSTR(PROP_MANUFACTURER); break;
+ default:
+ return VERR_NOT_SUPPORTED;
+ }
+
+ mach_port_t MasterPort;
+ kern_return_t kr = IOMasterPort(MACH_PORT_NULL, &MasterPort);
+ if (kr != kIOReturnSuccess)
+ {
+ if (kr == KERN_NO_ACCESS)
+ return VERR_ACCESS_DENIED;
+ return RTErrConvertFromDarwinIO(kr);
+ }
+
+ CFDictionaryRef ClassToMatch = IOServiceMatching(IOCLASS_PLATFORMEXPERTDEVICE);
+ if (!ClassToMatch)
+ return VERR_NOT_SUPPORTED;
+
+ /* IOServiceGetMatchingServices will always consume ClassToMatch. */
+ io_iterator_t Iterator;
+ kr = IOServiceGetMatchingServices(MasterPort, ClassToMatch, &Iterator);
+ if (kr != kIOReturnSuccess)
+ return RTErrConvertFromDarwinIO(kr);
+
+ int rc = VERR_NOT_SUPPORTED;
+ io_service_t ServiceObject;
+ while ((ServiceObject = IOIteratorNext(Iterator)))
+ {
+ if ( enmString == RTSYSDMISTR_PRODUCT_NAME
+ || enmString == RTSYSDMISTR_PRODUCT_VERSION
+ || enmString == RTSYSDMISTR_MANUFACTURER
+ )
+ {
+ CFDataRef DataRef = (CFDataRef)IORegistryEntryCreateCFProperty(ServiceObject, PropStringRef,
+ kCFAllocatorDefault, kNilOptions);
+ if (DataRef)
+ {
+ size_t cbData = CFDataGetLength(DataRef);
+ const char *pchData = (const char *)CFDataGetBytePtr(DataRef);
+ rc = RTStrCopyEx(pszBuf, cbBuf, pchData, cbData);
+ CFRelease(DataRef);
+ break;
+ }
+ }
+ else
+ {
+ CFStringRef StringRef = (CFStringRef)IORegistryEntryCreateCFProperty(ServiceObject, PropStringRef,
+ kCFAllocatorDefault, kNilOptions);
+ if (StringRef)
+ {
+ Boolean fRc = CFStringGetCString(StringRef, pszBuf, cbBuf, kCFStringEncodingUTF8);
+ if (fRc)
+ rc = VINF_SUCCESS;
+ else
+ {
+ CFIndex cwc = CFStringGetLength(StringRef);
+ size_t cbTmp = cwc + 1;
+ char *pszTmp = (char *)RTMemTmpAlloc(cbTmp);
+ int cTries = 1;
+ while ( pszTmp
+ && (fRc = CFStringGetCString(StringRef, pszTmp, cbTmp, kCFStringEncodingUTF8)) == FALSE
+ && cTries++ < 4)
+ {
+ RTMemTmpFree(pszTmp);
+ cbTmp *= 2;
+ pszTmp = (char *)RTMemTmpAlloc(cbTmp);
+ }
+ if (fRc)
+ rc = RTStrCopy(pszBuf, cbBuf, pszTmp);
+ else if (!pszTmp)
+ rc = VERR_NO_TMP_MEMORY;
+ else
+ rc = VERR_ACCESS_DENIED;
+ RTMemFree(pszTmp);
+ }
+ CFRelease(StringRef);
+ break;
+ }
+ }
+ }
+
+ IOObjectRelease(ServiceObject);
+ IOObjectRelease(Iterator);
+ return rc;
+}
+
diff --git a/src/VBox/Runtime/r3/darwin/filelock-darwin.cpp b/src/VBox/Runtime/r3/darwin/filelock-darwin.cpp
new file mode 100644
index 00000000..0d92d6a5
--- /dev/null
+++ b/src/VBox/Runtime/r3/darwin/filelock-darwin.cpp
@@ -0,0 +1,168 @@
+/* $Id: filelock-darwin.cpp $ */
+/** @file
+ * IPRT - File Locking, POSIX.
+ */
+
+/*
+ * Copyright (C) 2006-2020 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#define LOG_GROUP RTLOGGROUP_FILE
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/fcntl.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/time.h>
+
+#include <iprt/file.h>
+#include <iprt/assert.h>
+#include <iprt/string.h>
+#include <iprt/err.h>
+#include <iprt/log.h>
+#include "internal/file.h"
+#include "internal/fs.h"
+
+
+
+
+RTR3DECL(int) RTFileLock(RTFILE hFile, unsigned fLock, int64_t offLock, uint64_t cbLock)
+{
+ Assert(offLock >= 0);
+
+ /* Check arguments. */
+ if (fLock & ~RTFILE_LOCK_MASK)
+ {
+ AssertMsgFailed(("Invalid fLock=%08X\n", fLock));
+ return VERR_INVALID_PARAMETER;
+ }
+
+ /*
+ * Validate offset.
+ */
+ if ( sizeof(off_t) < sizeof(cbLock)
+ && ( (offLock >> 32) != 0
+ || (cbLock >> 32) != 0
+ || ((offLock + cbLock) >> 32) != 0))
+ {
+ AssertMsgFailed(("64-bit file i/o not supported! offLock=%lld cbLock=%lld\n", offLock, cbLock));
+ return VERR_NOT_SUPPORTED;
+ }
+
+ /* Prepare flock structure. */
+ struct flock fl;
+ Assert(RTFILE_LOCK_WRITE);
+ fl.l_type = (fLock & RTFILE_LOCK_WRITE) ? F_WRLCK : F_RDLCK;
+ fl.l_whence = SEEK_SET;
+ fl.l_start = (off_t)offLock;
+ fl.l_len = (off_t)cbLock;
+ fl.l_pid = 0;
+
+ Assert(RTFILE_LOCK_WAIT);
+ if (fcntl(RTFileToNative(hFile), (fLock & RTFILE_LOCK_WAIT) ? F_SETLKW : F_SETLK, &fl) >= 0)
+ return VINF_SUCCESS;
+ int iErr = errno;
+ if (iErr == ENOTSUP)
+ {
+ /*
+ * This is really bad hack for getting VDIs to work somewhat
+ * safely on SMB mounts.
+ */
+ /** @todo we need to keep track of these locks really. Anyone requiring to lock more
+ * than one part of a file will have to fix this. */
+ unsigned f = 0;
+ Assert(RTFILE_LOCK_WAIT);
+ if (fLock & RTFILE_LOCK_WAIT)
+ f |= LOCK_NB;
+ if (fLock & RTFILE_LOCK_WRITE)
+ f |= LOCK_EX;
+ else
+ f |= LOCK_SH;
+ if (!flock(RTFileToNative(hFile), f))
+ return VINF_SUCCESS;
+ iErr = errno;
+ if (iErr == EWOULDBLOCK)
+ return VERR_FILE_LOCK_VIOLATION;
+ }
+
+ if ( iErr == EAGAIN
+ || iErr == EACCES)
+ return VERR_FILE_LOCK_VIOLATION;
+
+ return RTErrConvertFromErrno(iErr);
+}
+
+
+RTR3DECL(int) RTFileChangeLock(RTFILE hFile, unsigned fLock, int64_t offLock, uint64_t cbLock)
+{
+ /** @todo We never returns VERR_FILE_NOT_LOCKED for now. */
+ return RTFileLock(hFile, fLock, offLock, cbLock);
+}
+
+
+RTR3DECL(int) RTFileUnlock(RTFILE hFile, int64_t offLock, uint64_t cbLock)
+{
+ Assert(offLock >= 0);
+
+ /*
+ * Validate offset.
+ */
+ if ( sizeof(off_t) < sizeof(cbLock)
+ && ( (offLock >> 32) != 0
+ || (cbLock >> 32) != 0
+ || ((offLock + cbLock) >> 32) != 0))
+ {
+ AssertMsgFailed(("64-bit file i/o not supported! offLock=%lld cbLock=%lld\n", offLock, cbLock));
+ return VERR_NOT_SUPPORTED;
+ }
+
+ /* Prepare flock structure. */
+ struct flock fl;
+ fl.l_type = F_UNLCK;
+ fl.l_whence = SEEK_SET;
+ fl.l_start = (off_t)offLock;
+ fl.l_len = (off_t)cbLock;
+ fl.l_pid = 0;
+
+ if (fcntl(RTFileToNative(hFile), F_SETLK, &fl) >= 0)
+ return VINF_SUCCESS;
+
+ int iErr = errno;
+ if (iErr == ENOTSUP)
+ {
+ /* A SMB hack, see RTFileLock. */
+ if (!flock(RTFileToNative(hFile), LOCK_UN))
+ return VINF_SUCCESS;
+ }
+
+ /** @todo check error codes for non existing lock. */
+ if ( iErr == EAGAIN
+ || iErr == EACCES)
+ return VERR_FILE_LOCK_VIOLATION;
+
+ return RTErrConvertFromErrno(iErr);
+}
+
diff --git a/src/VBox/Runtime/r3/darwin/krnlmod-darwin.cpp b/src/VBox/Runtime/r3/darwin/krnlmod-darwin.cpp
new file mode 100644
index 00000000..1aa3f739
--- /dev/null
+++ b/src/VBox/Runtime/r3/darwin/krnlmod-darwin.cpp
@@ -0,0 +1,391 @@
+/* $Id: krnlmod-darwin.cpp $ */
+/** @file
+ * IPRT - Kernel module, Darwin.
+ */
+
+/*
+ * Copyright (C) 2017-2020 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#define LOG_GROUP RTLOGGROUP_SYSTEM
+#include <iprt/krnlmod.h>
+
+#include <iprt/asm.h>
+#include <iprt/assert.h>
+#include <iprt/errcore.h>
+#include <iprt/ldr.h>
+#include <iprt/mem.h>
+#include <iprt/once.h>
+#include <iprt/string.h>
+#include <iprt/types.h>
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <IOKit/IOKitLib.h>
+
+
+/** @name Missing/private IOKitLib declarations and definitions.
+ * @{ */
+/** OSKextCopyLoadedKextInfo in IOKit. */
+typedef CFDictionaryRef (* PFNOSKEXTCOPYLOADEDKEXTINFO)(CFArrayRef, CFArrayRef);
+
+#ifndef kOSBundleRetainCountKey
+# define kOSBundleRetainCountKey CFSTR("OSBundleRetainCount")
+#endif
+#ifndef kOSBundleLoadSizeKey
+# define kOSBundleLoadSizeKey CFSTR("OSBundleLoadSize")
+#endif
+#ifndef kOSBundleLoadAddressKey
+# define kOSBundleLoadAddressKey CFSTR("OSBundleLoadAddress")
+#endif
+/** @} */
+
+
+/*********************************************************************************************************************************
+* Structures and Typedefs *
+*********************************************************************************************************************************/
+/**
+ * Internal kernel information record state.
+ */
+typedef struct RTKRNLMODINFOINT
+{
+ /** Reference counter. */
+ volatile uint32_t cRefs;
+ /** The dictionary containing our data. */
+ CFDictionaryRef hDictKext;
+} RTKRNLMODINFOINT;
+/** Pointer to the internal kernel module information record. */
+typedef RTKRNLMODINFOINT *PRTKRNLMODINFOINT;
+/** Pointer to a const internal kernel module information record. */
+typedef const RTKRNLMODINFOINT *PCRTKRNLMODINFOINT;
+
+
+/*********************************************************************************************************************************
+* Global Variables *
+*********************************************************************************************************************************/
+static RTONCE g_GetIoKitApisOnce = RTONCE_INITIALIZER;
+static PFNOSKEXTCOPYLOADEDKEXTINFO g_pfnOSKextCopyLoadedKextInfo = NULL;
+
+/** Do-once callback for setting g_pfnOSKextCopyLoadedKextInfo. */
+static DECLCALLBACK(int) rtKrnlModDarwinResolveIoKitApis(void *pvUser)
+{
+ RTLDRMOD hMod;
+// int rc = RTLdrLoad("/System/Library/Frameworks/IOKit.framework/Versions/Current/IOKit", &hMod);
+ int rc = RTLdrLoadEx("/System/Library/Frameworks/IOKit.framework/Versions/Current/IOKit", &hMod, RTLDRLOAD_FLAGS_NO_SUFFIX, NULL);
+ if (RT_SUCCESS(rc))
+ RTLdrGetSymbol(hMod, "OSKextCopyLoadedKextInfo", (void **)&g_pfnOSKextCopyLoadedKextInfo);
+
+ RT_NOREF(pvUser);
+ return VINF_SUCCESS;
+}
+
+/**
+ * Returns the kext information dictionary structure matching the given name.
+ *
+ * @returns Pointer to the matching module information record on success or NULL if not found.
+ * @param pszName The name to look for.
+ */
+static CFDictionaryRef rtKrnlModDarwinGetKextInfoByName(const char *pszName)
+{
+ CFDictionaryRef hDictKext = NULL;
+
+ RTOnce(&g_GetIoKitApisOnce, rtKrnlModDarwinResolveIoKitApis, NULL);
+ if (g_pfnOSKextCopyLoadedKextInfo)
+ {
+ CFStringRef hKextName = CFStringCreateWithCString(kCFAllocatorDefault, pszName, kCFStringEncodingUTF8);
+ if (hKextName)
+ {
+ CFArrayRef hArrKextIdRef = CFArrayCreate(kCFAllocatorDefault, (const void **)&hKextName, 1, &kCFTypeArrayCallBacks);
+ if (hArrKextIdRef)
+ {
+ CFDictionaryRef hLoadedKexts = g_pfnOSKextCopyLoadedKextInfo(hArrKextIdRef, NULL /* all info */);
+ if (hLoadedKexts)
+ {
+ if (CFDictionaryGetCount(hLoadedKexts) > 0)
+ {
+ hDictKext = (CFDictionaryRef)CFDictionaryGetValue(hLoadedKexts, hKextName);
+ CFRetain(hDictKext);
+ }
+
+ CFRelease(hLoadedKexts);
+ }
+ CFRelease(hArrKextIdRef);
+ }
+ CFRelease(hKextName);
+ }
+ }
+
+ return hDictKext;
+}
+
+/**
+ * Destroy the given kernel module information record.
+ *
+ * @returns nothing.
+ * @param pThis The record to destroy.
+ */
+static void rtKrnlModInfoDestroy(PRTKRNLMODINFOINT pThis)
+{
+ CFRelease(pThis->hDictKext);
+ RTMemFree(pThis);
+}
+
+
+RTDECL(int) RTKrnlModQueryLoaded(const char *pszName, bool *pfLoaded)
+{
+ AssertPtrReturn(pszName, VERR_INVALID_POINTER);
+ AssertPtrReturn(pfLoaded, VERR_INVALID_POINTER);
+
+ CFDictionaryRef hDictKext = rtKrnlModDarwinGetKextInfoByName(pszName);
+ *pfLoaded = hDictKext != NULL;
+ if (hDictKext)
+ CFRelease(hDictKext);
+
+ return VINF_SUCCESS;
+}
+
+
+RTDECL(int) RTKrnlModLoadedQueryInfo(const char *pszName, PRTKRNLMODINFO phKrnlModInfo)
+{
+ AssertPtrReturn(pszName, VERR_INVALID_POINTER);
+ AssertPtrReturn(phKrnlModInfo, VERR_INVALID_POINTER);
+
+ int rc = VINF_SUCCESS;
+ CFDictionaryRef hDictKext = rtKrnlModDarwinGetKextInfoByName(pszName);
+ if (hDictKext)
+ {
+ PRTKRNLMODINFOINT pThis = (PRTKRNLMODINFOINT)RTMemAllocZ(sizeof(RTKRNLMODINFOINT));
+ if (pThis)
+ {
+ pThis->cRefs = 1;
+ pThis->hDictKext = hDictKext;
+
+ *phKrnlModInfo = pThis;
+ }
+ else
+ rc = VERR_NO_MEMORY;
+ }
+ else
+ rc = VERR_NOT_FOUND;
+
+ return rc;
+}
+
+
+RTDECL(uint32_t) RTKrnlModLoadedGetCount(void)
+{
+ uint32_t cLoadedKexts = 0;
+ RTOnce(&g_GetIoKitApisOnce, rtKrnlModDarwinResolveIoKitApis, NULL);
+ if (g_pfnOSKextCopyLoadedKextInfo)
+ {
+ CFDictionaryRef hLoadedKexts = g_pfnOSKextCopyLoadedKextInfo(NULL, NULL /* all info */);
+ if (hLoadedKexts)
+ {
+ cLoadedKexts = CFDictionaryGetCount(hLoadedKexts);
+ CFRelease(hLoadedKexts);
+ }
+ }
+
+ return cLoadedKexts;
+}
+
+
+RTDECL(int) RTKrnlModLoadedQueryInfoAll(PRTKRNLMODINFO pahKrnlModInfo, uint32_t cEntriesMax,
+ uint32_t *pcEntries)
+{
+ AssertReturn(VALID_PTR(pahKrnlModInfo) || cEntriesMax == 0, VERR_INVALID_PARAMETER);
+
+ int rc = VINF_SUCCESS;
+ RTOnce(&g_GetIoKitApisOnce, rtKrnlModDarwinResolveIoKitApis, NULL);
+ if (g_pfnOSKextCopyLoadedKextInfo)
+ {
+ CFDictionaryRef hLoadedKexts = g_pfnOSKextCopyLoadedKextInfo(NULL, NULL /* all info */);
+ if (hLoadedKexts)
+ {
+ uint32_t cLoadedKexts = CFDictionaryGetCount(hLoadedKexts);
+ if (cLoadedKexts <= cEntriesMax)
+ {
+ CFDictionaryRef *pahDictKext = (CFDictionaryRef *)RTMemTmpAllocZ(cLoadedKexts * sizeof(CFDictionaryRef));
+ if (pahDictKext)
+ {
+ CFDictionaryGetKeysAndValues(hLoadedKexts, NULL, (const void **)pahDictKext);
+ for (uint32_t i = 0; i < cLoadedKexts; i++)
+ {
+ PRTKRNLMODINFOINT pThis = (PRTKRNLMODINFOINT)RTMemAllocZ(sizeof(RTKRNLMODINFOINT));
+ if (RT_LIKELY(pThis))
+ {
+ pThis->cRefs = 1;
+ pThis->hDictKext = pahDictKext[i];
+ CFRetain(pThis->hDictKext);
+ pahKrnlModInfo[i] = pThis;
+ }
+ else
+ {
+ rc = VERR_NO_MEMORY;
+ /* Rollback. */
+ while (i-- > 0)
+ {
+ CFRelease(pahKrnlModInfo[i]->hDictKext);
+ RTMemFree(pahKrnlModInfo[i]);
+ }
+ }
+ }
+
+ if ( RT_SUCCESS(rc)
+ && pcEntries)
+ *pcEntries = cLoadedKexts;
+
+ RTMemTmpFree(pahDictKext);
+ }
+ else
+ rc = VERR_NO_MEMORY;
+ }
+ else
+ {
+ rc = VERR_BUFFER_OVERFLOW;
+
+ if (pcEntries)
+ *pcEntries = cLoadedKexts;
+ }
+
+ CFRelease(hLoadedKexts);
+ }
+ else
+ rc = VERR_NOT_SUPPORTED;
+ }
+ else
+ rc = VERR_NOT_SUPPORTED;
+
+ return rc;
+}
+
+
+RTDECL(uint32_t) RTKrnlModInfoRetain(RTKRNLMODINFO hKrnlModInfo)
+{
+ PRTKRNLMODINFOINT pThis = hKrnlModInfo;
+ AssertPtrReturn(pThis, UINT32_MAX);
+
+ uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
+ AssertMsg(cRefs > 1 && cRefs < _1M, ("%#x %p\n", cRefs, pThis));
+ return cRefs;
+}
+
+
+RTDECL(uint32_t) RTKrnlModInfoRelease(RTKRNLMODINFO hKrnlModInfo)
+{
+ PRTKRNLMODINFOINT pThis = hKrnlModInfo;
+ if (!pThis)
+ return 0;
+ AssertPtrReturn(pThis, UINT32_MAX);
+
+ uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs);
+ AssertMsg(cRefs < _1M, ("%#x %p\n", cRefs, pThis));
+ if (cRefs == 0)
+ rtKrnlModInfoDestroy(pThis);
+ return cRefs;
+}
+
+
+RTDECL(uint32_t) RTKrnlModInfoGetRefCnt(RTKRNLMODINFO hKrnlModInfo)
+{
+ PRTKRNLMODINFOINT pThis = hKrnlModInfo;
+ AssertPtrReturn(pThis, 0);
+
+ uint32_t cRefCnt = 0;
+ CFNumberRef hRetainCnt = (CFNumberRef)CFDictionaryGetValue(pThis->hDictKext,
+ kOSBundleRetainCountKey);
+ if (hRetainCnt)
+ CFNumberGetValue(hRetainCnt, kCFNumberSInt32Type, &cRefCnt);
+
+ return cRefCnt;
+}
+
+
+RTDECL(const char *) RTKrnlModInfoGetName(RTKRNLMODINFO hKrnlModInfo)
+{
+ PRTKRNLMODINFOINT pThis = hKrnlModInfo;
+ AssertPtrReturn(pThis, NULL);
+
+ const char *pszName = NULL;
+ CFStringRef hBundleId = (CFStringRef)CFDictionaryGetValue(pThis->hDictKext,
+ kCFBundleIdentifierKey);
+ if (hBundleId)
+ pszName = CFStringGetCStringPtr(hBundleId, kCFStringEncodingUTF8);
+
+ return pszName;
+}
+
+
+RTDECL(const char *) RTKrnlModInfoGetFilePath(RTKRNLMODINFO hKrnlModInfo)
+{
+ PRTKRNLMODINFOINT pThis = hKrnlModInfo;
+ AssertPtrReturn(pThis, NULL);
+
+ return NULL;
+}
+
+
+RTDECL(size_t) RTKrnlModInfoGetSize(RTKRNLMODINFO hKrnlModInfo)
+{
+ PRTKRNLMODINFOINT pThis = hKrnlModInfo;
+ AssertPtrReturn(pThis, 0);
+
+ size_t cbKrnlMod = 0;
+ CFNumberRef hKrnlModSize = (CFNumberRef)CFDictionaryGetValue(pThis->hDictKext,
+ kOSBundleLoadSizeKey);
+ if (hKrnlModSize)
+ {
+ uint32_t cbTmp = 0;
+ CFNumberGetValue(hKrnlModSize, kCFNumberSInt32Type, &cbTmp);
+ cbKrnlMod = cbTmp;
+ }
+
+ return cbKrnlMod;
+}
+
+
+RTDECL(RTR0UINTPTR) RTKrnlModInfoGetLoadAddr(RTKRNLMODINFO hKrnlModInfo)
+{
+ PRTKRNLMODINFOINT pThis = hKrnlModInfo;
+ AssertPtrReturn(pThis, 0);
+
+ RTR0UINTPTR uKrnlModLoadAddr = 0;
+ CFNumberRef hKrnlModLoadAddr = (CFNumberRef)CFDictionaryGetValue(pThis->hDictKext,
+ kOSBundleLoadAddressKey);
+ if (hKrnlModLoadAddr)
+ {
+ uint64_t uAddrTmp = 0;
+ CFNumberGetValue(hKrnlModLoadAddr, kCFNumberSInt64Type, &uAddrTmp);
+ uKrnlModLoadAddr = uAddrTmp;
+ }
+
+ return uKrnlModLoadAddr;
+}
+
+
+RTDECL(int) RTKrnlModInfoQueryRefModInfo(RTKRNLMODINFO hKrnlModInfo, uint32_t idx,
+ PRTKRNLMODINFO phKrnlModInfoRef)
+{
+ RT_NOREF3(hKrnlModInfo, idx, phKrnlModInfoRef);
+ return VERR_NOT_IMPLEMENTED;
+}
diff --git a/src/VBox/Runtime/r3/darwin/mp-darwin.cpp b/src/VBox/Runtime/r3/darwin/mp-darwin.cpp
new file mode 100644
index 00000000..33d9b623
--- /dev/null
+++ b/src/VBox/Runtime/r3/darwin/mp-darwin.cpp
@@ -0,0 +1,256 @@
+/* $Id: mp-darwin.cpp $ */
+/** @file
+ * IPRT - Multiprocessor, Darwin.
+ */
+
+/*
+ * Copyright (C) 2006-2020 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#define LOG_GROUP RTLOGGROUP_SYSTEM
+#include <iprt/types.h>
+
+#include <unistd.h>
+#include <stdio.h>
+#include <sys/sysctl.h>
+#include <sys/stat.h>
+#include <sys/fcntl.h>
+#include <errno.h>
+#include <mach/mach.h>
+
+#include <iprt/mp.h>
+#include <iprt/cpuset.h>
+#include <iprt/assert.h>
+#include <iprt/string.h>
+
+
+/**
+ * Internal worker that determines the max possible logical CPU count (hyperthreads).
+ *
+ * @returns Max cpus.
+ */
+static RTCPUID rtMpDarwinMaxLogicalCpus(void)
+{
+ int cCpus = -1;
+ size_t cb = sizeof(cCpus);
+ int rc = sysctlbyname("hw.logicalcpu_max", &cCpus, &cb, NULL, 0);
+ if (rc != -1 && cCpus >= 1)
+ return cCpus;
+ AssertFailed();
+ return 1;
+}
+
+/**
+ * Internal worker that determines the max possible physical core count.
+ *
+ * @returns Max cpus.
+ */
+static RTCPUID rtMpDarwinMaxPhysicalCpus(void)
+{
+ int cCpus = -1;
+ size_t cb = sizeof(cCpus);
+ int rc = sysctlbyname("hw.physicalcpu_max", &cCpus, &cb, NULL, 0);
+ if (rc != -1 && cCpus >= 1)
+ return cCpus;
+ AssertFailed();
+ return 1;
+}
+
+
+#if 0 /* unused */
+/**
+ * Internal worker that determines the current number of logical CPUs (hyperthreads).
+ *
+ * @returns Max cpus.
+ */
+static RTCPUID rtMpDarwinOnlineLogicalCpus(void)
+{
+ int cCpus = -1;
+ size_t cb = sizeof(cCpus);
+ int rc = sysctlbyname("hw.logicalcpu", &cCpus, &cb, NULL, 0);
+ if (rc != -1 && cCpus >= 1)
+ return cCpus;
+ AssertFailed();
+ return 1;
+}
+#endif /* unused */
+
+
+/**
+ * Internal worker that determines the current number of physical CPUs.
+ *
+ * @returns Max cpus.
+ */
+static RTCPUID rtMpDarwinOnlinePhysicalCpus(void)
+{
+ int cCpus = -1;
+ size_t cb = sizeof(cCpus);
+ int rc = sysctlbyname("hw.physicalcpu", &cCpus, &cb, NULL, 0);
+ if (rc != -1 && cCpus >= 1)
+ return cCpus;
+ AssertFailed();
+ return 1;
+}
+
+
+/** @todo RTmpCpuId(). */
+
+RTDECL(int) RTMpCpuIdToSetIndex(RTCPUID idCpu)
+{
+ return idCpu < RTCPUSET_MAX_CPUS && idCpu < rtMpDarwinMaxLogicalCpus() ? idCpu : -1;
+}
+
+
+RTDECL(RTCPUID) RTMpCpuIdFromSetIndex(int iCpu)
+{
+ return (unsigned)iCpu < rtMpDarwinMaxLogicalCpus() ? iCpu : NIL_RTCPUID;
+}
+
+
+RTDECL(RTCPUID) RTMpGetMaxCpuId(void)
+{
+ return rtMpDarwinMaxLogicalCpus() - 1;
+}
+
+
+RTDECL(bool) RTMpIsCpuOnline(RTCPUID idCpu)
+{
+#if 0
+ return RTMpIsCpuPossible(idCpu);
+#else
+ /** @todo proper ring-3 support on darwin, see @bugref{3014}. */
+ natural_t nCpus;
+ processor_basic_info_t pinfo;
+ mach_msg_type_number_t count;
+ kern_return_t krc = host_processor_info(mach_host_self(),
+ PROCESSOR_BASIC_INFO, &nCpus, (processor_info_array_t*)&pinfo, &count);
+ AssertReturn (krc == KERN_SUCCESS, true);
+ bool isOnline = idCpu < nCpus ? pinfo[idCpu].running : false;
+ vm_deallocate(mach_task_self(), (vm_address_t)pinfo, count * sizeof(*pinfo));
+ return isOnline;
+#endif
+}
+
+
+RTDECL(bool) RTMpIsCpuPossible(RTCPUID idCpu)
+{
+ return idCpu != NIL_RTCPUID
+ && idCpu < rtMpDarwinMaxLogicalCpus();
+}
+
+
+RTDECL(PRTCPUSET) RTMpGetSet(PRTCPUSET pSet)
+{
+#if 0
+ RTCPUID cCpus = rtMpDarwinMaxLogicalCpus();
+ return RTCpuSetFromU64(RT_BIT_64(cCpus) - 1);
+
+#else
+ RTCpuSetEmpty(pSet);
+ RTCPUID cMax = rtMpDarwinMaxLogicalCpus();
+ for (RTCPUID idCpu = 0; idCpu < cMax; idCpu++)
+ if (RTMpIsCpuPossible(idCpu))
+ RTCpuSetAdd(pSet, idCpu);
+ return pSet;
+#endif
+}
+
+
+RTDECL(RTCPUID) RTMpGetCount(void)
+{
+ return rtMpDarwinMaxLogicalCpus();
+}
+
+
+RTDECL(RTCPUID) RTMpGetCoreCount(void)
+{
+ return rtMpDarwinMaxPhysicalCpus();
+}
+
+
+RTDECL(PRTCPUSET) RTMpGetOnlineSet(PRTCPUSET pSet)
+{
+#if 0
+ return RTMpGetSet(pSet);
+#else
+ RTCpuSetEmpty(pSet);
+ RTCPUID cMax = rtMpDarwinMaxLogicalCpus();
+ for (RTCPUID idCpu = 0; idCpu < cMax; idCpu++)
+ if (RTMpIsCpuOnline(idCpu))
+ RTCpuSetAdd(pSet, idCpu);
+ return pSet;
+#endif
+}
+
+
+RTDECL(RTCPUID) RTMpGetOnlineCount(void)
+{
+ RTCPUSET Set;
+ RTMpGetOnlineSet(&Set);
+ return RTCpuSetCount(&Set);
+}
+
+
+RTDECL(RTCPUID) RTMpGetOnlineCoreCount(void)
+{
+ return rtMpDarwinOnlinePhysicalCpus();
+}
+
+
+RTDECL(uint32_t) RTMpGetCurFrequency(RTCPUID idCpu)
+{
+ /** @todo figure out how to get the current cpu speed on darwin. Have to check what powermanagement does. */
+ NOREF(idCpu);
+ return 0;
+}
+
+
+RTDECL(uint32_t) RTMpGetMaxFrequency(RTCPUID idCpu)
+{
+ if (!RTMpIsCpuOnline(idCpu))
+ return 0;
+
+ /*
+ * Try the 'hw.cpufrequency_max' one.
+ */
+ uint64_t CpuFrequencyMax = 0;
+ size_t cb = sizeof(CpuFrequencyMax);
+ int rc = sysctlbyname("hw.cpufrequency_max", &CpuFrequencyMax, &cb, NULL, 0);
+ if (!rc)
+ return (CpuFrequencyMax + 999999) / 1000000;
+
+ /*
+ * Use the deprecated one.
+ */
+ int aiMib[2];
+ aiMib[0] = CTL_HW;
+ aiMib[1] = HW_CPU_FREQ;
+ int cCpus = -1;
+ cb = sizeof(cCpus);
+ rc = sysctl(aiMib, RT_ELEMENTS(aiMib), &cCpus, &cb, NULL, 0);
+ if (rc != -1 && cCpus >= 1)
+ return cCpus;
+ AssertFailed();
+ return 0;
+}
diff --git a/src/VBox/Runtime/r3/darwin/pathhost-darwin.cpp b/src/VBox/Runtime/r3/darwin/pathhost-darwin.cpp
new file mode 100644
index 00000000..6b2567db
--- /dev/null
+++ b/src/VBox/Runtime/r3/darwin/pathhost-darwin.cpp
@@ -0,0 +1,107 @@
+/* $Id: pathhost-darwin.cpp $ */
+/** @file
+ * IPRT - Path Conversions, Darwin.
+ *
+ * On darwin path names on the disk are decomposed using normalization
+ * form D (NFD). Since this behavior is unique for the Mac, we will precompose
+ * the path name strings we get from the XNU kernel.
+ */
+
+/*
+ * Copyright (C) 2006-2020 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#define LOG_GROUP RTLOGGROUP_PATH
+#include <iprt/assert.h>
+#include <iprt/string.h>
+#include "internal/iprt.h"
+
+#include "internal/path.h"
+
+
+int rtPathToNative(const char **ppszNativePath, const char *pszPath, const char *pszBasePath)
+{
+ /** @todo We should decompose the string here, but the file system will do
+ * that for us if we don't, so why bother. */
+ *ppszNativePath = (char *)pszPath;
+ NOREF(pszBasePath); /* We don't query the FS for codeset preferences. */
+ return VINF_SUCCESS;
+}
+
+
+void rtPathFreeNative(char const *pszNativePath, const char *pszPath)
+{
+ Assert(pszNativePath == pszPath || !pszNativePath);
+ NOREF(pszNativePath);
+ NOREF(pszPath);
+}
+
+
+int rtPathFromNative(char const **ppszPath, const char *pszNativePath, const char *pszBasePath)
+{
+ /** @todo We must compose the codepoints in the string here. We get file names
+ * in normalization form D so we'll end up with normalization form C
+ * whatever approach we take. */
+ int rc = RTStrValidateEncodingEx(pszNativePath, RTSTR_MAX, 0 /*fFlags*/);
+ if (RT_SUCCESS(rc))
+ *ppszPath = pszNativePath;
+ else
+ *ppszPath = NULL;
+ NOREF(pszBasePath); /* We don't query the FS for codeset preferences. */
+ return rc;
+}
+
+
+void rtPathFreeIprt(const char *pszPath, const char *pszNativePath)
+{
+ Assert(pszPath == pszNativePath || !pszPath);
+ NOREF(pszPath); NOREF(pszNativePath);
+}
+
+
+int rtPathFromNativeCopy(char *pszPath, size_t cbPath, const char *pszNativePath, const char *pszBasePath)
+{
+ /** @todo We must compose the codepoints in the string here. We get file names
+ * in normalization form D so we'll end up with normalization form C
+ * whatever approach we take. */
+ int rc = RTStrValidateEncodingEx(pszNativePath, RTSTR_MAX, 0 /*fFlags*/);
+ if (RT_SUCCESS(rc))
+ rc = RTStrCopyEx(pszPath, cbPath, pszNativePath, RTSTR_MAX);
+ NOREF(pszBasePath); /* We don't query the FS for codeset preferences. */
+ return rc;
+}
+
+
+int rtPathFromNativeDup(char **ppszPath, const char *pszNativePath, const char *pszBasePath)
+{
+ /** @todo We must compose the codepoints in the string here. We get file names
+ * in normalization form D so we'll end up with normalization form C
+ * whatever approach we take. */
+ int rc = RTStrValidateEncodingEx(pszNativePath, RTSTR_MAX, 0 /*fFlags*/);
+ if (RT_SUCCESS(rc))
+ rc = RTStrDupEx(ppszPath, pszNativePath);
+ NOREF(pszBasePath); /* We don't query the FS for codeset preferences. */
+ return rc;
+}
+
diff --git a/src/VBox/Runtime/r3/darwin/rtProcInitExePath-darwin.cpp b/src/VBox/Runtime/r3/darwin/rtProcInitExePath-darwin.cpp
new file mode 100644
index 00000000..68a71541
--- /dev/null
+++ b/src/VBox/Runtime/r3/darwin/rtProcInitExePath-darwin.cpp
@@ -0,0 +1,66 @@
+/* $Id: rtProcInitExePath-darwin.cpp $ */
+/** @file
+ * IPRT - rtProcInitName, Darwin.
+ */
+
+/*
+ * Copyright (C) 2006-2020 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#define LOG_GROUP RTLOGGROUP_PROCESS
+#ifdef RT_OS_DARWIN
+# include <mach-o/dyld.h>
+#endif
+
+#include <stdlib.h>
+#include <limits.h>
+#include <errno.h>
+#include <iprt/string.h>
+#include <iprt/assert.h>
+#include <iprt/errcore.h>
+#include <iprt/path.h>
+#include "internal/process.h"
+#include "internal/path.h"
+
+
+DECLHIDDEN(int) rtProcInitExePath(char *pszPath, size_t cchPath)
+{
+ /*
+ * Query the image name from the dynamic linker, convert and return it.
+ */
+ const char *pszImageName = _dyld_get_image_name(0);
+ AssertReturn(pszImageName, VERR_INTERNAL_ERROR);
+
+ char szTmpPath[PATH_MAX + 1];
+ const char *psz = realpath(pszImageName, szTmpPath);
+ int rc;
+ if (psz)
+ rc = rtPathFromNativeCopy(pszPath, cchPath, szTmpPath, NULL);
+ else
+ rc = RTErrConvertFromErrno(errno);
+ AssertMsgRCReturn(rc, ("rc=%Rrc pszLink=\"%s\"\nhex: %.*Rhxs\n", rc, pszPath, strlen(pszImageName), pszPath), rc);
+
+ return VINF_SUCCESS;
+}
+
diff --git a/src/VBox/Runtime/r3/darwin/sched-darwin.cpp b/src/VBox/Runtime/r3/darwin/sched-darwin.cpp
new file mode 100644
index 00000000..cefd1b28
--- /dev/null
+++ b/src/VBox/Runtime/r3/darwin/sched-darwin.cpp
@@ -0,0 +1,353 @@
+/* $Id: sched-darwin.cpp $ */
+/** @file
+ * IPRT - Scheduling, Darwin.
+ */
+
+/*
+ * Copyright (C) 2006-2020 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#define LOG_GROUP RTLOGGROUP_THREAD
+#include <mach/thread_act.h>
+#include <mach/thread_policy.h>
+#include <mach/thread_info.h>
+#include <mach/host_info.h>
+#include <mach/mach_init.h>
+#include <mach/mach_host.h>
+#include <sched.h>
+#include <pthread.h>
+#include <limits.h>
+#include <errno.h>
+
+#include <iprt/thread.h>
+#include <iprt/log.h>
+#include <iprt/assert.h>
+#include <iprt/errcore.h>
+#include <iprt/asm.h>
+#include <iprt/assert.h>
+#include "internal/sched.h"
+#include "internal/thread.h"
+
+
+/*********************************************************************************************************************************
+* Structures and Typedefs *
+*********************************************************************************************************************************/
+/**
+ * Configuration of one priority.
+ */
+typedef struct
+{
+ /** The priority. */
+ RTPROCPRIORITY enmPriority;
+ /** The name of this priority. */
+ const char *pszName;
+ /** Array scheduler attributes corresponding to each of the thread types. */
+ struct
+ {
+ /** For sanity include the array index. */
+ RTTHREADTYPE enmType;
+ /** The desired mach base_priority value. */
+ int iBasePriority;
+ /** The suggested priority value. (Same as iBasePriority seems to do the
+ * trick.) */
+ int iPriority;
+ } aTypes[RTTHREADTYPE_END];
+} PROCPRIORITY;
+
+
+/*********************************************************************************************************************************
+* Global Variables *
+*********************************************************************************************************************************/
+/**
+ * Array of static priority configurations.
+ *
+ * ASSUMES that pthread_setschedparam takes a sched_priority argument in the
+ * range 0..127, which is translated into mach base_priority 0..63 and mach
+ * importance -31..32 (among other things). We also ASSUMES SCHED_OTHER.
+ *
+ * The base_priority range can be checked with tstDarwinSched, we're assuming it's
+ * 0..63 for user processes.
+ *
+ * Further we observe that fseventsd and mds both run at (mach) priority 50,
+ * while Finder runs at 47. At priority 63 we find the dynamic pager, the login
+ * window, UserEventAgent, SystemUIServer and coreaudiod. We do not wish to upset the
+ * dynamic pager, UI or audio, but we wish for I/O to not be bothered by spotlight
+ * (mds/fseventsd).
+ */
+static const PROCPRIORITY g_aPriorities[] =
+{
+ {
+ RTPROCPRIORITY_DEFAULT, "Default",
+ {
+ { RTTHREADTYPE_INVALID, INT_MIN, INT_MIN },
+ { RTTHREADTYPE_INFREQUENT_POLLER, 29, 29 },
+ { RTTHREADTYPE_MAIN_HEAVY_WORKER, 30, 30 },
+ { RTTHREADTYPE_EMULATION, 31, 31 }, /* the default priority */
+ { RTTHREADTYPE_DEFAULT, 32, 32 },
+ { RTTHREADTYPE_GUI, 32, 32 },
+ { RTTHREADTYPE_MAIN_WORKER, 32, 32 },
+ { RTTHREADTYPE_VRDP_IO, 39, 39 },
+ { RTTHREADTYPE_DEBUGGER, 42, 42 },
+ { RTTHREADTYPE_MSG_PUMP, 47, 47 },
+ { RTTHREADTYPE_IO, 52, 52 },
+ { RTTHREADTYPE_TIMER, 55, 55 }
+ }
+ },
+ {
+ RTPROCPRIORITY_LOW, "Low",
+ {
+ { RTTHREADTYPE_INVALID, INT_MIN, INT_MIN },
+ { RTTHREADTYPE_INFREQUENT_POLLER, 20, 20 },
+ { RTTHREADTYPE_MAIN_HEAVY_WORKER, 22, 22 },
+ { RTTHREADTYPE_EMULATION, 24, 24 },
+ { RTTHREADTYPE_DEFAULT, 28, 28 },
+ { RTTHREADTYPE_GUI, 29, 29 },
+ { RTTHREADTYPE_MAIN_WORKER, 30, 30 },
+ { RTTHREADTYPE_VRDP_IO, 31, 31 },
+ { RTTHREADTYPE_DEBUGGER, 31, 31 },
+ { RTTHREADTYPE_MSG_PUMP, 31, 31 },
+ { RTTHREADTYPE_IO, 31, 31 },
+ { RTTHREADTYPE_TIMER, 31, 31 }
+ }
+ },
+ {
+ RTPROCPRIORITY_NORMAL, "Normal",
+ {
+ { RTTHREADTYPE_INVALID, INT_MIN, INT_MIN },
+ { RTTHREADTYPE_INFREQUENT_POLLER, 29, 29 },
+ { RTTHREADTYPE_MAIN_HEAVY_WORKER, 30, 30 },
+ { RTTHREADTYPE_EMULATION, 31, 31 }, /* the default priority */
+ { RTTHREADTYPE_DEFAULT, 32, 32 },
+ { RTTHREADTYPE_GUI, 32, 32 },
+ { RTTHREADTYPE_MAIN_WORKER, 32, 32 },
+ { RTTHREADTYPE_VRDP_IO, 39, 39 },
+ { RTTHREADTYPE_DEBUGGER, 42, 42 },
+ { RTTHREADTYPE_MSG_PUMP, 47, 47 },
+ { RTTHREADTYPE_IO, 52, 52 },
+ { RTTHREADTYPE_TIMER, 55, 55 }
+ }
+ },
+ {
+ RTPROCPRIORITY_HIGH, "High",
+ {
+ { RTTHREADTYPE_INVALID, INT_MIN, INT_MIN },
+ { RTTHREADTYPE_INFREQUENT_POLLER, 30, 30 },
+ { RTTHREADTYPE_MAIN_HEAVY_WORKER, 31, 31 },
+ { RTTHREADTYPE_EMULATION, 32, 32 },
+ { RTTHREADTYPE_DEFAULT, 40, 40 },
+ { RTTHREADTYPE_GUI, 41, 41 },
+ { RTTHREADTYPE_MAIN_WORKER, 43, 43 },
+ { RTTHREADTYPE_VRDP_IO, 45, 45 },
+ { RTTHREADTYPE_DEBUGGER, 47, 47 },
+ { RTTHREADTYPE_MSG_PUMP, 49, 49 },
+ { RTTHREADTYPE_IO, 57, 57 },
+ { RTTHREADTYPE_TIMER, 61, 61 }
+ }
+ },
+ /* last */
+ {
+ RTPROCPRIORITY_FLAT, "Flat",
+ {
+ { RTTHREADTYPE_INVALID, INT_MIN, INT_MIN },
+ { RTTHREADTYPE_INFREQUENT_POLLER, 31, 31 },
+ { RTTHREADTYPE_MAIN_HEAVY_WORKER, 31, 31 },
+ { RTTHREADTYPE_EMULATION, 31, 31 },
+ { RTTHREADTYPE_DEFAULT, 31, 31 },
+ { RTTHREADTYPE_GUI, 31, 31 },
+ { RTTHREADTYPE_MAIN_WORKER, 31, 31 },
+ { RTTHREADTYPE_VRDP_IO, 31, 31 },
+ { RTTHREADTYPE_DEBUGGER, 31, 31 },
+ { RTTHREADTYPE_MSG_PUMP, 31, 31 },
+ { RTTHREADTYPE_IO, 31, 31 },
+ { RTTHREADTYPE_TIMER, 31, 31 }
+ }
+ },
+};
+
+
+/**
+ * The dynamic default priority configuration.
+ *
+ * This can be recalulated at runtime depending on what the
+ * system allow us to do. Presently we don't do this as it seems
+ * Darwin generally lets us do whatever we want.
+ *
+ * @remarks this is the same as "Normal" above.
+ */
+static PROCPRIORITY g_aDefaultPriority =
+{
+ RTPROCPRIORITY_DEFAULT, "Default",
+ {
+ { RTTHREADTYPE_INVALID, INT_MIN, INT_MIN },
+ { RTTHREADTYPE_INFREQUENT_POLLER, 29, 29 },
+ { RTTHREADTYPE_MAIN_HEAVY_WORKER, 30, 30 },
+ { RTTHREADTYPE_EMULATION, 31, 31 }, /* the default priority */
+ { RTTHREADTYPE_DEFAULT, 32, 32 },
+ { RTTHREADTYPE_GUI, 32, 32 },
+ { RTTHREADTYPE_MAIN_WORKER, 32, 32 },
+ { RTTHREADTYPE_VRDP_IO, 39, 39 },
+ { RTTHREADTYPE_DEBUGGER, 42, 42 },
+ { RTTHREADTYPE_MSG_PUMP, 47, 47 },
+ { RTTHREADTYPE_IO, 52, 52 },
+ { RTTHREADTYPE_TIMER, 55, 55 }
+ }
+};
+
+
+/** Pointer to the current priority configuration. */
+static const PROCPRIORITY *g_pProcessPriority = &g_aDefaultPriority;
+
+
+/**
+ * Get's the priority information for the current thread.
+ *
+ * @returns The base priority
+ * @param pThread The thread to get it for. NULL for current.
+ */
+static int rtSchedDarwinGetBasePriority(PRTTHREADINT pThread)
+{
+ /* the base_priority. */
+ mach_msg_type_number_t Count = POLICY_TIMESHARE_INFO_COUNT;
+ struct policy_timeshare_info TSInfo = {0,0,0,0,0};
+ kern_return_t krc = thread_info(!pThread ? mach_thread_self() : pthread_mach_thread_np((pthread_t)pThread->Core.Key),
+ THREAD_SCHED_TIMESHARE_INFO, (thread_info_t)&TSInfo, &Count);
+ Assert(krc == KERN_SUCCESS); NOREF(krc);
+
+ return TSInfo.base_priority;
+}
+
+
+DECLHIDDEN(int) rtSchedNativeCalcDefaultPriority(RTTHREADTYPE enmType)
+{
+ Assert(enmType > RTTHREADTYPE_INVALID && enmType < RTTHREADTYPE_END);
+
+ /*
+ * Get the current priority.
+ */
+ int iBasePriority = rtSchedDarwinGetBasePriority(NULL);
+ Assert(iBasePriority >= 0 && iBasePriority <= 63);
+
+ /*
+ * If it doesn't match the default, select the closest one from the table.
+ */
+ int offBest = RT_ABS(g_pProcessPriority->aTypes[enmType].iBasePriority - iBasePriority);
+ if (offBest)
+ {
+ for (unsigned i = 0; i < RT_ELEMENTS(g_aPriorities); i++)
+ {
+ int off = RT_ABS(g_aPriorities[i].aTypes[enmType].iBasePriority - iBasePriority);
+ if (off < offBest)
+ {
+ g_pProcessPriority = &g_aPriorities[i];
+ if (!off)
+ break;
+ offBest = off;
+ }
+ }
+ }
+
+ return VINF_SUCCESS;
+}
+
+
+DECLHIDDEN(int) rtProcNativeSetPriority(RTPROCPRIORITY enmPriority)
+{
+ Assert(enmPriority > RTPROCPRIORITY_INVALID && enmPriority < RTPROCPRIORITY_LAST);
+
+ /*
+ * No checks necessary, we assume we can set any priority in the user process range.
+ */
+ const PROCPRIORITY *pProcessPriority = &g_aDefaultPriority;
+ for (unsigned i = 0; i < RT_ELEMENTS(g_aPriorities); i++)
+ if (g_aPriorities[i].enmPriority == enmPriority)
+ {
+ pProcessPriority = &g_aPriorities[i];
+ break;
+ }
+ Assert(pProcessPriority != &g_aDefaultPriority);
+ ASMAtomicUoWritePtr(&g_pProcessPriority, pProcessPriority);
+
+ return VINF_SUCCESS;
+}
+
+
+DECLHIDDEN(int) rtThreadNativeSetPriority(PRTTHREADINT pThread, RTTHREADTYPE enmType)
+{
+ Assert(enmType > RTTHREADTYPE_INVALID && enmType < RTTHREADTYPE_END);
+ AssertMsg(g_pProcessPriority && g_pProcessPriority->aTypes[enmType].enmType == enmType,
+ ("enmType=%d entry=%d\n", enmType, g_pProcessPriority->aTypes[enmType].enmType));
+
+ /*
+ * Get the current policy and params first since there are
+ * opaque members in the param structure and we don't wish to
+ * change the policy.
+ */
+ int iSchedPolicy = SCHED_OTHER;
+ struct sched_param SchedParam = {0, {0,0,0,0} };
+ int err = pthread_getschedparam((pthread_t)pThread->Core.Key, &iSchedPolicy, &SchedParam);
+ if (!err)
+ {
+ int const iDesiredBasePriority = g_pProcessPriority->aTypes[enmType].iBasePriority;
+ int iPriority = g_pProcessPriority->aTypes[enmType].iPriority;
+
+ /*
+ * First try with the given pthread priority number.
+ * Then make adjustments in case we missed the desired base priority (interface
+ * changed or whatever - its using an obsolete mach api).
+ */
+ SchedParam.sched_priority = iPriority;
+ err = pthread_setschedparam((pthread_t)pThread->Core.Key, iSchedPolicy, &SchedParam);
+ if (!err)
+ {
+ int i = 0;
+ int iBasePriority = rtSchedDarwinGetBasePriority(pThread);
+
+ while ( !err
+ && iBasePriority < iDesiredBasePriority
+ && i++ < 256)
+ {
+ SchedParam.sched_priority = ++iPriority;
+ err = pthread_setschedparam((pthread_t)pThread->Core.Key, iSchedPolicy, &SchedParam);
+ iBasePriority = rtSchedDarwinGetBasePriority(pThread);
+ }
+
+ while ( !err
+ && iPriority > 0
+ && iBasePriority > iDesiredBasePriority
+ && i++ < 256)
+ {
+ SchedParam.sched_priority = --iPriority;
+ err = pthread_setschedparam((pthread_t)pThread->Core.Key, iSchedPolicy, &SchedParam);
+ iBasePriority = rtSchedDarwinGetBasePriority(pThread);
+ }
+
+ return VINF_SUCCESS;
+ }
+ }
+ int rc = RTErrConvertFromErrno(err);
+ AssertMsgRC(rc, ("rc=%Rrc err=%d iSchedPolicy=%d sched_priority=%d\n",
+ rc, err, iSchedPolicy, SchedParam.sched_priority));
+ return rc;
+}
+
diff --git a/src/VBox/Runtime/r3/darwin/systemmem-darwin.cpp b/src/VBox/Runtime/r3/darwin/systemmem-darwin.cpp
new file mode 100644
index 00000000..eeb70451
--- /dev/null
+++ b/src/VBox/Runtime/r3/darwin/systemmem-darwin.cpp
@@ -0,0 +1,86 @@
+/* $Id: systemmem-darwin.cpp $ */
+/** @file
+ * IPRT - RTSystemQueryTotalRam, darwin ring-3.
+ */
+
+/*
+ * Copyright (C) 2012-2020 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#include <iprt/system.h>
+#include "internal/iprt.h"
+
+#include <iprt/errcore.h>
+#include <iprt/assert.h>
+
+#include <errno.h>
+#include <unistd.h>
+#include <sys/sysctl.h>
+#include <sys/stat.h>
+#include <mach/mach.h>
+
+
+
+RTDECL(int) RTSystemQueryTotalRam(uint64_t *pcb)
+{
+ AssertPtrReturn(pcb, VERR_INVALID_POINTER);
+
+ int aiMib[2];
+ aiMib[0] = CTL_HW;
+ aiMib[1] = HW_MEMSIZE;
+ uint64_t cbPhysMem = UINT64_MAX;
+ size_t cb = sizeof(cbPhysMem);
+ int rc = sysctl(aiMib, RT_ELEMENTS(aiMib), &cbPhysMem, &cb, NULL, 0);
+ if (rc == 0)
+ {
+ *pcb = cbPhysMem;
+ return VINF_SUCCESS;
+ }
+ return RTErrConvertFromErrno(errno);
+}
+
+
+RTDECL(int) RTSystemQueryAvailableRam(uint64_t *pcb)
+{
+ AssertPtrReturn(pcb, VERR_INVALID_POINTER);
+
+ static mach_port_t volatile s_hSelfPort = 0;
+ mach_port_t hSelfPort = s_hSelfPort;
+ if (hSelfPort == 0)
+ s_hSelfPort = hSelfPort = mach_host_self();
+
+ vm_statistics_data_t VmStats;
+ mach_msg_type_number_t cItems = sizeof(VmStats) / sizeof(natural_t);
+
+ kern_return_t krc = host_statistics(hSelfPort, HOST_VM_INFO, (host_info_t)&VmStats, &cItems);
+ if (krc == KERN_SUCCESS)
+ {
+ uint64_t cPages = VmStats.inactive_count;
+ cPages += VmStats.free_count;
+ *pcb = cPages * PAGE_SIZE;
+ return VINF_SUCCESS;
+ }
+ return RTErrConvertFromDarwin(krc);
+}
+
diff --git a/src/VBox/Runtime/r3/darwin/time-darwin.cpp b/src/VBox/Runtime/r3/darwin/time-darwin.cpp
new file mode 100644
index 00000000..fc6b970f
--- /dev/null
+++ b/src/VBox/Runtime/r3/darwin/time-darwin.cpp
@@ -0,0 +1,115 @@
+/* $Id: time-darwin.cpp $ */
+/** @file
+ * IPRT - Time, Darwin.
+ */
+
+/*
+ * Copyright (C) 2006-2020 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#define LOG_GROUP RTLOGGROUP_TIME
+#define RTTIME_INCL_TIMEVAL
+#include <mach/mach_time.h>
+#include <mach/kern_return.h>
+#include <sys/time.h>
+#include <time.h>
+
+#include <iprt/time.h>
+#include <iprt/assert.h>
+#include "internal/time.h"
+
+
+/*********************************************************************************************************************************
+* Global Variables *
+*********************************************************************************************************************************/
+static struct mach_timebase_info g_Info = { 0, 0 };
+static double g_rdFactor = 0.0;
+static bool g_fFailedToGetTimeBaseInfo = false;
+
+
+/**
+ * Perform lazy init (pray we're not racing anyone in a bad way).
+ */
+static void rtTimeDarwinLazyInit(void)
+{
+ struct mach_timebase_info Info;
+ if (mach_timebase_info(&Info) == KERN_SUCCESS)
+ {
+ g_rdFactor = (double)Info.numer / (double)Info.denom;
+ g_Info = Info;
+ }
+ else
+ {
+ g_fFailedToGetTimeBaseInfo = true;
+ Assert(g_Info.denom == 0 && g_Info.numer == 0 && g_rdFactor == 0.0);
+ }
+}
+
+
+/**
+ * Internal worker.
+ * @returns Nanosecond timestamp.
+ */
+DECLINLINE(uint64_t) rtTimeGetSystemNanoTS(void)
+{
+ /* Lazy init. */
+ if (RT_UNLIKELY(g_Info.denom == 0 && !g_fFailedToGetTimeBaseInfo))
+ rtTimeDarwinLazyInit();
+
+ /* special case: absolute time is in nanoseconds */
+ if (g_Info.denom == 1 && g_Info.numer == 1)
+ return mach_absolute_time();
+
+ /* general case: multiply by factor to get nanoseconds. */
+ if (g_rdFactor != 0.0)
+ return mach_absolute_time() * g_rdFactor;
+
+ /* worst case: fallback to gettimeofday(). */
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ return (uint64_t)tv.tv_sec * RT_NS_1SEC_64
+ + (uint64_t)(tv.tv_usec * RT_NS_1US);
+}
+
+
+RTDECL(uint64_t) RTTimeSystemNanoTS(void)
+{
+ return rtTimeGetSystemNanoTS();
+}
+
+
+RTDECL(uint64_t) RTTimeSystemMilliTS(void)
+{
+ return rtTimeGetSystemNanoTS() / RT_NS_1MS;
+}
+
+
+RTDECL(PRTTIMESPEC) RTTimeNow(PRTTIMESPEC pTime)
+{
+ /** @todo find nanosecond API for getting time of day. */
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ return RTTimeSpecSetTimeval(pTime, &tv);
+}
+