/** @interface_method_impl{PDMHPETHLPR3,pfnSetLegacyMode} */ static DECLCALLBACK(int) pdmR3HpetHlp_SetLegacyMode(PPDMDEVINS pDevIns, bool fActivated) { PDMDEV_ASSERT_DEVINS(pDevIns); LogFlow(("pdmR3HpetHlp_SetLegacyMode: caller='%s'/%d: fActivated=%RTbool\n", pDevIns->pReg->szName, pDevIns->iInstance, fActivated)); size_t i; int rc = VINF_SUCCESS; static const char * const s_apszDevsToNotify[] = { "i8254", "mc146818" }; for (i = 0; i < RT_ELEMENTS(s_apszDevsToNotify); i++) { PPDMIBASE pBase; rc = PDMR3QueryDevice(pDevIns->Internal.s.pVMR3->pUVM, "i8254", 0, &pBase); if (RT_SUCCESS(rc)) { PPDMIHPETLEGACYNOTIFY pPort = PDMIBASE_QUERY_INTERFACE(pBase, PDMIHPETLEGACYNOTIFY); AssertLogRelMsgBreakStmt(pPort, ("%s\n", s_apszDevsToNotify[i]), rc = VERR_PDM_HPET_LEGACY_NOTIFY_MISSING); pPort->pfnModeChanged(pPort, fActivated); } else if ( rc == VERR_PDM_DEVICE_NOT_FOUND || rc == VERR_PDM_DEVICE_INSTANCE_NOT_FOUND) rc = VINF_SUCCESS; /* the device isn't configured, ignore. */ else AssertLogRelMsgFailedBreak(("%s -> %Rrc\n", s_apszDevsToNotify[i], rc)); } /* Don't bother cleaning up, any failure here will cause a guru meditation. */ LogFlow(("pdmR3HpetHlp_SetLegacyMode: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc)); return rc; }
static DECLCALLBACK(int) drvHostALSAAudioCaptureIn(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHSTSTRMIN pHstStrmIn, uint32_t *pcSamplesCaptured) { NOREF(pInterface); AssertPtrReturn(pHstStrmIn, VERR_INVALID_POINTER); PALSAAUDIOSTREAMIN pThisStrmIn = (PALSAAUDIOSTREAMIN)pHstStrmIn; snd_pcm_sframes_t cAvail; int rc = drvHostALSAAudioGetAvail(pThisStrmIn->phPCM, &cAvail); if (RT_FAILURE(rc)) { LogFunc(("Error getting number of captured frames, rc=%Rrc\n", rc)); return rc; } if (!cAvail) /* No data yet? */ { snd_pcm_state_t state = snd_pcm_state(pThisStrmIn->phPCM); switch (state) { case SND_PCM_STATE_PREPARED: cAvail = AudioMixBufFree(&pHstStrmIn->MixBuf); break; case SND_PCM_STATE_SUSPENDED: { rc = drvHostALSAAudioResume(pThisStrmIn->phPCM); if (RT_FAILURE(rc)) break; LogFlow(("Resuming suspended input stream\n")); break; } default: LogFlow(("No frames available, state=%d\n", state)); break; } if (!cAvail) { if (pcSamplesCaptured) *pcSamplesCaptured = 0; return VINF_SUCCESS; } } /* * Check how much we can read from the capture device without overflowing * the mixer buffer. */ Assert(cAvail); size_t cbMixFree = AudioMixBufFreeBytes(&pHstStrmIn->MixBuf); size_t cbToRead = RT_MIN((size_t)AUDIOMIXBUF_S2B(&pHstStrmIn->MixBuf, cAvail), cbMixFree); LogFlowFunc(("cbToRead=%zu, cAvail=%RI32\n", cbToRead, cAvail)); uint32_t cWrittenTotal = 0; snd_pcm_uframes_t cToRead; snd_pcm_sframes_t cRead; while ( cbToRead && RT_SUCCESS(rc)) { cToRead = RT_MIN(AUDIOMIXBUF_B2S(&pHstStrmIn->MixBuf, cbToRead), AUDIOMIXBUF_B2S(&pHstStrmIn->MixBuf, pThisStrmIn->cbBuf)); AssertBreakStmt(cToRead, rc = VERR_NO_DATA); cRead = snd_pcm_readi(pThisStrmIn->phPCM, pThisStrmIn->pvBuf, cToRead); if (cRead <= 0) { switch (cRead) { case 0: { LogFunc(("No input frames available\n")); rc = VERR_ACCESS_DENIED; break; } case -EAGAIN: /* * Don't set error here because EAGAIN means there are no further frames * available at the moment, try later. As we might have read some frames * already these need to be processed instead. */ cbToRead = 0; break; case -EPIPE: { rc = drvHostALSAAudioRecover(pThisStrmIn->phPCM); if (RT_FAILURE(rc)) break; LogFlowFunc(("Recovered from capturing\n")); continue; } default: LogFunc(("Failed to read input frames: %s\n", snd_strerror(cRead))); rc = VERR_GENERAL_FAILURE; /** @todo Fudge! */ break; } } else { uint32_t cWritten; rc = AudioMixBufWriteCirc(&pHstStrmIn->MixBuf, pThisStrmIn->pvBuf, AUDIOMIXBUF_S2B(&pHstStrmIn->MixBuf, cRead), &cWritten); if (RT_FAILURE(rc)) break; /* * We should not run into a full mixer buffer or we loose samples and * run into an endless loop if ALSA keeps producing samples ("null" * capture device for example). */ AssertLogRelMsgBreakStmt(cWritten > 0, ("Mixer buffer shouldn't be full at this point!\n"), rc = VERR_INTERNAL_ERROR); uint32_t cbWritten = AUDIOMIXBUF_S2B(&pHstStrmIn->MixBuf, cWritten); Assert(cbToRead >= cbWritten); cbToRead -= cbWritten; cWrittenTotal += cWritten; } } if (RT_SUCCESS(rc)) { uint32_t cProcessed = 0; if (cWrittenTotal) rc = AudioMixBufMixToParent(&pHstStrmIn->MixBuf, cWrittenTotal, &cProcessed); if (pcSamplesCaptured) *pcSamplesCaptured = cWrittenTotal; LogFlowFunc(("cWrittenTotal=%RU32 (%RU32 processed), rc=%Rrc\n", cWrittenTotal, cProcessed, rc)); } LogFlowFuncLeaveRC(rc); return rc; }
/** * Watcher thread. */ /*static*/ DECLCALLBACK(int) VirtualBoxSDS::i_watcherThreadProc(RTTHREAD hSelf, void *pvUser) { VBoxSDSWatcher *pThis = (VBoxSDSWatcher *)pvUser; VirtualBoxSDS *pVBoxSDS = pThis->pVBoxSDS; RT_NOREF(hSelf); /* * This thread may release references to IVBoxSVCRegistration objects. */ CoInitializeEx(NULL, COINIT_MULTITHREADED); /* * The loop. */ RTCritSectEnter(&pVBoxSDS->m_WatcherCritSect); while (!pThis->fShutdown) { /* * Deal with the todo list. */ uint32_t cHandles = pThis->cHandles; uint32_t cTodos = pThis->cTodos; for (uint32_t i = 0; i < cTodos; i++) { VBoxSDSPerUserData *pUserData = pThis->aTodos[i].Data.pUserData; AssertContinue(pUserData); if (pThis->aTodos[i].hProcess != NULL) { /* Add: */ AssertLogRelMsgBreakStmt(cHandles < RT_ELEMENTS(pThis->aHandles), ("cHandles=%u cTodos=%u i=%u iWatcher=%u\n", cHandles, cTodos, i, pThis->iWatcher), pThis->fShutdown = true); pThis->aHandles[cHandles] = pThis->aTodos[i].hProcess; pThis->aData[cHandles] = pThis->aTodos[i].Data; cHandles++; } else { /* Remove: */ uint32_t cRemoved = 0; uint32_t j = cHandles; while (j-- > 1) if (pThis->aData[j].pUserData == pUserData) { cHandles = pThis->removeHandle(j, cHandles); pUserData->i_release(); cRemoved++; } if (cRemoved != 1) LogRel(("i_watcherThreadProc/#%u: Warning! cRemoved=%u pUserData=%p\n", pThis->iWatcher, cRemoved, pUserData)); } /* Zap the entry in case we assert and leave further up. */ pThis->aTodos[i].Data.setNull(); pThis->aTodos[i].hProcess = NULL; } Assert(cHandles > 0 && cHandles <= RT_ELEMENTS(pThis->aHandles)); pThis->cHandles = cHandles; pThis->cHandlesEffective = cHandles; pThis->cTodos = 0; if (pThis->fShutdown) break; /* * Wait. */ RTCritSectLeave(&pVBoxSDS->m_WatcherCritSect); LogRel(("i_watcherThreadProc/#%u: Waiting on %u handles...\n", pThis->iWatcher, cHandles)); DWORD const dwWait = WaitForMultipleObjects(cHandles, pThis->aHandles, FALSE /*fWaitAll*/, INFINITE); LogRel(("i_watcherThreadProc/#%u: ... wait returned: %#x (%d)\n", pThis->iWatcher, dwWait, dwWait)); uint32_t const iHandle = dwWait - WAIT_OBJECT_0; if (iHandle < cHandles && iHandle > 0) { /* * A VBoxSVC process has terminated. * * Note! We need to take the user data lock before the watcher one here. */ VBoxSDSPerUserData * const pUserData = pThis->aData[iHandle].pUserData; uint32_t const iRevision = pThis->aData[iHandle].iRevision; RTPROCESS const pid = pThis->aData[iHandle].pid; pUserData->i_lock(); RTCritSectEnter(&pVBoxSDS->m_WatcherCritSect); DWORD dwExit = 0; GetExitCodeProcess(pThis->aHandles[iHandle], &dwExit); LogRel(("i_watcherThreadProc/#%u: %p/%s: PID %u/%#x termination detected: %d (%#x) [iRev=%u, cur %u]\n", pThis->iWatcher, pUserData, pUserData->m_strUsername.c_str(), pid, pid, dwExit, dwExit, iRevision, pUserData->m_iTheChosenOneRevision)); /* Remove it from the handle array. */ CloseHandle(pThis->aHandles[iHandle]); pThis->cHandles = cHandles = pThis->removeHandle(iHandle, cHandles); pThis->cHandlesEffective -= 1; /* If the process we were watching is still the current chosen one, unchoose it and decrement the client count. Otherwise we were subject to a deregistration/termination race (unlikely). */ if (pUserData->m_iTheChosenOneRevision == iRevision) { pUserData->i_unchooseTheOne(true /*fIrregular*/); pUserData->i_unlock(); pVBoxSDS->i_decrementClientCount(); } else pUserData->i_unlock(); pUserData->i_release(); } else { RTCritSectEnter(&pThis->pVBoxSDS->m_WatcherCritSect); AssertLogRelMsgBreak(iHandle == 0 || dwWait == WAIT_TIMEOUT, ("dwWait=%u (%#x) cHandles=%u\n", dwWait, dwWait, cHandles)); } } RTCritSectLeave(&pThis->pVBoxSDS->m_WatcherCritSect); /* * In case we quit w/o being told, signal i_watchIt that we're out of action. */ pThis->fShutdown = true; /* * Release all our data on the way out. */ uint32_t i = pThis->cHandles; while (i-- > 1) { if (pThis->aData[i].pUserData) { pThis->aData[i].pUserData->i_release(); pThis->aData[i].pUserData = NULL; } if (pThis->aHandles[i]) { CloseHandle(pThis->aHandles[i]); pThis->aHandles[i] = NULL; } } if (pThis->aHandles[0]) { CloseHandle(pThis->aHandles[0]); pThis->aHandles[0] = NULL; } i = pThis->cTodos; pThis->cTodos = 0; while (i-- > 0) { if (pThis->aTodos[i].Data.pUserData) { pThis->aTodos[i].Data.pUserData->i_release(); pThis->aTodos[i].Data.pUserData = NULL; } if (pThis->aTodos[i].hProcess) { CloseHandle(pThis->aTodos[i].hProcess); pThis->aTodos[i].hProcess = NULL; } } if (ASMAtomicDecU32(&pThis->cRefs) == 0) RTMemFree(pThis); return VINF_SUCCESS; }