int GuestWaitEventBase::Wait(RTMSINTERVAL uTimeoutMS) { int rc = VINF_SUCCESS; if (ASMAtomicReadBool(&mfAborted)) rc = VERR_CANCELLED; if (RT_SUCCESS(rc)) { AssertReturn(mEventSem != NIL_RTSEMEVENT, VERR_CANCELLED); RTMSINTERVAL msInterval = uTimeoutMS; if (!uTimeoutMS) msInterval = RT_INDEFINITE_WAIT; rc = RTSemEventWait(mEventSem, msInterval); if (ASMAtomicReadBool(&mfAborted)) rc = VERR_CANCELLED; if (RT_SUCCESS(rc)) { /* If waiting succeeded, return the overall * result code. */ rc = mRc; } } return rc; }
RTDECL(bool) RTReqQueueIsBusy(RTREQQUEUE hQueue) { PRTREQQUEUEINT pQueue = hQueue; AssertPtrReturn(pQueue, false); if (ASMAtomicReadBool(&pQueue->fBusy)) return true; if (ASMAtomicReadPtrT(&pQueue->pReqs, PRTREQ) != NULL) return true; if (ASMAtomicReadBool(&pQueue->fBusy)) return true; return false; }
int GuestWaitEventBase::SignalInternal(int rc, int guestRc, const GuestWaitEventPayload *pPayload) { if (ASMAtomicReadBool(&mfAborted)) return VERR_CANCELLED; #ifdef VBOX_STRICT if (rc == VERR_GSTCTL_GUEST_ERROR) AssertMsg(RT_FAILURE(guestRc), ("Guest error indicated but no actual guest error set (%Rrc)\n", guestRc)); else AssertMsg(RT_SUCCESS(guestRc), ("No guest error indicated but actual guest error set (%Rrc)\n", guestRc)); #endif int rc2; if (pPayload) rc2 = mPayload.CopyFromDeep(*pPayload); else rc2 = VINF_SUCCESS; if (RT_SUCCESS(rc2)) { mRc = rc; mGuestRc = guestRc; rc2 = RTSemEventSignal(mEventSem); } return rc2; }
/** * Internal worker for waking up the waiting thread. */ static void rtFileAioCtxWakeup(PRTFILEAIOCTXINTERNAL pCtxInt) { /* * Read the thread handle before the status flag. * If we read the handle after the flag we might * end up with an invalid handle because the thread * waiting in RTFileAioCtxWakeup() might get scheduled * before we read the flag and returns. * We can ensure that the handle is valid if fWaiting is true * when reading the handle before the status flag. */ RTTHREAD hThread; ASMAtomicReadHandle(&pCtxInt->hThreadWait, &hThread); bool fWaiting = ASMAtomicReadBool(&pCtxInt->fWaiting); if (fWaiting) { /* * If a thread waits the handle must be valid. * It is possible that the thread returns from * aio_suspend() before the signal is send. * This is no problem because we already set fWokenUp * to true which will let the thread return VERR_INTERRUPTED * and the next call to RTFileAioCtxWait() will not * return VERR_INTERRUPTED because signals are not saved * and will simply vanish if the destination thread can't * receive it. */ Assert(hThread != NIL_RTTHREAD); RTThreadPoke(hThread); } }
RTDECL(bool) RTCircBufIsWriting(PRTCIRCBUF pBuf) { /* Validate input. */ AssertPtrReturn(pBuf, 0); return ASMAtomicReadBool(&pBuf->fWriting); }
/** * Stop this service. */ void org_virtualbox_VBoxVFS::stop(IOService *pProvider) { int rc; AssertReturnVoid(ASMAtomicReadBool(&g_fInstantiated)); rc = VBoxVFSUnRegisterFilesystem(); if (RT_FAILURE(rc)) { PERROR("VBoxVFS filesystem is busy. Make sure all " "shares are unmounted (%d)", rc); } vboxDisconnect(&g_vboxSFClient); PINFO("VBox client disconnected"); vboxUninit(); PINFO("Low level uninit done"); coreService->release(); PINFO("VBoxGuest service released"); IOService::stop(pProvider); ASMAtomicWriteBool(&g_fInstantiated, false); PINFO("Successfully stopped I/O kit class instance"); }
int GuestCtrlEvent::Cancel(void) { int rc = VINF_SUCCESS; if (!ASMAtomicReadBool(&fCompleted)) { if (!ASMAtomicReadBool(&fCanceled)) { ASMAtomicXchgBool(&fCanceled, true); LogFlowThisFunc(("Cancelling event ...\n")); rc = hEventSem != NIL_RTSEMEVENT ? RTSemEventSignal(hEventSem) : VINF_SUCCESS; } } return rc; }
/** * Reads a register value. * * @returns VBox status code. * @param pVBoxSCSI Pointer to the SCSI state. * @param iRegister Index of the register to read. * @param pu32Value Where to store the content of the register. */ int vboxscsiReadRegister(PVBOXSCSI pVBoxSCSI, uint8_t iRegister, uint32_t *pu32Value) { uint8_t uVal = 0; switch (iRegister) { case 0: { if (ASMAtomicReadBool(&pVBoxSCSI->fBusy) == true) { uVal |= VBOX_SCSI_BUSY; /* There is an I/O operation in progress. * Yield the execution thread to let the I/O thread make progress. */ RTThreadYield(); } else uVal &= ~VBOX_SCSI_BUSY; break; } case 1: { if (pVBoxSCSI->cbBuf > 0) { AssertMsg(pVBoxSCSI->pBuf, ("pBuf is NULL\n")); uVal = pVBoxSCSI->pBuf[pVBoxSCSI->iBuf]; pVBoxSCSI->iBuf++; pVBoxSCSI->cbBuf--; if (pVBoxSCSI->cbBuf == 0) { /** The guest read the last byte from the data in buffer. * Clear everything and reset command buffer. */ RTMemFree(pVBoxSCSI->pBuf); pVBoxSCSI->pBuf = NULL; pVBoxSCSI->cbCDB = 0; pVBoxSCSI->iCDB = 0; pVBoxSCSI->iBuf = 0; pVBoxSCSI->uTargetDevice = 0; pVBoxSCSI->enmState = VBOXSCSISTATE_NO_COMMAND; memset(pVBoxSCSI->aCDB, 0, sizeof(pVBoxSCSI->aCDB)); } } break; } case 2: { uVal = pVBoxSCSI->regIdentify; break; } default: AssertMsgFailed(("Invalid register to read from %u\n", iRegister)); } *pu32Value = uVal; return VINF_SUCCESS; }
DECLHIDDEN(void) rtR0MpNotificationNativeTerm(void) { if (ASMAtomicReadBool(&g_fSolCpuWatch) == true) { mutex_enter(&cpu_lock); unregister_cpu_setup_func(rtMpNotificationCpuEvent, NULL /* pvArg */); ASMAtomicWriteBool(&g_fSolCpuWatch, false); mutex_exit(&cpu_lock); } }
/** * Block the main thread until the service shuts down. */ void VBoxServiceMainWait(void) { int rc; VBoxServiceReportStatus(VBoxGuestFacilityStatus_Active); #ifdef RT_OS_WINDOWS /* * Wait for the semaphore to be signalled. */ VBoxServiceVerbose(1, "Waiting in main thread\n"); rc = RTSemEventCreate(&g_hEvtWindowsService); AssertRC(rc); while (!ASMAtomicReadBool(&g_fWindowsServiceShutdown)) { rc = RTSemEventWait(g_hEvtWindowsService, RT_INDEFINITE_WAIT); AssertRC(rc); } RTSemEventDestroy(g_hEvtWindowsService); g_hEvtWindowsService = NIL_RTSEMEVENT; #else /* * Wait explicitly for a HUP, INT, QUIT, ABRT or TERM signal, blocking * all important signals. * * The annoying EINTR/ERESTART loop is for the benefit of Solaris where * sigwait returns when we receive a SIGCHLD. Kind of makes sense since */ sigset_t signalMask; sigemptyset(&signalMask); sigaddset(&signalMask, SIGHUP); sigaddset(&signalMask, SIGINT); sigaddset(&signalMask, SIGQUIT); sigaddset(&signalMask, SIGABRT); sigaddset(&signalMask, SIGTERM); pthread_sigmask(SIG_BLOCK, &signalMask, NULL); int iSignal; do { iSignal = -1; rc = sigwait(&signalMask, &iSignal); } while ( rc == EINTR # ifdef ERESTART || rc == ERESTART # endif ); VBoxServiceVerbose(3, "VBoxServiceMainWait: Received signal %d (rc=%d)\n", iSignal, rc); #endif /* !RT_OS_WINDOWS */ }
static void pdmacFileAioMgrWakeup(PPDMACEPFILEMGR pAioMgr) { bool fWokenUp = ASMAtomicXchgBool(&pAioMgr->fWokenUp, true); if (!fWokenUp) { bool fWaitingEventSem = ASMAtomicReadBool(&pAioMgr->fWaitingEventSem); if (fWaitingEventSem) { int rc = RTSemEventSignal(pAioMgr->EventSem); AssertRC(rc); } } }
RTDECL(int) RTFileAioCtxWakeup(RTFILEAIOCTX hAioCtx) { PRTFILEAIOCTXINTERNAL pCtxInt = hAioCtx; RTFILEAIOCTX_VALID_RETURN(pCtxInt); /** @todo r=bird: Define the protocol for how to resume work after calling * this function. */ bool fWokenUp = ASMAtomicXchgBool(&pCtxInt->fWokenUp, true); /* * Read the thread handle before the status flag. * If we read the handle after the flag we might * end up with an invalid handle because the thread * waiting in RTFileAioCtxWakeup() might get scheduled * before we read the flag and returns. * We can ensure that the handle is valid if fWaiting is true * when reading the handle before the status flag. */ RTTHREAD hThread; ASMAtomicReadHandle(&pCtxInt->hThreadWait, &hThread); bool fWaiting = ASMAtomicReadBool(&pCtxInt->fWaiting); if ( !fWokenUp && fWaiting) { /* * If a thread waits the handle must be valid. * It is possible that the thread returns from * rtFileAsyncIoLinuxGetEvents() before the signal * is send. * This is no problem because we already set fWokenUp * to true which will let the thread return VERR_INTERRUPTED * and the next call to RTFileAioCtxWait() will not * return VERR_INTERRUPTED because signals are not saved * and will simply vanish if the destination thread can't * receive it. */ Assert(hThread != NIL_RTTHREAD); RTThreadPoke(hThread); } return VINF_SUCCESS; }
DECLHIDDEN(int) rtR0MpNotificationNativeInit(void) { if (ASMAtomicReadBool(&g_fSolCpuWatch) == true) return VERR_WRONG_ORDER; /* * Register the callback building the online cpu set as we do so. */ RTCpuSetEmpty(&g_rtMpSolCpuSet); mutex_enter(&cpu_lock); register_cpu_setup_func(rtMpNotificationCpuEvent, NULL /* pvArg */); for (int i = 0; i < (int)RTMpGetCount(); ++i) if (cpu_is_online(cpu[i])) rtMpNotificationCpuEvent(CPU_ON, i, NULL /* pvArg */); ASMAtomicWriteBool(&g_fSolCpuWatch, true); mutex_exit(&cpu_lock); return VINF_SUCCESS; }
RTDECL(int) RTFileAioCtxWakeup(RTFILEAIOCTX hAioCtx) { int rc = VINF_SUCCESS; PRTFILEAIOCTXINTERNAL pCtxInt = hAioCtx; RTFILEAIOCTX_VALID_RETURN(pCtxInt); bool fWokenUp = ASMAtomicXchgBool(&pCtxInt->fWokenUp, true); bool fWaiting = ASMAtomicReadBool(&pCtxInt->fWaiting); if ( !fWokenUp && fWaiting) { BOOL fSucceeded = PostQueuedCompletionStatus(pCtxInt->hIoCompletionPort, 0, AIO_CONTEXT_WAKEUP_EVENT, NULL); if (!fSucceeded) rc = RTErrConvertFromWin32(GetLastError()); } return rc; }
bool GuestCtrlEvent::Canceled(void) { return ASMAtomicReadBool(&fCanceled); }
static DECLCALLBACK(int) gimDevR3DbgRecvThread(RTTHREAD hThreadSelf, void *pvUser) { RT_NOREF1(hThreadSelf); /* * Validate. */ PPDMDEVINS pDevIns = (PPDMDEVINS)pvUser; AssertReturn(pDevIns, VERR_INVALID_PARAMETER); PDMDEV_CHECK_VERSIONS_RETURN(pDevIns); PGIMDEV pThis = PDMINS_2_DATA(pDevIns, PGIMDEV); AssertReturn(pThis, VERR_INVALID_POINTER); AssertReturn(pThis->DbgSetup.cbDbgRecvBuf, VERR_INTERNAL_ERROR); AssertReturn(pThis->Dbg.hDbgRecvThreadSem != NIL_RTSEMEVENTMULTI, VERR_INTERNAL_ERROR_2); AssertReturn(pThis->Dbg.pvDbgRecvBuf, VERR_INTERNAL_ERROR_3); PVM pVM = PDMDevHlpGetVM(pDevIns); AssertReturn(pVM, VERR_INVALID_POINTER); PPDMISTREAM pDbgDrvStream = pThis->Dbg.pDbgDrvStream; AssertReturn(pDbgDrvStream, VERR_INVALID_POINTER); for (;;) { /* * Read incoming debug data. */ size_t cbRead = pThis->DbgSetup.cbDbgRecvBuf; int rc = pDbgDrvStream->pfnRead(pDbgDrvStream, pThis->Dbg.pvDbgRecvBuf, &cbRead); if ( RT_SUCCESS(rc) && cbRead > 0) { /* * Notify the consumer thread. */ if (ASMAtomicReadBool(&pThis->Dbg.fDbgRecvBufRead) == false) { if (pThis->DbgSetup.pfnDbgRecvBufAvail) pThis->DbgSetup.pfnDbgRecvBufAvail(pVM); pThis->Dbg.cbDbgRecvBufRead = cbRead; RTSemEventMultiReset(pThis->Dbg.hDbgRecvThreadSem); ASMAtomicWriteBool(&pThis->Dbg.fDbgRecvBufRead, true); } /* * Wait until the consumer thread has acknowledged reading of the * current buffer or we're asked to shut down. * * It is important that we do NOT re-invoke 'pfnRead' before the * current buffer is consumed, otherwise we risk data corruption. */ while ( ASMAtomicReadBool(&pThis->Dbg.fDbgRecvBufRead) == true && !pThis->fDbgRecvThreadShutdown) { RTSemEventMultiWait(pThis->Dbg.hDbgRecvThreadSem, RT_INDEFINITE_WAIT); } } #ifdef RT_OS_LINUX else if (rc == VERR_NET_CONNECTION_REFUSED) { /* * With the current, simplistic PDMISTREAM interface, this is the best we can do. * Even using RTSocketSelectOne[Ex] on Linux returns immediately with 'ready-to-read' * on localhost UDP sockets that are not connected on the other end. */ /** @todo Fix socket waiting semantics on localhost Linux unconnected UDP sockets. */ RTThreadSleep(400); } #endif else if ( rc != VINF_TRY_AGAIN && rc != VERR_TRY_AGAIN && rc != VERR_NET_CONNECTION_RESET_BY_PEER) { LogRel(("GIMDev: Debug thread terminating with rc=%Rrc\n", rc)); break; } if (pThis->fDbgRecvThreadShutdown) { LogRel(("GIMDev: Debug thread shutting down\n")); break; } } return VINF_SUCCESS; }
/** * A fallback method in case something goes wrong with the normal * I/O manager. */ DECLCALLBACK(int) pdmacFileAioMgrFailsafe(RTTHREAD hThreadSelf, void *pvUser) { int rc = VINF_SUCCESS; PPDMACEPFILEMGR pAioMgr = (PPDMACEPFILEMGR)pvUser; NOREF(hThreadSelf); while ( (pAioMgr->enmState == PDMACEPFILEMGRSTATE_RUNNING) || (pAioMgr->enmState == PDMACEPFILEMGRSTATE_SUSPENDING)) { ASMAtomicWriteBool(&pAioMgr->fWaitingEventSem, true); if (!ASMAtomicReadBool(&pAioMgr->fWokenUp)) rc = RTSemEventWait(pAioMgr->EventSem, pAioMgr->msBwLimitExpired); ASMAtomicWriteBool(&pAioMgr->fWaitingEventSem, false); Assert(RT_SUCCESS(rc) || rc == VERR_TIMEOUT); LogFlow(("Got woken up\n")); ASMAtomicWriteBool(&pAioMgr->fWokenUp, false); /* Process endpoint events first. */ PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint = pAioMgr->pEndpointsHead; while (pEndpoint) { pAioMgr->msBwLimitExpired = RT_INDEFINITE_WAIT; rc = pdmacFileAioMgrFailsafeProcessEndpoint(pAioMgr, pEndpoint); AssertRC(rc); pEndpoint = pEndpoint->AioMgr.pEndpointNext; } /* Now check for an external blocking event. */ if (pAioMgr->fBlockingEventPending) { switch (pAioMgr->enmBlockingEvent) { case PDMACEPFILEAIOMGRBLOCKINGEVENT_ADD_ENDPOINT: { PPDMASYNCCOMPLETIONENDPOINTFILE pEndpointNew = pAioMgr->BlockingEventData.AddEndpoint.pEndpoint; AssertMsg(VALID_PTR(pEndpointNew), ("Adding endpoint event without a endpoint to add\n")); pEndpointNew->enmState = PDMASYNCCOMPLETIONENDPOINTFILESTATE_ACTIVE; pEndpointNew->AioMgr.pEndpointNext = pAioMgr->pEndpointsHead; pEndpointNew->AioMgr.pEndpointPrev = NULL; if (pAioMgr->pEndpointsHead) pAioMgr->pEndpointsHead->AioMgr.pEndpointPrev = pEndpointNew; pAioMgr->pEndpointsHead = pEndpointNew; pAioMgr->cEndpoints++; /* * Process the task list the first time. There might be pending requests * if the endpoint was migrated from another endpoint. */ rc = pdmacFileAioMgrFailsafeProcessEndpoint(pAioMgr, pEndpointNew); AssertRC(rc); break; } case PDMACEPFILEAIOMGRBLOCKINGEVENT_REMOVE_ENDPOINT: { PPDMASYNCCOMPLETIONENDPOINTFILE pEndpointRemove = pAioMgr->BlockingEventData.RemoveEndpoint.pEndpoint; AssertMsg(VALID_PTR(pEndpointRemove), ("Removing endpoint event without a endpoint to remove\n")); pEndpointRemove->enmState = PDMASYNCCOMPLETIONENDPOINTFILESTATE_REMOVING; PPDMASYNCCOMPLETIONENDPOINTFILE pPrev = pEndpointRemove->AioMgr.pEndpointPrev; PPDMASYNCCOMPLETIONENDPOINTFILE pNext = pEndpointRemove->AioMgr.pEndpointNext; if (pPrev) pPrev->AioMgr.pEndpointNext = pNext; else pAioMgr->pEndpointsHead = pNext; if (pNext) pNext->AioMgr.pEndpointPrev = pPrev; pAioMgr->cEndpoints--; break; } case PDMACEPFILEAIOMGRBLOCKINGEVENT_CLOSE_ENDPOINT: { PPDMASYNCCOMPLETIONENDPOINTFILE pEndpointClose = pAioMgr->BlockingEventData.CloseEndpoint.pEndpoint; AssertMsg(VALID_PTR(pEndpointClose), ("Close endpoint event without a endpoint to Close\n")); pEndpointClose->enmState = PDMASYNCCOMPLETIONENDPOINTFILESTATE_CLOSING; /* Make sure all tasks finished. */ rc = pdmacFileAioMgrFailsafeProcessEndpoint(pAioMgr, pEndpointClose); AssertRC(rc); break; } case PDMACEPFILEAIOMGRBLOCKINGEVENT_SHUTDOWN: pAioMgr->enmState = PDMACEPFILEMGRSTATE_SHUTDOWN; break; case PDMACEPFILEAIOMGRBLOCKINGEVENT_SUSPEND: pAioMgr->enmState = PDMACEPFILEMGRSTATE_SUSPENDING; break; case PDMACEPFILEAIOMGRBLOCKINGEVENT_RESUME: pAioMgr->enmState = PDMACEPFILEMGRSTATE_RUNNING; break; default: AssertMsgFailed(("Invalid event type %d\n", pAioMgr->enmBlockingEvent)); } ASMAtomicWriteBool(&pAioMgr->fBlockingEventPending, false); pAioMgr->enmBlockingEvent = PDMACEPFILEAIOMGRBLOCKINGEVENT_INVALID; /* Release the waiting thread. */ rc = RTSemEventSignal(pAioMgr->EventSemBlock); AssertRC(rc); } } return rc; }