handletablectx.cpp revision 8e2e6c9f8f2157e3ec6599f87343bdc453734c4c
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * IPRT - Handle Tables.
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * Copyright (C) 2008 Sun Microsystems, Inc.
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 * 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 * 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 * 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* Header Files *
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync*******************************************************************************/
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncRTDECL(int) RTHandleTableAllocWithCtx(RTHANDLETABLE hHandleTable, void *pvObj, void *pvCtx, uint32_t *ph)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* validate the input */
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);
2daaccf68be3773aee600c5c3e48bcf5401418a6vboxsync * Allocation loop.
7666082b743c5e146a8cee6cc794ff4bc3fd0ffdvboxsync * Try grab a free entry from the head of the free list.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync PRTHTENTRYFREE pFree = (PRTHTENTRYFREE)rtHandleTableLookupWithCtxIdx(pThis, i);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pThis->iFreeTail = pThis->iFreeHead = NIL_RTHT_INDEX;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Setup the entry and return.
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * Must expand the handle table, unless it's full.
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * Do we have to expand the 1st level table too?
22e281e75ed636601178296c6daebda8f1d17c59vboxsync uint32_t const iLevel1 = pThis->cCur / RTHT_LEVEL2_ENTRIES;
22e281e75ed636601178296c6daebda8f1d17c59vboxsync Assert(!cLevel1 || pThis->cMax / RTHT_LEVEL2_ENTRIES >= RTHT_LEVEL1_DYN_ALLOC_THRESHOLD);
22e281e75ed636601178296c6daebda8f1d17c59vboxsync /* leave the lock (never do fancy stuff from behind a spinlock). */
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * Do the allocation(s).
22e281e75ed636601178296c6daebda8f1d17c59vboxsync papvLevel1 = (void **)RTMemAlloc(sizeof(void *) * cLevel1);
22e281e75ed636601178296c6daebda8f1d17c59vboxsync paTable = (PRTHTENTRYCTX)RTMemAlloc(sizeof(*paTable) * RTHT_LEVEL2_ENTRIES);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* re-enter the lock. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Insert the new bits, but be a bit careful as someone might have
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * raced us expanding the table.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* deal with the 1st level lookup expansion first */
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 /* free the obsolete one (outside the lock of course) */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* insert the table we allocated. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* link all entries into a free list. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTHT_SET_FREE_IDX((PRTHTENTRYFREE)&paTable[i], i + 1 + pThis->cCur);
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 /* join the free list with the other. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync PRTHTENTRYFREE pPrev = (PRTHTENTRYFREE)rtHandleTableLookupWithCtxIdx(pThis, pThis->iFreeTail);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pThis->iFreeTail = pThis->cCur + RTHT_LEVEL2_ENTRIES - 1;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* free the table (raced someone, and we lost). */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncRTDECL(void *) RTHandleTableLookupWithCtx(RTHANDLETABLE hHandleTable, uint32_t h, void *pvCtx)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* validate the input */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertReturn(pThis->u32Magic == RTHANDLETABLE_MAGIC, NULL);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertReturn(pThis->fFlags & RTHANDLETABLE_FLAGS_CONTEXT, NULL);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* acquire the lock */
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync * Perform the lookup and retaining.
3ecd8008b81f02a04220705ae0033142af363280vboxsync int rc = pThis->pfnRetain(hHandleTable, pEntry->pvObj, pvCtx, pThis->pvRetainUser);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* release the lock */
3ecd8008b81f02a04220705ae0033142af363280vboxsyncRTDECL(void *) RTHandleTableFreeWithCtx(RTHANDLETABLE hHandleTable, uint32_t h, void *pvCtx)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* validate the input */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertReturn(pThis->u32Magic == RTHANDLETABLE_MAGIC, NULL);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertReturn(pThis->fFlags & RTHANDLETABLE_FLAGS_CONTEXT, NULL);
22e281e75ed636601178296c6daebda8f1d17c59vboxsync /* acquire the lock */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Perform the lookup and retaining.
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync int rc = pThis->pfnRetain(hHandleTable, pEntry->pvObj, pvCtx, pThis->pvRetainUser);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Link it into the free list.
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync PRTHTENTRYFREE pPrev = (PRTHTENTRYFREE)rtHandleTableLookupWithCtxIdx(pThis, pThis->iFreeTail);
57399ab65e2825c324fb9dcb4642d4ae2c232509vboxsync /* release the lock */