handletable.cpp revision 4d0b8f024a4654c1f61c8c4b7e16320719f7fea4
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync/* $Id$ */
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync/** @file
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync * IPRT - Handle Tables.
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync */
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync/*
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync * Copyright (C) 2008 Sun Microsystems, Inc.
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync *
df03c5ed15c9b5bf6d75fedcdf5057d3ffce8577vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync * available from http://www.virtualbox.org. This file is free software;
92a27575521748a392dcd1b996fce55b87411a00vboxsync * you can redistribute it and/or modify it under the terms of the GNU
92a27575521748a392dcd1b996fce55b87411a00vboxsync * General Public License (GPL) as published by the Free Software
92a27575521748a392dcd1b996fce55b87411a00vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
92a27575521748a392dcd1b996fce55b87411a00vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
92a27575521748a392dcd1b996fce55b87411a00vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
92a27575521748a392dcd1b996fce55b87411a00vboxsync *
92a27575521748a392dcd1b996fce55b87411a00vboxsync * The contents of this file may alternatively be used under the terms
92a27575521748a392dcd1b996fce55b87411a00vboxsync * of the Common Development and Distribution License Version 1.0
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync * VirtualBox OSE distribution, in which case the provisions of the
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync * CDDL are applicable instead of those of the GPL.
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync *
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync * You may elect to license modified versions of this file under the
10cdf5733351fdcd857d439ca32189e812f18682vboxsync * terms and conditions of either the GPL or the CDDL or both.
10cdf5733351fdcd857d439ca32189e812f18682vboxsync *
10cdf5733351fdcd857d439ca32189e812f18682vboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
10cdf5733351fdcd857d439ca32189e812f18682vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
10cdf5733351fdcd857d439ca32189e812f18682vboxsync * additional information or have any questions.
10cdf5733351fdcd857d439ca32189e812f18682vboxsync */
10cdf5733351fdcd857d439ca32189e812f18682vboxsync
10cdf5733351fdcd857d439ca32189e812f18682vboxsync/*******************************************************************************
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync* Header Files *
10cdf5733351fdcd857d439ca32189e812f18682vboxsync*******************************************************************************/
10cdf5733351fdcd857d439ca32189e812f18682vboxsync#include <iprt/handletable.h>
10cdf5733351fdcd857d439ca32189e812f18682vboxsync#include <iprt/mem.h>
10cdf5733351fdcd857d439ca32189e812f18682vboxsync#include <iprt/spinlock.h>
10cdf5733351fdcd857d439ca32189e812f18682vboxsync#include <iprt/err.h>
10cdf5733351fdcd857d439ca32189e812f18682vboxsync#include <iprt/assert.h>
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync#include <iprt/param.h>
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync#include <iprt/string.h>
cd9e4940318086a06a68bf301960563dcb72b939vboxsync#include "internal/magics.h"
cd9e4940318086a06a68bf301960563dcb72b939vboxsync
cd9e4940318086a06a68bf301960563dcb72b939vboxsync
10cdf5733351fdcd857d439ca32189e812f18682vboxsync/*******************************************************************************
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync* Defined Constants And Macros *
10cdf5733351fdcd857d439ca32189e812f18682vboxsync*******************************************************************************/
10cdf5733351fdcd857d439ca32189e812f18682vboxsync/** The number of entries in the 2nd level lookup table. */
10cdf5733351fdcd857d439ca32189e812f18682vboxsync#define RTHT_LEVEL2_ENTRIES 2048
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
10cdf5733351fdcd857d439ca32189e812f18682vboxsync/** The number of (max) 1st level entries requiring dynamic allocation of the
10cdf5733351fdcd857d439ca32189e812f18682vboxsync * 1st level table. If the max number is below this threshold, the 1st level
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync * table will be allocated as part of the handle table structure. */
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync#define RTHT_LEVEL1_DYN_ALLOC_THRESHOLD 256
10cdf5733351fdcd857d439ca32189e812f18682vboxsync
10cdf5733351fdcd857d439ca32189e812f18682vboxsync/** Checks whether a object pointer is really a free entry or not. */
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync#define RTHT_IS_FREE(pvObj) ( ((uintptr_t)(pvObj) & 3) == 3 )
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync/** Sets RTHTENTRYFREE::iNext. */
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync#define RTHT_SET_FREE_IDX(pFree, idx) \
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync do { \
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync (pFree)->iNext = ((uintptr_t)(idx) << 2) | 3; \
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync } while (0)
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync/** Gets the index part of RTHTENTRYFREE::iNext. */
cd9e4940318086a06a68bf301960563dcb72b939vboxsync#define RTHT_GET_FREE_IDX(pFree) ( (uint32_t)((pFree)->iNext >> 2) )
10cdf5733351fdcd857d439ca32189e812f18682vboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync/** @def NIL_RTHT_INDEX
10cdf5733351fdcd857d439ca32189e812f18682vboxsync * The NIL handle index for use in the free list. (The difference between
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync * 32-bit and 64-bit hosts here comes down to the shifting performed for
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync * RTHTENTRYFREE::iNext.) */
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync#if ARCH_BITS == 32
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync# define NIL_RTHT_INDEX ( UINT32_C(0x3fffffff) )
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync#elif ARCH_BITS >= 34
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync# define NIL_RTHT_INDEX ( UINT32_C(0xffffffff) )
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync#else
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync# error "Missing or unsupported ARCH_BITS."
86abc60770f825f8c2ed4257675b50a08743b687vboxsync#endif
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
23ee8310386e73ba6760fa30831a7964713d34b6vboxsync
23ee8310386e73ba6760fa30831a7964713d34b6vboxsync/*******************************************************************************
23ee8310386e73ba6760fa30831a7964713d34b6vboxsync* Structures and Typedefs *
23ee8310386e73ba6760fa30831a7964713d34b6vboxsync*******************************************************************************/
23ee8310386e73ba6760fa30831a7964713d34b6vboxsync
23ee8310386e73ba6760fa30831a7964713d34b6vboxsync/**
4a429a59b1a82ce092626ea5f7512466c18f2015vboxsync * Handle table entry, simple variant.
4a429a59b1a82ce092626ea5f7512466c18f2015vboxsync */
4a429a59b1a82ce092626ea5f7512466c18f2015vboxsynctypedef struct RTHTENTRY
4a429a59b1a82ce092626ea5f7512466c18f2015vboxsync{
4a429a59b1a82ce092626ea5f7512466c18f2015vboxsync /** The object. */
4a429a59b1a82ce092626ea5f7512466c18f2015vboxsync void *pvObj;
4a429a59b1a82ce092626ea5f7512466c18f2015vboxsync} RTHTENTRY;
4a429a59b1a82ce092626ea5f7512466c18f2015vboxsync/** Pointer to a handle table entry, simple variant. */
4a429a59b1a82ce092626ea5f7512466c18f2015vboxsynctypedef RTHTENTRY *PRTHTENTRY;
4a429a59b1a82ce092626ea5f7512466c18f2015vboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync/**
23ee8310386e73ba6760fa30831a7964713d34b6vboxsync * Handle table entry, context variant.
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync */
23ee8310386e73ba6760fa30831a7964713d34b6vboxsynctypedef struct RTHTENTRYCTX
23ee8310386e73ba6760fa30831a7964713d34b6vboxsync{
23ee8310386e73ba6760fa30831a7964713d34b6vboxsync /** The context. */
23ee8310386e73ba6760fa30831a7964713d34b6vboxsync void *pvCtx;
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync /** The object. */
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync void *pvObj;
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync} RTHTENTRYCTX;
86abc60770f825f8c2ed4257675b50a08743b687vboxsync/** Pointer to a handle table entry, context variant. */
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsynctypedef RTHTENTRYCTX *PRTHTENTRYCTX;
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
86abc60770f825f8c2ed4257675b50a08743b687vboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync/**
23ee8310386e73ba6760fa30831a7964713d34b6vboxsync * Free handle table entry, shared by all variants.
23ee8310386e73ba6760fa30831a7964713d34b6vboxsync */
23ee8310386e73ba6760fa30831a7964713d34b6vboxsynctypedef struct RTHTENTRYFREE
23ee8310386e73ba6760fa30831a7964713d34b6vboxsync{
23ee8310386e73ba6760fa30831a7964713d34b6vboxsync /** The index of the next handle, special format.
23ee8310386e73ba6760fa30831a7964713d34b6vboxsync * In order to distinguish free and used handle table entries we exploit
23ee8310386e73ba6760fa30831a7964713d34b6vboxsync * the heap alignment and use the lower two bits to do this. Used entries
23ee8310386e73ba6760fa30831a7964713d34b6vboxsync * will have these bits set to 0, while free entries will have tem set
23ee8310386e73ba6760fa30831a7964713d34b6vboxsync * to 3. Use the RTHT_GET_FREE_IDX and RTHT_SET_FREE_IDX macros to access
360c39d88dfa26b17181b57ebafdb24c2a113c63vboxsync * this field. */
360c39d88dfa26b17181b57ebafdb24c2a113c63vboxsync uintptr_t iNext;
360c39d88dfa26b17181b57ebafdb24c2a113c63vboxsync} RTHTENTRYFREE;
360c39d88dfa26b17181b57ebafdb24c2a113c63vboxsync/** Pointer to a free handle table entry. */
360c39d88dfa26b17181b57ebafdb24c2a113c63vboxsynctypedef RTHTENTRYFREE *PRTHTENTRYFREE;
360c39d88dfa26b17181b57ebafdb24c2a113c63vboxsync
23ee8310386e73ba6760fa30831a7964713d34b6vboxsyncAssertCompile(sizeof(RTHTENTRYFREE) <= sizeof(RTHTENTRY));
02fb80eb0db13569db21d1ce5e0f3e0d5a6122aavboxsyncAssertCompile(sizeof(RTHTENTRYFREE) <= sizeof(RTHTENTRYCTX));
23ee8310386e73ba6760fa30831a7964713d34b6vboxsync
23ee8310386e73ba6760fa30831a7964713d34b6vboxsync
23ee8310386e73ba6760fa30831a7964713d34b6vboxsync/**
23ee8310386e73ba6760fa30831a7964713d34b6vboxsync * Internal handle table structure.
23ee8310386e73ba6760fa30831a7964713d34b6vboxsync */
23ee8310386e73ba6760fa30831a7964713d34b6vboxsynctypedef struct RTHANDLETABLEINT
23ee8310386e73ba6760fa30831a7964713d34b6vboxsync{
6967517de4be849f55b0141d6089add0eff2aa7bvboxsync /** Magic value (RTHANDLETABLE_MAGIC). */
6967517de4be849f55b0141d6089add0eff2aa7bvboxsync uint32_t u32Magic;
23ee8310386e73ba6760fa30831a7964713d34b6vboxsync /** The handle table flags specified to RTHandleTableCreateEx. */
86abc60770f825f8c2ed4257675b50a08743b687vboxsync uint32_t fFlags;
7b213bb002950f9fcf809f605cc584fa543481advboxsync /** The base handle value (i.e. the first handle). */
7b213bb002950f9fcf809f605cc584fa543481advboxsync uint32_t uBase;
7b213bb002950f9fcf809f605cc584fa543481advboxsync /** The current number of handles.
7b213bb002950f9fcf809f605cc584fa543481advboxsync * This indirectly gives the size of the first level lookup table. */
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync uint32_t cCur;
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync /** The spinlock handle (NIL if RTHANDLETABLE_FLAGS_LOCKED wasn't used). */
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync RTSPINLOCK hSpinlock;
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync /** The level one lookup table. */
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync void **papvLevel1;
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync /** The retainer callback. Can be NULL. */
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync PFNRTHANDLETABLERETAIN pfnRetain;
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync /** The user argument to the retainer. */
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync void *pvRetainUser;
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync /** The max number of handles. */
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync uint32_t cMax;
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync /** The number of handles currently allocated. (for optimizing destruction) */
cd9e4940318086a06a68bf301960563dcb72b939vboxsync uint32_t cCurAllocated;
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync /** The current number of 1st level entries. */
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync uint32_t cLevel1;
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync /** Head of the list of free handle entires (index). */
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync uint32_t iFreeHead;
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync /** Tail of the list of free handle entires (index). */
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync uint32_t iFreeTail;
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync} RTHANDLETABLEINT;
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync/** Pointer to an handle table structure. */
1cc3bd5463294790ba54c78fde5313264185e50cvboxsynctypedef RTHANDLETABLEINT *PRTHANDLETABLEINT;
cd9e4940318086a06a68bf301960563dcb72b939vboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
cd9e4940318086a06a68bf301960563dcb72b939vboxsync
8364ffb7e421fa1ec2bd282ab4c52ac718873d46vboxsync/**
8364ffb7e421fa1ec2bd282ab4c52ac718873d46vboxsync * Looks up a simple handle.
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync *
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync * @returns Pointer to the handle table entry on success, NULL on failure.
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync * @param pThis The handle table structure.
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync * @param h The handle to look up.
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync */
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsyncDECLINLINE(PRTHTENTRY) rtHandleTableLookupSimple(PRTHANDLETABLEINT pThis, uint32_t h)
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync{
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync uint32_t i = h - pThis->uBase;
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync if (i < pThis->cCur)
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync {
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync PRTHTENTRY paTable = (PRTHTENTRY)pThis->papvLevel1[i / RTHT_LEVEL2_ENTRIES];
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync if (paTable)
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync return &paTable[i % RTHT_LEVEL2_ENTRIES];
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync }
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync return NULL;
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync}
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync/**
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync * Looks up a context handle.
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync *
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync * @returns Pointer to the handle table entry on success, NULL on failure.
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync * @param pThis The handle table structure.
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync * @param h The handle to look up.
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync */
c7a92d481aced08517570d43bf75e2a9f3a8aaeavboxsyncDECLINLINE(PRTHTENTRYCTX) rtHandleTableLookupWithCtx(PRTHANDLETABLEINT pThis, uint32_t h)
c7a92d481aced08517570d43bf75e2a9f3a8aaeavboxsync{
c7a92d481aced08517570d43bf75e2a9f3a8aaeavboxsync uint32_t i = h - pThis->uBase;
c7a92d481aced08517570d43bf75e2a9f3a8aaeavboxsync if (i < pThis->cCur)
c7a92d481aced08517570d43bf75e2a9f3a8aaeavboxsync {
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync PRTHTENTRYCTX paTable = (PRTHTENTRYCTX)pThis->papvLevel1[i / RTHT_LEVEL2_ENTRIES];
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync if (paTable)
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync return &paTable[i % RTHT_LEVEL2_ENTRIES];
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync }
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync return NULL;
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync}
c7a92d481aced08517570d43bf75e2a9f3a8aaeavboxsync
541ba632c438350cc8044d7ce2c8623dca446546vboxsync
08a80484275b5172ce23729ecccc934c6a92d201vboxsyncDECLINLINE(void) rtHandleTableLock(PRTHANDLETABLEINT pThis, PRTSPINLOCKTMP pTmp)
08a80484275b5172ce23729ecccc934c6a92d201vboxsync{
08a80484275b5172ce23729ecccc934c6a92d201vboxsync if (pThis->hSpinlock != NIL_RTSPINLOCK)
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync RTSpinlockRelease(pThis->hSpinlock, pTmp);
86abc60770f825f8c2ed4257675b50a08743b687vboxsync}
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
48f33dfd8f615d457106bf76ae2d09b8b9167c1avboxsyncDECLINLINE(void) rtHandleTableUnlock(PRTHANDLETABLEINT pThis, PRTSPINLOCKTMP pTmp)
48f33dfd8f615d457106bf76ae2d09b8b9167c1avboxsync{
48f33dfd8f615d457106bf76ae2d09b8b9167c1avboxsync if (pThis->hSpinlock != NIL_RTSPINLOCK)
48f33dfd8f615d457106bf76ae2d09b8b9167c1avboxsync RTSpinlockAcquire(pThis->hSpinlock, pTmp);
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync}
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsyncRTDECL(int) RTHandleTableCreateEx(PRTHANDLETABLE phHandleTable, uint32_t fFlags, uint32_t uBase, uint32_t cMax,
fc148a6b23d25a87561beaffe0ba06c3ba93bf5avboxsync PFNRTHANDLETABLERETAIN pfnRetain, void *pvUser)
fc148a6b23d25a87561beaffe0ba06c3ba93bf5avboxsync{
fc148a6b23d25a87561beaffe0ba06c3ba93bf5avboxsync return VERR_NOT_IMPLEMENTED;
fc148a6b23d25a87561beaffe0ba06c3ba93bf5avboxsync}
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsyncRTDECL(int) RTHandleTableCreate(PRTHANDLETABLE phHandleTable)
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync{
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync return RTHandleTableCreateEx(phHandleTable, RTHANDLETABLE_FLAGS_LOCKED, 1, 65534, NULL, NULL);
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync}
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsyncRTDECL(int) RTHandleTableDestroy(RTHANDLETABLE hHandleTable, PFNRTHANDLETABLEDELETE pfnDelete, void *pvUser)
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync{
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync return -1;
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync}
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync/**
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync * Allocates a handle from the handle table.
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync *
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync * @returns IPRT status code, almost any.
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync * @retval VINF_SUCCESS on success.
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync * @retval VERR_NO_MEMORY if we failed to extend the handle table.
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync * @retval VERR_NO_MORE_HANDLES if we're out of handles.
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync *
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync * @param hHandleTable The handle to the handle table.
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync * @param pvObj The object to associate with the new handle.
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync * @param ph Where to return the handle on success.
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync *
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync * @remarks Do not call this if RTHANDLETABLE_FLAGS_CONTEXT was used during creation.
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync */
bc8beda7587b16cafe7de7bea19149de1bd4b498vboxsyncRTDECL(int) RTHandleTableAlloc(RTHANDLETABLE hHandleTable, void *pvObj, uint32_t *ph);
bc8beda7587b16cafe7de7bea19149de1bd4b498vboxsync
59e30364f54880dd846c263711a2506d1182b1b5vboxsync/**
59e30364f54880dd846c263711a2506d1182b1b5vboxsync * Looks up a handle.
59e30364f54880dd846c263711a2506d1182b1b5vboxsync *
59e30364f54880dd846c263711a2506d1182b1b5vboxsync * @returns The object pointer on success. NULL on failure.
3acaac88e9a4c925226db26f0d374f9f4876b74fvboxsync *
cc8517c11be66037a9873fa03f280e7742efed6dvboxsync * @param hHandleTable The handle to the handle table.
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync * @param h The handle to lookup.
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync *
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync * @remarks Do not call this if RTHANDLETABLE_FLAGS_CONTEXT was used during creation.
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync */
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsyncRTDECL(void *) RTHandleTableLookup(RTHANDLETABLE hHandleTable, uint32_t h);
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync/**
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync * Looks up and frees a handle.
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync *
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync * @returns The object pointer on success. NULL on failure.
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync *
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync * @param hHandleTable The handle to the handle table.
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync * @param h The handle to lookup.
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync *
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync * @remarks Do not call this if RTHANDLETABLE_FLAGS_CONTEXT was used during creation.
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync */
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsyncRTDECL(void *) RTHandleTableFree(RTHANDLETABLE hHandleTable, uint32_t h);
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsyncRTDECL(int) RTHandleTableAllocWithCtx(RTHANDLETABLE hHandleTable, void *pvObj, void *pvCtx, uint32_t *ph)
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync{
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync /* validate the input */
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync PRTHANDLETABLEINT pThis = (PRTHANDLETABLEINT)hHandleTable;
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync AssertReturn(pThis->u32Magic == RTHANDLETABLE_MAGIC, VERR_INVALID_HANDLE);
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync AssertReturn(pThis->fFlags & RTHANDLETABLE_FLAGS_CONTEXT, VERR_INVALID_FUNCTION);
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync AssertReturn(RTHT_IS_FREE(pvObj), VERR_INVALID_PARAMETER);
541ba632c438350cc8044d7ce2c8623dca446546vboxsync AssertPtrReturn(ph, VERR_INVALID_POINTER);
08a56d5836eceeb24642b61eaa52a4edb0a7b482vboxsync *ph = pThis->uBase - 1;
08a56d5836eceeb24642b61eaa52a4edb0a7b482vboxsync
08a56d5836eceeb24642b61eaa52a4edb0a7b482vboxsync /*
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync * Allocation loop.
3b3bc8a9383a065307e540b83fc3a3d6c548a082vboxsync */
48f33dfd8f615d457106bf76ae2d09b8b9167c1avboxsync RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
48f33dfd8f615d457106bf76ae2d09b8b9167c1avboxsync rtHandleTableLock(pThis, &Tmp);
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
48f33dfd8f615d457106bf76ae2d09b8b9167c1avboxsync int rc;
48f33dfd8f615d457106bf76ae2d09b8b9167c1avboxsync do
48f33dfd8f615d457106bf76ae2d09b8b9167c1avboxsync {
48f33dfd8f615d457106bf76ae2d09b8b9167c1avboxsync /*
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync * Try grab a free entry from the head of the free list.
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync */
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync uint32_t i = pThis->iFreeHead;
3196a540aa11c41264b0e79857b879e4ab566f4bvboxsync if (i != NIL_RTHT_INDEX)
3196a540aa11c41264b0e79857b879e4ab566f4bvboxsync {
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync PRTHTENTRYFREE pFree = (PRTHTENTRYFREE)rtHandleTableLookupWithCtx(pThis, i + pThis->uBase);
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync Assert(pFree);
3196a540aa11c41264b0e79857b879e4ab566f4bvboxsync if (i == pThis->iFreeTail)
3196a540aa11c41264b0e79857b879e4ab566f4bvboxsync pThis->iFreeTail = pThis->iFreeHead = NIL_RTHT_INDEX;
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync else
16aeb8f83239d4a4a10ecac1fb46fe24a8bdbb66vboxsync pThis->iFreeHead = RTHT_GET_FREE_IDX(pFree);
16aeb8f83239d4a4a10ecac1fb46fe24a8bdbb66vboxsync pThis->cCurAllocated++;
16aeb8f83239d4a4a10ecac1fb46fe24a8bdbb66vboxsync Assert(pThis->cCurAllocated <= pThis->cCur);
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync /*
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync * Setup the entry and return.
2705a216ac12110a0813d671e230797c886b4788vboxsync */
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync PRTHTENTRYCTX pEntry = (PRTHTENTRYCTX)pFree;
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync pEntry->pvObj = pvObj;
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync pEntry->pvCtx = pvCtx;
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync *ph = i + pThis->uBase;
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync rc = VINF_SUCCESS;
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync }
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync /*
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync * Must expand the handle table, unless it's full.
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync */
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync else if (pThis->cCur >= pThis->cMax)
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync {
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync rc = VERR_NO_MORE_HANDLES;
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync Assert(pThis->cCur == pThis->cCurAllocated);
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync }
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync else
24b88f881835a6c392e72177f74f1d5e4544ba1evboxsync {
f8244da4b4e02d8d4ce0669eeb4093e31c301888vboxsync /*
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync * Do we have to expand the 1st level table too?
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync */
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync uint32_t const iLevel1 = pThis->cCur / RTHT_LEVEL2_ENTRIES;
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync uint32_t cLevel1 = iLevel1 + 1 >= pThis->cLevel1
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync ? pThis->cLevel1 + PAGE_SIZE / sizeof(void *)
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync : 0;
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync if (cLevel1 > pThis->cMax / RTHT_LEVEL2_ENTRIES)
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync cLevel1 = pThis->cMax / RTHT_LEVEL2_ENTRIES;
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync /* leave the lock (never do fancy stuff from behind a spinlock). */
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync rtHandleTableUnlock(pThis, &Tmp);
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync /*
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync * Do the allocation(s).
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync */
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync rc = VERR_TRY_AGAIN;
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync void **papvLevel1 = NULL;
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync if (cLevel1)
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync {
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync papvLevel1 = (void **)RTMemAlloc(sizeof(void *) * cLevel1);
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync if (!papvLevel1)
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync return VERR_NO_MEMORY;
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync }
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync PRTHTENTRYCTX paTable = (PRTHTENTRYCTX)RTMemAlloc(sizeof(*paTable) * RTHT_LEVEL2_ENTRIES);
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync if (!paTable)
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync {
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync RTMemFree(papvLevel1);
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync return VERR_NO_MEMORY;
bee07f28c146fb5313ea13d84dcd508d8f604a10vboxsync }
441e51789084e8795573747fec9f5108e8b54e98vboxsync
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync /* re-enter the lock. */
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync rtHandleTableLock(pThis, &Tmp);
15ca5f803f0c1bfc86a224523ef482f8aa960388vboxsync
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync /*
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync * Insert the new bits, but be a bit careful as someone might have
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync * raced us expanding the table.
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync */
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync if (cLevel1)
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync {
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync if (cLevel1 > pThis->cLevel1)
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync {
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync /* Replace the 1st level table. */
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync memcpy(papvLevel1, pThis->papvLevel1, sizeof(void *) * pThis->cLevel1);
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync memset(&papvLevel1[pThis->cLevel1], 0, sizeof(void *) * (cLevel1 - pThis->cLevel1));
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync void **papvTmp = pThis->papvLevel1;
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync pThis->papvLevel1 = papvLevel1;
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync papvLevel1 = papvTmp;
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync }
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync /* free the obsolete one (outside the lock of course) */
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync rtHandleTableLock(pThis, &Tmp);
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync RTMemFree(papvLevel1);
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync rtHandleTableUnlock(pThis, &Tmp);
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync }
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync /* insert the table we allocated */
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync if (pThis->cCur < pThis->cMax)
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync {
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync uint32_t iLevel1New = pThis->cCur / RTHT_LEVEL2_ENTRIES;
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync pThis->papvLevel1[iLevel1New] = paTable;
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync /* link all entries into a free list. */
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync Assert(!(pThis->cCur % RTHT_LEVEL2_ENTRIES));
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync for (uint32_t i = 0; i < RTHT_LEVEL2_ENTRIES - 1; i++)
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync {
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync RTHT_SET_FREE_IDX((PRTHTENTRYFREE)&paTable[i], i + 1);
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync paTable[i].pvCtx = (void *)~(uintptr_t)7;
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync }
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync RTHT_SET_FREE_IDX((PRTHTENTRYFREE)&paTable[RTHT_LEVEL2_ENTRIES - 1], NIL_RTHT_INDEX);
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync paTable[RTHT_LEVEL2_ENTRIES - 1].pvCtx = (void *)~(uintptr_t)7;
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync /* join the free list with the other. */
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync if (pThis->iFreeTail == NIL_RTHT_INDEX)
8d466f9285d86e81f927c2bf053a2eb7ec325746vboxsync pThis->iFreeHead = pThis->cCur;
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync else
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync {
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync PRTHTENTRYFREE pPrev = (PRTHTENTRYFREE)rtHandleTableLookupWithCtx(pThis, pThis->iFreeTail);
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync Assert(pPrev);
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync RTHT_SET_FREE_IDX(pPrev, pThis->cCur);
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync }
1cc3bd5463294790ba54c78fde5313264185e50cvboxsync pThis->iFreeTail = pThis->cCur + RTHT_LEVEL2_ENTRIES - 1;
efda5c4c4db213abd0692df0ea34a26f6230d59avboxsync
2c76fd8cdec6f32663a03b16fb5871f7c54330a6vboxsync pThis->cCur += RTHT_LEVEL2_ENTRIES;
2c76fd8cdec6f32663a03b16fb5871f7c54330a6vboxsync }
2705a216ac12110a0813d671e230797c886b4788vboxsync else
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync {
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync /* free the table (raced someone, and we lost). */
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync rtHandleTableLock(pThis, &Tmp);
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync RTMemFree(paTable);
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync rtHandleTableUnlock(pThis, &Tmp);
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync }
c7a92d481aced08517570d43bf75e2a9f3a8aaeavboxsync
541ba632c438350cc8044d7ce2c8623dca446546vboxsync rc = VERR_TRY_AGAIN;
42d36464aee6c81b4f206b6c02035587501ff67cvboxsync }
c3e38cccf650831700227918a021e6c4097ace82vboxsync } while (rc == VERR_TRY_AGAIN);
42d36464aee6c81b4f206b6c02035587501ff67cvboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync rtHandleTableUnlock(pThis, &Tmp);
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync return rc;
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync}
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
3b3bc8a9383a065307e540b83fc3a3d6c548a082vboxsync
48f33dfd8f615d457106bf76ae2d09b8b9167c1avboxsyncRTDECL(void *) RTHandleTableLookupWithCtx(RTHANDLETABLE hHandleTable, uint32_t h, void *pvCtx)
48f33dfd8f615d457106bf76ae2d09b8b9167c1avboxsync{
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync /* validate the input */
48f33dfd8f615d457106bf76ae2d09b8b9167c1avboxsync PRTHANDLETABLEINT pThis = (PRTHANDLETABLEINT)hHandleTable;
48f33dfd8f615d457106bf76ae2d09b8b9167c1avboxsync AssertPtrReturn(pThis, NULL);
48f33dfd8f615d457106bf76ae2d09b8b9167c1avboxsync AssertReturn(pThis->u32Magic == RTHANDLETABLE_MAGIC, NULL);
48f33dfd8f615d457106bf76ae2d09b8b9167c1avboxsync AssertReturn(pThis->fFlags & RTHANDLETABLE_FLAGS_CONTEXT, NULL);
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync void *pvObj = NULL;
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync /* acquire the lock */
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync rtHandleTableLock(pThis, &Tmp);
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync /*
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync * Perform the lookup and retaining.
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync */
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync PRTHTENTRYCTX pEntry = rtHandleTableLookupWithCtx(pThis, h);
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync if (pEntry && pEntry->pvCtx == pvCtx)
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync {
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync pvObj = pEntry->pvObj;
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync if (!RTHT_IS_FREE(pvObj))
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync {
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync if (pThis->pfnRetain)
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync {
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync int rc = pThis->pfnRetain(hHandleTable, pEntry->pvObj, pvCtx, pThis->pvRetainUser);
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync if (RT_FAILURE(rc))
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync pvObj = NULL;
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync }
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync }
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync else
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync pvObj = NULL;
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync }
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync /* release the lock */
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync rtHandleTableUnlock(pThis, &Tmp);
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync return pvObj;
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync}
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsyncRTDECL(void *) RTHandleTableFreeWithCtx(RTHANDLETABLE hHandleTable, uint32_t h, void *pvCtx)
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync{
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync /* validate the input */
cd9e4940318086a06a68bf301960563dcb72b939vboxsync PRTHANDLETABLEINT pThis = (PRTHANDLETABLEINT)hHandleTable;
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync AssertPtrReturn(pThis, NULL);
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync AssertReturn(pThis->u32Magic == RTHANDLETABLE_MAGIC, NULL);
5857f4e58ce2ef50d7f0c450fe4897026f9a9c3dvboxsync AssertReturn(pThis->fFlags & RTHANDLETABLE_FLAGS_CONTEXT, NULL);
42dc09ee69e746b8641cfa190931a15ecfd7295cvboxsync
e0b91e4f93fb43371374df4aeb636dffea336056vboxsync void *pvObj = NULL;
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync /* acquire the lock */
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync rtHandleTableLock(pThis, &Tmp);
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync /*
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync * Perform the lookup and retaining.
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync */
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync PRTHTENTRYCTX pEntry = rtHandleTableLookupWithCtx(pThis, h);
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync if (pEntry && pEntry->pvCtx == pvCtx)
2705a216ac12110a0813d671e230797c886b4788vboxsync {
2705a216ac12110a0813d671e230797c886b4788vboxsync pvObj = pEntry->pvObj;
2705a216ac12110a0813d671e230797c886b4788vboxsync if (!RTHT_IS_FREE(pvObj))
bcc95fabf162c0f743d7eaafb0d21f7ef967e9f4vboxsync {
2705a216ac12110a0813d671e230797c886b4788vboxsync if (pThis->pfnRetain)
2705a216ac12110a0813d671e230797c886b4788vboxsync {
2705a216ac12110a0813d671e230797c886b4788vboxsync int rc = pThis->pfnRetain(hHandleTable, pEntry->pvObj, pvCtx, pThis->pvRetainUser);
2705a216ac12110a0813d671e230797c886b4788vboxsync if (RT_FAILURE(rc))
2705a216ac12110a0813d671e230797c886b4788vboxsync pvObj = NULL;
2705a216ac12110a0813d671e230797c886b4788vboxsync }
2705a216ac12110a0813d671e230797c886b4788vboxsync
2705a216ac12110a0813d671e230797c886b4788vboxsync /*
de86a09bf42f7e7d80a0a5acf1e8e99d445be1d3vboxsync * Link it into the free list.
c0da96af18c7b40ac5cfd7e7ea398a398540f224vboxsync */
c0da96af18c7b40ac5cfd7e7ea398a398540f224vboxsync if (pvObj)
c0da96af18c7b40ac5cfd7e7ea398a398540f224vboxsync {
c0da96af18c7b40ac5cfd7e7ea398a398540f224vboxsync pEntry->pvCtx = (void *)~(uintptr_t)7;
c0da96af18c7b40ac5cfd7e7ea398a398540f224vboxsync
c0da96af18c7b40ac5cfd7e7ea398a398540f224vboxsync PRTHTENTRYFREE pFree = (PRTHTENTRYFREE)pEntry;
c0da96af18c7b40ac5cfd7e7ea398a398540f224vboxsync RTHT_SET_FREE_IDX(pFree, NIL_RTHT_INDEX);
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync
8e77372da4b53557362ee8ea967def86f7bed166vboxsync uint32_t const i = h - pThis->uBase;
8e77372da4b53557362ee8ea967def86f7bed166vboxsync if (pThis->iFreeTail == NIL_RTHT_INDEX)
2705a216ac12110a0813d671e230797c886b4788vboxsync pThis->iFreeHead = pThis->iFreeTail = i;
2705a216ac12110a0813d671e230797c886b4788vboxsync else
2705a216ac12110a0813d671e230797c886b4788vboxsync {
2705a216ac12110a0813d671e230797c886b4788vboxsync PRTHTENTRYFREE pPrev = (PRTHTENTRYFREE)rtHandleTableLookupWithCtx(pThis, pThis->iFreeTail + pThis->uBase);
2705a216ac12110a0813d671e230797c886b4788vboxsync Assert(pPrev);
95d42763b8808d795c23148d7dbc00a3b7b40d6fvboxsync RTHT_SET_FREE_IDX(pPrev, i);
2705a216ac12110a0813d671e230797c886b4788vboxsync pThis->iFreeTail = i;
2705a216ac12110a0813d671e230797c886b4788vboxsync }
2705a216ac12110a0813d671e230797c886b4788vboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync Assert(pThis->cCurAllocated > 0);
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync pThis->cCurAllocated--;
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync }
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync }
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync else
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync pvObj = NULL;
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync }
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync /* release the lock */
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync rtHandleTableUnlock(pThis, &Tmp);
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync return pvObj;
5c571d69a0355bedb9a401ce4de992a2b0ef3515vboxsync}
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync
db3dbd0ed7eb69f804a8921fa23a1267ea01f46evboxsync