diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 14:19:18 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 14:19:18 +0000 |
commit | 4035b1bfb1e5843a539a8b624d21952b756974d1 (patch) | |
tree | f1e9cd5bf548cbc57ff2fddfb2b4aa9ae95587e2 /src/VBox/Runtime/r0drv/generic | |
parent | Initial commit. (diff) | |
download | virtualbox-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/r0drv/generic')
12 files changed, 1043 insertions, 0 deletions
diff --git a/src/VBox/Runtime/r0drv/generic/Makefile.kup b/src/VBox/Runtime/r0drv/generic/Makefile.kup new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/src/VBox/Runtime/r0drv/generic/Makefile.kup diff --git a/src/VBox/Runtime/r0drv/generic/RTMpIsCpuWorkPending-r0drv-generic.cpp b/src/VBox/Runtime/r0drv/generic/RTMpIsCpuWorkPending-r0drv-generic.cpp new file mode 100644 index 00000000..1d788e0c --- /dev/null +++ b/src/VBox/Runtime/r0drv/generic/RTMpIsCpuWorkPending-r0drv-generic.cpp @@ -0,0 +1,45 @@ +/* $Id: RTMpIsCpuWorkPending-r0drv-generic.cpp $ */ +/** @file + * IPRT - RTMpIsCpuWorkPending, Generic. + */ + +/* + * Copyright (C) 2009-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/mp.h> +#include "internal/iprt.h" + + +/** + * Check if there's work (DPCs on Windows) pending on the current CPU. + * + * @return true if there's pending work on the current CPU, false otherwise. + */ +RTDECL(bool) RTMpIsCpuWorkPending(void) +{ + return false; +} +RT_EXPORT_SYMBOL(RTMpIsCpuWorkPending); + diff --git a/src/VBox/Runtime/r0drv/generic/RTMpOn-r0drv-generic.cpp b/src/VBox/Runtime/r0drv/generic/RTMpOn-r0drv-generic.cpp new file mode 100644 index 00000000..20573f5e --- /dev/null +++ b/src/VBox/Runtime/r0drv/generic/RTMpOn-r0drv-generic.cpp @@ -0,0 +1,94 @@ +/* $Id: RTMpOn-r0drv-generic.cpp $ */ +/** @file + * IPRT - Multiprocessor, Ring-0 Driver, Generic Stubs. + */ + +/* + * Copyright (C) 2008-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/mp.h> +#include "internal/iprt.h" + +#include <iprt/errcore.h> + + +RTDECL(int) RTMpOnAll(PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2) +{ + NOREF(pfnWorker); + NOREF(pvUser1); + NOREF(pvUser2); + return VERR_NOT_SUPPORTED; +} +RT_EXPORT_SYMBOL(RTMpOnAll); + + +RTDECL(bool) RTMpOnAllIsConcurrentSafe(void) +{ + return false; +} +RT_EXPORT_SYMBOL(RTMpOnAllIsConcurrentSafe); + + +RTDECL(int) RTMpOnOthers(PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2) +{ + NOREF(pfnWorker); + NOREF(pvUser1); + NOREF(pvUser2); + return VERR_NOT_SUPPORTED; +} +RT_EXPORT_SYMBOL(RTMpOnOthers); + + +RTDECL(int) RTMpOnSpecific(RTCPUID idCpu, PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2) +{ + NOREF(idCpu); + NOREF(pfnWorker); + NOREF(pvUser1); + NOREF(pvUser2); + return VERR_NOT_SUPPORTED; +} +RT_EXPORT_SYMBOL(RTMpOnSpecific); + + +RTDECL(int) RTMpOnPair(RTCPUID idCpu1, RTCPUID idCpu2, uint32_t fFlags, PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2) +{ + NOREF(idCpu1); + NOREF(idCpu2); + NOREF(fFlags); + NOREF(pfnWorker); + NOREF(pvUser1); + NOREF(pvUser2); + return VERR_NOT_SUPPORTED; +} +RT_EXPORT_SYMBOL(RTMpOnPair); + + + +RTDECL(bool) RTMpOnPairIsConcurrentExecSupported(void) +{ + return false; +} +RT_EXPORT_SYMBOL(RTMpOnPairIsConcurrentExecSupported); + diff --git a/src/VBox/Runtime/r0drv/generic/RTMpPokeCpu-r0drv-generic.cpp b/src/VBox/Runtime/r0drv/generic/RTMpPokeCpu-r0drv-generic.cpp new file mode 100644 index 00000000..5c379408 --- /dev/null +++ b/src/VBox/Runtime/r0drv/generic/RTMpPokeCpu-r0drv-generic.cpp @@ -0,0 +1,48 @@ +/* $Id: RTMpPokeCpu-r0drv-generic.cpp $ */ +/** @file + * IPRT - RTMpPokeCpu, Generic Implementation. + */ + +/* + * Copyright (C) 2009-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/mp.h> +#include "internal/iprt.h" + + +static DECLCALLBACK(void) rtMpNtPokeCpuDummy(RTCPUID idCpu, void *pvUser1, void *pvUser2) +{ + NOREF(idCpu); + NOREF(pvUser1); + NOREF(pvUser2); +} + + +RTDECL(int) RTMpPokeCpu(RTCPUID idCpu) +{ + return RTMpOnSpecific(idCpu, rtMpNtPokeCpuDummy, NULL, NULL); +} +RT_EXPORT_SYMBOL(RTMpPokeCpu); + diff --git a/src/VBox/Runtime/r0drv/generic/RTThreadPreemptDisable-r0drv-generic.cpp b/src/VBox/Runtime/r0drv/generic/RTThreadPreemptDisable-r0drv-generic.cpp new file mode 100644 index 00000000..6482acbd --- /dev/null +++ b/src/VBox/Runtime/r0drv/generic/RTThreadPreemptDisable-r0drv-generic.cpp @@ -0,0 +1,44 @@ +/* $Id: RTThreadPreemptDisable-r0drv-generic.cpp $ */ +/** @file + * IPRT - RTThreadPreemptDisable, Generic ring-0 driver implementation. + */ + +/* + * Copyright (C) 2008-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/thread.h> +#include "internal/iprt.h" + +#include <iprt/assert.h> + + +RTDECL(void) RTThreadPreemptDisable(PRTTHREADPREEMPTSTATE pState) +{ + AssertPtr(pState); + Assert(pState->u32Reserved == 0); + pState->u32Reserved = 42; +} +RT_EXPORT_SYMBOL(RTThreadPreemptDisable); + diff --git a/src/VBox/Runtime/r0drv/generic/RTThreadPreemptIsEnabled-r0drv-generic.cpp b/src/VBox/Runtime/r0drv/generic/RTThreadPreemptIsEnabled-r0drv-generic.cpp new file mode 100644 index 00000000..8fd15fc6 --- /dev/null +++ b/src/VBox/Runtime/r0drv/generic/RTThreadPreemptIsEnabled-r0drv-generic.cpp @@ -0,0 +1,43 @@ +/* $Id: RTThreadPreemptIsEnabled-r0drv-generic.cpp $ */ +/** @file + * IPRT - RTThreadPreemptIsEnabled, Generic ring-0 driver implementation. + */ + +/* + * Copyright (C) 2008-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/thread.h> +#include "internal/iprt.h" + +#include <iprt/assert.h> + + +RTDECL(bool) RTThreadPreemptIsEnabled(RTTHREAD hThread) +{ + Assert(hThread == NIL_RTTHREAD); + return true; +} +RT_EXPORT_SYMBOL(RTThreadPreemptIsEnabled); + diff --git a/src/VBox/Runtime/r0drv/generic/RTThreadPreemptIsPending-r0drv-generic.cpp b/src/VBox/Runtime/r0drv/generic/RTThreadPreemptIsPending-r0drv-generic.cpp new file mode 100644 index 00000000..c896559d --- /dev/null +++ b/src/VBox/Runtime/r0drv/generic/RTThreadPreemptIsPending-r0drv-generic.cpp @@ -0,0 +1,43 @@ +/* $Id: RTThreadPreemptIsPending-r0drv-generic.cpp $ */ +/** @file + * IPRT - RTThreadPreemptIsPending, Generic ring-0 driver implementation. + */ + +/* + * Copyright (C) 2008-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/thread.h> +#include "internal/iprt.h" + +#include <iprt/assert.h> + + +RTDECL(bool) RTThreadPreemptIsPending(RTTHREAD hThread) +{ + Assert(hThread == NIL_RTTHREAD); + return false; +} +RT_EXPORT_SYMBOL(RTThreadPreemptIsPending); + diff --git a/src/VBox/Runtime/r0drv/generic/RTThreadPreemptIsPendingTrusty-r0drv-generic.cpp b/src/VBox/Runtime/r0drv/generic/RTThreadPreemptIsPendingTrusty-r0drv-generic.cpp new file mode 100644 index 00000000..1515ba90 --- /dev/null +++ b/src/VBox/Runtime/r0drv/generic/RTThreadPreemptIsPendingTrusty-r0drv-generic.cpp @@ -0,0 +1,41 @@ +/* $Id: RTThreadPreemptIsPendingTrusty-r0drv-generic.cpp $ */ +/** @file + * IPRT - RTThreadPreemptIsPendingTrusty, Generic ring-0 driver implementation. + */ + +/* + * Copyright (C) 2009-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/thread.h> +#include "internal/iprt.h" + + +RTDECL(bool) RTThreadPreemptIsPendingTrusty(void) +{ + /* no, RTThreadPreemptIsPending is not reliable. */ + return false; +} +RT_EXPORT_SYMBOL(RTThreadPreemptIsPendingTrusty); + diff --git a/src/VBox/Runtime/r0drv/generic/RTThreadPreemptRestore-r0drv-generic.cpp b/src/VBox/Runtime/r0drv/generic/RTThreadPreemptRestore-r0drv-generic.cpp new file mode 100644 index 00000000..1683f668 --- /dev/null +++ b/src/VBox/Runtime/r0drv/generic/RTThreadPreemptRestore-r0drv-generic.cpp @@ -0,0 +1,44 @@ +/* $Id: RTThreadPreemptRestore-r0drv-generic.cpp $ */ +/** @file + * IPRT - RTThreadPreemptRestore, Generic ring-0 driver implementation. + */ + +/* + * Copyright (C) 2008-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/thread.h> +#include "internal/iprt.h" + +#include <iprt/assert.h> + + +RTDECL(void) RTThreadPreemptRestore(PRTTHREADPREEMPTSTATE pState) +{ + AssertPtr(pState); + Assert(pState->u32Reserved == 42); + pState->u32Reserved = 0; +} +RT_EXPORT_SYMBOL(RTThreadPreemptRestore); + diff --git a/src/VBox/Runtime/r0drv/generic/mpnotification-r0drv-generic.cpp b/src/VBox/Runtime/r0drv/generic/mpnotification-r0drv-generic.cpp new file mode 100644 index 00000000..3ae07820 --- /dev/null +++ b/src/VBox/Runtime/r0drv/generic/mpnotification-r0drv-generic.cpp @@ -0,0 +1,65 @@ +/* $Id: mpnotification-r0drv-generic.cpp $ */ +/** @file + * IPRT - Multiprocessor Notifications, Ring-0 Driver, Generic Stubs. + */ + +/* + * Copyright (C) 2008-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/mp.h> +#include "internal/iprt.h" + +#include <iprt/errcore.h> +#include "r0drv/mp-r0drv.h" + + +RTDECL(int) RTMpNotificationRegister(PFNRTMPNOTIFICATION pfnCallback, void *pvUser) +{ + NOREF(pfnCallback); + NOREF(pvUser); + return VINF_SUCCESS; +} +RT_EXPORT_SYMBOL(RTMpNotificationRegister); + + +RTDECL(int) RTMpNotificationDeregister(PFNRTMPNOTIFICATION pfnCallback, void *pvUser) +{ + NOREF(pfnCallback); + NOREF(pvUser); + return VINF_SUCCESS; +} +RT_EXPORT_SYMBOL(RTMpNotificationDeregister); + + +DECLHIDDEN(int) rtR0MpNotificationInit(void) +{ + return VINF_SUCCESS; +} + + +DECLHIDDEN(void) rtR0MpNotificationTerm(void) +{ +} + diff --git a/src/VBox/Runtime/r0drv/generic/semspinmutex-r0drv-generic.c b/src/VBox/Runtime/r0drv/generic/semspinmutex-r0drv-generic.c new file mode 100644 index 00000000..57dbe49a --- /dev/null +++ b/src/VBox/Runtime/r0drv/generic/semspinmutex-r0drv-generic.c @@ -0,0 +1,503 @@ +/* $Id: semspinmutex-r0drv-generic.c $ */ +/** @file + * IPRT - Spinning Mutex Semaphores, Ring-0 Driver, Generic. + */ + +/* + * Copyright (C) 2009-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 * +*********************************************************************************************************************************/ +#ifdef RT_OS_WINDOWS +# include "../nt/the-nt-kernel.h" +#endif +#include "internal/iprt.h" + +#include <iprt/semaphore.h> +#include <iprt/asm.h> +#include <iprt/asm-amd64-x86.h> +#include <iprt/assert.h> +#include <iprt/err.h> +#include <iprt/mem.h> +#include <iprt/thread.h> +#include "internal/magics.h" + + +/********************************************************************************************************************************* +* Structures and Typedefs * +*********************************************************************************************************************************/ +/** + * Saved state information. + */ +typedef struct RTSEMSPINMUTEXSTATE +{ + /** Saved flags register. */ + RTCCUINTREG fSavedFlags; + /** Preemption state. */ + RTTHREADPREEMPTSTATE PreemptState; + /** Whether to spin or sleep. */ + bool fSpin; + /** Whether the flags have been saved. */ + bool fValidFlags; +} RTSEMSPINMUTEXSTATE; + +/** + * Spinning mutex semaphore. + */ +typedef struct RTSEMSPINMUTEXINTERNAL +{ + /** Magic value (RTSEMSPINMUTEX_MAGIC) + * RTCRITSECT_MAGIC is the value of an initialized & operational section. */ + uint32_t volatile u32Magic; + /** Flags. This is a combination of RTSEMSPINMUTEX_FLAGS_XXX and + * RTSEMSPINMUTEX_INT_FLAGS_XXX. */ + uint32_t volatile fFlags; + /** The owner thread. + * This is NIL if the semaphore is not owned by anyone. */ + RTNATIVETHREAD volatile hOwner; + /** Number of threads that are fighting for the lock. */ + int32_t volatile cLockers; + /** The semaphore to block on. */ + RTSEMEVENT hEventSem; + /** Saved state information of the owner. + * This will be restored by RTSemSpinRelease. */ + RTSEMSPINMUTEXSTATE SavedState; +} RTSEMSPINMUTEXINTERNAL; + + +/********************************************************************************************************************************* +* Defined Constants And Macros * +*********************************************************************************************************************************/ +/*#define RTSEMSPINMUTEX_INT_FLAGS_MUST*/ + +/** Validates the handle, returning if invalid. */ +#define RTSEMSPINMUTEX_VALIDATE_RETURN(pThis) \ + do \ + { \ + uint32_t u32Magic; \ + AssertPtr(pThis); \ + u32Magic = (pThis)->u32Magic; \ + if (u32Magic != RTSEMSPINMUTEX_MAGIC) \ + { \ + AssertMsgFailed(("u32Magic=%#x pThis=%p\n", u32Magic, pThis)); \ + return u32Magic == RTSEMSPINMUTEX_MAGIC_DEAD ? VERR_SEM_DESTROYED : VERR_INVALID_HANDLE; \ + } \ + } while (0) + + +RTDECL(int) RTSemSpinMutexCreate(PRTSEMSPINMUTEX phSpinMtx, uint32_t fFlags) +{ + RTSEMSPINMUTEXINTERNAL *pThis; + int rc; + + AssertReturn(!(fFlags & ~RTSEMSPINMUTEX_FLAGS_VALID_MASK), VERR_INVALID_PARAMETER); + AssertPtr(phSpinMtx); + + /* + * Allocate and initialize the structure. + */ + pThis = (RTSEMSPINMUTEXINTERNAL *)RTMemAllocZ(sizeof(*pThis)); + if (!pThis) + return VERR_NO_MEMORY; + pThis->u32Magic = RTSEMSPINMUTEX_MAGIC; + pThis->fFlags = fFlags; + pThis->hOwner = NIL_RTNATIVETHREAD; + pThis->cLockers = 0; + rc = RTSemEventCreateEx(&pThis->hEventSem, RTSEMEVENT_FLAGS_NO_LOCK_VAL, NIL_RTLOCKVALCLASS, NULL); + if (RT_SUCCESS(rc)) + { + *phSpinMtx = pThis; + return VINF_SUCCESS; + } + + RTMemFree(pThis); + return rc; +} +RT_EXPORT_SYMBOL(RTSemSpinMutexCreate); + + +/** + * Helper for RTSemSpinMutexTryRequest and RTSemSpinMutexRequest. + * + * This will check the current context and see if it's usui + * + * @returns VINF_SUCCESS or VERR_SEM_BAD_CONTEXT. + * @param pState Output structure. + */ +static int rtSemSpinMutexEnter(RTSEMSPINMUTEXSTATE *pState, RTSEMSPINMUTEXINTERNAL *pThis) +{ +#ifndef RT_OS_WINDOWS + RTTHREADPREEMPTSTATE const StateInit = RTTHREADPREEMPTSTATE_INITIALIZER; +#endif + int rc = VINF_SUCCESS; + + /** @todo Later #1: When entering in interrupt context and we're not able to + * wake up threads from it, we could try switch the lock into pure + * spinlock mode. This would require that there are no other threads + * currently waiting on it and that the RTSEMSPINMUTEX_FLAGS_IRQ_SAFE + * flag is set. + * + * Later #2: Similarly, it is possible to turn on the + * RTSEMSPINMUTEX_FLAGS_IRQ_SAFE at run time if we manage to grab the + * semaphore ownership at interrupt time. We might want to try delay the + * RTSEMSPINMUTEX_FLAGS_IRQ_SAFE even, since we're fine if we get it... + */ + +#ifdef RT_OS_WINDOWS + /* + * NT: IRQL <= DISPATCH_LEVEL for waking up threads; IRQL < DISPATCH_LEVEL for sleeping. + */ + pState->PreemptState.uchOldIrql = KeGetCurrentIrql(); + if (pState->PreemptState.uchOldIrql > DISPATCH_LEVEL) + return VERR_SEM_BAD_CONTEXT; + + if (pState->PreemptState.uchOldIrql >= DISPATCH_LEVEL) + pState->fSpin = true; + else + { + pState->fSpin = false; + KeRaiseIrql(DISPATCH_LEVEL, &pState->PreemptState.uchOldIrql); + Assert(pState->PreemptState.uchOldIrql < DISPATCH_LEVEL); + } + +#elif defined(RT_OS_SOLARIS) + /* + * Solaris: RTSemEventSignal will do bad stuff on S10 if interrupts are disabled. + */ + if (!ASMIntAreEnabled()) + return VERR_SEM_BAD_CONTEXT; + + pState->fSpin = !RTThreadPreemptIsEnabled(NIL_RTTHREAD); + if (RTThreadIsInInterrupt(NIL_RTTHREAD)) + { + if (!(pThis->fFlags & RTSEMSPINMUTEX_FLAGS_IRQ_SAFE)) + rc = VINF_SEM_BAD_CONTEXT; /* Try, but owner might be interrupted. */ + pState->fSpin = true; + } + pState->PreemptState = StateInit; + RTThreadPreemptDisable(&pState->PreemptState); + +#elif defined(RT_OS_LINUX) || defined(RT_OS_OS2) + /* + * OSes on which RTSemEventSignal can be called from any context. + */ + pState->fSpin = !RTThreadPreemptIsEnabled(NIL_RTTHREAD); + if (RTThreadIsInInterrupt(NIL_RTTHREAD)) + { + if (!(pThis->fFlags & RTSEMSPINMUTEX_FLAGS_IRQ_SAFE)) + rc = VINF_SEM_BAD_CONTEXT; /* Try, but owner might be interrupted. */ + pState->fSpin = true; + } + pState->PreemptState = StateInit; + RTThreadPreemptDisable(&pState->PreemptState); + +#else /* PORTME: Check for context where we cannot wake up threads. */ + /* + * Default: ASSUME thread can be woken up if interrupts are enabled and + * we're not in an interrupt context. + * ASSUME that we can go to sleep if preemption is enabled. + */ + if ( RTThreadIsInInterrupt(NIL_RTTHREAD) + || !ASMIntAreEnabled()) + return VERR_SEM_BAD_CONTEXT; + + pState->fSpin = !RTThreadPreemptIsEnabled(NIL_RTTHREAD); + pState->PreemptState = StateInit; + RTThreadPreemptDisable(&pState->PreemptState); +#endif + + /* + * Disable interrupts if necessary. + */ + pState->fValidFlags = !!(pThis->fFlags & RTSEMSPINMUTEX_FLAGS_IRQ_SAFE); + if (pState->fValidFlags) + pState->fSavedFlags = ASMIntDisableFlags(); + else + pState->fSavedFlags = 0; + + return rc; +} + + +/** + * Helper for RTSemSpinMutexTryRequest, RTSemSpinMutexRequest and + * RTSemSpinMutexRelease. + * + * @param pState + */ +DECL_FORCE_INLINE(void) rtSemSpinMutexLeave(RTSEMSPINMUTEXSTATE *pState) +{ + /* + * Restore the interrupt flag. + */ + if (pState->fValidFlags) + ASMSetFlags(pState->fSavedFlags); + +#ifdef RT_OS_WINDOWS + /* + * NT: Lower the IRQL if we raised it. + */ + if (pState->PreemptState.uchOldIrql < DISPATCH_LEVEL) + KeLowerIrql(pState->PreemptState.uchOldIrql); +#else + /* + * Default: Restore preemption. + */ + RTThreadPreemptRestore(&pState->PreemptState); +#endif +} + + +RTDECL(int) RTSemSpinMutexTryRequest(RTSEMSPINMUTEX hSpinMtx) +{ + RTSEMSPINMUTEXINTERNAL *pThis = hSpinMtx; + RTNATIVETHREAD hSelf = RTThreadNativeSelf(); + RTSEMSPINMUTEXSTATE State; + bool fRc; + int rc; + + Assert(hSelf != NIL_RTNATIVETHREAD); + RTSEMSPINMUTEX_VALIDATE_RETURN(pThis); + + /* + * Check context, disable preemption and save flags if necessary. + */ + rc = rtSemSpinMutexEnter(&State, pThis); + if (RT_FAILURE(rc)) + return rc; + + /* + * Try take the ownership. + */ + ASMAtomicCmpXchgHandle(&pThis->hOwner, hSelf, NIL_RTNATIVETHREAD, fRc); + if (!fRc) + { + /* Busy, too bad. Check for attempts at nested access. */ + rc = VERR_SEM_BUSY; + if (RT_UNLIKELY(pThis->hOwner == hSelf)) + { + AssertMsgFailed(("%p attempt at nested access\n")); + rc = VERR_SEM_NESTED; + } + + rtSemSpinMutexLeave(&State); + return rc; + } + + /* + * We're the semaphore owner. + */ + ASMAtomicIncS32(&pThis->cLockers); + pThis->SavedState = State; + return VINF_SUCCESS; +} +RT_EXPORT_SYMBOL(RTSemSpinMutexTryRequest); + + +RTDECL(int) RTSemSpinMutexRequest(RTSEMSPINMUTEX hSpinMtx) +{ + RTSEMSPINMUTEXINTERNAL *pThis = hSpinMtx; + RTNATIVETHREAD hSelf = RTThreadNativeSelf(); + RTSEMSPINMUTEXSTATE State; + bool fRc; + int rc; + + Assert(hSelf != NIL_RTNATIVETHREAD); + RTSEMSPINMUTEX_VALIDATE_RETURN(pThis); + + /* + * Check context, disable preemption and save flags if necessary. + */ + rc = rtSemSpinMutexEnter(&State, pThis); + if (RT_FAILURE(rc)) + return rc; + + /* + * Try take the ownership. + */ + ASMAtomicIncS32(&pThis->cLockers); + ASMAtomicCmpXchgHandle(&pThis->hOwner, hSelf, NIL_RTNATIVETHREAD, fRc); + if (!fRc) + { + uint32_t cSpins; + + /* + * It's busy. Check if it's an attempt at nested access. + */ + if (RT_UNLIKELY(pThis->hOwner == hSelf)) + { + AssertMsgFailed(("%p attempt at nested access\n")); + rtSemSpinMutexLeave(&State); + return VERR_SEM_NESTED; + } + + /* + * Return if we're in interrupt context and the semaphore isn't + * configure to be interrupt safe. + */ + if (rc == VINF_SEM_BAD_CONTEXT) + { + rtSemSpinMutexLeave(&State); + return VERR_SEM_BAD_CONTEXT; + } + + /* + * Ok, we have to wait. + */ + if (State.fSpin) + { + for (cSpins = 0; ; cSpins++) + { + ASMAtomicCmpXchgHandle(&pThis->hOwner, hSelf, NIL_RTNATIVETHREAD, fRc); + if (fRc) + break; + ASMNopPause(); + if (RT_UNLIKELY(pThis->u32Magic != RTSEMSPINMUTEX_MAGIC)) + { + rtSemSpinMutexLeave(&State); + return VERR_SEM_DESTROYED; + } + + /* + * "Yield" once in a while. This may lower our IRQL/PIL which + * may preempting us, and it will certainly stop the hammering + * of hOwner for a little while. + */ + if ((cSpins & 0x7f) == 0x1f) + { + rtSemSpinMutexLeave(&State); + rtSemSpinMutexEnter(&State, pThis); + Assert(State.fSpin); + } + } + } + else + { + for (cSpins = 0;; cSpins++) + { + ASMAtomicCmpXchgHandle(&pThis->hOwner, hSelf, NIL_RTNATIVETHREAD, fRc); + if (fRc) + break; + ASMNopPause(); + if (RT_UNLIKELY(pThis->u32Magic != RTSEMSPINMUTEX_MAGIC)) + { + rtSemSpinMutexLeave(&State); + return VERR_SEM_DESTROYED; + } + + if ((cSpins & 15) == 15) /* spin a bit before going sleep (again). */ + { + rtSemSpinMutexLeave(&State); + + rc = RTSemEventWait(pThis->hEventSem, RT_INDEFINITE_WAIT); + ASMCompilerBarrier(); + if (RT_SUCCESS(rc)) + AssertReturn(pThis->u32Magic == RTSEMSPINMUTEX_MAGIC, VERR_SEM_DESTROYED); + else if (rc == VERR_INTERRUPTED) + AssertRC(rc); /* shouldn't happen */ + else + { + AssertRC(rc); + return rc; + } + + rc = rtSemSpinMutexEnter(&State, pThis); + AssertRCReturn(rc, rc); + Assert(!State.fSpin); + } + } + } + } + + /* + * We're the semaphore owner. + */ + pThis->SavedState = State; + Assert(pThis->hOwner == hSelf); + return VINF_SUCCESS; +} +RT_EXPORT_SYMBOL(RTSemSpinMutexRequest); + + +RTDECL(int) RTSemSpinMutexRelease(RTSEMSPINMUTEX hSpinMtx) +{ + RTSEMSPINMUTEXINTERNAL *pThis = hSpinMtx; + RTNATIVETHREAD hSelf = RTThreadNativeSelf(); + uint32_t cLockers; + RTSEMSPINMUTEXSTATE State; + bool fRc; + + Assert(hSelf != NIL_RTNATIVETHREAD); + RTSEMSPINMUTEX_VALIDATE_RETURN(pThis); + + /* + * Get the saved state and try release the semaphore. + */ + State = pThis->SavedState; + ASMCompilerBarrier(); + ASMAtomicCmpXchgHandle(&pThis->hOwner, NIL_RTNATIVETHREAD, hSelf, fRc); + AssertMsgReturn(fRc, + ("hOwner=%p hSelf=%p cLockers=%d\n", pThis->hOwner, hSelf, pThis->cLockers), + VERR_NOT_OWNER); + + cLockers = ASMAtomicDecS32(&pThis->cLockers); + rtSemSpinMutexLeave(&State); + if (cLockers > 0) + { + int rc = RTSemEventSignal(pThis->hEventSem); + AssertReleaseMsg(RT_SUCCESS(rc), ("RTSemEventSignal -> %Rrc\n", rc)); + } + return VINF_SUCCESS; +} +RT_EXPORT_SYMBOL(RTSemSpinMutexRelease); + + +RTDECL(int) RTSemSpinMutexDestroy(RTSEMSPINMUTEX hSpinMtx) +{ + RTSEMSPINMUTEXINTERNAL *pThis; + RTSEMEVENT hEventSem; + int rc; + + if (hSpinMtx == NIL_RTSEMSPINMUTEX) + return VINF_SUCCESS; + pThis = hSpinMtx; + RTSEMSPINMUTEX_VALIDATE_RETURN(pThis); + + /* No destruction races allowed! */ + AssertMsg( pThis->cLockers == 0 + && pThis->hOwner == NIL_RTNATIVETHREAD, + ("pThis=%p cLockers=%d hOwner=%p\n", pThis, pThis->cLockers, pThis->hOwner)); + + /* + * Invalidate the structure, free the mutex and free the structure. + */ + ASMAtomicWriteU32(&pThis->u32Magic, RTSEMSPINMUTEX_MAGIC_DEAD); + hEventSem = pThis->hEventSem; + pThis->hEventSem = NIL_RTSEMEVENT; + rc = RTSemEventDestroy(hEventSem); AssertRC(rc); + + RTMemFree(pThis); + return rc; +} +RT_EXPORT_SYMBOL(RTSemSpinMutexDestroy); + diff --git a/src/VBox/Runtime/r0drv/generic/threadctxhooks-r0drv-generic.cpp b/src/VBox/Runtime/r0drv/generic/threadctxhooks-r0drv-generic.cpp new file mode 100644 index 00000000..f268cb02 --- /dev/null +++ b/src/VBox/Runtime/r0drv/generic/threadctxhooks-r0drv-generic.cpp @@ -0,0 +1,73 @@ +/* $Id: threadctxhooks-r0drv-generic.cpp $ */ +/** @file + * IPRT - Thread Context Switching Hook, Ring-0 Driver, Generic. + */ + +/* + * Copyright (C) 2013-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/thread.h> +#include <iprt/errcore.h> + +#include "internal/iprt.h" + +RTDECL(int) RTThreadCtxHookCreate(PRTTHREADCTXHOOK phCtxHook, uint32_t fFlags, PFNRTTHREADCTXHOOK pfnCallback, void *pvUser) +{ + RT_NOREF4(phCtxHook, fFlags, pfnCallback, pvUser); + return VERR_NOT_SUPPORTED; +} +RT_EXPORT_SYMBOL(RTThreadCtxHookCreate); + + +RTDECL(int) RTThreadCtxHookDestroy(RTTHREADCTXHOOK hCtxHook) +{ + return hCtxHook == NIL_RTTHREADCTXHOOK ? VINF_SUCCESS : VERR_INVALID_HANDLE; +} +RT_EXPORT_SYMBOL(RTThreadCtxHookDestroy); + + +RTDECL(int) RTThreadCtxHookEnable(RTTHREADCTXHOOK hCtxHook) +{ + NOREF(hCtxHook); + return VERR_NOT_SUPPORTED; +} +RT_EXPORT_SYMBOL(RTThreadCtxHookEnable); + + +RTDECL(int) RTThreadCtxHookDisable(RTTHREADCTXHOOK hCtxHook) +{ + NOREF(hCtxHook); + return VERR_NOT_SUPPORTED; +} +RT_EXPORT_SYMBOL(RTThreadCtxHookDisable); + + +RTDECL(bool) RTThreadCtxHookIsEnabled(RTTHREADCTXHOOK hCtxHook) +{ + NOREF(hCtxHook); + return false; +} +RT_EXPORT_SYMBOL(RTThreadCtxHookIsEnabled); + |