handletablectx.cpp revision c7814cf6e1240a519cbec0441e033d0e2470ed00
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync/* $Id$ */
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync/** @file
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * IPRT - Handle Tables.
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync */
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync/*
e64031e20c39650a7bc902a3e1aba613b9415deevboxsync * Copyright (C) 2008-2012 Oracle Corporation
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync *
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * available from http://www.virtualbox.org. This file is free software;
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * you can redistribute it and/or modify it under the terms of the GNU
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * General Public License (GPL) as published by the Free Software
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync *
0d12c7f9423f2745f8e282523d0930f91bff03b3vboxsync * The contents of this file may alternatively be used under the terms
0d12c7f9423f2745f8e282523d0930f91bff03b3vboxsync * of the Common Development and Distribution License Version 1.0
0d12c7f9423f2745f8e282523d0930f91bff03b3vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
0d12c7f9423f2745f8e282523d0930f91bff03b3vboxsync * VirtualBox OSE distribution, in which case the provisions of the
0d12c7f9423f2745f8e282523d0930f91bff03b3vboxsync * CDDL are applicable instead of those of the GPL.
0d12c7f9423f2745f8e282523d0930f91bff03b3vboxsync *
0d12c7f9423f2745f8e282523d0930f91bff03b3vboxsync * You may elect to license modified versions of this file under the
0d12c7f9423f2745f8e282523d0930f91bff03b3vboxsync * terms and conditions of either the GPL or the CDDL or both.
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync */
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync/*******************************************************************************
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync* Header Files *
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync*******************************************************************************/
032a52c5b2984e26e84c2961f8f7f98a3954c8f2vboxsync#include <iprt/handletable.h>
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync#include "internal/iprt.h"
590bfe12ce22cd3716448fbb9f4dc51664bfe5e2vboxsync
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync#include <iprt/mem.h>
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync#include <iprt/spinlock.h>
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync#include <iprt/err.h>
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync#include <iprt/assert.h>
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync#include <iprt/param.h>
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync#include <iprt/string.h>
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync#include <iprt/asm.h>
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync#include "internal/magics.h"
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync#include "handletable.h"
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsyncRTDECL(int) RTHandleTableAllocWithCtx(RTHANDLETABLE hHandleTable, void *pvObj, void *pvCtx, uint32_t *ph)
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync{
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync PRTHANDLETABLEINT pThis;
c2046db2cc346cc299f0cd9b2d1e160179159cfcvboxsync int rc;
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync
c2046db2cc346cc299f0cd9b2d1e160179159cfcvboxsync /* validate the input */
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync pThis = (PRTHANDLETABLEINT)hHandleTable;
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
c2046db2cc346cc299f0cd9b2d1e160179159cfcvboxsync AssertReturn(pThis->u32Magic == RTHANDLETABLE_MAGIC, VERR_INVALID_HANDLE);
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync AssertReturn(pThis->fFlags & RTHANDLETABLE_FLAGS_CONTEXT, VERR_INVALID_FUNCTION);
c2046db2cc346cc299f0cd9b2d1e160179159cfcvboxsync AssertReturn(!RTHT_IS_FREE(pvObj), VERR_INVALID_PARAMETER);
c2046db2cc346cc299f0cd9b2d1e160179159cfcvboxsync AssertPtrReturn(ph, VERR_INVALID_POINTER);
c2046db2cc346cc299f0cd9b2d1e160179159cfcvboxsync *ph = pThis->uBase - 1;
c2046db2cc346cc299f0cd9b2d1e160179159cfcvboxsync
c2046db2cc346cc299f0cd9b2d1e160179159cfcvboxsync /*
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * Allocation loop.
044af0d1e6474076366759db86f101778c5f20ccvboxsync */
044af0d1e6474076366759db86f101778c5f20ccvboxsync rtHandleTableLock(pThis);
044af0d1e6474076366759db86f101778c5f20ccvboxsync
044af0d1e6474076366759db86f101778c5f20ccvboxsync do
044af0d1e6474076366759db86f101778c5f20ccvboxsync {
044af0d1e6474076366759db86f101778c5f20ccvboxsync /*
044af0d1e6474076366759db86f101778c5f20ccvboxsync * Try grab a free entry from the head of the free list.
044af0d1e6474076366759db86f101778c5f20ccvboxsync */
044af0d1e6474076366759db86f101778c5f20ccvboxsync uint32_t i = pThis->iFreeHead;
044af0d1e6474076366759db86f101778c5f20ccvboxsync if (i != NIL_RTHT_INDEX)
044af0d1e6474076366759db86f101778c5f20ccvboxsync {
044af0d1e6474076366759db86f101778c5f20ccvboxsync PRTHTENTRYCTX pEntry;
044af0d1e6474076366759db86f101778c5f20ccvboxsync PRTHTENTRYFREE pFree = (PRTHTENTRYFREE)rtHandleTableLookupWithCtxIdx(pThis, i);
044af0d1e6474076366759db86f101778c5f20ccvboxsync Assert(pFree);
044af0d1e6474076366759db86f101778c5f20ccvboxsync if (i == pThis->iFreeTail)
044af0d1e6474076366759db86f101778c5f20ccvboxsync pThis->iFreeTail = pThis->iFreeHead = NIL_RTHT_INDEX;
044af0d1e6474076366759db86f101778c5f20ccvboxsync else
044af0d1e6474076366759db86f101778c5f20ccvboxsync pThis->iFreeHead = RTHT_GET_FREE_IDX(pFree);
044af0d1e6474076366759db86f101778c5f20ccvboxsync pThis->cCurAllocated++;
044af0d1e6474076366759db86f101778c5f20ccvboxsync Assert(pThis->cCurAllocated <= pThis->cCur);
044af0d1e6474076366759db86f101778c5f20ccvboxsync
044af0d1e6474076366759db86f101778c5f20ccvboxsync /*
044af0d1e6474076366759db86f101778c5f20ccvboxsync * Setup the entry and return.
044af0d1e6474076366759db86f101778c5f20ccvboxsync */
044af0d1e6474076366759db86f101778c5f20ccvboxsync pEntry = (PRTHTENTRYCTX)pFree;
044af0d1e6474076366759db86f101778c5f20ccvboxsync pEntry->pvObj = pvObj;
044af0d1e6474076366759db86f101778c5f20ccvboxsync pEntry->pvCtx = pvCtx;
044af0d1e6474076366759db86f101778c5f20ccvboxsync *ph = i + pThis->uBase;
044af0d1e6474076366759db86f101778c5f20ccvboxsync rc = VINF_SUCCESS;
044af0d1e6474076366759db86f101778c5f20ccvboxsync }
044af0d1e6474076366759db86f101778c5f20ccvboxsync /*
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * Must expand the handle table, unless it's full.
044af0d1e6474076366759db86f101778c5f20ccvboxsync */
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync else if (pThis->cCur >= pThis->cMax)
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync {
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync rc = VERR_NO_MORE_HANDLES;
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync Assert(pThis->cCur == pThis->cCurAllocated);
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync }
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync else
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync {
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync void **papvLevel1;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync uint32_t iLevel1New;
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync PRTHTENTRYCTX paTable;
044af0d1e6474076366759db86f101778c5f20ccvboxsync
044af0d1e6474076366759db86f101778c5f20ccvboxsync /*
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync * Do we have to expand the 1st level table too?
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync */
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync uint32_t const iLevel1 = pThis->cCur / RTHT_LEVEL2_ENTRIES;
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync uint32_t cLevel1 = iLevel1 >= pThis->cLevel1
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync ? pThis->cLevel1 + PAGE_SIZE / sizeof(void *)
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync : 0;
044af0d1e6474076366759db86f101778c5f20ccvboxsync if (cLevel1 > pThis->cMax / RTHT_LEVEL2_ENTRIES)
044af0d1e6474076366759db86f101778c5f20ccvboxsync cLevel1 = pThis->cMax / RTHT_LEVEL2_ENTRIES;
044af0d1e6474076366759db86f101778c5f20ccvboxsync Assert(!cLevel1 || pThis->cMax / RTHT_LEVEL2_ENTRIES >= RTHT_LEVEL1_DYN_ALLOC_THRESHOLD);
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync /* leave the lock (never do fancy stuff from behind a spinlock). */
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync rtHandleTableUnlock(pThis);
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync /*
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * Do the allocation(s).
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync */
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync rc = VERR_TRY_AGAIN;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync papvLevel1 = NULL;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync if (cLevel1)
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync {
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync papvLevel1 = (void **)RTMemAlloc(sizeof(void *) * cLevel1);
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync if (!papvLevel1)
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync return VERR_NO_MEMORY;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync }
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync paTable = (PRTHTENTRYCTX)RTMemAlloc(sizeof(*paTable) * RTHT_LEVEL2_ENTRIES);
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync if (!paTable)
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync {
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync RTMemFree(papvLevel1);
a1df400bbe9d64aad400442e56eb637019300a5evboxsync return VERR_NO_MEMORY;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync }
a1df400bbe9d64aad400442e56eb637019300a5evboxsync
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync /* re-enter the lock. */
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync rtHandleTableLock(pThis);
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync /*
a1df400bbe9d64aad400442e56eb637019300a5evboxsync * Insert the new bits, but be a bit careful as someone might have
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync * raced us expanding the table.
a1df400bbe9d64aad400442e56eb637019300a5evboxsync */
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync /* deal with the 1st level lookup expansion first */
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync if (cLevel1)
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync {
044af0d1e6474076366759db86f101778c5f20ccvboxsync Assert(papvLevel1);
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync if (cLevel1 > pThis->cLevel1)
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync {
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync void **papvTmp;
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync /* Replace the 1st level table. */
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync memcpy(papvLevel1, pThis->papvLevel1, sizeof(void *) * pThis->cLevel1);
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync memset(&papvLevel1[pThis->cLevel1], 0, sizeof(void *) * (cLevel1 - pThis->cLevel1));
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync pThis->cLevel1 = cLevel1;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync papvTmp = pThis->papvLevel1;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync pThis->papvLevel1 = papvLevel1;
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync papvLevel1 = papvTmp;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync }
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync /* free the obsolete one (outside the lock of course) */
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync rtHandleTableUnlock(pThis);
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync RTMemFree(papvLevel1);
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync rtHandleTableLock(pThis);
044af0d1e6474076366759db86f101778c5f20ccvboxsync }
044af0d1e6474076366759db86f101778c5f20ccvboxsync
044af0d1e6474076366759db86f101778c5f20ccvboxsync /* insert the table we allocated. */
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync iLevel1New = pThis->cCur / RTHT_LEVEL2_ENTRIES;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync if ( iLevel1New < pThis->cLevel1
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync && pThis->cCur < pThis->cMax)
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync {
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync pThis->papvLevel1[iLevel1New] = paTable;
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync /* link all entries into a free list. */
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync Assert(!(pThis->cCur % RTHT_LEVEL2_ENTRIES));
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync for (i = 0; i < RTHT_LEVEL2_ENTRIES - 1; i++)
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync {
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync RTHT_SET_FREE_IDX((PRTHTENTRYFREE)&paTable[i], i + 1 + pThis->cCur);
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync paTable[i].pvCtx = (void *)~(uintptr_t)7;
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync }
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync RTHT_SET_FREE_IDX((PRTHTENTRYFREE)&paTable[RTHT_LEVEL2_ENTRIES - 1], NIL_RTHT_INDEX);
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync paTable[RTHT_LEVEL2_ENTRIES - 1].pvCtx = (void *)~(uintptr_t)7;
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync /* join the free list with the other. */
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync if (pThis->iFreeTail == NIL_RTHT_INDEX)
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync pThis->iFreeHead = pThis->cCur;
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync else
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync {
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync PRTHTENTRYFREE pPrev = (PRTHTENTRYFREE)rtHandleTableLookupWithCtxIdx(pThis, pThis->iFreeTail);
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync Assert(pPrev);
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync RTHT_SET_FREE_IDX(pPrev, pThis->cCur);
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync }
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync pThis->iFreeTail = pThis->cCur + RTHT_LEVEL2_ENTRIES - 1;
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync pThis->cCur += RTHT_LEVEL2_ENTRIES;
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync }
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync else
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync {
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync /* free the table (raced someone, and we lost). */
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync rtHandleTableUnlock(pThis);
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync RTMemFree(paTable);
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync rtHandleTableLock(pThis);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync rc = VERR_TRY_AGAIN;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync } while (rc == VERR_TRY_AGAIN);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync rtHandleTableUnlock(pThis);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync return rc;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync}
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsyncRT_EXPORT_SYMBOL(RTHandleTableAllocWithCtx);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsyncRTDECL(void *) RTHandleTableLookupWithCtx(RTHANDLETABLE hHandleTable, uint32_t h, void *pvCtx)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync{
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync void *pvObj = NULL;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync PRTHTENTRYCTX pEntry;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync PRTHANDLETABLEINT pThis;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync /* validate the input */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync pThis = (PRTHANDLETABLEINT)hHandleTable;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync AssertPtrReturn(pThis, NULL);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync AssertReturn(pThis->u32Magic == RTHANDLETABLE_MAGIC, NULL);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync AssertReturn(pThis->fFlags & RTHANDLETABLE_FLAGS_CONTEXT, NULL);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync /* acquire the lock */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync rtHandleTableLock(pThis);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync /*
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync * Perform the lookup and retaining.
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync pEntry = rtHandleTableLookupWithCtx(pThis, h);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (pEntry && pEntry->pvCtx == pvCtx)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync pvObj = pEntry->pvObj;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (!RTHT_IS_FREE(pvObj))
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (pThis->pfnRetain)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync int rc = pThis->pfnRetain(hHandleTable, pEntry->pvObj, pvCtx, pThis->pvRetainUser);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (RT_FAILURE(rc))
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync pvObj = NULL;
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync }
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync }
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync else
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync pvObj = NULL;
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync }
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync /* release the lock */
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync rtHandleTableUnlock(pThis);
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync return pvObj;
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync}
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsyncRT_EXPORT_SYMBOL(RTHandleTableLookupWithCtx);
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsyncRTDECL(void *) RTHandleTableFreeWithCtx(RTHANDLETABLE hHandleTable, uint32_t h, void *pvCtx)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync{
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync void *pvObj = NULL;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync PRTHTENTRYCTX pEntry;
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync PRTHANDLETABLEINT pThis;
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync /* validate the input */
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync pThis = (PRTHANDLETABLEINT)hHandleTable;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync AssertPtrReturn(pThis, NULL);
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync AssertReturn(pThis->u32Magic == RTHANDLETABLE_MAGIC, NULL);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync AssertReturn(pThis->fFlags & RTHANDLETABLE_FLAGS_CONTEXT, NULL);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync /* acquire the lock */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync rtHandleTableLock(pThis);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync /*
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync * Perform the lookup and retaining.
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync */
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync pEntry = rtHandleTableLookupWithCtx(pThis, h);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (pEntry && pEntry->pvCtx == pvCtx)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync pvObj = pEntry->pvObj;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (!RTHT_IS_FREE(pvObj))
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (pThis->pfnRetain)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync int rc = pThis->pfnRetain(hHandleTable, pEntry->pvObj, pvCtx, pThis->pvRetainUser);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (RT_FAILURE(rc))
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync pvObj = NULL;
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync }
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync /*
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync * Link it into the free list.
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync */
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (pvObj)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync PRTHTENTRYFREE pFree;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync uint32_t i;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync pEntry->pvCtx = (void *)~(uintptr_t)7;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync pFree = (PRTHTENTRYFREE)pEntry;
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync RTHT_SET_FREE_IDX(pFree, NIL_RTHT_INDEX);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync i = h - pThis->uBase;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync if (pThis->iFreeTail == NIL_RTHT_INDEX)
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync pThis->iFreeHead = pThis->iFreeTail = i;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync else
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync {
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync PRTHTENTRYFREE pPrev = (PRTHTENTRYFREE)rtHandleTableLookupWithCtxIdx(pThis, pThis->iFreeTail);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync Assert(pPrev);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync RTHT_SET_FREE_IDX(pPrev, i);
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync pThis->iFreeTail = i;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync Assert(pThis->cCurAllocated > 0);
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync pThis->cCurAllocated--;
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync }
4a1654dd5b9f0ae4e149d909843a3ab07b8bec33vboxsync else
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync pvObj = NULL;
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync }
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync /* release the lock */
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync rtHandleTableUnlock(pThis);
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync return pvObj;
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync}
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsyncRT_EXPORT_SYMBOL(RTHandleTableFreeWithCtx);
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync