cc66247640b520463f925a5533fc9e5de06aa982vboxsync/* $Id$ */
cc66247640b520463f925a5533fc9e5de06aa982vboxsync/** @file
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * IPRT - Handle Tables, internal header.
cc66247640b520463f925a5533fc9e5de06aa982vboxsync */
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync/*
506922036e4604028e862309a96bb403eee83a48vboxsync * Copyright (C) 2008-2013 Oracle Corporation
cc66247640b520463f925a5533fc9e5de06aa982vboxsync *
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * available from http://www.virtualbox.org. This file is free software;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * you can redistribute it and/or modify it under the terms of the GNU
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * General Public License (GPL) as published by the Free Software
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
cc66247640b520463f925a5533fc9e5de06aa982vboxsync *
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * The contents of this file may alternatively be used under the terms
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * of the Common Development and Distribution License Version 1.0
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * VirtualBox OSE distribution, in which case the provisions of the
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * CDDL are applicable instead of those of the GPL.
cc66247640b520463f925a5533fc9e5de06aa982vboxsync *
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * You may elect to license modified versions of this file under the
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * terms and conditions of either the GPL or the CDDL or both.
cc66247640b520463f925a5533fc9e5de06aa982vboxsync */
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync/*******************************************************************************
cc66247640b520463f925a5533fc9e5de06aa982vboxsync* Defined Constants And Macros *
cc66247640b520463f925a5533fc9e5de06aa982vboxsync*******************************************************************************/
cc66247640b520463f925a5533fc9e5de06aa982vboxsync/** The number of entries in the 2nd level lookup table. */
cc66247640b520463f925a5533fc9e5de06aa982vboxsync#define RTHT_LEVEL2_ENTRIES 2048
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync/** The number of (max) 1st level entries requiring dynamic allocation of the
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * 1st level table. If the max number is below this threshold, the 1st level
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * table will be allocated as part of the handle table structure. */
cc66247640b520463f925a5533fc9e5de06aa982vboxsync#define RTHT_LEVEL1_DYN_ALLOC_THRESHOLD 256
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync/** Checks whether a object pointer is really a free entry or not. */
cc66247640b520463f925a5533fc9e5de06aa982vboxsync#define RTHT_IS_FREE(pvObj) ( ((uintptr_t)(pvObj) & 3) == 3 )
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync/** Sets RTHTENTRYFREE::iNext. */
cc66247640b520463f925a5533fc9e5de06aa982vboxsync#define RTHT_SET_FREE_IDX(pFree, idx) \
cc66247640b520463f925a5533fc9e5de06aa982vboxsync do { \
cc66247640b520463f925a5533fc9e5de06aa982vboxsync (pFree)->iNext = ((uintptr_t)((uint32_t)(idx)) << 2) | 3U; \
cc66247640b520463f925a5533fc9e5de06aa982vboxsync } while (0)
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync/** Gets the index part of RTHTENTRYFREE::iNext. */
cc66247640b520463f925a5533fc9e5de06aa982vboxsync#define RTHT_GET_FREE_IDX(pFree) ( (uint32_t)((pFree)->iNext >> 2) )
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync/** @def NIL_RTHT_INDEX
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * The NIL handle index for use in the free list. (The difference between
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * 32-bit and 64-bit hosts here comes down to the shifting performed for
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * RTHTENTRYFREE::iNext.) */
cc66247640b520463f925a5533fc9e5de06aa982vboxsync#if ARCH_BITS == 32
cc66247640b520463f925a5533fc9e5de06aa982vboxsync# define NIL_RTHT_INDEX ( UINT32_C(0x3fffffff) )
cc66247640b520463f925a5533fc9e5de06aa982vboxsync#elif ARCH_BITS >= 34
cc66247640b520463f925a5533fc9e5de06aa982vboxsync# define NIL_RTHT_INDEX ( UINT32_C(0xffffffff) )
cc66247640b520463f925a5533fc9e5de06aa982vboxsync#else
cc66247640b520463f925a5533fc9e5de06aa982vboxsync# error "Missing or unsupported ARCH_BITS."
cc66247640b520463f925a5533fc9e5de06aa982vboxsync#endif
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync/*******************************************************************************
cc66247640b520463f925a5533fc9e5de06aa982vboxsync* Structures and Typedefs *
cc66247640b520463f925a5533fc9e5de06aa982vboxsync*******************************************************************************/
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync/**
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * Handle table entry, simple variant.
cc66247640b520463f925a5533fc9e5de06aa982vboxsync */
cc66247640b520463f925a5533fc9e5de06aa982vboxsynctypedef struct RTHTENTRY
cc66247640b520463f925a5533fc9e5de06aa982vboxsync{
cc66247640b520463f925a5533fc9e5de06aa982vboxsync /** The object. */
cc66247640b520463f925a5533fc9e5de06aa982vboxsync void *pvObj;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync} RTHTENTRY;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync/** Pointer to a handle table entry, simple variant. */
cc66247640b520463f925a5533fc9e5de06aa982vboxsynctypedef RTHTENTRY *PRTHTENTRY;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync/**
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * Handle table entry, context variant.
cc66247640b520463f925a5533fc9e5de06aa982vboxsync */
cc66247640b520463f925a5533fc9e5de06aa982vboxsynctypedef struct RTHTENTRYCTX
cc66247640b520463f925a5533fc9e5de06aa982vboxsync{
cc66247640b520463f925a5533fc9e5de06aa982vboxsync /** The object. */
cc66247640b520463f925a5533fc9e5de06aa982vboxsync void *pvObj;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync /** The context. */
cc66247640b520463f925a5533fc9e5de06aa982vboxsync void *pvCtx;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync} RTHTENTRYCTX;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync/** Pointer to a handle table entry, context variant. */
cc66247640b520463f925a5533fc9e5de06aa982vboxsynctypedef RTHTENTRYCTX *PRTHTENTRYCTX;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync/**
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * Free handle table entry, shared by all variants.
cc66247640b520463f925a5533fc9e5de06aa982vboxsync */
cc66247640b520463f925a5533fc9e5de06aa982vboxsynctypedef struct RTHTENTRYFREE
cc66247640b520463f925a5533fc9e5de06aa982vboxsync{
cc66247640b520463f925a5533fc9e5de06aa982vboxsync /** The index of the next handle, special format.
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * In order to distinguish free and used handle table entries we exploit
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * the heap alignment and use the lower two bits to do this. Used entries
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * will have these bits set to 0, while free entries will have tem set
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * to 3. Use the RTHT_GET_FREE_IDX and RTHT_SET_FREE_IDX macros to access
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * this field. */
cc66247640b520463f925a5533fc9e5de06aa982vboxsync uintptr_t iNext;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync} RTHTENTRYFREE;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync/** Pointer to a free handle table entry. */
cc66247640b520463f925a5533fc9e5de06aa982vboxsynctypedef RTHTENTRYFREE *PRTHTENTRYFREE;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsyncAssertCompile(sizeof(RTHTENTRYFREE) <= sizeof(RTHTENTRY));
cc66247640b520463f925a5533fc9e5de06aa982vboxsyncAssertCompile(sizeof(RTHTENTRYFREE) <= sizeof(RTHTENTRYCTX));
cc66247640b520463f925a5533fc9e5de06aa982vboxsyncAssertCompileMemberOffset(RTHTENTRYFREE, iNext, 0);
cc66247640b520463f925a5533fc9e5de06aa982vboxsyncAssertCompileMemberOffset(RTHTENTRY, pvObj, 0);
cc66247640b520463f925a5533fc9e5de06aa982vboxsyncAssertCompileMemberOffset(RTHTENTRYCTX, pvObj, 0);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync/**
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * Internal handle table structure.
cc66247640b520463f925a5533fc9e5de06aa982vboxsync */
cc66247640b520463f925a5533fc9e5de06aa982vboxsynctypedef struct RTHANDLETABLEINT
cc66247640b520463f925a5533fc9e5de06aa982vboxsync{
cc66247640b520463f925a5533fc9e5de06aa982vboxsync /** Magic value (RTHANDLETABLE_MAGIC). */
cc66247640b520463f925a5533fc9e5de06aa982vboxsync uint32_t u32Magic;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync /** The handle table flags specified to RTHandleTableCreateEx. */
cc66247640b520463f925a5533fc9e5de06aa982vboxsync uint32_t fFlags;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync /** The base handle value (i.e. the first handle). */
cc66247640b520463f925a5533fc9e5de06aa982vboxsync uint32_t uBase;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync /** The current number of handle table entries. */
cc66247640b520463f925a5533fc9e5de06aa982vboxsync uint32_t cCur;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync /** The spinlock handle (NIL if RTHANDLETABLE_FLAGS_LOCKED wasn't used). */
cc66247640b520463f925a5533fc9e5de06aa982vboxsync RTSPINLOCK hSpinlock;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync /** The level one lookup table. */
cc66247640b520463f925a5533fc9e5de06aa982vboxsync void **papvLevel1;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync /** The retainer callback. Can be NULL. */
cc66247640b520463f925a5533fc9e5de06aa982vboxsync PFNRTHANDLETABLERETAIN pfnRetain;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync /** The user argument to the retainer. */
cc66247640b520463f925a5533fc9e5de06aa982vboxsync void *pvRetainUser;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync /** The max number of handles. */
cc66247640b520463f925a5533fc9e5de06aa982vboxsync uint32_t cMax;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync /** The number of handles currently allocated. (for optimizing destruction) */
cc66247640b520463f925a5533fc9e5de06aa982vboxsync uint32_t cCurAllocated;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync /** The current number of 1st level entries. */
cc66247640b520463f925a5533fc9e5de06aa982vboxsync uint32_t cLevel1;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync /** Head of the list of free handle entires (index). */
cc66247640b520463f925a5533fc9e5de06aa982vboxsync uint32_t iFreeHead;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync /** Tail of the list of free handle entires (index). */
cc66247640b520463f925a5533fc9e5de06aa982vboxsync uint32_t iFreeTail;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync} RTHANDLETABLEINT;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync/** Pointer to an handle table structure. */
cc66247640b520463f925a5533fc9e5de06aa982vboxsynctypedef RTHANDLETABLEINT *PRTHANDLETABLEINT;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync/**
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * Looks up a simple index.
cc66247640b520463f925a5533fc9e5de06aa982vboxsync *
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * @returns Pointer to the handle table entry on success, NULL on failure.
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * @param pThis The handle table structure.
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * @param i The index to look up.
cc66247640b520463f925a5533fc9e5de06aa982vboxsync */
cc66247640b520463f925a5533fc9e5de06aa982vboxsyncDECLINLINE(PRTHTENTRY) rtHandleTableLookupSimpleIdx(PRTHANDLETABLEINT pThis, uint32_t i)
cc66247640b520463f925a5533fc9e5de06aa982vboxsync{
cc66247640b520463f925a5533fc9e5de06aa982vboxsync if (i < pThis->cCur)
cc66247640b520463f925a5533fc9e5de06aa982vboxsync {
cc66247640b520463f925a5533fc9e5de06aa982vboxsync PRTHTENTRY paTable = (PRTHTENTRY)pThis->papvLevel1[i / RTHT_LEVEL2_ENTRIES];
cc66247640b520463f925a5533fc9e5de06aa982vboxsync if (paTable)
cc66247640b520463f925a5533fc9e5de06aa982vboxsync return &paTable[i % RTHT_LEVEL2_ENTRIES];
cc66247640b520463f925a5533fc9e5de06aa982vboxsync }
210e87cc03f92d54681b81a81cc1fdbd48a9d2c8vboxsync return NULL;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync}
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync/**
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * Looks up a simple handle.
cc66247640b520463f925a5533fc9e5de06aa982vboxsync *
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * @returns Pointer to the handle table entry on success, NULL on failure.
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * @param pThis The handle table structure.
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * @param h The handle to look up.
cc66247640b520463f925a5533fc9e5de06aa982vboxsync */
cc66247640b520463f925a5533fc9e5de06aa982vboxsyncDECLINLINE(PRTHTENTRY) rtHandleTableLookupSimple(PRTHANDLETABLEINT pThis, uint32_t h)
cc66247640b520463f925a5533fc9e5de06aa982vboxsync{
cc66247640b520463f925a5533fc9e5de06aa982vboxsync return rtHandleTableLookupSimpleIdx(pThis, h - pThis->uBase);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync}
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync/**
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * Looks up a context index.
cc66247640b520463f925a5533fc9e5de06aa982vboxsync *
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * @returns Pointer to the handle table entry on success, NULL on failure.
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * @param pThis The handle table structure.
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * @param i The index to look up.
cc66247640b520463f925a5533fc9e5de06aa982vboxsync */
cc66247640b520463f925a5533fc9e5de06aa982vboxsyncDECLINLINE(PRTHTENTRYCTX) rtHandleTableLookupWithCtxIdx(PRTHANDLETABLEINT pThis, uint32_t i)
cc66247640b520463f925a5533fc9e5de06aa982vboxsync{
cc66247640b520463f925a5533fc9e5de06aa982vboxsync if (i < pThis->cCur)
cc66247640b520463f925a5533fc9e5de06aa982vboxsync {
cc66247640b520463f925a5533fc9e5de06aa982vboxsync PRTHTENTRYCTX paTable = (PRTHTENTRYCTX)pThis->papvLevel1[i / RTHT_LEVEL2_ENTRIES];
cc66247640b520463f925a5533fc9e5de06aa982vboxsync if (paTable)
cc66247640b520463f925a5533fc9e5de06aa982vboxsync return &paTable[i % RTHT_LEVEL2_ENTRIES];
cc66247640b520463f925a5533fc9e5de06aa982vboxsync }
210e87cc03f92d54681b81a81cc1fdbd48a9d2c8vboxsync return NULL;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync}
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync/**
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * Looks up a context handle.
cc66247640b520463f925a5533fc9e5de06aa982vboxsync *
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * @returns Pointer to the handle table entry on success, NULL on failure.
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * @param pThis The handle table structure.
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * @param h The handle to look up.
cc66247640b520463f925a5533fc9e5de06aa982vboxsync */
cc66247640b520463f925a5533fc9e5de06aa982vboxsyncDECLINLINE(PRTHTENTRYCTX) rtHandleTableLookupWithCtx(PRTHANDLETABLEINT pThis, uint32_t h)
cc66247640b520463f925a5533fc9e5de06aa982vboxsync{
cc66247640b520463f925a5533fc9e5de06aa982vboxsync return rtHandleTableLookupWithCtxIdx(pThis, h - pThis->uBase);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync}
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync/**
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * Locks the handle table.
cc66247640b520463f925a5533fc9e5de06aa982vboxsync *
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * @param pThis The handle table structure.
cc66247640b520463f925a5533fc9e5de06aa982vboxsync */
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsyncDECLINLINE(void) rtHandleTableLock(PRTHANDLETABLEINT pThis)
cc66247640b520463f925a5533fc9e5de06aa982vboxsync{
cc66247640b520463f925a5533fc9e5de06aa982vboxsync if (pThis->hSpinlock != NIL_RTSPINLOCK)
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync RTSpinlockAcquire(pThis->hSpinlock);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync}
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync/**
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * Locks the handle table.
cc66247640b520463f925a5533fc9e5de06aa982vboxsync *
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * @param pThis The handle table structure.
cc66247640b520463f925a5533fc9e5de06aa982vboxsync */
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsyncDECLINLINE(void) rtHandleTableUnlock(PRTHANDLETABLEINT pThis)
cc66247640b520463f925a5533fc9e5de06aa982vboxsync{
cc66247640b520463f925a5533fc9e5de06aa982vboxsync if (pThis->hSpinlock != NIL_RTSPINLOCK)
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync RTSpinlockRelease(pThis->hSpinlock);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync}
cc66247640b520463f925a5533fc9e5de06aa982vboxsync