diff options
Diffstat (limited to 'src/VBox/Runtime/r0drv/linux')
20 files changed, 408 insertions, 30 deletions
diff --git a/src/VBox/Runtime/r0drv/linux/RTLogWriteDebugger-r0drv-linux.c b/src/VBox/Runtime/r0drv/linux/RTLogWriteDebugger-r0drv-linux.c index 144d637e..c34f8543 100644 --- a/src/VBox/Runtime/r0drv/linux/RTLogWriteDebugger-r0drv-linux.c +++ b/src/VBox/Runtime/r0drv/linux/RTLogWriteDebugger-r0drv-linux.c @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2006-2007 Oracle Corporation + * Copyright (C) 2006-2010 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; diff --git a/src/VBox/Runtime/r0drv/linux/alloc-r0drv-linux.c b/src/VBox/Runtime/r0drv/linux/alloc-r0drv-linux.c index 2f597651..21e124bd 100644 --- a/src/VBox/Runtime/r0drv/linux/alloc-r0drv-linux.c +++ b/src/VBox/Runtime/r0drv/linux/alloc-r0drv-linux.c @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2006-2010 Oracle Corporation + * Copyright (C) 2006-2012 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -173,7 +173,7 @@ static PRTMEMHDR rtR0MemAllocExecVmArea(size_t cb) for (iPage = 0; iPage < cPages; iPage++) { - papPages[iPage] = alloc_page(GFP_KERNEL | __GFP_HIGHMEM); + papPages[iPage] = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | __GFP_NOWARN); if (!papPages[iPage]) break; } @@ -383,15 +383,15 @@ RTR0DECL(void *) RTMemContAlloc(PRTCCPHYS pPhys, size_t cb) cOrder = CalcPowerOf2Order(cPages); #if (defined(RT_ARCH_AMD64) || defined(CONFIG_X86_PAE)) && defined(GFP_DMA32) /* ZONE_DMA32: 0-4GB */ - paPages = alloc_pages(GFP_DMA32, cOrder); + paPages = alloc_pages(GFP_DMA32 | __GFP_NOWARN, cOrder); if (!paPages) #endif #ifdef RT_ARCH_AMD64 /* ZONE_DMA; 0-16MB */ - paPages = alloc_pages(GFP_DMA, cOrder); + paPages = alloc_pages(GFP_DMA | __GFP_NOWARN, cOrder); #else /* ZONE_NORMAL: 0-896MB */ - paPages = alloc_pages(GFP_USER, cOrder); + paPages = alloc_pages(GFP_USER | __GFP_NOWARN, cOrder); #endif if (paPages) { diff --git a/src/VBox/Runtime/r0drv/linux/assert-r0drv-linux.c b/src/VBox/Runtime/r0drv/linux/assert-r0drv-linux.c index 2a7fef9f..11b3a27e 100644 --- a/src/VBox/Runtime/r0drv/linux/assert-r0drv-linux.c +++ b/src/VBox/Runtime/r0drv/linux/assert-r0drv-linux.c @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2007 Oracle Corporation + * Copyright (C) 2007-2011 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; diff --git a/src/VBox/Runtime/r0drv/linux/initterm-r0drv-linux.c b/src/VBox/Runtime/r0drv/linux/initterm-r0drv-linux.c index 5cf9ad66..fda6e35f 100644 --- a/src/VBox/Runtime/r0drv/linux/initterm-r0drv-linux.c +++ b/src/VBox/Runtime/r0drv/linux/initterm-r0drv-linux.c @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2006-2011 Oracle Corporation + * Copyright (C) 2006-2012 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; diff --git a/src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c b/src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c index e21af78c..2840dd4d 100644 --- a/src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c +++ b/src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c @@ -1,10 +1,10 @@ -/* $Revision: 81432 $ */ +/* $Revision: 91595 $ */ /** @file * IPRT - Ring-0 Memory Objects, Linux. */ /* - * Copyright (C) 2006-2007 Oracle Corporation + * Copyright (C) 2006-2012 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -320,9 +320,9 @@ static int rtR0MemObjLinuxAllocPages(PRTR0MEMOBJLNX *ppMemLnx, RTR0MEMOBJTYPE en || cb <= PAGE_SIZE * 2) { # ifdef VBOX_USE_INSERT_PAGE - paPages = alloc_pages(fFlagsLnx | __GFP_COMP, rtR0MemObjLinuxOrder(cPages)); + paPages = alloc_pages(fFlagsLnx | __GFP_COMP | __GFP_NOWARN, rtR0MemObjLinuxOrder(cPages)); # else - paPages = alloc_pages(fFlagsLnx, rtR0MemObjLinuxOrder(cPages)); + paPages = alloc_pages(fFlagsLnx | __GFP_NOWARN, rtR0MemObjLinuxOrder(cPages)); # endif if (paPages) { @@ -341,7 +341,7 @@ static int rtR0MemObjLinuxAllocPages(PRTR0MEMOBJLNX *ppMemLnx, RTR0MEMOBJTYPE en { for (iPage = 0; iPage < cPages; iPage++) { - pMemLnx->apPages[iPage] = alloc_page(fFlagsLnx); + pMemLnx->apPages[iPage] = alloc_page(fFlagsLnx | __GFP_NOWARN); if (RT_UNLIKELY(!pMemLnx->apPages[iPage])) { while (iPage-- > 0) @@ -1170,7 +1170,7 @@ DECLHIDDEN(int) rtR0MemObjNativeReserveKernel(PPRTR0MEMOBJINTERNAL ppMem, void * * Allocate a dummy page and create a page pointer array for vmap such that * the dummy page is mapped all over the reserved area. */ - pDummyPage = alloc_page(GFP_HIGHUSER); + pDummyPage = alloc_page(GFP_HIGHUSER | __GFP_NOWARN); if (!pDummyPage) return VERR_NO_MEMORY; papPages = RTMemAlloc(sizeof(*papPages) * cPages); @@ -1407,7 +1407,7 @@ DECLHIDDEN(int) rtR0MemObjNativeMapUser(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMOBJ p /* * Allocate a dummy page for use when mapping the memory. */ - pDummyPage = alloc_page(GFP_USER); + pDummyPage = alloc_page(GFP_USER | __GFP_NOWARN); if (!pDummyPage) return VERR_NO_MEMORY; SetPageReserved(pDummyPage); @@ -1527,6 +1527,25 @@ DECLHIDDEN(int) rtR0MemObjNativeMapUser(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMOBJ p } } +#ifdef CONFIG_NUMA_BALANCING + if (RT_SUCCESS(rc)) + { + /** @todo Ugly hack! But right now we have no other means to disable + * automatic NUMA page balancing. */ +# ifdef RT_OS_X86 +# if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0) + pTask->mm->numa_next_reset = jiffies + 0x7fffffffUL; +# endif + pTask->mm->numa_next_scan = jiffies + 0x7fffffffUL; +# else +# if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0) + pTask->mm->numa_next_reset = jiffies + 0x7fffffffffffffffUL; +# endif + pTask->mm->numa_next_scan = jiffies + 0x7fffffffffffffffUL; +# endif + } +#endif + up_write(&pTask->mm->mmap_sem); if (RT_SUCCESS(rc)) diff --git a/src/VBox/Runtime/r0drv/linux/memuserkernel-r0drv-linux.c b/src/VBox/Runtime/r0drv/linux/memuserkernel-r0drv-linux.c index 55431c99..211fc361 100644 --- a/src/VBox/Runtime/r0drv/linux/memuserkernel-r0drv-linux.c +++ b/src/VBox/Runtime/r0drv/linux/memuserkernel-r0drv-linux.c @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2009 Oracle Corporation + * Copyright (C) 2009-2012 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; diff --git a/src/VBox/Runtime/r0drv/linux/mp-r0drv-linux.c b/src/VBox/Runtime/r0drv/linux/mp-r0drv-linux.c index 32ab1234..88971ac5 100644 --- a/src/VBox/Runtime/r0drv/linux/mp-r0drv-linux.c +++ b/src/VBox/Runtime/r0drv/linux/mp-r0drv-linux.c @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2008 Oracle Corporation + * Copyright (C) 2008-2011 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; diff --git a/src/VBox/Runtime/r0drv/linux/mpnotification-r0drv-linux.c b/src/VBox/Runtime/r0drv/linux/mpnotification-r0drv-linux.c index b2a6ab9c..687f3bbd 100644 --- a/src/VBox/Runtime/r0drv/linux/mpnotification-r0drv-linux.c +++ b/src/VBox/Runtime/r0drv/linux/mpnotification-r0drv-linux.c @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2008 Oracle Corporation + * Copyright (C) 2008-2011 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; diff --git a/src/VBox/Runtime/r0drv/linux/process-r0drv-linux.c b/src/VBox/Runtime/r0drv/linux/process-r0drv-linux.c index e69aeace..ce2fe313 100644 --- a/src/VBox/Runtime/r0drv/linux/process-r0drv-linux.c +++ b/src/VBox/Runtime/r0drv/linux/process-r0drv-linux.c @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2006-2007 Oracle Corporation + * Copyright (C) 2006-2010 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; diff --git a/src/VBox/Runtime/r0drv/linux/semevent-r0drv-linux.c b/src/VBox/Runtime/r0drv/linux/semevent-r0drv-linux.c index 2506adc8..9c4c131f 100644 --- a/src/VBox/Runtime/r0drv/linux/semevent-r0drv-linux.c +++ b/src/VBox/Runtime/r0drv/linux/semevent-r0drv-linux.c @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2006-2010 Oracle Corporation + * Copyright (C) 2006-2011 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; diff --git a/src/VBox/Runtime/r0drv/linux/semeventmulti-r0drv-linux.c b/src/VBox/Runtime/r0drv/linux/semeventmulti-r0drv-linux.c index 74cc3900..702e1d00 100644 --- a/src/VBox/Runtime/r0drv/linux/semeventmulti-r0drv-linux.c +++ b/src/VBox/Runtime/r0drv/linux/semeventmulti-r0drv-linux.c @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2006-2010 Oracle Corporation + * Copyright (C) 2006-2011 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; diff --git a/src/VBox/Runtime/r0drv/linux/semmutex-r0drv-linux.c b/src/VBox/Runtime/r0drv/linux/semmutex-r0drv-linux.c index 8297d6dd..25f07654 100644 --- a/src/VBox/Runtime/r0drv/linux/semmutex-r0drv-linux.c +++ b/src/VBox/Runtime/r0drv/linux/semmutex-r0drv-linux.c @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2006-2010 Oracle Corporation + * Copyright (C) 2006-2011 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; diff --git a/src/VBox/Runtime/r0drv/linux/spinlock-r0drv-linux.c b/src/VBox/Runtime/r0drv/linux/spinlock-r0drv-linux.c index 714bc35f..eb141e82 100644 --- a/src/VBox/Runtime/r0drv/linux/spinlock-r0drv-linux.c +++ b/src/VBox/Runtime/r0drv/linux/spinlock-r0drv-linux.c @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2006-2010 Oracle Corporation + * Copyright (C) 2006-2013 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -93,6 +93,7 @@ RTDECL(int) RTSpinlockCreate(PRTSPINLOCK pSpinlock, uint32_t fFlags, const char pThis->idCpuOwner = NIL_RTCPUID; pThis->idAssertCpu = NIL_RTCPUID; #endif + spin_lock_init(&pThis->Spinlock); *pSpinlock = pThis; @@ -129,6 +130,9 @@ RTDECL(void) RTSpinlockAcquire(RTSPINLOCK Spinlock) AssertMsg(pThis && pThis->u32Magic == RTSPINLOCK_MAGIC, ("pThis=%p u32Magic=%08x\n", pThis, pThis ? (int)pThis->u32Magic : 0)); +#if defined(CONFIG_PROVE_LOCKING) && !defined(RT_STRICT) + lockdep_off(); +#endif if (pThis->fFlags & RTSPINLOCK_FLAGS_INTERRUPT_SAFE) { unsigned long fIntSaved; @@ -137,6 +141,9 @@ RTDECL(void) RTSpinlockAcquire(RTSPINLOCK Spinlock) } else spin_lock(&pThis->Spinlock); +#if defined(CONFIG_PROVE_LOCKING) && !defined(RT_STRICT) + lockdep_on(); +#endif RT_ASSERT_PREEMPT_CPUID_SPIN_ACQUIRED(pThis); } @@ -151,6 +158,9 @@ RTDECL(void) RTSpinlockRelease(RTSPINLOCK Spinlock) ("pThis=%p u32Magic=%08x\n", pThis, pThis ? (int)pThis->u32Magic : 0)); RT_ASSERT_PREEMPT_CPUID_SPIN_RELEASE(pThis); +#if defined(CONFIG_PROVE_LOCKING) && !defined(RT_STRICT) + lockdep_off(); +#endif if (pThis->fFlags & RTSPINLOCK_FLAGS_INTERRUPT_SAFE) { unsigned long fIntSaved = pThis->fIntSaved; @@ -159,6 +169,9 @@ RTDECL(void) RTSpinlockRelease(RTSPINLOCK Spinlock) } else spin_unlock(&pThis->Spinlock); +#if defined(CONFIG_PROVE_LOCKING) && !defined(RT_STRICT) + lockdep_on(); +#endif RT_ASSERT_PREEMPT_CPUID(); } diff --git a/src/VBox/Runtime/r0drv/linux/string.h b/src/VBox/Runtime/r0drv/linux/string.h index f2f31941..2314d13c 100644 --- a/src/VBox/Runtime/r0drv/linux/string.h +++ b/src/VBox/Runtime/r0drv/linux/string.h @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2006-2007 Oracle Corporation + * Copyright (C) 2006-2010 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; diff --git a/src/VBox/Runtime/r0drv/linux/the-linux-kernel.h b/src/VBox/Runtime/r0drv/linux/the-linux-kernel.h index eebf6734..a1791eea 100644 --- a/src/VBox/Runtime/r0drv/linux/the-linux-kernel.h +++ b/src/VBox/Runtime/r0drv/linux/the-linux-kernel.h @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2006-2011 Oracle Corporation + * Copyright (C) 2006-2012 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -90,6 +90,9 @@ #include <linux/slab.h> #include <linux/time.h> #include <linux/sched.h> +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) +# include <linux/sched/rt.h> +#endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 7) # include <linux/jiffies.h> #endif @@ -121,6 +124,11 @@ #include <asm/uaccess.h> #include <asm/div64.h> +/* For thread-context hooks. */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) && defined(CONFIG_PREEMPT_NOTIFIERS) +# include <linux/preempt.h> +#endif + /* for workqueue / task queues. */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 41) # include <linux/workqueue.h> @@ -142,6 +150,10 @@ # define DEFINE_WAIT(name) DECLARE_WAITQUEUE(name, current) #endif +#ifndef __GFP_NOWARN +# define __GFP_NOWARN 0 +#endif + /* * 2.4 / early 2.6 compatibility wrappers */ diff --git a/src/VBox/Runtime/r0drv/linux/thread-r0drv-linux.c b/src/VBox/Runtime/r0drv/linux/thread-r0drv-linux.c index ecd53717..d5b69d62 100644 --- a/src/VBox/Runtime/r0drv/linux/thread-r0drv-linux.c +++ b/src/VBox/Runtime/r0drv/linux/thread-r0drv-linux.c @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2006-2007 Oracle Corporation + * Copyright (C) 2006-2011 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -87,6 +87,7 @@ RTDECL(bool) RTThreadYield(void) #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 20) yield(); #else + /** @todo r=ramshankar: Can we use cond_resched() instead? */ set_current_state(TASK_RUNNING); sys_sched_yield(); schedule(); @@ -159,6 +160,8 @@ RT_EXPORT_SYMBOL(RTThreadPreemptIsPendingTrusty); RTDECL(bool) RTThreadPreemptIsPossible(void) { + /** @todo r=ramshankar: What about CONFIG_PREEMPT_VOLUNTARY? That can preempt + * too but does so in voluntarily in explicit preemption points. */ #ifdef CONFIG_PREEMPT return true; /* yes, kernel preemption is possible. */ #else @@ -174,6 +177,7 @@ RTDECL(void) RTThreadPreemptDisable(PRTTHREADPREEMPTSTATE pState) AssertPtr(pState); Assert(pState->u32Reserved == 0); pState->u32Reserved = 42; + /* This ASSUMES that CONFIG_PREEMPT_COUNT is always defined with CONFIG_PREEMPT. */ preempt_disable(); RT_ASSERT_PREEMPT_CPUID_DISABLE(pState); diff --git a/src/VBox/Runtime/r0drv/linux/thread2-r0drv-linux.c b/src/VBox/Runtime/r0drv/linux/thread2-r0drv-linux.c index a9561c42..01956565 100644 --- a/src/VBox/Runtime/r0drv/linux/thread2-r0drv-linux.c +++ b/src/VBox/Runtime/r0drv/linux/thread2-r0drv-linux.c @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2006-2011 Oracle Corporation + * Copyright (C) 2006-2012 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; diff --git a/src/VBox/Runtime/r0drv/linux/threadctxhooks-r0drv-linux.c b/src/VBox/Runtime/r0drv/linux/threadctxhooks-r0drv-linux.c new file mode 100644 index 00000000..c0b39371 --- /dev/null +++ b/src/VBox/Runtime/r0drv/linux/threadctxhooks-r0drv-linux.c @@ -0,0 +1,330 @@ +/* $Id: threadctxhooks-r0drv-linux.c $ */ +/** @file + * IPRT - Thread-Context Hook, Ring-0 Driver, Linux. + */ + +/* + * Copyright (C) 2013 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 "the-linux-kernel.h" +#include "internal/iprt.h" + +#include <iprt/mem.h> +#include <iprt/assert.h> +#include <iprt/thread.h> +#include <iprt/err.h> +#include <iprt/asm.h> +#include "internal/thread.h" + +/* + * Linux kernel 2.6.23 introduced thread-context hooks but RedHat 2.6.18 kernels + * got it backported. + */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) && defined(CONFIG_PREEMPT_NOTIFIERS) + +/******************************************************************************* +* Structures and Typedefs * +*******************************************************************************/ +/** + * The internal thread-context object. + */ +typedef struct RTTHREADCTXINT +{ + /** Magic value (RTTHREADCTXINT_MAGIC). */ + uint32_t volatile u32Magic; + /** The thread handle (owner) for which the context-hooks are registered. */ + RTNATIVETHREAD hOwner; + /** The preemption notifier object. */ + struct preempt_notifier hPreemptNotifier; + /** Whether this handle has any hooks registered or not. */ + bool fRegistered; + /** Pointer to the registered thread-context hook. */ + PFNRTTHREADCTXHOOK pfnThreadCtxHook; + /** User argument passed to the thread-context hook. */ + void *pvUser; + /** The thread-context operations. */ + struct preempt_ops hPreemptOps; + /** The reference count for this object. */ + uint32_t volatile cRefs; +} RTTHREADCTXINT, *PRTTHREADCTXINT; + + +/** + * Hook function for the thread-preempting event. + * + * @param pPreemptNotifier Pointer to the preempt_notifier struct. + * @param pNext Pointer to the task that is preempting the + * current thread. + * + * @remarks Called with the rq (runqueue) lock held and with preemption and + * interrupts disabled! + */ +static void rtThreadCtxHooksLnxSchedOut(struct preempt_notifier *pPreemptNotifier, struct task_struct *pNext) +{ + PRTTHREADCTXINT pThis = RT_FROM_MEMBER(pPreemptNotifier, RTTHREADCTXINT, hPreemptNotifier); + AssertPtr(pThis); + AssertPtr(pThis->pfnThreadCtxHook); + Assert(pThis->fRegistered); + Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD)); + + pThis->pfnThreadCtxHook(RTTHREADCTXEVENT_PREEMPTING, pThis->pvUser); +} + + +/** + * Hook function for the thread-resumed event. + * + * @param pPreemptNotifier Pointer to the preempt_notifier struct. + * @param iCpu The CPU this thread is scheduled on. + * + * @remarks Called without holding the rq (runqueue) lock and with preemption + * enabled! + */ +static void rtThreadCtxHooksLnxSchedIn(struct preempt_notifier *pPreemptNotifier, int iCpu) +{ + PRTTHREADCTXINT pThis = RT_FROM_MEMBER(pPreemptNotifier, RTTHREADCTXINT, hPreemptNotifier); + AssertPtr(pThis); + AssertPtr(pThis->pfnThreadCtxHook); + Assert(pThis->fRegistered); + + pThis->pfnThreadCtxHook(RTTHREADCTXEVENT_RESUMED, pThis->pvUser); +} + + +/** + * Worker function for RTThreadCtxHooks(Deregister|Release)(). + * + * @param pThis Pointer to the internal thread-context object. + */ +DECLINLINE(void) rtThreadCtxHooksDeregister(PRTTHREADCTXINT pThis) +{ + preempt_notifier_unregister(&pThis->hPreemptNotifier); + pThis->hPreemptOps.sched_out = NULL; + pThis->hPreemptOps.sched_in = NULL; + pThis->fRegistered = false; +} + + +RTDECL(int) RTThreadCtxHooksCreate(PRTTHREADCTX phThreadCtx) +{ + PRTTHREADCTXINT pThis; + Assert(RTThreadPreemptIsEnabled(NIL_RTTHREAD)); + + pThis = (PRTTHREADCTXINT)RTMemAllocZ(sizeof(*pThis)); + if (RT_UNLIKELY(!pThis)) + return VERR_NO_MEMORY; + pThis->u32Magic = RTTHREADCTXINT_MAGIC; + pThis->hOwner = RTThreadNativeSelf(); + pThis->fRegistered = false; + preempt_notifier_init(&pThis->hPreemptNotifier, &pThis->hPreemptOps); + pThis->cRefs = 1; + + *phThreadCtx = pThis; + return VINF_SUCCESS; +} +RT_EXPORT_SYMBOL(RTThreadCtxHooksCreate); + + +RTDECL(uint32_t) RTThreadCtxHooksRetain(RTTHREADCTX hThreadCtx) +{ + /* + * Validate input. + */ + uint32_t cRefs; + PRTTHREADCTXINT pThis = hThreadCtx; + AssertPtr(pThis); + AssertMsgReturn(pThis->u32Magic == RTTHREADCTXINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), + UINT32_MAX); + + cRefs = ASMAtomicIncU32(&pThis->cRefs); + Assert(cRefs < UINT32_MAX / 2); + return cRefs; +} +RT_EXPORT_SYMBOL(RTThreadCtxHooksRetain); + + + +RTDECL(uint32_t) RTThreadCtxHooksRelease(RTTHREADCTX hThreadCtx) +{ + /* + * Validate input. + */ + uint32_t cRefs; + PRTTHREADCTXINT pThis = hThreadCtx; + if (pThis == NIL_RTTHREADCTX) + return 0; + + AssertPtr(pThis); + AssertMsgReturn(pThis->u32Magic == RTTHREADCTXINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), + UINT32_MAX); + Assert(RTThreadPreemptIsEnabled(NIL_RTTHREAD)); + + cRefs = ASMAtomicDecU32(&pThis->cRefs); + if (!cRefs) + { + /* + * If there's still a registered thread-context hook, deregister it now before destroying the object. + */ + if (pThis->fRegistered) + rtThreadCtxHooksDeregister(pThis); + + /* + * Paranoia... but since these are ring-0 threads we can't be too careful. + */ + Assert(!pThis->fRegistered); + Assert(!pThis->hPreemptOps.sched_out); + Assert(!pThis->hPreemptOps.sched_in); + + ASMAtomicWriteU32(&pThis->u32Magic, ~RTTHREADCTXINT_MAGIC); + RTMemFree(pThis); + } + else + Assert(cRefs < UINT32_MAX / 2); + + return cRefs; +} +RT_EXPORT_SYMBOL(RTThreadCtxHooksRelease); + + +RTDECL(int) RTThreadCtxHooksRegister(RTTHREADCTX hThreadCtx, PFNRTTHREADCTXHOOK pfnThreadCtxHook, void *pvUser) +{ + /* + * Validate input. + */ + PRTTHREADCTXINT pThis = hThreadCtx; + if (pThis == NIL_RTTHREADCTX) + return VERR_INVALID_HANDLE; + AssertPtr(pThis); + AssertMsgReturn(pThis->u32Magic == RTTHREADCTXINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), + VERR_INVALID_HANDLE); + Assert(pThis->hOwner == RTThreadNativeSelf()); + Assert(!pThis->hPreemptOps.sched_out); + Assert(!pThis->hPreemptOps.sched_in); + + /* + * Register the callback. + */ + pThis->hPreemptOps.sched_out = rtThreadCtxHooksLnxSchedOut; + pThis->hPreemptOps.sched_in = rtThreadCtxHooksLnxSchedIn; + pThis->pvUser = pvUser; + pThis->pfnThreadCtxHook = pfnThreadCtxHook; + pThis->fRegistered = true; + preempt_notifier_register(&pThis->hPreemptNotifier); + + return VINF_SUCCESS; +} +RT_EXPORT_SYMBOL(RTThreadCtxHooksRegister); + + +RTDECL(int) RTThreadCtxHooksDeregister(RTTHREADCTX hThreadCtx) +{ + /* + * Validate input. + */ + PRTTHREADCTXINT pThis = hThreadCtx; + if (pThis == NIL_RTTHREADCTX) + return VERR_INVALID_HANDLE; + AssertPtr(pThis); + AssertMsgReturn(pThis->u32Magic == RTTHREADCTXINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), + VERR_INVALID_HANDLE); + Assert(pThis->hOwner == RTThreadNativeSelf()); + Assert(pThis->fRegistered); + + /* + * Deregister the callback. + */ + rtThreadCtxHooksDeregister(pThis); + return VINF_SUCCESS; +} +RT_EXPORT_SYMBOL(RTThreadCtxHooksDeregister); + + +RTDECL(bool) RTThreadCtxHooksAreRegistered(RTTHREADCTX hThreadCtx) +{ + /* + * Validate input. + */ + PRTTHREADCTXINT pThis = hThreadCtx; + if (pThis == NIL_RTTHREADCTX) + return false; + AssertPtr(pThis); + AssertMsg(pThis->u32Magic == RTTHREADCTXINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis)); + + return pThis->fRegistered; +} + +#else /* Not supported / Not needed */ + +RTDECL(int) RTThreadCtxHooksCreate(PRTTHREADCTX phThreadCtx) +{ + NOREF(phThreadCtx); + return VERR_NOT_SUPPORTED; +} +RT_EXPORT_SYMBOL(RTThreadCtxHooksCreate); + + +RTDECL(uint32_t) RTThreadCtxHooksRetain(RTTHREADCTX hThreadCtx) +{ + NOREF(hThreadCtx); + return UINT32_MAX; +} +RT_EXPORT_SYMBOL(RTThreadCtxHooksRetain); + + +RTDECL(uint32_t) RTThreadCtxHooksRelease(RTTHREADCTX hThreadCtx) +{ + NOREF(hThreadCtx); + return UINT32_MAX; +} +RT_EXPORT_SYMBOL(RTThreadCtxHooksRelease); + + +RTDECL(int) RTThreadCtxHooksRegister(RTTHREADCTX hThreadCtx, PFNRTTHREADCTXHOOK pfnThreadCtxHook, void *pvUser) +{ + NOREF(hThreadCtx); + NOREF(pfnThreadCtxHook); + NOREF(pvUser); + return VERR_NOT_SUPPORTED; +} +RT_EXPORT_SYMBOL(RTThreadCtxHooksRegister); + + +RTDECL(int) RTThreadCtxHooksDeregister(RTTHREADCTX hThreadCtx) +{ + NOREF(hThreadCtx); + return VERR_NOT_SUPPORTED; +} +RT_EXPORT_SYMBOL(RTThreadCtxHooksDeregister); + + +RTDECL(bool) RTThreadCtxHooksAreRegistered(RTTHREADCTX hThreadCtx) +{ + NOREF(hThreadCtx); + return false; +} +RT_EXPORT_SYMBOL(RTThreadCtxHooksAreRegistered); + +#endif /* Not supported / Not needed */ + diff --git a/src/VBox/Runtime/r0drv/linux/time-r0drv-linux.c b/src/VBox/Runtime/r0drv/linux/time-r0drv-linux.c index c0fb357f..cd2e70f1 100644 --- a/src/VBox/Runtime/r0drv/linux/time-r0drv-linux.c +++ b/src/VBox/Runtime/r0drv/linux/time-r0drv-linux.c @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2006-2008 Oracle Corporation + * Copyright (C) 2006-2010 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; diff --git a/src/VBox/Runtime/r0drv/linux/timer-r0drv-linux.c b/src/VBox/Runtime/r0drv/linux/timer-r0drv-linux.c index 710a0489..b5c875d3 100644 --- a/src/VBox/Runtime/r0drv/linux/timer-r0drv-linux.c +++ b/src/VBox/Runtime/r0drv/linux/timer-r0drv-linux.c @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2006-2011 Oracle Corporation + * Copyright (C) 2006-2012 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -1557,7 +1557,7 @@ RTDECL(int) RTTimerCreateEx(PRTTIMER *ppTimer, uint64_t u64NanoInterval, uint32_ */ if (cCpus > 1) { - int rc = RTSpinlockCreate(&pTimer->hSpinlock, RTSPINLOCK_FLAGS_INTERRUPT_UNSAFE, "RTTimerLnx"); + int rc = RTSpinlockCreate(&pTimer->hSpinlock, RTSPINLOCK_FLAGS_INTERRUPT_SAFE, "RTTimerLnx"); if (RT_SUCCESS(rc)) rc = RTMpNotificationRegister(rtTimerLinuxMpEvent, pTimer); else |