threadctxhooks-r0drv-linux.c revision 154e168eaf5b66be007b6e9b57e7d1a46971af6b
/* $Id$ */
/** @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;
* 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"
/*
* Linux kernel 2.6.23 introduced thread-context hooks but RedHat 2.6.18 kernels
* got it backported.
*/
/*******************************************************************************
* Structures and Typedefs *
*******************************************************************************/
/**
* The internal thread-context object.
*/
typedef struct RTTHREADCTXINT
{
/** Magic value (RTTHREADCTXINT_MAGIC). */
/** The thread handle (owner) for which the context-hooks are registered. */
/** 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. */
/** User argument passed to the thread-context hook. */
void *pvUser;
/** The thread-context operations. */
struct preempt_ops hPreemptOps;
/** The reference count for this object. */
/**
* 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)
{
stac();
clac();
}
/**
* 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!
*/
{
stac();
clac();
}
/**
* Worker function for RTThreadCtxHooks(Deregister|Release)().
*
* @param pThis Pointer to the internal thread-context object.
*/
{
pThis->fRegistered = false;
}
{
if (RT_UNLIKELY(!pThis))
return VERR_NO_MEMORY;
pThis->fRegistered = false;
*phThreadCtx = pThis;
return VINF_SUCCESS;
}
{
/*
* Validate input.
*/
AssertMsgReturn(pThis->u32Magic == RTTHREADCTXINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis),
return cRefs;
}
{
/*
* Validate input.
*/
if (pThis == NIL_RTTHREADCTX)
return 0;
AssertMsgReturn(pThis->u32Magic == RTTHREADCTXINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis),
if (!cRefs)
{
/*
* If there's still a registered thread-context hook, deregister it now before destroying the object.
*/
if (pThis->fRegistered)
/*
* Paranoia... but since these are ring-0 threads we can't be too careful.
*/
}
else
return cRefs;
}
RTDECL(int) RTThreadCtxHooksRegister(RTTHREADCTX hThreadCtx, PFNRTTHREADCTXHOOK pfnThreadCtxHook, void *pvUser)
{
/*
* Validate input.
*/
if (pThis == NIL_RTTHREADCTX)
return VERR_INVALID_HANDLE;
AssertMsgReturn(pThis->u32Magic == RTTHREADCTXINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis),
/*
* Register the callback.
*/
pThis->fRegistered = true;
return VINF_SUCCESS;
}
{
/*
* Validate input.
*/
if (pThis == NIL_RTTHREADCTX)
return VERR_INVALID_HANDLE;
AssertMsgReturn(pThis->u32Magic == RTTHREADCTXINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis),
/*
* Deregister the callback.
*/
return VINF_SUCCESS;
}
{
/*
* Validate input.
*/
if (pThis == NIL_RTTHREADCTX)
return false;
AssertMsg(pThis->u32Magic == RTTHREADCTXINT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis));
return pThis->fRegistered;
}
#else /* Not supported / Not needed */
{
return VERR_NOT_SUPPORTED;
}
{
return UINT32_MAX;
}
{
return UINT32_MAX;
}
RTDECL(int) RTThreadCtxHooksRegister(RTTHREADCTX hThreadCtx, PFNRTTHREADCTXHOOK pfnThreadCtxHook, void *pvUser)
{
return VERR_NOT_SUPPORTED;
}
{
return VERR_NOT_SUPPORTED;
}
{
return false;
}
#endif /* Not supported / Not needed */