/** * @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; }
/** * @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; }
/** * 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); }
/** * 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; }
/** * 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; }
/** * 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); }
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); }