handletablectx.cpp revision 8e2e6c9f8f2157e3ec6599f87343bdc453734c4c
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* $Id$ */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/** @file
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * IPRT - Handle Tables.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/*
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * Copyright (C) 2008 Sun Microsystems, Inc.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * available from http://www.virtualbox.org. This file is free software;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * you can redistribute it and/or modify it under the terms of the GNU
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * General Public License (GPL) as published by the Free Software
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync *
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * The contents of this file may alternatively be used under the terms
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * of the Common Development and Distribution License Version 1.0
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * VirtualBox OSE distribution, in which case the provisions of the
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * CDDL are applicable instead of those of the GPL.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * You may elect to license modified versions of this file under the
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * terms and conditions of either the GPL or the CDDL or both.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * additional information or have any questions.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
7e960d3a0a8a3a84d7aba2cca45d72b1c31cc97bvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/*******************************************************************************
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync* Header Files *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync*******************************************************************************/
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <iprt/handletable.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include "internal/iprt.h"
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <iprt/mem.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <iprt/spinlock.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <iprt/err.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <iprt/assert.h>
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync#include <iprt/param.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <iprt/string.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include <iprt/asm.h>
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include "internal/magics.h"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#include "handletable.h"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
590bfe12ce22cd3716448fbb9f4dc51664bfe5e2vboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncRTDECL(int) RTHandleTableAllocWithCtx(RTHANDLETABLE hHandleTable, void *pvObj, void *pvCtx, uint32_t *ph)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync{
223cf005b18af2c21352a70693ebaf0582f68ebcvboxsync PRTHANDLETABLEINT pThis;
223cf005b18af2c21352a70693ebaf0582f68ebcvboxsync RTSPINLOCKTMP Tmp /*= no init */;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int rc;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* validate the input */
afed5ab737f4aacfae3fe73776f40e989190a7cavboxsync pThis = (PRTHANDLETABLEINT)hHandleTable;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertReturn(pThis->u32Magic == RTHANDLETABLE_MAGIC, VERR_INVALID_HANDLE);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertReturn(pThis->fFlags & RTHANDLETABLE_FLAGS_CONTEXT, VERR_INVALID_FUNCTION);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertReturn(!RTHT_IS_FREE(pvObj), VERR_INVALID_PARAMETER);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertPtrReturn(ph, VERR_INVALID_POINTER);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *ph = pThis->uBase - 1;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
0174432b2b1a760b89840ba696f7ba51def65dddvboxsync /*
2daaccf68be3773aee600c5c3e48bcf5401418a6vboxsync * Allocation loop.
0174432b2b1a760b89840ba696f7ba51def65dddvboxsync */
7666082b743c5e146a8cee6cc794ff4bc3fd0ffdvboxsync rtHandleTableLock(pThis, &Tmp);
7666082b743c5e146a8cee6cc794ff4bc3fd0ffdvboxsync
7666082b743c5e146a8cee6cc794ff4bc3fd0ffdvboxsync do
7666082b743c5e146a8cee6cc794ff4bc3fd0ffdvboxsync {
7666082b743c5e146a8cee6cc794ff4bc3fd0ffdvboxsync /*
7666082b743c5e146a8cee6cc794ff4bc3fd0ffdvboxsync * Try grab a free entry from the head of the free list.
7666082b743c5e146a8cee6cc794ff4bc3fd0ffdvboxsync */
7666082b743c5e146a8cee6cc794ff4bc3fd0ffdvboxsync uint32_t i = pThis->iFreeHead;
590bfe12ce22cd3716448fbb9f4dc51664bfe5e2vboxsync if (i != NIL_RTHT_INDEX)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync PRTHTENTRYCTX pEntry;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync PRTHTENTRYFREE pFree = (PRTHTENTRYFREE)rtHandleTableLookupWithCtxIdx(pThis, i);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Assert(pFree);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (i == pThis->iFreeTail)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pThis->iFreeTail = pThis->iFreeHead = NIL_RTHT_INDEX;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pThis->iFreeHead = RTHT_GET_FREE_IDX(pFree);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pThis->cCurAllocated++;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Assert(pThis->cCurAllocated <= pThis->cCur);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Setup the entry and return.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pEntry = (PRTHTENTRYCTX)pFree;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pEntry->pvObj = pvObj;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pEntry->pvCtx = pvCtx;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync *ph = i + pThis->uBase;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = VINF_SUCCESS;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * Must expand the handle table, unless it's full.
22e281e75ed636601178296c6daebda8f1d17c59vboxsync */
22e281e75ed636601178296c6daebda8f1d17c59vboxsync else if (pThis->cCur >= pThis->cMax)
22e281e75ed636601178296c6daebda8f1d17c59vboxsync {
22e281e75ed636601178296c6daebda8f1d17c59vboxsync rc = VERR_NO_MORE_HANDLES;
22e281e75ed636601178296c6daebda8f1d17c59vboxsync Assert(pThis->cCur == pThis->cCurAllocated);
22e281e75ed636601178296c6daebda8f1d17c59vboxsync }
22e281e75ed636601178296c6daebda8f1d17c59vboxsync else
22e281e75ed636601178296c6daebda8f1d17c59vboxsync {
22e281e75ed636601178296c6daebda8f1d17c59vboxsync void **papvLevel1;
22e281e75ed636601178296c6daebda8f1d17c59vboxsync uint32_t iLevel1New;
22e281e75ed636601178296c6daebda8f1d17c59vboxsync PRTHTENTRYCTX paTable;
22e281e75ed636601178296c6daebda8f1d17c59vboxsync
22e281e75ed636601178296c6daebda8f1d17c59vboxsync /*
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * Do we have to expand the 1st level table too?
22e281e75ed636601178296c6daebda8f1d17c59vboxsync */
22e281e75ed636601178296c6daebda8f1d17c59vboxsync uint32_t const iLevel1 = pThis->cCur / RTHT_LEVEL2_ENTRIES;
22e281e75ed636601178296c6daebda8f1d17c59vboxsync uint32_t cLevel1 = iLevel1 >= pThis->cLevel1
22e281e75ed636601178296c6daebda8f1d17c59vboxsync ? pThis->cLevel1 + PAGE_SIZE / sizeof(void *)
22e281e75ed636601178296c6daebda8f1d17c59vboxsync : 0;
22e281e75ed636601178296c6daebda8f1d17c59vboxsync if (cLevel1 > pThis->cMax / RTHT_LEVEL2_ENTRIES)
22e281e75ed636601178296c6daebda8f1d17c59vboxsync cLevel1 = pThis->cMax / RTHT_LEVEL2_ENTRIES;
22e281e75ed636601178296c6daebda8f1d17c59vboxsync Assert(!cLevel1 || pThis->cMax / RTHT_LEVEL2_ENTRIES >= RTHT_LEVEL1_DYN_ALLOC_THRESHOLD);
7b80828e5760a8814fe6cd494d2715a4544fbddcvboxsync
22e281e75ed636601178296c6daebda8f1d17c59vboxsync /* leave the lock (never do fancy stuff from behind a spinlock). */
22e281e75ed636601178296c6daebda8f1d17c59vboxsync rtHandleTableUnlock(pThis, &Tmp);
22e281e75ed636601178296c6daebda8f1d17c59vboxsync
22e281e75ed636601178296c6daebda8f1d17c59vboxsync /*
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * Do the allocation(s).
22e281e75ed636601178296c6daebda8f1d17c59vboxsync */
22e281e75ed636601178296c6daebda8f1d17c59vboxsync rc = VERR_TRY_AGAIN;
22e281e75ed636601178296c6daebda8f1d17c59vboxsync papvLevel1 = NULL;
22e281e75ed636601178296c6daebda8f1d17c59vboxsync if (cLevel1)
22e281e75ed636601178296c6daebda8f1d17c59vboxsync {
22e281e75ed636601178296c6daebda8f1d17c59vboxsync papvLevel1 = (void **)RTMemAlloc(sizeof(void *) * cLevel1);
22e281e75ed636601178296c6daebda8f1d17c59vboxsync if (!papvLevel1)
22e281e75ed636601178296c6daebda8f1d17c59vboxsync return VERR_NO_MEMORY;
22e281e75ed636601178296c6daebda8f1d17c59vboxsync }
22e281e75ed636601178296c6daebda8f1d17c59vboxsync
22e281e75ed636601178296c6daebda8f1d17c59vboxsync paTable = (PRTHTENTRYCTX)RTMemAlloc(sizeof(*paTable) * RTHT_LEVEL2_ENTRIES);
22e281e75ed636601178296c6daebda8f1d17c59vboxsync if (!paTable)
d1cbbd799d8912978f5146960b6780f387bb414bvboxsync {
22e281e75ed636601178296c6daebda8f1d17c59vboxsync RTMemFree(papvLevel1);
22e281e75ed636601178296c6daebda8f1d17c59vboxsync return VERR_NO_MEMORY;
c17f5c90f2cb60b38ecabebce128724c6ff2d036vboxsync }
22e281e75ed636601178296c6daebda8f1d17c59vboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* re-enter the lock. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rtHandleTableLock(pThis, &Tmp);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Insert the new bits, but be a bit careful as someone might have
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * raced us expanding the table.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* deal with the 1st level lookup expansion first */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (cLevel1)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Assert(papvLevel1);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (cLevel1 > pThis->cLevel1)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync void **papvTmp;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Replace the 1st level table. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync memcpy(papvLevel1, pThis->papvLevel1, sizeof(void *) * pThis->cLevel1);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync memset(&papvLevel1[pThis->cLevel1], 0, sizeof(void *) * (cLevel1 - pThis->cLevel1));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pThis->cLevel1 = cLevel1;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync papvTmp = pThis->papvLevel1;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pThis->papvLevel1 = papvLevel1;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync papvLevel1 = papvTmp;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* free the obsolete one (outside the lock of course) */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rtHandleTableUnlock(pThis, &Tmp);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTMemFree(papvLevel1);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rtHandleTableLock(pThis, &Tmp);
b1c3cdef473df2fbc621d5da81acc82dbfb8a11avboxsync }
a11c569636fa6838bd423f4631a9660a5a84204bvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* insert the table we allocated. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync iLevel1New = pThis->cCur / RTHT_LEVEL2_ENTRIES;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if ( iLevel1New < pThis->cLevel1
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync && pThis->cCur < pThis->cMax)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync uint32_t i;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pThis->papvLevel1[iLevel1New] = paTable;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* link all entries into a free list. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Assert(!(pThis->cCur % RTHT_LEVEL2_ENTRIES));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync for (i = 0; i < RTHT_LEVEL2_ENTRIES - 1; i++)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTHT_SET_FREE_IDX((PRTHTENTRYFREE)&paTable[i], i + 1 + pThis->cCur);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync paTable[i].pvCtx = (void *)~(uintptr_t)7;
3ecf9412133496b2aeb090cfd33a286404ec59fbvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTHT_SET_FREE_IDX((PRTHTENTRYFREE)&paTable[RTHT_LEVEL2_ENTRIES - 1], NIL_RTHT_INDEX);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync paTable[RTHT_LEVEL2_ENTRIES - 1].pvCtx = (void *)~(uintptr_t)7;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* join the free list with the other. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (pThis->iFreeTail == NIL_RTHT_INDEX)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pThis->iFreeHead = pThis->cCur;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync PRTHTENTRYFREE pPrev = (PRTHTENTRYFREE)rtHandleTableLookupWithCtxIdx(pThis, pThis->iFreeTail);
750d4d0506a38b2e80c997075d40aad474e675fbvboxsync Assert(pPrev);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTHT_SET_FREE_IDX(pPrev, pThis->cCur);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pThis->iFreeTail = pThis->cCur + RTHT_LEVEL2_ENTRIES - 1;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pThis->cCur += RTHT_LEVEL2_ENTRIES;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* free the table (raced someone, and we lost). */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rtHandleTableUnlock(pThis, &Tmp);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTMemFree(paTable);
aaeb2e2f6ed5b164f1dec9a16a7adeb84f64cf31vboxsync rtHandleTableLock(pThis, &Tmp);
223cf005b18af2c21352a70693ebaf0582f68ebcvboxsync }
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync rc = VERR_TRY_AGAIN;
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync }
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync } while (rc == VERR_TRY_AGAIN);
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync rtHandleTableUnlock(pThis, &Tmp);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync return rc;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync}
576d4214137bce409cdcf01e8df4a0bca5e0b2d1vboxsyncRT_EXPORT_SYMBOL(RTHandleTableAllocWithCtx);
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncRTDECL(void *) RTHandleTableLookupWithCtx(RTHANDLETABLE hHandleTable, uint32_t h, void *pvCtx)
72ef2b9fc5ffc01d0dabd5052d6e8baa3a952773vboxsync{
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync void *pvObj = NULL;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync PRTHTENTRYCTX pEntry;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync PRTHANDLETABLEINT pThis;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTSPINLOCKTMP Tmp /*= no init */;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* validate the input */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pThis = (PRTHANDLETABLEINT)hHandleTable;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertPtrReturn(pThis, NULL);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertReturn(pThis->u32Magic == RTHANDLETABLE_MAGIC, NULL);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertReturn(pThis->fFlags & RTHANDLETABLE_FLAGS_CONTEXT, NULL);
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* acquire the lock */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rtHandleTableLock(pThis, &Tmp);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync * Perform the lookup and retaining.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pEntry = rtHandleTableLookupWithCtx(pThis, h);
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync if (pEntry && pEntry->pvCtx == pvCtx)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
909f4391cc20b4a3a9a2d3f8718084b669663ab2vboxsync pvObj = pEntry->pvObj;
e08de24d4792d31b7f2aac29db5cb8840d940009vboxsync if (!RTHT_IS_FREE(pvObj))
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync {
22e281e75ed636601178296c6daebda8f1d17c59vboxsync if (pThis->pfnRetain)
8a132edc1577cbe2a19cd778c1b2bea6ae5e8515vboxsync {
3ecd8008b81f02a04220705ae0033142af363280vboxsync int rc = pThis->pfnRetain(hHandleTable, pEntry->pvObj, pvCtx, pThis->pvRetainUser);
3ecd8008b81f02a04220705ae0033142af363280vboxsync if (RT_FAILURE(rc))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pvObj = NULL;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
576d4214137bce409cdcf01e8df4a0bca5e0b2d1vboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pvObj = NULL;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* release the lock */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rtHandleTableUnlock(pThis, &Tmp);
f9147fe1eaa4e35287f8f39282c7f92f0d7de0b7vboxsync return pvObj;
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync}
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncRT_EXPORT_SYMBOL(RTHandleTableLookupWithCtx);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
3ecd8008b81f02a04220705ae0033142af363280vboxsync
3ecd8008b81f02a04220705ae0033142af363280vboxsyncRTDECL(void *) RTHandleTableFreeWithCtx(RTHANDLETABLE hHandleTable, uint32_t h, void *pvCtx)
22e281e75ed636601178296c6daebda8f1d17c59vboxsync{
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync void *pvObj = NULL;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync PRTHTENTRYCTX pEntry;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync PRTHANDLETABLEINT pThis;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTSPINLOCKTMP Tmp /*= no init */;
22e281e75ed636601178296c6daebda8f1d17c59vboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* validate the input */
247b55faa8d054157f2481e68caca36f4dc9542cvboxsync pThis = (PRTHANDLETABLEINT)hHandleTable;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertPtrReturn(pThis, NULL);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertReturn(pThis->u32Magic == RTHANDLETABLE_MAGIC, NULL);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertReturn(pThis->fFlags & RTHANDLETABLE_FLAGS_CONTEXT, NULL);
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync
57399ab65e2825c324fb9dcb4642d4ae2c232509vboxsync
22e281e75ed636601178296c6daebda8f1d17c59vboxsync /* acquire the lock */
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync rtHandleTableLock(pThis, &Tmp);
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /*
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Perform the lookup and retaining.
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pEntry = rtHandleTableLookupWithCtx(pThis, h);
6ae4b1c72625a8e5c369effea7f018b578d733c4vboxsync if (pEntry && pEntry->pvCtx == pvCtx)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pvObj = pEntry->pvObj;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (!RTHT_IS_FREE(pvObj))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (pThis->pfnRetain)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync {
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync int rc = pThis->pfnRetain(hHandleTable, pEntry->pvObj, pvCtx, pThis->pvRetainUser);
22e281e75ed636601178296c6daebda8f1d17c59vboxsync if (RT_FAILURE(rc))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pvObj = NULL;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync }
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
247b55faa8d054157f2481e68caca36f4dc9542cvboxsync /*
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Link it into the free list.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (pvObj)
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync {
22e281e75ed636601178296c6daebda8f1d17c59vboxsync PRTHTENTRYFREE pFree;
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync uint32_t i;
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync pEntry->pvCtx = (void *)~(uintptr_t)7;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pFree = (PRTHTENTRYFREE)pEntry;
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync RTHT_SET_FREE_IDX(pFree, NIL_RTHT_INDEX);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync
6ae4b1c72625a8e5c369effea7f018b578d733c4vboxsync i = h - pThis->uBase;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (pThis->iFreeTail == NIL_RTHT_INDEX)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pThis->iFreeHead = pThis->iFreeTail = i;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync else
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync {
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync PRTHTENTRYFREE pPrev = (PRTHTENTRYFREE)rtHandleTableLookupWithCtxIdx(pThis, pThis->iFreeTail);
00599f6d39cc25ca39845c2433cd75de7b9f6971vboxsync Assert(pPrev);
00599f6d39cc25ca39845c2433cd75de7b9f6971vboxsync RTHT_SET_FREE_IDX(pPrev, i);
00599f6d39cc25ca39845c2433cd75de7b9f6971vboxsync pThis->iFreeTail = i;
00599f6d39cc25ca39845c2433cd75de7b9f6971vboxsync }
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync Assert(pThis->cCurAllocated > 0);
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync pThis->cCurAllocated--;
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync }
22e281e75ed636601178296c6daebda8f1d17c59vboxsync }
00599f6d39cc25ca39845c2433cd75de7b9f6971vboxsync else
e50404712a2b5234c42bdf9740bddab5729ba188vboxsync pvObj = NULL;
57399ab65e2825c324fb9dcb4642d4ae2c232509vboxsync }
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync
57399ab65e2825c324fb9dcb4642d4ae2c232509vboxsync /* release the lock */
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync rtHandleTableUnlock(pThis, &Tmp);
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync return pvObj;
1843553dbdf4e46417158b4c6348c503adf10740vboxsync}
1843553dbdf4e46417158b4c6348c503adf10740vboxsyncRT_EXPORT_SYMBOL(RTHandleTableFreeWithCtx);
22e281e75ed636601178296c6daebda8f1d17c59vboxsync
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync