VirtualBox

Changeset 10819 in vbox for trunk/src/VBox/Devices


Ignore:
Timestamp:
Jul 22, 2008 5:58:54 PM (16 years ago)
Author:
vboxsync
Message:

intnet: Use the IPRT handle table, validate against the session when looking up the handle, and do proper reference counting of the interfaces when resolving a handle. Fixed an issue in the interface destructure where anyone that could (very theorically) be sleeping on it wouldn't decrement the waiter count as we wanted them to.

Location:
trunk/src/VBox/Devices/Network
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Network/SrvIntNetR0.cpp

    r10806 r10819  
    3737#include <iprt/string.h>
    3838#include <iprt/time.h>
     39#include <iprt/handletable.h>
    3940
    4041
     
    6162    /** Whether the interface is active or not. */
    6263    bool                    fActive;
     64    /** Whether someone is currently in the destructor. */
     65    bool volatile           fDestroying;
    6366    /** Number of yields done to try make the interface read pending data.
    6467     * We will stop yeilding when this reaches a threshold assuming that the VM is paused or
     
    7578    R3PTRTYPE(PINTNETBUF)   pIntBufDefaultR3;
    7679    /** Event semaphore which a receiver thread will sleep on while waiting for data to arrive. */
    77     RTSEMEVENT              Event;
     80    RTSEMEVENT volatile     Event;
    7881    /** Number of threads sleeping on the Event semaphore. */
    7982    uint32_t                cSleepers;
     
    8184     * When this is INTNET_HANDLE_INVALID a sleeper which is waking up
    8285     * should return with the appropriate error condition. */
    83     INTNETIFHANDLE         hIf;
     86    INTNETIFHANDLE volatile hIf;
    8487    /** Pointer to the network this interface is connected to.
    8588     * This is protected by the INTNET::FastMutex. */
     
    160163
    161164/**
    162  * Handle table entry.
    163  * @todo move to IPRT.
    164  */
    165 typedef union INTNETHTE
    166 {
    167     /** Pointer to the object we're a handle for. */
    168     PINTNETIF               pIF;
    169     /** Index to the next free entry. */
    170     uintptr_t               iNext;
    171 } INTNETHTE;
    172 /** Pointer to a handle table entry. */
    173 typedef INTNETHTE *PINTNETHTE;
    174 
    175 
    176 /**
    177  * Handle table.
    178  * @todo move to IPRT (RTHandleTableCreate/Destroy/Add/Delete/Lookup).
    179  */
    180 typedef struct INTNETHT
    181 {
    182     /** Spinlock protecting all access. */
    183     RTSPINLOCK              Spinlock;
    184     /** Pointer to the handle table. */
    185     PINTNETHTE              paEntries;
    186     /** The number of allocated handles. */
    187     uint32_t                cAllocated;
    188     /** The index of the first free handle entry.
    189      * UINT32_MAX means empty list. */
    190     uint32_t volatile       iHead;
    191     /** The index of the last free handle entry.
    192      * UINT32_MAX means empty list. */
    193     uint32_t volatile       iTail;
    194 } INTNETHT;
    195 /** Pointer to a handle table. */
    196 typedef INTNETHT *PINTNETHT;
    197 
    198 
    199 /**
    200165 * Internal networking instance.
    201166 */
     
    208173    PINTNETNETWORK volatile pNetworks;
    209174    /** Handle table for the interfaces. */
    210     INTNETHT                IfHandles;
     175    RTHANDLETABLE           hHtIfs;
    211176} INTNET;
    212177
     
    223188
    224189/**
    225  * Validates and translates an interface handle to a interface pointer.
    226  *
    227  * The caller already owns the spinlock, which means this is
    228  * for internal use only.
    229  *
    230  * @returns Pointer to interface.
    231  * @returns NULL if the handle is invalid.
    232  * @param   pHT         Pointer to the handle table.
    233  * @param   hIF         The interface handle to validate and translate.
    234  *
    235  * @internal
    236  */
    237 DECLINLINE(PINTNETIF) intnetR0Handle2IFPtrLocked(PINTNETHT pHT, INTNETIFHANDLE hIF)
    238 {
    239     if (RT_LIKELY((hIF & INTNET_HANDLE_MAGIC) == INTNET_HANDLE_MAGIC))
    240     {
    241         const uint32_t i = hIF & INTNET_HANDLE_INDEX_MASK;
    242         if (RT_LIKELY(   i < pHT->cAllocated
    243                       && pHT->paEntries[i].iNext >= INTNET_HANDLE_MAX
    244                       && pHT->paEntries[i].iNext != UINT32_MAX))
    245             return pHT->paEntries[i].pIF;
    246     }
    247     return NULL;
    248 }
    249 
    250 
    251 /**
    252  * Validates and translates an interface handle to a interface pointer.
    253  *
    254  * @returns Pointer to interface.
    255  * @returns NULL if the handle is invalid.
    256  * @param   pHT         Pointer to the handle table.
    257  * @param   hIF         The interface handle to validate and translate.
    258  */
    259 DECLINLINE(PINTNETIF) intnetR0Handle2IFPtr(PINTNETHT pHT, INTNETIFHANDLE hIF)
    260 {
    261     AssertPtr(pHT);
    262     RTSPINLOCKTMP   Tmp = RTSPINLOCKTMP_INITIALIZER;
    263     RTSpinlockAcquire(pHT->Spinlock, &Tmp);
    264     PINTNETIF pIF = intnetR0Handle2IFPtrLocked(pHT, hIF);
    265     RTSpinlockRelease(pHT->Spinlock, &Tmp);
    266 
    267     return pIF;
    268 }
    269 
    270 
    271 /**
    272  * Allocates a handle for an interface.
    273  *
    274  * @returns Handle on success.
    275  * @returns Invalid handle on failure.
    276  * @param   pIntNet     Pointer to the instance data.
    277  * @param   pIF         The interface which we're allocating a handle for.
    278  */
    279 static INTNETIFHANDLE intnetR0HandleAllocate(PINTNET pIntNet, PINTNETIF pIF)
    280 {
    281     Assert(pIF);
    282     Assert(pIntNet);
    283     unsigned    cTries = 10;
    284     PINTNETHT   pHT = &pIntNet->IfHandles;
    285     PINTNETHTE  paNew = NULL;
    286 
    287     RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
    288     RTSpinlockAcquire(pHT->Spinlock, &Tmp);
    289     for (;;)
    290     {
    291         /*
    292          * Check the free list.
    293          */
    294         uint32_t i = pHT->iHead;
    295         if (i != UINT32_MAX)
    296         {
    297             pHT->iHead = pHT->paEntries[i].iNext;
    298             if (pHT->iHead == UINT32_MAX)
    299                 pHT->iTail = UINT32_MAX;
    300 
    301             pHT->paEntries[i].pIF = pIF;
    302             RTSpinlockRelease(pHT->Spinlock, &Tmp);
    303             if (paNew)
    304                 RTMemFree(paNew);
    305             return i | INTNET_HANDLE_MAGIC;
    306         }
    307 
    308         /*
    309          * Leave the spinlock and allocate a new array.
    310          */
    311         const unsigned cNew = pHT->cAllocated + 128;
    312         RTSpinlockRelease(pHT->Spinlock, &Tmp);
    313         if (--cTries <= 0)
    314         {
    315             AssertMsgFailed(("Giving up!\n"));
    316             break;
    317         }
    318         paNew = (PINTNETHTE)RTMemAlloc(sizeof(*paNew) * cNew);
    319         if (!paNew)
    320             break;
    321 
    322         /*
    323          * Acquire the spinlock and check if someone raced us.
    324          */
    325         RTSpinlockAcquire(pHT->Spinlock, &Tmp);
    326         if (pHT->cAllocated < cNew)
    327         {
    328             /* copy the current table. */
    329             memcpy(paNew, pHT->paEntries, pHT->cAllocated * sizeof(*paNew));
    330 
    331             /* link the new entries into the free chain. */
    332             i = pHT->cAllocated;
    333             uint32_t iTail = pHT->iTail;
    334             if (iTail == UINT32_MAX)
    335                 pHT->iHead = iTail = i++;
    336             while (i < cNew)
    337             {
    338                 paNew[iTail].iNext = i;
    339                 iTail = i++;
    340             }
    341             paNew[iTail].iNext = UINT32_MAX;
    342             pHT->iTail = iTail;
    343 
    344             /* update the handle table. */
    345             pHT->cAllocated = cNew;
    346             paNew = (PINTNETHTE)ASMAtomicXchgPtr((void * volatile *)&pHT->paEntries, paNew);
    347         }
    348     }
    349 
    350     if (paNew)
    351         RTMemFree(paNew);
    352     return INTNET_HANDLE_INVALID;
    353 }
    354 
    355 
    356 /**
    357  * Validates and frees a handle.
    358  *
    359  * @returns Pointer to interface.
    360  * @returns NULL if the handle is invalid.
    361  * @param   pHT         Pointer to the handle table.
    362  * @param   h           The handle we're freeing.
    363  */
    364 static PINTNETIF intnetR0HandleFree(PINTNETHT pHT, INTNETIFHANDLE h)
    365 {
    366     RTSPINLOCKTMP   Tmp = RTSPINLOCKTMP_INITIALIZER;
    367     RTSpinlockAcquire(pHT->Spinlock, &Tmp);
    368 
    369     /*
    370      * Validate and get it, then insert the handle table entry
    371      * at the end of the free list.
    372      */
    373     PINTNETIF pIF = intnetR0Handle2IFPtrLocked(pHT, h);
    374     if (pIF)
    375     {
    376         const uint32_t i = h & INTNET_HANDLE_INDEX_MASK;
    377         pHT->paEntries[i].iNext = UINT32_MAX;
    378         const uint32_t iTail = pHT->iTail;
    379         if (iTail != UINT32_MAX)
    380             pHT->paEntries[iTail].iNext = i;
    381         else
    382             pHT->iHead = i;
    383         pHT->iTail = i;
    384     }
    385 
    386     RTSpinlockRelease(pHT->Spinlock, &Tmp);
    387 
    388     AssertMsg(pIF, ("%d >= %d\n", h & INTNET_HANDLE_INDEX_MASK, pHT->cAllocated));
    389     return pIF;
     190 * Retain an interface.
     191 *
     192 * @returns VBox status code, can assume success in most situations.
     193 * @param   pIf                 The interface instance.
     194 * @param   pSession            The current session.
     195 */
     196DECLINLINE(int) intnetR0IfRetain(PINTNETIF pIf, PSUPDRVSESSION pSession)
     197{
     198    int rc = SUPR0ObjAddRef(pIf->pvObj, pSession);
     199    AssertRCReturn(rc, rc);
     200    return VINF_SUCCESS;
     201}
     202
     203
     204/**
     205 * Release an interface previously retained by intnetR0IfRetain or
     206 * by handle lookup/freeing.
     207 *
     208 * @returns VBox status code, can assume success in most situations.
     209 * @param   pIf                 The interface instance.
     210 * @param   pSession            The current session.
     211 */
     212DECLINLINE(void) intnetR0IfRelease(PINTNETIF pIf, PSUPDRVSESSION pSession)
     213{
     214    int rc = SUPR0ObjRelease(pIf->pvObj, pSession);
     215    AssertRC(rc);
     216}
     217
     218
     219/**
     220 * RTHandleCreateEx callback that retains an object in the
     221 * handle table before returning it.
     222 *
     223 * (Avoids racing the freeing of the handle.)
     224 *
     225 * @returns VBox status code.
     226 * @param   hHandleTable        The handle table (ignored).
     227 * @param   pvObj               The object (INTNETIF).
     228 * @param   pvCtx               The context (SUPDRVSESSION).
     229 * @param   pvUser              The user context (ignored).
     230 */
     231static DECLCALLBACK(int) intnetR0IfRetainHandle(RTHANDLETABLE hHandleTable, void *pvObj, void *pvCtx, void *pvUser)
     232{
     233    NOREF(pvUser);
     234    NOREF(hHandleTable);
     235    PINTNETIF pIf = (PINTNETIF)pvObj;
     236    if (pIf->hIf != INTNET_HANDLE_INVALID) /* Don't try retain it if called from intnetR0IfDestruct. */
     237        return intnetR0IfRetain(pIf, (PSUPDRVSESSION)pvCtx);
     238    return VINF_SUCCESS;
    390239}
    391240
     
    991840INTNETR0DECL(int) INTNETR0IfSend(PINTNET pIntNet, INTNETIFHANDLE hIf, PSUPDRVSESSION pSession, const void *pvFrame, unsigned cbFrame)
    992841{
    993 //    LogFlow(("INTNETR0IfSend: pIntNet=%p hIf=%RX32 pvFrame=%p cbFrame=%u\n", pIntNet, hIf, pvFrame, cbFrame));
     842    Log5(("INTNETR0IfSend: pIntNet=%p hIf=%RX32 pvFrame=%p cbFrame=%u\n", pIntNet, hIf, pvFrame, cbFrame));
    994843
    995844    /*
    996845     * Validate input and translate the handle.
    997846     */
    998     /** @todo add an exctra reference to the interface! */
    999847    AssertReturn(pIntNet, VERR_INVALID_PARAMETER);
    1000     PINTNETIF pIf = intnetR0Handle2IFPtr(&pIntNet->IfHandles, hIf);
    1001     if (!pIf)
    1002         return VERR_INVALID_HANDLE;
    1003848    if (pvFrame && cbFrame)
    1004849    {
     
    1010855        ASMProbeReadBuffer(pvFrame, cbFrame);
    1011856    }
     857    PINTNETIF pIf = (PINTNETIF)RTHandleTableLookupWithCtx(pIntNet->hHtIfs, hIf, pSession);
     858    if (!pIf)
     859        return VERR_INVALID_HANDLE;
    1012860
    1013861    /*
     
    1021869    int rc = RTSemFastMutexRequest(pNetwork->FastMutex);
    1022870    if (RT_FAILURE(rc))
     871    {
     872        intnetR0IfRelease(pIf, pSession);
    1023873        return rc;
     874    }
    1024875    PINTNETTRUNKIF pTrunkIf = intnetR0TrunkIfRetain(pNetwork->pTrunkIF);
    1025876    if (pTrunkIf)
     
    1030881        {
    1031882            intnetR0TrunkIfRelease(pTrunkIf);
     883            intnetR0IfRelease(pIf, pSession);
    1032884            return VERR_SEM_DESTROYED;
    1033885        }
     
    1038890            intnetR0TrunkIfOutUnlock(pTrunkIf);
    1039891            intnetR0TrunkIfRelease(pTrunkIf);
     892            intnetR0IfRelease(pIf, pSession);
    1040893            return rc;
    1041894        }
     
    1087940    }
    1088941
     942    intnetR0IfRelease(pIf, pSession);
    1089943    return rc;
    1090944}
     
    1124978     */
    1125979    AssertReturn(pIntNet, VERR_INVALID_PARAMETER);
    1126     PINTNETIF pIf = intnetR0Handle2IFPtr(&pIntNet->IfHandles, hIf);
     980    AssertPtrReturn(ppRing3Buf, VERR_INVALID_PARAMETER);
     981    *ppRing3Buf = 0;
     982    PINTNETIF pIf = (PINTNETIF)RTHandleTableLookupWithCtx(pIntNet->hHtIfs, hIf, pSession);
    1127983    if (!pIf)
    1128984        return VERR_INVALID_HANDLE;
    1129     AssertPtrReturn(ppRing3Buf, VERR_INVALID_PARAMETER);
    1130985
    1131986    /*
     
    1135990     */
    1136991    int rc = RTSemFastMutexRequest(pIf->pNetwork->FastMutex);
    1137     if (RT_FAILURE(rc))
    1138         return rc;
    1139 
    1140     *ppRing3Buf = pIf->pIntBufR3;
    1141 
    1142     rc = RTSemFastMutexRelease(pIf->pNetwork->FastMutex);
     992    if (RT_SUCCESS(rc))
     993    {
     994        *ppRing3Buf = pIf->pIntBufR3;
     995        rc = RTSemFastMutexRelease(pIf->pNetwork->FastMutex);
     996    }
     997
     998    intnetR0IfRelease(pIf, pSession);
    1143999    LogFlow(("INTNETR0IfGetRing3Buffer: returns %Rrc *ppRing3Buf=%p\n", rc, *ppRing3Buf));
    11441000    return rc;
     
    11661022 *
    11671023 * @returns VBox status code.
    1168  * @param   pIntNet     The instance data.
    1169  * @param   hIf         The interface handle.
    1170  * @param   ppRing0Buf  Where to store the address of the ring-3 mapping.
    1171  */
    1172 INTNETR0DECL(int) INTNETR0IfGetRing0Buffer(PINTNET pIntNet, INTNETIFHANDLE hIf, PINTNETBUF *ppRing0Buf)
     1024 * @param   pIntNet         The instance data.
     1025 * @param   hIf             The interface handle.
     1026 * @param   pSession        The caller's session.
     1027 * @param   ppRing0Buf      Where to store the address of the ring-3 mapping.
     1028 */
     1029INTNETR0DECL(int) INTNETR0IfGetRing0Buffer(PINTNET pIntNet, INTNETIFHANDLE hIf, PSUPDRVSESSION pSession, PINTNETBUF *ppRing0Buf)
    11731030{
    11741031    LogFlow(("INTNETR0IfGetRing0Buffer: pIntNet=%p hIf=%RX32 ppRing0Buf=%p\n", pIntNet, hIf, ppRing0Buf));
     
    11801037    *ppRing0Buf = NULL;
    11811038    AssertPtrReturn(pIntNet, VERR_INVALID_PARAMETER);
    1182     PINTNETIF pIf = intnetR0Handle2IFPtr(&pIntNet->IfHandles, hIf);
     1039    PINTNETIF pIf = (PINTNETIF)RTHandleTableLookupWithCtx(pIntNet->hHtIfs, hIf, pSession);
    11831040    if (!pIf)
    11841041        return VERR_INVALID_HANDLE;
     
    11891046     */
    11901047    int rc = RTSemFastMutexRequest(pIf->pNetwork->FastMutex);
    1191     if (RT_FAILURE(rc))
    1192         return rc;
    1193 
    1194     *ppRing0Buf = pIf->pIntBuf;
    1195 
    1196     rc = RTSemFastMutexRelease(pIf->pNetwork->FastMutex);
     1048    if (RT_SUCCESS(rc))
     1049    {
     1050        *ppRing0Buf = pIf->pIntBuf;
     1051
     1052        rc = RTSemFastMutexRelease(pIf->pNetwork->FastMutex);
     1053    }
     1054    intnetR0IfRelease(pIf, pSession);
    11971055    LogFlow(("INTNETR0IfGetRing0Buffer: returns %Rrc *ppRing0Buf=%p\n", rc, *ppRing0Buf));
    11981056    return rc;
     
    12161074     */
    12171075    AssertReturn(pIntNet, VERR_INVALID_PARAMETER);
    1218     PINTNETIF pIf = intnetR0Handle2IFPtr(&pIntNet->IfHandles, hIf);
     1076    AssertPtrReturn(paPages, VERR_INVALID_PARAMETER);
     1077    AssertPtrReturn((uint8_t *)&paPages[cPages] - 1, VERR_INVALID_PARAMETER);
     1078    PINTNETIF pIf = (PINTNETIF)RTHandleTableLookupWithCtx(pIntNet->hHtIfs, hIf, pSession);
    12191079    if (!pIf)
    12201080        return VERR_INVALID_HANDLE;
    1221     AssertPtrReturn(paPages, VERR_INVALID_PARAMETER);
    1222     AssertPtrReturn((uint8_t *)&paPages[cPages] - 1, VERR_INVALID_PARAMETER);
    12231081
    12241082    /*
     
    12271085     */
    12281086    int rc = RTSemFastMutexRequest(pIf->pNetwork->FastMutex);
    1229     if (RT_FAILURE(rc))
    1230         return rc;
    1231 
    1232     /** @todo make a SUPR0 api for obtaining the array. SUPR0/IPRT is keeping track of everything, there
    1233      * is no need for any extra bookkeeping here.. */
    1234     //*ppRing0Buf = pIf->pIntBuf;
    1235 
    1236     //return RTSemFastMutexRelease(pIf->pNetwork->FastMutex);
    1237     RTSemFastMutexRelease(pIf->pNetwork->FastMutex);
     1087    if (RT_SUCCESS(rc))
     1088    {
     1089        /** @todo make a SUPR0 api for obtaining the array. SUPR0/IPRT is keeping track of everything, there
     1090         * is no need for any extra bookkeeping here.. */
     1091
     1092        rc = RTSemFastMutexRelease(pIf->pNetwork->FastMutex);
     1093    }
     1094    intnetR0IfRelease(pIf, pSession);
    12381095    return VERR_NOT_IMPLEMENTED;
    12391096}
     
    12581115     */
    12591116    AssertReturn(pIntNet, VERR_INVALID_PARAMETER);
    1260     PINTNETIF pIf = intnetR0Handle2IFPtr(&pIntNet->IfHandles, hIf);
     1117    PINTNETIF pIf = (PINTNETIF)RTHandleTableLookupWithCtx(pIntNet->hHtIfs, hIf, pSession);
    12611118    if (!pIf)
    12621119    {
    1263         LogFlow(("INTNETR0IfSetPromiscuousMode: returns VERR_INVALID_HANDLE\n"));
     1120        Log(("INTNETR0IfSetPromiscuousMode: returns VERR_INVALID_HANDLE\n"));
    12641121        return VERR_INVALID_HANDLE;
    12651122    }
     
    12681125     * Grab the network semaphore and make the change.
    12691126     */
     1127    int rc;
    12701128    PINTNETNETWORK pNetwork = pIf->pNetwork;
    1271     if (!pNetwork)
    1272         return VERR_WRONG_ORDER;
    1273     int rc = RTSemFastMutexRequest(pNetwork->FastMutex);
    1274     if (RT_FAILURE(rc))
    1275         return rc;
    1276 
    1277     if (pIf->fPromiscuous != fPromiscuous)
    1278     {
    1279         Log(("INTNETR0IfSetPromiscuousMode: hIf=%RX32: Changed from %d -> %d\n",
    1280              hIf, !fPromiscuous, !!fPromiscuous));
    1281         ASMAtomicUoWriteBool(&pIf->fPromiscuous, fPromiscuous);
    1282     }
    1283 
    1284     RTSemFastMutexRelease(pNetwork->FastMutex);
    1285     return VINF_SUCCESS;
     1129    if (pNetwork)
     1130    {
     1131        rc = RTSemFastMutexRequest(pNetwork->FastMutex);
     1132        if (RT_SUCCESS(rc))
     1133        {
     1134            if (pIf->fPromiscuous != fPromiscuous)
     1135            {
     1136                Log(("INTNETR0IfSetPromiscuousMode: hIf=%RX32: Changed from %d -> %d\n",
     1137                     hIf, !fPromiscuous, !!fPromiscuous));
     1138                ASMAtomicUoWriteBool(&pIf->fPromiscuous, fPromiscuous);
     1139            }
     1140
     1141            rc = RTSemFastMutexRelease(pNetwork->FastMutex);
     1142        }
     1143    }
     1144    else
     1145        rc = VERR_WRONG_ORDER;
     1146
     1147    intnetR0IfRelease(pIf, pSession);
     1148    return rc;
    12861149}
    12871150
     
    14091272INTNETR0DECL(int) INTNETR0IfWait(PINTNET pIntNet, INTNETIFHANDLE hIf, PSUPDRVSESSION pSession, uint32_t cMillies)
    14101273{
    1411 //    LogFlow(("INTNETR0IfWait: pIntNet=%p hIf=%RX32 cMillies=%u\n", pIntNet, hIf, cMillies));
     1274    Log4(("INTNETR0IfWait: pIntNet=%p hIf=%RX32 cMillies=%u\n", pIntNet, hIf, cMillies));
    14121275
    14131276    /*
    14141277     * Get and validate essential handles.
    14151278     */
    1416     AssertReturn(pIntNet, VERR_INVALID_PARAMETER);
    1417     PINTNETIF pIf = intnetR0Handle2IFPtr(&pIntNet->IfHandles, hIf);
     1279    AssertPtrReturn(pIntNet, VERR_INVALID_PARAMETER);
     1280    PINTNETIF pIf = (PINTNETIF)RTHandleTableLookupWithCtx(pIntNet->hHtIfs, hIf, pSession);
    14181281    if (!pIf)
    14191282    {
    1420         LogFlow(("INTNETR0IfWait: returns VERR_INVALID_HANDLE\n"));
     1283        Log(("INTNETR0IfWait: returns VERR_INVALID_HANDLE\n"));
    14211284        return VERR_INVALID_HANDLE;
    14221285    }
    14231286    const INTNETIFHANDLE    hIfSelf = pIf->hIf;
    14241287    const RTSEMEVENT        Event = pIf->Event;
    1425     if (    hIfSelf != hIf
     1288    if (    hIfSelf != hIf              /* paranoia */
    14261289        &&  Event != NIL_RTSEMEVENT)
    14271290    {
    1428         LogFlow(("INTNETR0IfWait: returns VERR_SEM_DESTROYED\n"));
     1291        Log(("INTNETR0IfWait: returns VERR_SEM_DESTROYED\n"));
    14291292        return VERR_SEM_DESTROYED;
    14301293    }
     
    14391302    /*
    14401303     * Increment the number of waiters before starting the wait.
    1441      * Upon wakeup we must assert reality checking that we're not
    1442      * already destroyed or in the process of being destroyed.
     1304     * Upon wakeup we must assert reality, checking that we're not
     1305     * already destroyed or in the process of being destroyed. This
     1306     * code must be aligned with the waiting code in intnetR0IfDestruct.
    14431307     */
    14441308    ASMAtomicIncU32(&pIf->cSleepers);
     
    14471311    {
    14481312        ASMAtomicDecU32(&pIf->cSleepers);
    1449         if (pIf->hIf != hIf)
     1313        if (!pIf->fDestroying)
     1314        {
     1315            intnetR0IfRelease(pIf, pSession);
     1316            if (pIf->hIf != hIf)
     1317                rc = VERR_SEM_DESTROYED;
     1318        }
     1319        else
    14501320            rc = VERR_SEM_DESTROYED;
    14511321    }
    14521322    else
    14531323        rc = VERR_SEM_DESTROYED;
    1454 //    LogFlow(("INTNETR0IfWait: returns %Rrc\n", rc));
     1324    Log4(("INTNETR0IfWait: returns %Rrc\n", rc));
    14551325    return rc;
    14561326}
     
    14861356
    14871357    /*
    1488      * Validate, get and free the handle.
     1358     * Validate and free the handle.
    14891359     */
    14901360    AssertPtrReturn(pIntNet, VERR_INVALID_PARAMETER);
    1491     PINTNETIF pIf = intnetR0HandleFree(&pIntNet->IfHandles, hIf);
     1361    PINTNETIF pIf = (PINTNETIF)RTHandleTableFreeWithCtx(pIntNet->hHtIfs, hIf, pSession);
    14921362    if (!pIf)
    14931363        return VERR_INVALID_HANDLE;
     1364
     1365    /* mark the handle as freed so intnetR0IfDestruct won't free it again. */
    14941366    ASMAtomicWriteU32(&pIf->hIf, INTNET_HANDLE_INVALID);
    14951367
    1496     /*
    1497      * Release our reference to the interface object.
    1498      */
    1499     int rc = SUPR0ObjRelease(pIf->pvObj, pIf->pSession);
     1368
     1369    /*
     1370     * Release the references to the interface object (handle + free lookup).
     1371     * But signal the event semaphore first so any waiter holding a reference
     1372     * will wake up too (he'll see hIf == invalid and return correctly).
     1373     */
     1374    RTSemEventSignal(pIf->Event);
     1375
     1376    void *pvObj = pIf->pvObj;
     1377    intnetR0IfRelease(pIf, pSession); /* (RTHandleTableFreeWithCtx) */
     1378
     1379    int rc = SUPR0ObjRelease(pvObj, pSession);
    15001380    LogFlow(("INTNETR0IfClose: returns %Rrc\n", rc));
    15011381    return rc;
     
    15361416
    15371417    /*
    1538      * Delete the interface handle so the object no longer can be opened.
     1418     * Mark the interface as being destroyed so the waiter
     1419     * can behave appropriately (theoretical case).
     1420     */
     1421    ASMAtomicWriteBool(&pIf->fDestroying, true);
     1422
     1423    /*
     1424     * Delete the interface handle so the object no longer can be used.
     1425     * (Can happen if the client didn't close its session.)
    15391426     */
    15401427    INTNETIFHANDLE hIf = ASMAtomicXchgU32(&pIf->hIf, INTNET_HANDLE_INVALID);
    15411428    if (hIf != INTNET_HANDLE_INVALID)
    1542         intnetR0HandleFree(&pIntNet->IfHandles, hIf);
     1429    {
     1430        void *pvObj2 = RTHandleTableFreeWithCtx(pIntNet->hHtIfs, hIf, pIf->pSession);
     1431        AssertMsg(pvObj2 == pIf, ("%p, %p, hIf=%#x pSession=%p\n", pvObj2, pIf, hIf, pIf->pSession));
     1432    }
    15431433
    15441434    /*
     
    15891479    {
    15901480        RTSEMEVENT Event = pIf->Event;
    1591         ASMAtomicXchgSize(&pIf->Event, NIL_RTSEMEVENT);
    15921481        unsigned cMaxWait = 0x1000;
    15931482        while (pIf->cSleepers && cMaxWait-- > 0)
     
    16071496            }
    16081497        }
     1498
    16091499        RTSemEventDestroy(Event);
     1500        pIf->Event = NIL_RTSEMEVENT;
    16101501    }
    16111502
     
    16771568    //pIf->fPromiscuous = false;
    16781569    //pIf->fActive = false;
     1570    //pIf->fDestroying = false;
    16791571    //pIf->pIntBuf = 0;
    16801572    //pIf->pIntBufR3 = NIL_RTR3PTR;
     
    16881580    pIf->pSession = pSession;
    16891581    //pIf->pvObj = NULL;
    1690     int rc = RTSemEventCreate(&pIf->Event);
     1582    int rc = RTSemEventCreate((PRTSEMEVENT)&pIf->Event);
    16911583    if (RT_SUCCESS(rc))
    16921584    {
     
    17351627                if (pIf->pvObj)
    17361628                {
    1737                     pIf->hIf = intnetR0HandleAllocate(pNetwork->pIntNet, pIf);
    1738                     if (pIf->hIf != INTNET_HANDLE_INVALID)
     1629                    rc = RTHandleTableAllocWithCtx(pNetwork->pIntNet->hHtIfs, pIf, pSession, (uint32_t *)&pIf->hIf);
     1630                    if (RT_SUCCESS(rc))
    17391631                    {
    17401632                        /* auto activation */ /** @todo do this manually in the future, ditto for setting the MAC address. */
     
    17471639                        return VINF_SUCCESS;
    17481640                    }
    1749                     rc = VERR_NO_MEMORY;
    17501641
    17511642                    SUPR0ObjRelease(pIf->pvObj, pSession);
     
    17541645                }
    17551646
    1756                 rc = VERR_NO_MEMORY;
    17571647                RTSemFastMutexDestroy(pNetwork->FastMutex);
    17581648                pNetwork->FastMutex = NIL_RTSEMFASTMUTEX;
     
    25472437        pIntNet->FastMutex = NIL_RTSEMFASTMUTEX;
    25482438    }
    2549     if (pIntNet->IfHandles.Spinlock != NIL_RTSPINLOCK)
    2550     {
    2551         RTSpinlockDestroy(pIntNet->IfHandles.Spinlock);
    2552         pIntNet->IfHandles.Spinlock = NIL_RTSPINLOCK;
     2439    if (pIntNet->hHtIfs != NIL_RTHANDLETABLE)
     2440    {
     2441        /** @todo does it make sense to have a deleter here? */
     2442        RTHandleTableDestroy(pIntNet->hHtIfs, NULL, NULL);
     2443        pIntNet->hHtIfs = NIL_RTHANDLETABLE;
    25532444    }
    25542445
     
    25712462    {
    25722463        //pIntNet->pNetworks              = NULL;
    2573         //pIntNet->IfHandles.paEntries    = NULL;
    2574         //pIntNet->IfHandles.cAllocated   = 0;
    2575         pIntNet->IfHandles.iHead        = UINT32_MAX;
    2576         pIntNet->IfHandles.iTail        = UINT32_MAX;
    25772464
    25782465        rc = RTSemFastMutexCreate(&pIntNet->FastMutex);
    25792466        if (RT_SUCCESS(rc))
    25802467        {
    2581             rc = RTSpinlockCreate(&pIntNet->IfHandles.Spinlock);
     2468            rc = RTHandleTableCreateEx(&pIntNet->hHtIfs, RTHANDLETABLE_FLAGS_LOCKED | RTHANDLETABLE_FLAGS_CONTEXT,
     2469                                       UINT32_C(0x8ffe0000), 4096, intnetR0IfRetainHandle, NULL);
    25822470            if (RT_SUCCESS(rc))
    25832471            {
     
    25862474                return VINF_SUCCESS;
    25872475            }
     2476
    25882477            RTSemFastMutexDestroy(pIntNet->FastMutex);
    25892478        }
  • trunk/src/VBox/Devices/Network/testcase/tstIntNetR0.cpp

    r10806 r10819  
    3434#undef DECLR0CALLBACKMEMBER
    3535#define DECLR0CALLBACKMEMBER(type, name, args) DECLR3CALLBACKMEMBER(type, name, args)
     36#include <VBox/types.h>
     37typedef void *MYPSUPDRVSESSION;
     38#define PSUPDRVSESSION  MYPSUPDRVSESSION
     39
    3640#include <VBox/intnet.h>
    3741#include <VBox/sup.h>
     
    8993    uint32_t volatile cRefs;
    9094} OBJREF, *POBJREF;
     95
    9196
    9297/*******************************************************************************
     
    450455                {
    451456                    PINTNETBUF pBuf0;
    452                     rc = INTNETR0IfGetRing0Buffer(pIntNet, hIf0, &pBuf0);
     457                    rc = INTNETR0IfGetRing0Buffer(pIntNet, hIf0, g_pSession, &pBuf0);
    453458                    if (VBOX_FAILURE(rc) || !pBuf0)
    454459                    {
     
    457462                    }
    458463                    PINTNETBUF pBuf1;
    459                     rc = INTNETR0IfGetRing0Buffer(pIntNet, hIf1, &pBuf1);
     464                    rc = INTNETR0IfGetRing0Buffer(pIntNet, hIf1, g_pSession, &pBuf1);
    460465                    if (VBOX_FAILURE(rc))
    461466                    {
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette