/** * @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; }
/** * @copydoc INTNETTRUNKIFPORT::pfnDisconnectAndRelease */ static DECLCALLBACK(void) vboxNetAdpPortDisconnectAndRelease(PINTNETTRUNKIFPORT pIfPort) { PVBOXNETADP pThis = IFPORT_2_VBOXNETADP(pIfPort); /* * Serious paranoia. */ AssertPtr(pThis); Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION); Assert(pThis->MyPort.u32VersionEnd == INTNETTRUNKIFPORT_VERSION); AssertPtr(pThis->pGlobals); Assert(pThis->hEventIdle != NIL_RTSEMEVENT); Assert(pThis->hSpinlock != NIL_RTSPINLOCK); /* * Disconnect and release it. */ RTSpinlockAcquire(pThis->hSpinlock); //Assert(vboxNetAdpGetState(pThis) == kVBoxNetAdpState_Connected); Assert(!pThis->cBusy); vboxNetAdpSetState(pThis, kVBoxNetAdpState_Transitional); RTSpinlockRelease(pThis->hSpinlock); vboxNetAdpOsDisconnectIt(pThis); pThis->pSwitchPort = NULL; RTSpinlockAcquire(pThis->hSpinlock); vboxNetAdpSetState(pThis, kVBoxNetAdpState_Available); RTSpinlockRelease(pThis->hSpinlock); vboxNetAdpRelease(pThis); }
RTDECL(int) RTTimerStart(PRTTIMER pTimer, uint64_t u64First) { if (!rtTimerIsValid(pTimer)) return VERR_INVALID_HANDLE; if (!pTimer->fSuspended) return VERR_TIMER_ACTIVE; /* * Calc when it should start firing and give the thread a kick so it get going. */ u64First += RTTimeNanoTS(); RTSpinlockAcquire(g_Spinlock); g_u32ChangeNo++; if (!g_cActiveTimers) { int rc = rtTimerOs2Arm(); if (RT_FAILURE(rc)) { RTSpinlockRelease(g_Spinlock); return rc; } } g_cActiveTimers++; pTimer->fSuspended = false; pTimer->fDone = true; /* next tick, not current! */ pTimer->iTick = 0; pTimer->u64StartTS = u64First; pTimer->u64NextTS = u64First; RTSpinlockRelease(g_Spinlock); return VINF_SUCCESS; }
/** * Sets the enmState member atomically after first acquiring the spinlock. * * Used for all updates. * * @param pThis The instance. * @param enmNewState The new value. */ DECLINLINE(void) vboxNetAdpSetStateWithLock(PVBOXNETADP pThis, VBOXNETADPSTATE enmNewState) { Log(("vboxNetAdpSetStateWithLock: pThis=%p, state=%d.\n", pThis, enmNewState)); RTSpinlockAcquire(pThis->hSpinlock); vboxNetAdpSetState(pThis, enmNewState); RTSpinlockRelease(pThis->hSpinlock); }
DECLASM(int) VBoxDrvIOCtlFast(uint16_t sfn, uint8_t iFunction) { /* * Find the session. */ const RTPROCESS Process = RTProcSelf(); const unsigned iHash = SESSION_HASH(sfn); PSUPDRVSESSION pSession; RTSpinlockAcquire(g_Spinlock); pSession = g_apSessionHashTab[iHash]; if (pSession && pSession->Process != Process) { do pSession = pSession->pNextHash; while ( pSession && ( pSession->sfn != sfn || pSession->Process != Process)); if (RT_LIKELY(pSession)) supdrvSessionRetain(pSession); } RTSpinlockRelease(g_Spinlock); if (RT_UNLIKELY(!pSession)) { OSDBGPRINT(("VBoxDrvIoctl: WHUT?!? pSession == NULL! This must be a mistake... pid=%d\n", (int)Process)); return VERR_INVALID_PARAMETER; } /* * Dispatch the fast IOCtl. */ supdrvIOCtlFast(iFunction, 0, &g_DevExt, pSession); supdrvSessionRelease(pSession); return 0; }
/** * OS specific free function. */ DECLHIDDEN(void) rtR0MemFree(PRTMEMHDR pHdr) { IPRT_LINUX_SAVE_EFL_AC(); pHdr->u32Magic += 1; if (pHdr->fFlags & RTMEMHDR_FLAG_KMALLOC) kfree(pHdr); #ifdef RTMEMALLOC_EXEC_HEAP else if (pHdr->fFlags & RTMEMHDR_FLAG_EXEC_HEAP) { RTSpinlockAcquire(g_HeapExecSpinlock); RTHeapSimpleFree(g_HeapExec, pHdr); RTSpinlockRelease(g_HeapExecSpinlock); } #endif #ifdef RTMEMALLOC_EXEC_VM_AREA else if (pHdr->fFlags & RTMEMHDR_FLAG_EXEC_VM_AREA) { PRTMEMLNXHDREX pHdrEx = RT_FROM_MEMBER(pHdr, RTMEMLNXHDREX, Hdr); size_t iPage = pHdrEx->pVmArea->nr_pages; struct page **papPages = pHdrEx->pVmArea->pages; void *pvMapping = pHdrEx->pVmArea->addr; vunmap(pvMapping); while (iPage-- > 0) __free_page(papPages[iPage]); kfree(papPages); } #endif else vfree(pHdr); IPRT_LINUX_RESTORE_EFL_AC(); }
void VBoxGuestNativeISRMousePollEvent(PVBOXGUESTDEVEXT pDevExt) { LogFlow((MODULE_NAME "::NativeISRMousePollEvent:\n")); status_t err = B_OK; //dprintf(MODULE_NAME ": isr mouse\n"); /* * Wake up poll waiters. */ //selwakeup(&g_SelInfo); //XXX:notify_select_event(); RTSpinlockAcquire(g_Spinlock); if (sState.selectSync) { //dprintf(MODULE_NAME ": isr mouse: notify\n"); notify_select_event(sState.selectSync, sState.selectEvent); sState.selectEvent = (uint8_t)0; sState.selectRef = (uint32_t)0; sState.selectSync = NULL; } else err = B_ERROR; RTSpinlockRelease(g_Spinlock); }
/** * Device I/O Control entry point. * * @returns Darwin for slow IOCtls and VBox status code for the fast ones. * @param Dev The device number (major+minor). * @param iCmd The IOCtl command. * @param pData Pointer to the data (if any it's a VBOXGUESTIOCTLDATA (kernel copy)). * @param fFlags Flag saying we're a character device (like we didn't know already). * @param pProcess The process issuing this request. */ static int VbgdDarwinIOCtl(dev_t Dev, u_long iCmd, caddr_t pData, int fFlags, struct proc *pProcess) { //const bool fUnrestricted = minor(Dev) == 0; const RTPROCESS Process = proc_pid(pProcess); const unsigned iHash = SESSION_HASH(Process); PVBOXGUESTSESSION pSession; /* * Find the session. */ RTSpinlockAcquire(g_Spinlock); pSession = g_apSessionHashTab[iHash]; while (pSession && pSession->Process != Process && (/*later: pSession->fUnrestricted != fUnrestricted ||*/ !pSession->fOpened)) pSession = pSession->pNextHash; RTSpinlockRelease(g_Spinlock); if (!pSession) { Log(("VBoxDrvDarwinIOCtl: WHAT?!? pSession == NULL! This must be a mistake... pid=%d iCmd=%#lx\n", (int)Process, iCmd)); return EINVAL; } /* * No high speed IOCtls here yet. */ return VbgdDarwinIOCtlSlow(pSession, iCmd, pData, pProcess); }
DECLHIDDEN(void) rtR0PowerNotificationTerm(void) { PRTPOWERNOTIFYREG pHead; RTSPINLOCK hSpinlock = g_hRTPowerNotifySpinLock; AssertReturnVoid(hSpinlock != NIL_RTSPINLOCK); /** @todo OS specific term here */ /* pick up the list and the spinlock. */ RTSpinlockAcquire(hSpinlock); ASMAtomicWriteHandle(&g_hRTPowerNotifySpinLock, NIL_RTSPINLOCK); pHead = g_pRTPowerCallbackHead; g_pRTPowerCallbackHead = NULL; ASMAtomicIncU32(&g_iRTPowerGeneration); RTSpinlockRelease(hSpinlock); /* free the list. */ while (pHead) { PRTPOWERNOTIFYREG pFree = pHead; pHead = pHead->pNext; pFree->pNext = NULL; pFree->pfnCallback = NULL; RTMemFree(pFree); } RTSpinlockDestroy(hSpinlock); }
int vboxNetAdpCreate(PINTNETTRUNKFACTORY pIfFactory, PVBOXNETADP *ppNew) { PVBOXNETADPGLOBALS pGlobals = (PVBOXNETADPGLOBALS)((uint8_t *)pIfFactory - RT_OFFSETOF(VBOXNETADPGLOBALS, TrunkFactory)); unsigned i; int rc; for (i = 0; i < RT_ELEMENTS(pGlobals->aAdapters); i++) { PVBOXNETADP pThis = &pGlobals->aAdapters[i]; if (vboxNetAdpCheckAndSetState(pThis, kVBoxNetAdpState_Invalid, kVBoxNetAdpState_Transitional)) { /* Found an empty slot -- use it. */ uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs); Assert(cRefs == 1); RTMAC Mac; vboxNetAdpComposeMACAddress(pThis, &Mac); rc = vboxNetAdpOsCreate(pThis, &Mac); *ppNew = pThis; RTSpinlockAcquire(pThis->hSpinlock); vboxNetAdpSetState(pThis, kVBoxNetAdpState_Available); RTSpinlockRelease(pThis->hSpinlock); return rc; } } /* All slots in adapter array are busy. */ return VERR_OUT_OF_RESOURCES; }
DECLHIDDEN(void) rtR0MpNotificationTerm(void) { PRTMPNOTIFYREG pHead; RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER; RTSPINLOCK hSpinlock = g_hRTMpNotifySpinLock; AssertReturnVoid(hSpinlock != NIL_RTSPINLOCK); rtR0MpNotificationNativeTerm(); /* pick up the list and the spinlock. */ RTSpinlockAcquire(hSpinlock, &Tmp); ASMAtomicWriteHandle(&g_hRTMpNotifySpinLock, NIL_RTSPINLOCK); pHead = g_pRTMpCallbackHead; g_pRTMpCallbackHead = NULL; ASMAtomicIncU32(&g_iRTMpGeneration); RTSpinlockRelease(hSpinlock, &Tmp); /* free the list. */ while (pHead) { PRTMPNOTIFYREG pFree = pHead; pHead = pHead->pNext; pFree->pNext = NULL; pFree->pfnCallback = NULL; RTMemFree(pFree); } RTSpinlockDestroy(hSpinlock); }
/** * Driver select hook. * * @param cookie The session. * @param event The event. * @param ref ??? * @param sync ??? * * @return Haiku status code. */ static status_t vgdrvHaikuSelect(void *cookie, uint8 event, uint32 ref, selectsync *sync) { PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)cookie; status_t err = B_OK; switch (event) { case B_SELECT_READ: break; default: return EINVAL; } RTSpinlockAcquire(g_DevExt.SessionSpinlock); uint32_t u32CurSeq = ASMAtomicUoReadU32(&g_DevExt.u32MousePosChangedSeq); if (pSession->u32MousePosChangedSeq != u32CurSeq) { pSession->u32MousePosChangedSeq = u32CurSeq; notify_select_event(sync, event); } else if (sState.selectSync == NULL) { sState.selectEvent = (uint8_t)event; sState.selectRef = (uint32_t)ref; sState.selectSync = (void *)sync; } else err = B_WOULD_BLOCK; RTSpinlockRelease(g_DevExt.SessionSpinlock); return err; }
DECLASM(int) VBoxDrvOpen(uint16_t sfn) { int rc; PSUPDRVSESSION pSession; /* * Create a new session. */ rc = supdrvCreateSession(&g_DevExt, true /* fUser */, true /*fUnrestricted*/, &pSession); if (RT_SUCCESS(rc)) { pSession->sfn = sfn; /* * Insert it into the hash table. */ unsigned iHash = SESSION_HASH(sfn); RTSpinlockAcquire(g_Spinlock); pSession->pNextHash = g_apSessionHashTab[iHash]; g_apSessionHashTab[iHash] = pSession; RTSpinlockRelease(g_Spinlock); } Log(("VBoxDrvOpen: g_DevExt=%p pSession=%p rc=%d pid=%d\n", &g_DevExt, pSession, rc, (int)RTProcSelf())); return rc; }
/** * @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; }
RTDECL(int) RTTimerDestroy(PRTTIMER pTimer) { /* It's ok to pass NULL pointer. */ if (pTimer == /*NIL_RTTIMER*/ NULL) return VINF_SUCCESS; if (!rtTimerIsValid(pTimer)) return VERR_INVALID_HANDLE; /* * Remove it from the list. */ RTSpinlockAcquire(g_Spinlock); g_u32ChangeNo++; if (g_pTimerHead == pTimer) g_pTimerHead = pTimer->pNext; else { PRTTIMER pPrev = g_pTimerHead; while (pPrev->pNext != pTimer) { pPrev = pPrev->pNext; if (RT_UNLIKELY(!pPrev)) { RTSpinlockRelease(g_Spinlock); return VERR_INVALID_HANDLE; } } pPrev->pNext = pTimer->pNext; } Assert(g_cTimers > 0); g_cTimers--; if (!pTimer->fSuspended) { Assert(g_cActiveTimers > 0); g_cActiveTimers--; if (!g_cActiveTimers) rtTimerOs2Dearm(); } RTSpinlockRelease(g_Spinlock); /* * Free the associated resources. */ pTimer->u32Magic++; RTMemFree(pTimer); return VINF_SUCCESS; }
DECLINLINE(void) vboxPciDevUnlock(PVBOXRAWPCIINS pThis) { #ifdef VBOX_WITH_SHARED_PCI_INTERRUPTS RTSpinlockRelease(pThis->hSpinlock); #else RTSemFastMutexRelease(pThis->hFastMtx); #endif }
int vboxNetFltOsInitInstance(PVBOXNETFLTINS pThis, void *pvContext) { char nam[NG_NODESIZ]; struct ifnet *ifp; node_p node; VBOXCURVNET_SET_FROM_UCRED(); NOREF(pvContext); ifp = ifunit(pThis->szName); if (ifp == NULL) return VERR_INTNET_FLT_IF_NOT_FOUND; /* Create a new netgraph node for this instance */ if (ng_make_node_common(&ng_vboxnetflt_typestruct, &node) != 0) return VERR_INTERNAL_ERROR; RTSpinlockAcquire(pThis->hSpinlock); ASMAtomicUoWritePtr(&pThis->u.s.ifp, ifp); pThis->u.s.node = node; bcopy(IF_LLADDR(ifp), &pThis->u.s.MacAddr, ETHER_ADDR_LEN); ASMAtomicUoWriteBool(&pThis->fDisconnectedFromHost, false); /* Initialize deferred input queue */ bzero(&pThis->u.s.inq, sizeof(struct ifqueue)); mtx_init(&pThis->u.s.inq.ifq_mtx, "vboxnetflt inq", NULL, MTX_SPIN); TASK_INIT(&pThis->u.s.tskin, 0, vboxNetFltFreeBSDinput, pThis); /* Initialize deferred output queue */ bzero(&pThis->u.s.outq, sizeof(struct ifqueue)); mtx_init(&pThis->u.s.outq.ifq_mtx, "vboxnetflt outq", NULL, MTX_SPIN); TASK_INIT(&pThis->u.s.tskout, 0, vboxNetFltFreeBSDoutput, pThis); RTSpinlockRelease(pThis->hSpinlock); NG_NODE_SET_PRIVATE(node, pThis); /* Attempt to name it vboxnetflt_<ifname> */ snprintf(nam, NG_NODESIZ, "vboxnetflt_%s", pThis->szName); ng_name_node(node, nam); /* Report MAC address, promiscuous mode and GSO capabilities. */ /** @todo keep these reports up to date, either by polling for changes or * intercept some control flow if possible. */ if (vboxNetFltTryRetainBusyNotDisconnected(pThis)) { Assert(pThis->pSwitchPort); pThis->pSwitchPort->pfnReportMacAddress(pThis->pSwitchPort, &pThis->u.s.MacAddr); pThis->pSwitchPort->pfnReportPromiscuousMode(pThis->pSwitchPort, vboxNetFltFreeBsdIsPromiscuous(pThis)); pThis->pSwitchPort->pfnReportGsoCapabilities(pThis->pSwitchPort, 0, INTNETTRUNKDIR_WIRE | INTNETTRUNKDIR_HOST); pThis->pSwitchPort->pfnReportNoPreemptDsts(pThis->pSwitchPort, 0 /* none */); vboxNetFltRelease(pThis, true /*fBusy*/); } VBOXCURVNET_RESTORE(); return VINF_SUCCESS; }
/** * 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; }
/** * 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; }
/** * Driver ioctl, an alternate entry point for this character driver. * * @param Dev Device number * @param Cmd Operation identifier * @param pArg Arguments from user to driver * @param Mode Information bitfield (read/write, address space etc.) * @param pCred User credentials * @param pVal Return value for calling process. * * @return corresponding solaris error code. */ static int VBoxDrvSolarisIOCtl(dev_t Dev, int Cmd, intptr_t pArgs, int Mode, cred_t *pCred, int *pVal) { #ifndef USE_SESSION_HASH /* * Get the session from the soft state item. */ vbox_devstate_t *pState = ddi_get_soft_state(g_pVBoxDrvSolarisState, getminor(Dev)); if (!pState) { LogRel(("VBoxDrvSolarisIOCtl: no state data for %#x (%d)\n", Dev, getminor(Dev))); return EINVAL; } PSUPDRVSESSION pSession = pState->pSession; if (!pSession) { LogRel(("VBoxDrvSolarisIOCtl: no session in state data for %#x (%d)\n", Dev, getminor(Dev))); return DDI_SUCCESS; } #else const RTPROCESS Process = RTProcSelf(); const unsigned iHash = SESSION_HASH(Process); PSUPDRVSESSION pSession; const bool fUnrestricted = getminor(Dev) == 0; /* * Find the session. */ RTSpinlockAcquire(g_Spinlock); pSession = g_apSessionHashTab[iHash]; while (pSession && pSession->Process != Process && pSession->fUnrestricted == fUnrestricted); pSession = pSession->pNextHash; RTSpinlockRelease(g_Spinlock); if (!pSession) { LogRel(("VBoxSupDrvIOCtl: WHAT?!? pSession == NULL! This must be a mistake... pid=%d iCmd=%#x Dev=%#x\n", (int)Process, Cmd, (int)Dev)); return EINVAL; } #endif /* * Deal with the two high-speed IOCtl that takes it's arguments from * the session and iCmd, and only returns a VBox status code. */ if ( ( Cmd == SUP_IOCTL_FAST_DO_RAW_RUN || Cmd == SUP_IOCTL_FAST_DO_HM_RUN || Cmd == SUP_IOCTL_FAST_DO_NOP) && pSession->fUnrestricted) { *pVal = supdrvIOCtlFast(Cmd, pArgs, &g_DevExt, pSession); return 0; } return VBoxDrvSolarisIOCtlSlow(pSession, Cmd, Mode, pArgs); }
RTDECL(void) RTSpinlockReleaseNoInts(RTSPINLOCK Spinlock) { #if 1 if (RT_UNLIKELY(!(Spinlock->fFlags & RTSPINLOCK_FLAGS_INTERRUPT_SAFE))) RTAssertMsg2("RTSpinlockReleaseNoInts: %p (magic=%#x)\n", Spinlock, Spinlock->u32Magic); #else AssertRelease(Spinlock->fFlags & RTSPINLOCK_FLAGS_INTERRUPT_SAFE); #endif RTSpinlockRelease(Spinlock); }
DECLASM(int) VBoxDrvClose(uint16_t sfn) { Log(("VBoxDrvClose: pid=%d sfn=%d\n", (int)RTProcSelf(), sfn)); /* * Remove from the hash table. */ PSUPDRVSESSION pSession; const RTPROCESS Process = RTProcSelf(); const unsigned iHash = SESSION_HASH(sfn); RTSpinlockAcquire(g_Spinlock); pSession = g_apSessionHashTab[iHash]; if (pSession) { if ( pSession->sfn == sfn && pSession->Process == Process) { g_apSessionHashTab[iHash] = pSession->pNextHash; pSession->pNextHash = NULL; } else { PSUPDRVSESSION pPrev = pSession; pSession = pSession->pNextHash; while (pSession) { if ( pSession->sfn == sfn && pSession->Process == Process) { pPrev->pNextHash = pSession->pNextHash; pSession->pNextHash = NULL; break; } /* next */ pPrev = pSession; pSession = pSession->pNextHash; } } } RTSpinlockRelease(g_Spinlock); if (!pSession) { OSDBGPRINT(("VBoxDrvIoctl: WHUT?!? pSession == NULL! This must be a mistake... pid=%d sfn=%d\n", (int)Process, sfn)); return VERR_INVALID_PARAMETER; } /* * Close the session. */ supdrvSessionRelease(pSession); return 0; }
/** * Device open. Called on open /dev/vboxguest and (later) /dev/vboxguestu. * * @param Dev The device number. * @param fFlags ???. * @param fDevType ???. * @param pProcess The process issuing this request. */ static int VbgdDarwinOpen(dev_t Dev, int fFlags, int fDevType, struct proc *pProcess) { /* * Only two minor devices numbers are allowed. */ if (minor(Dev) != 0 && minor(Dev) != 1) return EACCES; /* * Find the session created by org_virtualbox_VBoxGuestClient, fail * if no such session, and mark it as opened. We set the uid & gid * here too, since that is more straight forward at this point. */ //const bool fUnrestricted = minor(Dev) == 0; int rc = VINF_SUCCESS; PVBOXGUESTSESSION pSession = NULL; kauth_cred_t pCred = kauth_cred_proc_ref(pProcess); if (pCred) { RTPROCESS Process = RTProcSelf(); unsigned iHash = SESSION_HASH(Process); RTSpinlockAcquire(g_Spinlock); pSession = g_apSessionHashTab[iHash]; while (pSession && pSession->Process != Process) pSession = pSession->pNextHash; if (pSession) { if (!pSession->fOpened) { pSession->fOpened = true; /*pSession->fUnrestricted = fUnrestricted; - later */ } else rc = VERR_ALREADY_LOADED; } else rc = VERR_GENERAL_FAILURE; RTSpinlockRelease(g_Spinlock); #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 kauth_cred_unref(&pCred); #else /* 10.4 */ /* The 10.4u SDK headers and 10.4.11 kernel source have inconsistent definitions of kauth_cred_unref(), so use the other (now deprecated) API for releasing it. */ kauth_cred_rele(pCred); #endif /* 10.4 */ } else rc = VERR_INVALID_PARAMETER; Log(("VbgdDarwinOpen: g_DevExt=%p pSession=%p rc=%d pid=%d\n", &g_DevExt, pSession, rc, proc_pid(pProcess))); return VbgdDarwinErr2DarwinErr(rc); }
RTDECL(int) RTTimerCreateEx(PRTTIMER *ppTimer, uint64_t u64NanoInterval, uint32_t fFlags, PFNRTTIMER pfnTimer, void *pvUser) { *ppTimer = NULL; /* * We don't support the fancy MP features. */ if (fFlags & RTTIMER_FLAGS_CPU_SPECIFIC) return VERR_NOT_SUPPORTED; /* * Lazy initialize the spinlock. */ if (g_Spinlock == NIL_RTSPINLOCK) { RTSPINLOCK Spinlock; int rc = RTSpinlockCreate(&Spinlock, RTSPINLOCK_FLAGS_INTERRUPT_SAFE, "RTTimerOS2"); AssertRCReturn(rc, rc); //bool fRc; //ASMAtomicCmpXchgSize(&g_Spinlock, Spinlock, NIL_RTSPINLOCK, fRc); //if (!fRc) if (!ASMAtomicCmpXchgPtr((void * volatile *)&g_Spinlock, Spinlock, NIL_RTSPINLOCK)) RTSpinlockDestroy(Spinlock); } /* * Allocate and initialize the timer handle. */ PRTTIMER pTimer = (PRTTIMER)RTMemAlloc(sizeof(*pTimer)); if (!pTimer) return VERR_NO_MEMORY; pTimer->u32Magic = RTTIMER_MAGIC; pTimer->pNext = NULL; pTimer->fSuspended = true; pTimer->pfnTimer = pfnTimer; pTimer->pvUser = pvUser; pTimer->u64NanoInterval = u64NanoInterval; pTimer->u64StartTS = 0; /* * Insert the timer into the list (LIFO atm). */ RTSpinlockAcquire(g_Spinlock); g_u32ChangeNo++; pTimer->pNext = g_pTimerHead; g_pTimerHead = pTimer; g_cTimers++; RTSpinlockRelease(g_Spinlock); *ppTimer = pTimer; return VINF_SUCCESS; }
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; }
RTDECL(int) RTPowerNotificationDeregister(PFNRTPOWERNOTIFICATION pfnCallback, void *pvUser) { PRTPOWERNOTIFYREG pPrev; PRTPOWERNOTIFYREG pCur; RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER; /* * Validation. */ AssertPtrReturn(pfnCallback, VERR_INVALID_POINTER); AssertReturn(g_hRTPowerNotifySpinLock != NIL_RTSPINLOCK, VERR_WRONG_ORDER); RT_ASSERT_INTS_ON(); /* * Find and unlink the record from the list. */ RTSpinlockAcquire(g_hRTPowerNotifySpinLock, &Tmp); pPrev = NULL; for (pCur = g_pRTPowerCallbackHead; pCur; pCur = pCur->pNext) { if ( pCur->pvUser == pvUser && pCur->pfnCallback == pfnCallback) break; pPrev = pCur; } if (pCur) { if (pPrev) pPrev->pNext = pCur->pNext; else g_pRTPowerCallbackHead = pCur->pNext; ASMAtomicIncU32(&g_iRTPowerGeneration); } RTSpinlockRelease(g_hRTPowerNotifySpinLock, &Tmp); if (!pCur) return VERR_NOT_FOUND; /* * Invalidate and free the record. */ pCur->pNext = NULL; pCur->pfnCallback = NULL; RTMemFree(pCur); return VINF_SUCCESS; }
/** * 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; }
RTDECL(int) RTTimerStop(PRTTIMER pTimer) { if (!rtTimerIsValid(pTimer)) return VERR_INVALID_HANDLE; if (pTimer->fSuspended) return VERR_TIMER_SUSPENDED; /* * Suspend the timer. */ RTSpinlockAcquire(g_Spinlock); g_u32ChangeNo++; pTimer->fSuspended = true; Assert(g_cActiveTimers > 0); g_cActiveTimers--; if (!g_cActiveTimers) rtTimerOs2Dearm(); RTSpinlockRelease(g_Spinlock); return VINF_SUCCESS; }
/** * Driver deselect hook. * @param cookie The session. * @param event The event. * @param sync ??? * * @return Haiku status code. */ static status_t vgdrvHaikuDeselect(void *cookie, uint8 event, selectsync *sync) { PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)cookie; status_t err = B_OK; //dprintf(DRIVER_NAME "deselect(,%d,%p)\n", event, sync); RTSpinlockAcquire(g_DevExt.SessionSpinlock); if (sState.selectSync == sync) { //dprintf(DRIVER_NAME "deselect: dropping: %p %x\n", sState.selectSync, sState.selectEvent); sState.selectEvent = (uint8_t)0; sState.selectRef = (uint32_t)0; sState.selectSync = NULL; } else err = B_OK; RTSpinlockRelease(g_DevExt.SessionSpinlock); return err; }