semfastmutex-r0drv-nt.cpp revision 7a99c98125959dcc22e09cf74a744ccf37c0e55b
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync/* $Id$ */
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync/** @file
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * IPRT - Fast Mutex Semaphores, Ring-0 Driver, NT.
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync */
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync/*
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync *
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * available from http://www.virtualbox.org. This file is free software;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * you can redistribute it and/or modify it under the terms of the GNU
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * General Public License (GPL) as published by the Free Software
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync *
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * The contents of this file may alternatively be used under the terms
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * of the Common Development and Distribution License Version 1.0
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * VirtualBox OSE distribution, in which case the provisions of the
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * CDDL are applicable instead of those of the GPL.
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync *
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * You may elect to license modified versions of this file under the
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * terms and conditions of either the GPL or the CDDL or both.
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync *
6754e49069315bd28137abb0f9241e3aeb99a97evboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
b8908d384db2324f04a2f68a13e67ea32ebf609avboxsync * additional information or have any questions.
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync */
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync/*******************************************************************************
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync* Header Files *
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync*******************************************************************************/
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync#include "the-nt-kernel.h"
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync#include <iprt/semaphore.h>
b8908d384db2324f04a2f68a13e67ea32ebf609avboxsync#include <iprt/alloc.h>
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync#include <iprt/assert.h>
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync#include <iprt/asm.h>
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync#include <iprt/err.h>
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
b8908d384db2324f04a2f68a13e67ea32ebf609avboxsync#include "internal/magics.h"
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync/*******************************************************************************
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync* Structures and Typedefs *
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync*******************************************************************************/
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync/**
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * Wrapper for the linux semaphore structure.
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync */
b8908d384db2324f04a2f68a13e67ea32ebf609avboxsynctypedef struct RTSEMFASTMUTEXINTERNAL
8b98c71a5a01d215eafbc3605cb7a66cc91ea774vboxsync{
8b98c71a5a01d215eafbc3605cb7a66cc91ea774vboxsync /** Magic value (RTSEMFASTMUTEX_MAGIC). */
8b98c71a5a01d215eafbc3605cb7a66cc91ea774vboxsync uint32_t u32Magic;
8b98c71a5a01d215eafbc3605cb7a66cc91ea774vboxsync /** the NT fast mutex. */
8b98c71a5a01d215eafbc3605cb7a66cc91ea774vboxsync FAST_MUTEX Mutex;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync} RTSEMFASTMUTEXINTERNAL, *PRTSEMFASTMUTEXINTERNAL;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsyncRTDECL(int) RTSemFastMutexCreate(PRTSEMFASTMUTEX pMutexSem)
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync{
8b98c71a5a01d215eafbc3605cb7a66cc91ea774vboxsync /*
8b98c71a5a01d215eafbc3605cb7a66cc91ea774vboxsync * Allocate.
8b98c71a5a01d215eafbc3605cb7a66cc91ea774vboxsync */
8b98c71a5a01d215eafbc3605cb7a66cc91ea774vboxsync PRTSEMFASTMUTEXINTERNAL pFastInt;
8b98c71a5a01d215eafbc3605cb7a66cc91ea774vboxsync Assert(sizeof(*pFastInt) > sizeof(void *));
8b98c71a5a01d215eafbc3605cb7a66cc91ea774vboxsync pFastInt = (PRTSEMFASTMUTEXINTERNAL)RTMemAlloc(sizeof(*pFastInt));
8b98c71a5a01d215eafbc3605cb7a66cc91ea774vboxsync if (!pFastInt)
8b98c71a5a01d215eafbc3605cb7a66cc91ea774vboxsync return VERR_NO_MEMORY;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync /*
8b98c71a5a01d215eafbc3605cb7a66cc91ea774vboxsync * Initialize.
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync */
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync pFastInt->u32Magic = RTSEMFASTMUTEX_MAGIC;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync ExInitializeFastMutex(&pFastInt->Mutex);
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync *pMutexSem = pFastInt;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync return VINF_SUCCESS;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync}
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsyncRTDECL(int) RTSemFastMutexDestroy(RTSEMFASTMUTEX MutexSem)
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync{
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync /*
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * Validate.
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync */
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync PRTSEMFASTMUTEXINTERNAL pFastInt = (PRTSEMFASTMUTEXINTERNAL)MutexSem;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync if (!pFastInt)
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync return VERR_INVALID_PARAMETER;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync if (pFastInt->u32Magic != RTSEMFASTMUTEX_MAGIC)
6754e49069315bd28137abb0f9241e3aeb99a97evboxsync {
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync AssertMsgFailed(("pFastInt->u32Magic=%RX32 pMutexInt=%p\n", pFastInt->u32Magic, pFastInt));
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync return VERR_INVALID_PARAMETER;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync }
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync ASMAtomicIncU32(&pFastInt->u32Magic);
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync Assert(pFastInt->Mutex.Count == 1);
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync /* It's not very clear what this Contention field really means. Seems to be a counter for the number of times contention occurred. (see e.g. http://winprogger.com/?p=6)
6754e49069315bd28137abb0f9241e3aeb99a97evboxsync * The following assertion is therefor wrong:
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * Assert(pFastInt->Mutex.Contention == 0);
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync */
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync RTMemFree(pFastInt);
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync return VINF_SUCCESS;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync}
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
508452243fd3328f7b9e0405d39fb9dc004e31b8vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsyncRTDECL(int) RTSemFastMutexRequest(RTSEMFASTMUTEX MutexSem)
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync{
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync /*
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * Validate.
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync */
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync PRTSEMFASTMUTEXINTERNAL pFastInt = (PRTSEMFASTMUTEXINTERNAL)MutexSem;
6754e49069315bd28137abb0f9241e3aeb99a97evboxsync if ( !pFastInt
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync || pFastInt->u32Magic != RTSEMFASTMUTEX_MAGIC)
6754e49069315bd28137abb0f9241e3aeb99a97evboxsync {
6754e49069315bd28137abb0f9241e3aeb99a97evboxsync AssertMsgFailed(("pFastInt->u32Magic=%RX32 pMutexInt=%p\n", pFastInt ? pFastInt->u32Magic : 0, pFastInt));
6754e49069315bd28137abb0f9241e3aeb99a97evboxsync return VERR_INVALID_PARAMETER;
c8befbec2916e0bba4d254c81d87e5b0e78013bavboxsync }
6754e49069315bd28137abb0f9241e3aeb99a97evboxsync#if 1
508452243fd3328f7b9e0405d39fb9dc004e31b8vboxsync /*
6754e49069315bd28137abb0f9241e3aeb99a97evboxsync * ExAcquireFastMutex will set the IRQL to APC regardless of our current
8b98c71a5a01d215eafbc3605cb7a66cc91ea774vboxsync * level. Lowering the IRQL may screw things up, so to allow this.
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync */
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync# if 0 /** @todo enable this when the logger has been fixed. */
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync AssertMsg(KeGetCurrentIrql() <= APC_LEVEL,
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync ("%d\n", KeGetCurrentIrql()),
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync VERR_INVALID_STATE);
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync# else /* the gentler approach. */
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync KIRQL Irql = KeGetCurrentIrql();
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync if (Irql > APC_LEVEL)
8b98c71a5a01d215eafbc3605cb7a66cc91ea774vboxsync return VERR_INVALID_STATE;
# endif
#endif
ExAcquireFastMutex(&pFastInt->Mutex);
return VINF_SUCCESS;
}
RTDECL(int) RTSemFastMutexRelease(RTSEMFASTMUTEX MutexSem)
{
/*
* Validate.
*/
PRTSEMFASTMUTEXINTERNAL pFastInt = (PRTSEMFASTMUTEXINTERNAL)MutexSem;
if ( !pFastInt
|| pFastInt->u32Magic != RTSEMFASTMUTEX_MAGIC)
{
AssertMsgFailed(("pFastInt->u32Magic=%RX32 pMutexInt=%p\n", pFastInt ? pFastInt->u32Magic : 0, pFastInt));
return VERR_INVALID_PARAMETER;
}
ExReleaseFastMutex(&pFastInt->Mutex);
return VINF_SUCCESS;
}