Example #1
0
/**
 * @copydoc INTNETTRUNKIFPORT::pfnSetActive
 */
static DECLCALLBACK(bool) vboxNetAdpPortSetActive(PINTNETTRUNKIFPORT pIfPort, bool fActive)
{
    bool fPreviouslyActive;
    PVBOXNETADP pThis = IFPORT_2_VBOXNETADP(pIfPort);

    /*
     * Input validation.
     */
    AssertPtr(pThis);
    AssertPtr(pThis->pGlobals);
    Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);

    Log(("vboxNetAdpPortSetActive: pThis=%p, fActive=%d, state before: %d.\n", pThis, fActive, vboxNetAdpGetState(pThis)));
    RTSpinlockAcquire(pThis->hSpinlock);

    fPreviouslyActive = vboxNetAdpGetState(pThis) == kVBoxNetAdpState_Active;
    if (fPreviouslyActive != fActive)
    {
        switch (vboxNetAdpGetState(pThis))
        {
            case kVBoxNetAdpState_Connected:
                vboxNetAdpSetState(pThis, kVBoxNetAdpState_Active);
                break;
            case kVBoxNetAdpState_Active:
                vboxNetAdpSetState(pThis, kVBoxNetAdpState_Connected);
                break;
            default:
                break;
        }
    }

    RTSpinlockRelease(pThis->hSpinlock);
    Log(("vboxNetAdpPortSetActive: state after: %RTbool.\n", vboxNetAdpGetState(pThis)));
    return fPreviouslyActive;
}
Example #2
0
/**
 * @copydoc INTNETTRUNKIFPORT::pfnXmit
 */
static DECLCALLBACK(int) vboxNetAdpPortXmit(PINTNETTRUNKIFPORT pIfPort, PINTNETSG pSG, uint32_t fDst)
{
    PVBOXNETADP pThis = IFPORT_2_VBOXNETADP(pIfPort);
    int rc = VINF_SUCCESS;

    /*
     * Input validation.
     */
    AssertPtr(pThis);
    AssertPtr(pSG);
    Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);

    Log(("vboxNetAdpPortXmit: outgoing packet (len=%d)\n", pSG->cbTotal));

    /*
     * Do a retain/busy, invoke the OS specific code.
     */
    RTSpinlockAcquire(pThis->hSpinlock);
    if (vboxNetAdpGetState(pThis) != kVBoxNetAdpState_Active)
    {
        RTSpinlockRelease(pThis->hSpinlock);
        Log(("vboxNetAdpReceive: Dropping incoming packet for inactive interface %s.\n",
             pThis->szName));
        return VERR_INVALID_STATE;
    }
    vboxNetAdpRetain(pThis);
    vboxNetAdpBusy(pThis);
    RTSpinlockRelease(pThis->hSpinlock);

    rc = vboxNetAdpPortOsXmit(pThis, pSG, fDst);
    vboxNetAdpIdle(pThis);
    vboxNetAdpRelease(pThis);

    return rc;
}
Example #3
0
/**
 * Gets the enmState member with locking.
 *
 * Used for all reads.
 *
 * @returns The enmState value.
 * @param   pThis           The instance.
 */
DECLINLINE(VBOXNETADPSTATE) vboxNetAdpGetStateWithLock(PVBOXNETADP pThis)
{
    VBOXNETADPSTATE enmState;
    RTSpinlockAcquire(pThis->hSpinlock);
    enmState = vboxNetAdpGetState(pThis);
    RTSpinlockRelease(pThis->hSpinlock);
    Log(("vboxNetAdpGetStateWithLock: pThis=%p, state=%d.\n", pThis, enmState));
    return enmState;
}
/**
 * Gets the enmState member with locking.
 *
 * Used for all reads.
 *
 * @returns The enmState value.
 * @param   pThis           The instance.
 */
DECLINLINE(VBOXNETADPSTATE) vboxNetAdpGetStateWithLock(PVBOXNETADP pThis)
{
    VBOXNETADPSTATE enmState;
    RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
    RTSpinlockAcquireNoInts(pThis->hSpinlock, &Tmp);
    enmState = vboxNetAdpGetState(pThis);
    RTSpinlockReleaseNoInts(pThis->hSpinlock, &Tmp);
    Log(("vboxNetAdpGetStateWithLock: pThis=%p, state=%d.\n", pThis, enmState));
    return enmState;
}
static void vboxNetAdpSlotDestroy(PVBOXNETADP pThis)
{
    Assert(pThis->cRefs == 0);
    Assert(pThis->cBusy == 0);
    Assert(vboxNetAdpGetState(pThis) == kVBoxNetAdpState_Invalid);
    if (pThis->hEventIdle != NIL_RTSEMEVENT)
    {
        RTSemEventDestroy(pThis->hEventIdle);
        pThis->hEventIdle = NIL_RTSEMEVENT;
    }
    if (pThis->hSpinlock != NIL_RTSPINLOCK)
    {
        RTSpinlockDestroy(pThis->hSpinlock);
        pThis->hSpinlock = NIL_RTSPINLOCK;
    }
}
/**
 * Increments busy counter.
 *
 * @param   pThis           The instance.
 */
DECLHIDDEN(void) vboxNetAdpBusy(PVBOXNETADP pThis)
{
    uint32_t cBusy;

    /*
     * Are we vigilant enough?
     */
    AssertPtr(pThis);
    Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
    Assert(pThis->MyPort.u32VersionEnd == INTNETTRUNKIFPORT_VERSION);
    Assert(vboxNetAdpGetState(pThis) >= kVBoxNetAdpState_Connected);
    AssertPtr(pThis->pGlobals);
    Assert(pThis->hEventIdle != NIL_RTSEMEVENT);
    cBusy = ASMAtomicIncU32(&pThis->cBusy);
    Assert(cBusy > 0 && cBusy < UINT32_MAX / 2);

    NOREF(cBusy);
}
Example #7
0
/**
 * Finds a instance by its name, the caller does the locking.
 *
 * @returns Pointer to the instance by the given name. NULL if not found.
 * @param   pGlobals        The globals.
 * @param   pszName         The name of the instance.
 */
static PVBOXNETADP vboxNetAdpFind(PVBOXNETADPGLOBALS pGlobals, const char *pszName)
{
    unsigned i;

    for (i = 0; i < RT_ELEMENTS(pGlobals->aAdapters); i++)
    {
        PVBOXNETADP pThis = &pGlobals->aAdapters[i];
        RTSpinlockAcquire(pThis->hSpinlock);
        if (    vboxNetAdpGetState(pThis)
            &&  !strcmp(pThis->szName, pszName))
        {
            RTSpinlockRelease(pThis->hSpinlock);
            return pThis;
        }
        RTSpinlockRelease(pThis->hSpinlock);
    }
    return NULL;
}
Example #8
0
/**
 * Checks and sets the enmState member atomically.
 *
 * Used for all updates.
 *
 * @returns true if the state has been changed.
 * @param   pThis           The instance.
 * @param   enmNewState     The new value.
 */
DECLINLINE(bool) vboxNetAdpCheckAndSetState(PVBOXNETADP pThis, VBOXNETADPSTATE enmOldState, VBOXNETADPSTATE enmNewState)
{
    VBOXNETADPSTATE enmActualState;
    bool fRc = true; /* be optimistic */

    RTSpinlockAcquire(pThis->hSpinlock);
    enmActualState = vboxNetAdpGetState(pThis); /** @todo r=bird: ASMAtomicCmpXchgU32()*/
    if (enmActualState == enmOldState)
        vboxNetAdpSetState(pThis, enmNewState);
    else
        fRc = false;
    RTSpinlockRelease(pThis->hSpinlock);

    if (fRc)
        Log(("vboxNetAdpCheckAndSetState: pThis=%p, state changed: %d -> %d.\n", pThis, enmOldState, enmNewState));
    else
        Log(("vboxNetAdpCheckAndSetState: pThis=%p, no state change: %d != %d (expected).\n", pThis, enmActualState, enmOldState));
    return fRc;
}
Example #9
0
/**
 * Checks if receive is possible and increases busy and ref counters if so.
 *
 * @param   pThis           The instance.
 */
DECLHIDDEN(bool) vboxNetAdpPrepareToReceive(PVBOXNETADP pThis)
{
    bool fCanReceive  = false;
    /*
     * Input validation.
     */
    AssertPtr(pThis);
    Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
    RTSpinlockAcquire(pThis->hSpinlock);
    if (vboxNetAdpGetState(pThis) == kVBoxNetAdpState_Active)
    {
        fCanReceive = true;
        vboxNetAdpRetain(pThis);
        vboxNetAdpBusy(pThis);
    }
    RTSpinlockRelease(pThis->hSpinlock);
    Log(("vboxNetAdpPrepareToReceive: fCanReceive=%d.\n", fCanReceive));

    return fCanReceive;
}
/**
 * Releases a reference to the specified instance.
 *
 * @param   pThis           The instance.
 * @param   fBusy           Whether the busy counter should be decremented too.
 */
DECLHIDDEN(void) vboxNetAdpRelease(PVBOXNETADP pThis)
{
    uint32_t cRefs;

    /*
     * Paranoid Android.
     */
    AssertPtr(pThis);
    Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
    Assert(pThis->MyPort.u32VersionEnd == INTNETTRUNKIFPORT_VERSION);
    Assert(vboxNetAdpGetState(pThis) > kVBoxNetAdpState_Invalid);
    AssertPtr(pThis->pGlobals);
    Assert(pThis->hEventIdle != NIL_RTSEMEVENT);
    Assert(pThis->hSpinlock != NIL_RTSPINLOCK);
    Assert(pThis->szName[0]);

    /*
     * The object reference counting.
     */
    cRefs = ASMAtomicDecU32(&pThis->cRefs);
    Assert(cRefs < UINT32_MAX / 2);
}
Example #11
0
int vboxNetAdpDestroy(PVBOXNETADP pThis)
{
    int rc = VINF_SUCCESS;

    RTSpinlockAcquire(pThis->hSpinlock);
    if (vboxNetAdpGetState(pThis) != kVBoxNetAdpState_Available || pThis->cBusy)
    {
        RTSpinlockRelease(pThis->hSpinlock);
        return VERR_INTNET_FLT_IF_BUSY;
    }
    vboxNetAdpSetState(pThis, kVBoxNetAdpState_Transitional);
    RTSpinlockRelease(pThis->hSpinlock);
    vboxNetAdpRelease(pThis);

    vboxNetAdpOsDestroy(pThis);

    RTSpinlockAcquire(pThis->hSpinlock);
    vboxNetAdpSetState(pThis, kVBoxNetAdpState_Invalid);
    RTSpinlockRelease(pThis->hSpinlock);

    return rc;
}
/**
 * Decrements the busy counter and does idle wakeup.
 *
 * @param   pThis           The instance.
 */
DECLHIDDEN(void) vboxNetAdpIdle(PVBOXNETADP pThis)
{
    uint32_t cBusy;

    /*
     * Paranoid Android.
     */
    AssertPtr(pThis);
    Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
    Assert(pThis->MyPort.u32VersionEnd == INTNETTRUNKIFPORT_VERSION);
    Assert(vboxNetAdpGetState(pThis) >= kVBoxNetAdpState_Connected);
    AssertPtr(pThis->pGlobals);
    Assert(pThis->hEventIdle != NIL_RTSEMEVENT);

    cBusy = ASMAtomicDecU32(&pThis->cBusy);
    if (!cBusy)
    {
        int rc = RTSemEventSignal(pThis->hEventIdle);
        AssertRC(rc);
    }
    else
        Assert(cBusy < UINT32_MAX / 2);
}
/**
 * Sets the enmState member atomically.
 *
 * Used for all updates.
 *
 * @param   pThis           The instance.
 * @param   enmNewState     The new value.
 */
DECLINLINE(void) vboxNetAdpSetState(PVBOXNETADP pThis, VBOXNETADPSTATE enmNewState)
{
    Log(("vboxNetAdpSetState: pThis=%p, state change: %d -> %d.\n", pThis, vboxNetAdpGetState(pThis), enmNewState));
    ASMAtomicWriteU32((uint32_t volatile *)&pThis->enmState, enmNewState);
}