cc66247640b520463f925a5533fc9e5de06aa982vboxsync/* $Id$ */
cc66247640b520463f925a5533fc9e5de06aa982vboxsync/** @file
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * IPRT - Handle Tables.
cc66247640b520463f925a5533fc9e5de06aa982vboxsync */
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync/*
c7814cf6e1240a519cbec0441e033d0e2470ed00vboxsync * Copyright (C) 2008-2012 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
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync/*******************************************************************************
cc66247640b520463f925a5533fc9e5de06aa982vboxsync* Header Files *
cc66247640b520463f925a5533fc9e5de06aa982vboxsync*******************************************************************************/
cc66247640b520463f925a5533fc9e5de06aa982vboxsync#include <iprt/handletable.h>
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync#include "internal/iprt.h"
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync#include <iprt/mem.h>
cc66247640b520463f925a5533fc9e5de06aa982vboxsync#include <iprt/spinlock.h>
cc66247640b520463f925a5533fc9e5de06aa982vboxsync#include <iprt/err.h>
cc66247640b520463f925a5533fc9e5de06aa982vboxsync#include <iprt/assert.h>
cc66247640b520463f925a5533fc9e5de06aa982vboxsync#include <iprt/param.h>
cc66247640b520463f925a5533fc9e5de06aa982vboxsync#include <iprt/string.h>
cc66247640b520463f925a5533fc9e5de06aa982vboxsync#include <iprt/asm.h>
cc66247640b520463f925a5533fc9e5de06aa982vboxsync#include "internal/magics.h"
cc66247640b520463f925a5533fc9e5de06aa982vboxsync#include "handletable.h"
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsyncRTDECL(int) RTHandleTableAlloc(RTHANDLETABLE hHandleTable, void *pvObj, uint32_t *ph)
cc66247640b520463f925a5533fc9e5de06aa982vboxsync{
cc66247640b520463f925a5533fc9e5de06aa982vboxsync /* validate the input */
cc66247640b520463f925a5533fc9e5de06aa982vboxsync PRTHANDLETABLEINT pThis = (PRTHANDLETABLEINT)hHandleTable;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync AssertReturn(pThis->u32Magic == RTHANDLETABLE_MAGIC, VERR_INVALID_HANDLE);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync AssertReturn(!(pThis->fFlags & RTHANDLETABLE_FLAGS_CONTEXT), VERR_INVALID_FUNCTION);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync AssertReturn(!RTHT_IS_FREE(pvObj), VERR_INVALID_PARAMETER);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync AssertPtrReturn(ph, VERR_INVALID_POINTER);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync *ph = pThis->uBase - 1;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync /*
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * Allocation loop.
cc66247640b520463f925a5533fc9e5de06aa982vboxsync */
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync rtHandleTableLock(pThis);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync int rc;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync do
cc66247640b520463f925a5533fc9e5de06aa982vboxsync {
cc66247640b520463f925a5533fc9e5de06aa982vboxsync /*
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * Try grab a free entry from the head of the free list.
cc66247640b520463f925a5533fc9e5de06aa982vboxsync */
cc66247640b520463f925a5533fc9e5de06aa982vboxsync uint32_t i = pThis->iFreeHead;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync if (i != NIL_RTHT_INDEX)
cc66247640b520463f925a5533fc9e5de06aa982vboxsync {
cc66247640b520463f925a5533fc9e5de06aa982vboxsync PRTHTENTRYFREE pFree = (PRTHTENTRYFREE)rtHandleTableLookupSimpleIdx(pThis, i);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync Assert(pFree);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync if (i == pThis->iFreeTail)
cc66247640b520463f925a5533fc9e5de06aa982vboxsync pThis->iFreeTail = pThis->iFreeHead = NIL_RTHT_INDEX;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync else
cc66247640b520463f925a5533fc9e5de06aa982vboxsync pThis->iFreeHead = RTHT_GET_FREE_IDX(pFree);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync pThis->cCurAllocated++;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync Assert(pThis->cCurAllocated <= pThis->cCur);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync /*
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * Setup the entry and return.
cc66247640b520463f925a5533fc9e5de06aa982vboxsync */
cc66247640b520463f925a5533fc9e5de06aa982vboxsync PRTHTENTRY pEntry = (PRTHTENTRY)pFree;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync pEntry->pvObj = pvObj;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync *ph = i + pThis->uBase;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync rc = VINF_SUCCESS;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync }
cc66247640b520463f925a5533fc9e5de06aa982vboxsync /*
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * Must expand the handle table, unless it's full.
cc66247640b520463f925a5533fc9e5de06aa982vboxsync */
cc66247640b520463f925a5533fc9e5de06aa982vboxsync else if (pThis->cCur >= pThis->cMax)
cc66247640b520463f925a5533fc9e5de06aa982vboxsync {
cc66247640b520463f925a5533fc9e5de06aa982vboxsync rc = VERR_NO_MORE_HANDLES;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync Assert(pThis->cCur == pThis->cCurAllocated);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync }
cc66247640b520463f925a5533fc9e5de06aa982vboxsync else
cc66247640b520463f925a5533fc9e5de06aa982vboxsync {
cc66247640b520463f925a5533fc9e5de06aa982vboxsync /*
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * Do we have to expand the 1st level table too?
cc66247640b520463f925a5533fc9e5de06aa982vboxsync */
cc66247640b520463f925a5533fc9e5de06aa982vboxsync uint32_t const iLevel1 = pThis->cCur / RTHT_LEVEL2_ENTRIES;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync uint32_t cLevel1 = iLevel1 >= pThis->cLevel1
cc66247640b520463f925a5533fc9e5de06aa982vboxsync ? pThis->cLevel1 + PAGE_SIZE / sizeof(void *)
cc66247640b520463f925a5533fc9e5de06aa982vboxsync : 0;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync if (cLevel1 > pThis->cMax / RTHT_LEVEL2_ENTRIES)
cc66247640b520463f925a5533fc9e5de06aa982vboxsync cLevel1 = pThis->cMax / RTHT_LEVEL2_ENTRIES;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync Assert(!cLevel1 || pThis->cMax / RTHT_LEVEL2_ENTRIES >= RTHT_LEVEL1_DYN_ALLOC_THRESHOLD);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync /* leave the lock (never do fancy stuff from behind a spinlock). */
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync rtHandleTableUnlock(pThis);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync /*
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * Do the allocation(s).
cc66247640b520463f925a5533fc9e5de06aa982vboxsync */
cc66247640b520463f925a5533fc9e5de06aa982vboxsync rc = VERR_TRY_AGAIN;
210e87cc03f92d54681b81a81cc1fdbd48a9d2c8vboxsync void **papvLevel1 = NULL;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync if (cLevel1)
cc66247640b520463f925a5533fc9e5de06aa982vboxsync {
cc66247640b520463f925a5533fc9e5de06aa982vboxsync papvLevel1 = (void **)RTMemAlloc(sizeof(void *) * cLevel1);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync if (!papvLevel1)
cc66247640b520463f925a5533fc9e5de06aa982vboxsync return VERR_NO_MEMORY;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync }
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync PRTHTENTRY paTable = (PRTHTENTRY)RTMemAlloc(sizeof(*paTable) * RTHT_LEVEL2_ENTRIES);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync if (!paTable)
cc66247640b520463f925a5533fc9e5de06aa982vboxsync {
cc66247640b520463f925a5533fc9e5de06aa982vboxsync RTMemFree(papvLevel1);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync return VERR_NO_MEMORY;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync }
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync /* re-enter the lock. */
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync rtHandleTableLock(pThis);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync /*
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * Insert the new bits, but be a bit careful as someone might have
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * raced us expanding the table.
cc66247640b520463f925a5533fc9e5de06aa982vboxsync */
cc66247640b520463f925a5533fc9e5de06aa982vboxsync /* deal with the 1st level lookup expansion first */
cc66247640b520463f925a5533fc9e5de06aa982vboxsync if (cLevel1)
cc66247640b520463f925a5533fc9e5de06aa982vboxsync {
cc66247640b520463f925a5533fc9e5de06aa982vboxsync Assert(papvLevel1);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync if (cLevel1 > pThis->cLevel1)
cc66247640b520463f925a5533fc9e5de06aa982vboxsync {
cc66247640b520463f925a5533fc9e5de06aa982vboxsync /* Replace the 1st level table. */
cc66247640b520463f925a5533fc9e5de06aa982vboxsync memcpy(papvLevel1, pThis->papvLevel1, sizeof(void *) * pThis->cLevel1);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync memset(&papvLevel1[pThis->cLevel1], 0, sizeof(void *) * (cLevel1 - pThis->cLevel1));
cc66247640b520463f925a5533fc9e5de06aa982vboxsync pThis->cLevel1 = cLevel1;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync void **papvTmp = pThis->papvLevel1;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync pThis->papvLevel1 = papvLevel1;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync papvLevel1 = papvTmp;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync }
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync /* free the obsolete one (outside the lock of course) */
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync rtHandleTableUnlock(pThis);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync RTMemFree(papvLevel1);
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync rtHandleTableLock(pThis);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync }
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
8429669b672301e12d6ddab8bc9ce0618d930d2evboxsync /* insert the table we allocated. */
8429669b672301e12d6ddab8bc9ce0618d930d2evboxsync uint32_t iLevel1New = pThis->cCur / RTHT_LEVEL2_ENTRIES;
8429669b672301e12d6ddab8bc9ce0618d930d2evboxsync if ( iLevel1New < pThis->cLevel1
8429669b672301e12d6ddab8bc9ce0618d930d2evboxsync && pThis->cCur < pThis->cMax)
cc66247640b520463f925a5533fc9e5de06aa982vboxsync {
cc66247640b520463f925a5533fc9e5de06aa982vboxsync pThis->papvLevel1[iLevel1New] = paTable;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync /* link all entries into a free list. */
cc66247640b520463f925a5533fc9e5de06aa982vboxsync Assert(!(pThis->cCur % RTHT_LEVEL2_ENTRIES));
8f2f51347c7b5fe7c697debe7c2e46b46dd16489vboxsync for (i = 0; i < RTHT_LEVEL2_ENTRIES - 1; i++)
cc66247640b520463f925a5533fc9e5de06aa982vboxsync RTHT_SET_FREE_IDX((PRTHTENTRYFREE)&paTable[i], i + 1 + pThis->cCur);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync RTHT_SET_FREE_IDX((PRTHTENTRYFREE)&paTable[RTHT_LEVEL2_ENTRIES - 1], NIL_RTHT_INDEX);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync /* join the free list with the other. */
cc66247640b520463f925a5533fc9e5de06aa982vboxsync if (pThis->iFreeTail == NIL_RTHT_INDEX)
cc66247640b520463f925a5533fc9e5de06aa982vboxsync pThis->iFreeHead = pThis->cCur;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync else
cc66247640b520463f925a5533fc9e5de06aa982vboxsync {
cc66247640b520463f925a5533fc9e5de06aa982vboxsync PRTHTENTRYFREE pPrev = (PRTHTENTRYFREE)rtHandleTableLookupSimpleIdx(pThis, pThis->iFreeTail);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync Assert(pPrev);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync RTHT_SET_FREE_IDX(pPrev, pThis->cCur);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync }
cc66247640b520463f925a5533fc9e5de06aa982vboxsync pThis->iFreeTail = pThis->cCur + RTHT_LEVEL2_ENTRIES - 1;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync pThis->cCur += RTHT_LEVEL2_ENTRIES;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync }
cc66247640b520463f925a5533fc9e5de06aa982vboxsync else
cc66247640b520463f925a5533fc9e5de06aa982vboxsync {
cc66247640b520463f925a5533fc9e5de06aa982vboxsync /* free the table (raced someone, and we lost). */
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync rtHandleTableUnlock(pThis);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync RTMemFree(paTable);
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync rtHandleTableLock(pThis);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync }
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync rc = VERR_TRY_AGAIN;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync }
cc66247640b520463f925a5533fc9e5de06aa982vboxsync } while (rc == VERR_TRY_AGAIN);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync rtHandleTableUnlock(pThis);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync return rc;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync}
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsyncRT_EXPORT_SYMBOL(RTHandleTableAlloc);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsyncRTDECL(void *) RTHandleTableLookup(RTHANDLETABLE hHandleTable, uint32_t h)
cc66247640b520463f925a5533fc9e5de06aa982vboxsync{
cc66247640b520463f925a5533fc9e5de06aa982vboxsync /* validate the input */
cc66247640b520463f925a5533fc9e5de06aa982vboxsync PRTHANDLETABLEINT pThis = (PRTHANDLETABLEINT)hHandleTable;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync AssertPtrReturn(pThis, NULL);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync AssertReturn(pThis->u32Magic == RTHANDLETABLE_MAGIC, NULL);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync AssertReturn(!(pThis->fFlags & RTHANDLETABLE_FLAGS_CONTEXT), NULL);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync void *pvObj = NULL;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync /* acquire the lock */
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync rtHandleTableLock(pThis);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync /*
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * Perform the lookup and retaining.
cc66247640b520463f925a5533fc9e5de06aa982vboxsync */
cc66247640b520463f925a5533fc9e5de06aa982vboxsync PRTHTENTRY pEntry = rtHandleTableLookupSimple(pThis, h);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync if (pEntry)
cc66247640b520463f925a5533fc9e5de06aa982vboxsync {
cc66247640b520463f925a5533fc9e5de06aa982vboxsync pvObj = pEntry->pvObj;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync if (!RTHT_IS_FREE(pvObj))
cc66247640b520463f925a5533fc9e5de06aa982vboxsync {
cc66247640b520463f925a5533fc9e5de06aa982vboxsync if (pThis->pfnRetain)
cc66247640b520463f925a5533fc9e5de06aa982vboxsync {
cc66247640b520463f925a5533fc9e5de06aa982vboxsync int rc = pThis->pfnRetain(hHandleTable, pEntry->pvObj, NULL, pThis->pvRetainUser);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync if (RT_FAILURE(rc))
cc66247640b520463f925a5533fc9e5de06aa982vboxsync pvObj = NULL;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync }
cc66247640b520463f925a5533fc9e5de06aa982vboxsync }
cc66247640b520463f925a5533fc9e5de06aa982vboxsync else
cc66247640b520463f925a5533fc9e5de06aa982vboxsync pvObj = NULL;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync }
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync /* release the lock */
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync rtHandleTableUnlock(pThis);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync return pvObj;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync}
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsyncRT_EXPORT_SYMBOL(RTHandleTableLookup);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsyncRTDECL(void *) RTHandleTableFree(RTHANDLETABLE hHandleTable, uint32_t h)
cc66247640b520463f925a5533fc9e5de06aa982vboxsync{
cc66247640b520463f925a5533fc9e5de06aa982vboxsync /* validate the input */
cc66247640b520463f925a5533fc9e5de06aa982vboxsync PRTHANDLETABLEINT pThis = (PRTHANDLETABLEINT)hHandleTable;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync AssertPtrReturn(pThis, NULL);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync AssertReturn(pThis->u32Magic == RTHANDLETABLE_MAGIC, NULL);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync AssertReturn(!(pThis->fFlags & RTHANDLETABLE_FLAGS_CONTEXT), NULL);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync void *pvObj = NULL;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync /* acquire the lock */
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync rtHandleTableLock(pThis);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync /*
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * Perform the lookup and retaining.
cc66247640b520463f925a5533fc9e5de06aa982vboxsync */
cc66247640b520463f925a5533fc9e5de06aa982vboxsync PRTHTENTRY pEntry = rtHandleTableLookupSimple(pThis, h);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync if (pEntry)
cc66247640b520463f925a5533fc9e5de06aa982vboxsync {
cc66247640b520463f925a5533fc9e5de06aa982vboxsync pvObj = pEntry->pvObj;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync if (!RTHT_IS_FREE(pvObj))
cc66247640b520463f925a5533fc9e5de06aa982vboxsync {
cc66247640b520463f925a5533fc9e5de06aa982vboxsync if (pThis->pfnRetain)
cc66247640b520463f925a5533fc9e5de06aa982vboxsync {
cc66247640b520463f925a5533fc9e5de06aa982vboxsync int rc = pThis->pfnRetain(hHandleTable, pEntry->pvObj, NULL, pThis->pvRetainUser);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync if (RT_FAILURE(rc))
cc66247640b520463f925a5533fc9e5de06aa982vboxsync pvObj = NULL;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync }
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync /*
cc66247640b520463f925a5533fc9e5de06aa982vboxsync * Link it into the free list.
cc66247640b520463f925a5533fc9e5de06aa982vboxsync */
cc66247640b520463f925a5533fc9e5de06aa982vboxsync if (pvObj)
cc66247640b520463f925a5533fc9e5de06aa982vboxsync {
cc66247640b520463f925a5533fc9e5de06aa982vboxsync PRTHTENTRYFREE pFree = (PRTHTENTRYFREE)pEntry;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync RTHT_SET_FREE_IDX(pFree, NIL_RTHT_INDEX);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync uint32_t const i = h - pThis->uBase;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync if (pThis->iFreeTail == NIL_RTHT_INDEX)
cc66247640b520463f925a5533fc9e5de06aa982vboxsync pThis->iFreeHead = pThis->iFreeTail = i;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync else
cc66247640b520463f925a5533fc9e5de06aa982vboxsync {
cc66247640b520463f925a5533fc9e5de06aa982vboxsync PRTHTENTRYFREE pPrev = (PRTHTENTRYFREE)rtHandleTableLookupSimpleIdx(pThis, pThis->iFreeTail);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync Assert(pPrev);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync RTHT_SET_FREE_IDX(pPrev, i);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync pThis->iFreeTail = i;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync }
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync Assert(pThis->cCurAllocated > 0);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync pThis->cCurAllocated--;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync }
cc66247640b520463f925a5533fc9e5de06aa982vboxsync }
cc66247640b520463f925a5533fc9e5de06aa982vboxsync else
cc66247640b520463f925a5533fc9e5de06aa982vboxsync pvObj = NULL;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync }
cc66247640b520463f925a5533fc9e5de06aa982vboxsync
cc66247640b520463f925a5533fc9e5de06aa982vboxsync /* release the lock */
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync rtHandleTableUnlock(pThis);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync return pvObj;
cc66247640b520463f925a5533fc9e5de06aa982vboxsync}
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsyncRT_EXPORT_SYMBOL(RTHandleTableFree);
cc66247640b520463f925a5533fc9e5de06aa982vboxsync