RTDECL(int) RTPoll(RTPOLLSET hPollSet, RTMSINTERVAL cMillies, uint32_t *pfEvents, uint32_t *pid) { RTPOLLSETINTERNAL *pThis = hPollSet; AssertPtrReturn(pThis, VERR_INVALID_HANDLE); AssertReturn(pThis->u32Magic == RTPOLLSET_MAGIC, VERR_INVALID_HANDLE); AssertPtrNull(pfEvents); AssertPtrNull(pid); /* * Set the busy flag and do the job. */ AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true, false), VERR_CONCURRENT_ACCESS); int rc; if (cMillies == RT_INDEFINITE_WAIT || cMillies == 0) { do rc = rtPollNoResumeWorker(pThis, cMillies, pfEvents, pid); while (rc == VERR_INTERRUPTED); } else { uint64_t MsStart = RTTimeMilliTS(); rc = rtPollNoResumeWorker(pThis, cMillies, pfEvents, pid); while (RT_UNLIKELY(rc == VERR_INTERRUPTED)) { if (RTTimeMilliTS() - MsStart >= cMillies) { rc = VERR_TIMEOUT; break; } rc = rtPollNoResumeWorker(pThis, cMillies, pfEvents, pid); } } ASMAtomicWriteBool(&pThis->fBusy, false); return rc; }
HRESULT ListenerRecord::dequeue(IEvent **aEvent, LONG aTimeout, AutoLockBase &aAlock) { if (mActive) return VBOX_E_INVALID_OBJECT_STATE; // retain listener record RecordHolder<ListenerRecord> holder(this); ::RTCritSectEnter(&mcsQLock); mLastRead = RTTimeMilliTS(); /* * If waiting both desired and necessary, then try grab the event * semaphore and mark it busy. If it's NIL we've been shut down already. */ if (aTimeout != 0 && mQueue.empty()) { RTSEMEVENT hEvt = mQEvent; if (hEvt != NIL_RTSEMEVENT) { ASMAtomicIncS32(&mQEventBusyCnt); ::RTCritSectLeave(&mcsQLock); // release lock while waiting, listener will not go away due to above holder aAlock.release(); ::RTSemEventWait(hEvt, aTimeout); ASMAtomicDecS32(&mQEventBusyCnt); // reacquire lock aAlock.acquire(); ::RTCritSectEnter(&mcsQLock); } } if (mQueue.empty()) *aEvent = NULL; else { mQueue.front().queryInterfaceTo(aEvent); mQueue.pop_front(); } ::RTCritSectLeave(&mcsQLock); return S_OK; }
int ConfigurationManager::commitLease4Client(Client& client) { Lease l = client.lease(); AssertReturn(l != Lease::NullLease, VERR_INTERNAL_ERROR); l.bindingPhase(false); const NetworkConfigEntity *pCfg = l.getConfig(); AssertPtr(pCfg); l.setExpiration(pCfg->expirationPeriod()); l.phaseStart(RTTimeMilliTS()); saveToFile(); return VINF_SUCCESS; }
HRESULT ListenerRecord::dequeue (IEvent* *aEvent, LONG aTimeout, AutoLockBase& aAlock) { if (mActive) return VBOX_E_INVALID_OBJECT_STATE; // retain listener record RecordHolder<ListenerRecord> holder(this); ::RTCritSectEnter(&mcsQLock); mLastRead = RTTimeMilliTS(); if (mQueue.empty()) { ::RTCritSectLeave(&mcsQLock); // Speed up common case if (aTimeout == 0) { *aEvent = NULL; return S_OK; } // release lock while waiting, listener will not go away due to above holder aAlock.release(); ::RTSemEventWait(mQEvent, aTimeout); // reacquire lock aAlock.acquire(); ::RTCritSectEnter(&mcsQLock); } if (mQueue.empty()) { *aEvent = NULL; } else { mQueue.front().queryInterfaceTo(aEvent); mQueue.pop_front(); } ::RTCritSectLeave(&mcsQLock); return S_OK; }
HRESULT ListenerRecord::enqueue(IEvent *aEvent) { AssertMsg(!mActive, ("must be passive\n")); // put an event the queue ::RTCritSectEnter(&mcsQLock); // If there was no events reading from the listener for the long time, // and events keep coming, or queue is oversized we shall unregister this listener. uint64_t sinceRead = RTTimeMilliTS() - mLastRead; size_t queueSize = mQueue.size(); if (queueSize > 1000 || (queueSize > 500 && sinceRead > 60 * 1000)) { ::RTCritSectLeave(&mcsQLock); return E_ABORT; } RTSEMEVENT hEvt = mQEvent; if (queueSize != 0 && mQueue.back() == aEvent) /* if same event is being pushed multiple times - it's reusable event and we don't really need multiple instances of it in the queue */ hEvt = NIL_RTSEMEVENT; else if (hEvt != NIL_RTSEMEVENT) /* don't bother queuing after shutdown */ { mQueue.push_back(aEvent); ASMAtomicIncS32(&mQEventBusyCnt); } ::RTCritSectLeave(&mcsQLock); // notify waiters unless we've been shut down. if (hEvt != NIL_RTSEMEVENT) { ::RTSemEventSignal(hEvt); ASMAtomicDecS32(&mQEventBusyCnt); } return S_OK; }
ListenerRecord::ListenerRecord(IEventListener* aListener, com::SafeArray<VBoxEventType_T>& aInterested, BOOL aActive, EventSource* aOwner) : mActive(aActive), mOwner(aOwner), mRefCnt(0) { mListener = aListener; EventMap* aEvMap = &aOwner->m->mEvMap; for (size_t i = 0; i < aInterested.size(); ++i) { VBoxEventType_T interested = aInterested[i]; for (int j = FirstEvent; j < LastEvent; j++) { VBoxEventType_T candidate = (VBoxEventType_T)j; if (implies(interested, candidate)) { (*aEvMap)[j - FirstEvent].add(this); } } } if (!mActive) { ::RTCritSectInit(&mcsQLock); ::RTSemEventCreate (&mQEvent); mLastRead = RTTimeMilliTS(); } else { mQEvent =NIL_RTSEMEVENT; RT_ZERO(mcsQLock); mLastRead = 0; } }
void renderspu_SystemSwapBuffers(WindowInfo *window, GLint flags) { CRASSERT(window); CRASSERT(window->window); ContextInfo *context = renderspuGetWindowContext(window); if(!context) crError("Render SPU (renderspu_SystemSwapBuffers): SwapBuffers got a null context from the window"); RTSemFastMutexRequest(render_spu.syncMutex); // DEBUG_MSG_POETZSCH (("Swapped %d context %x visible: %d\n", window->BltInfo.Base.id, context->context, IsWindowVisible (window->window))); if (context->visual && context->visual->visAttribs & CR_DOUBLE_BIT) render_spu.ws.aglSwapBuffers(context->context); else glFlush(); RTSemFastMutexRelease(render_spu.syncMutex); /* This method seems called very often. To prevent the dock using all free * resources we update the dock only two times per second. */ uint64_t curTS = RTTimeMilliTS(); if ((curTS - render_spu.uiDockUpdateTS) > 500) { OSStatus status = noErr; /* Send a event to the main thread, cause some function of Carbon aren't * thread safe */ EventRef evt; status = CreateEvent(NULL, kEventClassVBox, kEventVBoxUpdateDock, 0, kEventAttributeNone, &evt); CHECK_CARBON_RC_RETURN_VOID (status, "Render SPU (renderspu_SystemSwapBuffers): CreateEvent Failed"); status = PostEventToQueue(GetMainEventQueue(), evt, kEventPriorityStandard); CHECK_CARBON_RC_RETURN_VOID (status, "Render SPU (renderspu_SystemSwapBuffers): PostEventToQueue Failed"); render_spu.uiDockUpdateTS = curTS; } }
/** * The client is requesting an offer. * * @returns true. * * @param pDhcpMsg The message. * @param cb The message size. */ bool NetworkManager::handleDhcpReqDiscover(PCRTNETBOOTP pDhcpMsg, size_t cb) { RawOption opt; RT_ZERO(opt); /* 1. Find client */ ConfigurationManager *confManager = ConfigurationManager::getConfigurationManager(); Client client = confManager->getClientByDhcpPacket(pDhcpMsg, cb); /* 2. Find/Bind lease for client */ Lease lease = confManager->allocateLease4Client(client, pDhcpMsg, cb); AssertReturn(lease != Lease::NullLease, VINF_SUCCESS); int rc = ConfigurationManager::extractRequestList(pDhcpMsg, cb, opt); /* 3. Send of offer */ lease.bindingPhase(true); lease.phaseStart(RTTimeMilliTS()); lease.setExpiration(300); /* 3 min. */ offer4Client(client, pDhcpMsg->bp_xid, opt.au8RawOpt, opt.cbRawOpt); return VINF_SUCCESS; }
RTDECL(int) RTLocalIpcSessionWaitForData(RTLOCALIPCSESSION hSession, uint32_t cMillies) { PRTLOCALIPCSESSIONINT pThis = (PRTLOCALIPCSESSIONINT)hSession; AssertPtrReturn(pThis, VERR_INVALID_HANDLE); AssertReturn(pThis->u32Magic == RTLOCALIPCSESSION_MAGIC, VERR_INVALID_HANDLE); uint64_t const StartMsTS = RTTimeMilliTS(); int rc = RTCritSectEnter(&pThis->CritSect); if (RT_FAILURE(rc)) return rc; for (unsigned iLoop = 0;; iLoop++) { HANDLE hWait = INVALID_HANDLE_VALUE; if (pThis->fIOPending) hWait = pThis->OverlappedIO.hEvent; else { /* Peek at the pipe buffer and see how many bytes it contains. */ DWORD cbAvailable; BOOL fRc = PeekNamedPipe(pThis->hNmPipe, NULL, 0, NULL, &cbAvailable, NULL); if ( fRc && cbAvailable) { rc = VINF_SUCCESS; break; } else if (!fRc) { rc = RTErrConvertFromWin32(GetLastError()); break; } /* Start a zero byte read operation that we can wait on. */ if (cMillies == 0) { rc = VERR_TIMEOUT; break; } AssertBreakStmt(pThis->cRefs == 1, rc = VERR_WRONG_ORDER); fRc = ResetEvent(pThis->OverlappedIO.hEvent); Assert(fRc == TRUE); DWORD cbRead = 0; if (ReadFile(pThis->hNmPipe, pThis->abBuf, 0, &cbRead, &pThis->OverlappedIO)) { rc = VINF_SUCCESS; if (iLoop > 10) RTThreadYield(); } else if (GetLastError() == ERROR_IO_PENDING) { pThis->cRefs++; pThis->fIOPending = true; pThis->fZeroByteRead = true; hWait = pThis->OverlappedIO.hEvent; } else rc = RTErrConvertFromWin32(GetLastError()); } if (RT_FAILURE(rc)) break; /* * Check for timeout. */ DWORD cMsMaxWait = INFINITE; if ( cMillies != RT_INDEFINITE_WAIT && ( hWait != INVALID_HANDLE_VALUE || iLoop > 10) ) { uint64_t cElapsed = RTTimeMilliTS() - StartMsTS; if (cElapsed >= cMillies) { rc = VERR_TIMEOUT; break; } cMsMaxWait = cMillies - (uint32_t)cElapsed; } /* * Wait. */ if (hWait != INVALID_HANDLE_VALUE) { RTCritSectLeave(&pThis->CritSect); DWORD dwRc = WaitForSingleObject(hWait, cMsMaxWait); if (dwRc == WAIT_OBJECT_0) rc = VINF_SUCCESS; else if (dwRc == WAIT_TIMEOUT) rc = VERR_TIMEOUT; else if (dwRc == WAIT_ABANDONED) rc = VERR_INVALID_HANDLE; else rc = RTErrConvertFromWin32(GetLastError()); if ( RT_FAILURE(rc) && pThis->u32Magic != RTLOCALIPCSESSION_MAGIC) return rc; int rc2 = RTCritSectEnter(&pThis->CritSect); AssertRC(rc2); if (pThis->fZeroByteRead) { Assert(pThis->cRefs); pThis->cRefs--; pThis->fIOPending = false; if (rc != VINF_SUCCESS) { BOOL fRc = CancelIo(pThis->hNmPipe); Assert(fRc == TRUE); } DWORD cbRead = 0; BOOL fRc = GetOverlappedResult(pThis->hNmPipe, &pThis->OverlappedIO, &cbRead, TRUE /*fWait*/); if ( !fRc && RT_SUCCESS(rc)) { DWORD dwRc = GetLastError(); if (dwRc == ERROR_OPERATION_ABORTED) rc = VERR_CANCELLED; else rc = RTErrConvertFromWin32(dwRc); } } if (RT_FAILURE(rc)) break; } } int rc2 = RTCritSectLeave(&pThis->CritSect); if (RT_SUCCESS(rc)) rc = rc2; return rc; }
static int vboxInitLogging(const char *pszFilename, bool bGenNameSuffix) { PRTLOGGER loggerRelease; static const char * const s_apszGroups[] = VBOX_LOGGROUP_NAMES; RTUINT fFlags = RTLOGFLAGS_PREFIX_TIME_PROG; #if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2) fFlags |= RTLOGFLAGS_USECRLF; #endif char szError[RTPATH_MAX + 128] = ""; const char * pszFilenameFmt; RTLOGDEST enmLogDest; if(pszFilename) { if(bGenNameSuffix) pszFilenameFmt = "%s.%ld.log"; else pszFilenameFmt = "%s"; enmLogDest = RTLOGDEST_FILE; } else { pszFilenameFmt = NULL; enmLogDest = RTLOGDEST_STDOUT; } int vrc = RTLogCreateEx(&loggerRelease, fFlags, "all", "VBOX_RELEASE_LOG", RT_ELEMENTS(s_apszGroups), s_apszGroups, enmLogDest, NULL /* pfnBeginEnd */, 0 /* cHistory */, 0 /* cbHistoryFileMax */, 0 /* uHistoryTimeMax */, szError, sizeof(szError), pszFilenameFmt, pszFilename, RTTimeMilliTS()); if (RT_SUCCESS(vrc)) { /* some introductory information */ RTTIMESPEC timeSpec; char szTmp[256]; RTTimeSpecToString(RTTimeNow(&timeSpec), szTmp, sizeof(szTmp)); RTLogRelLogger(loggerRelease, 0, ~0U, "VBoxTestGL %s r%u %s (%s %s) release log\n" #ifdef VBOX_BLEEDING_EDGE "EXPERIMENTAL build " VBOX_BLEEDING_EDGE "\n" #endif "Log opened %s\n", VBOX_VERSION_STRING, RTBldCfgRevision(), VBOX_BUILD_TARGET, __DATE__, __TIME__, szTmp); vrc = RTSystemQueryOSInfo(RTSYSOSINFO_PRODUCT, szTmp, sizeof(szTmp)); if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW) RTLogRelLogger(loggerRelease, 0, ~0U, "OS Product: %s\n", szTmp); vrc = RTSystemQueryOSInfo(RTSYSOSINFO_RELEASE, szTmp, sizeof(szTmp)); if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW) RTLogRelLogger(loggerRelease, 0, ~0U, "OS Release: %s\n", szTmp); vrc = RTSystemQueryOSInfo(RTSYSOSINFO_VERSION, szTmp, sizeof(szTmp)); if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW) RTLogRelLogger(loggerRelease, 0, ~0U, "OS Version: %s\n", szTmp); vrc = RTSystemQueryOSInfo(RTSYSOSINFO_SERVICE_PACK, szTmp, sizeof(szTmp)); if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW) RTLogRelLogger(loggerRelease, 0, ~0U, "OS Service Pack: %s\n", szTmp); // RTLogRelLogger(loggerRelease, 0, ~0U, "Host RAM: %uMB RAM, available: %uMB\n", // uHostRamMb, uHostRamAvailMb); /* the package type is interesting for Linux distributions */ char szExecName[RTPATH_MAX]; char *pszExecName = RTProcGetExecutablePath(szExecName, sizeof(szExecName)); RTLogRelLogger(loggerRelease, 0, ~0U, "Executable: %s\n" "Process ID: %u\n" "Package type: %s" #ifdef VBOX_OSE " (OSE)" #endif "\n", pszExecName ? pszExecName : "unknown", RTProcSelf(), VBOX_PACKAGE_STRING); /* register this logger as the release logger */ RTLogRelSetDefaultInstance(loggerRelease); return VINF_SUCCESS; } return vrc; }
int main(int argc, char *argv[]) { /* * Initialize the VBox runtime without loading * the support driver. */ int rc = RTR3InitExe(argc, &argv, 0); if (RT_FAILURE(rc)) { RTPrintf("tstCollector: RTR3InitExe() -> %d\n", rc); return 1; } if (argc > 1 && !strcmp(argv[1], "-child")) { /* We have spawned ourselves as a child process -- scratch the leg */ RTThreadSleep(1000000); return 1; } #ifdef RT_OS_WINDOWS HRESULT hRes = CoInitialize(NULL); /* * Need to initialize security to access performance enumerators. */ hRes = CoInitializeSecurity( NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_NONE, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, 0); #endif pm::CollectorHAL *collector = pm::createHAL(); if (!collector) { RTPrintf("tstCollector: createMetricFactory() failed\n", rc); return 1; } #if 1 pm::CollectorHints hints; hints.collectHostCpuLoad(); hints.collectHostRamUsage(); hints.collectProcessCpuLoad(RTProcSelf()); hints.collectProcessRamUsage(RTProcSelf()); uint64_t start; uint64_t hostUserStart, hostKernelStart, hostIdleStart; uint64_t hostUserStop, hostKernelStop, hostIdleStop, hostTotal; uint64_t processUserStart, processKernelStart, processTotalStart; uint64_t processUserStop, processKernelStop, processTotalStop; RTPrintf("tstCollector: TESTING - CPU load, sleeping for 5 sec\n"); rc = collector->preCollect(hints, 0); if (RT_FAILURE(rc)) { RTPrintf("tstCollector: preCollect() -> %Rrc\n", rc); return 1; } rc = collector->getRawHostCpuLoad(&hostUserStart, &hostKernelStart, &hostIdleStart); if (RT_FAILURE(rc)) { RTPrintf("tstCollector: getRawHostCpuLoad() -> %Rrc\n", rc); return 1; } rc = collector->getRawProcessCpuLoad(RTProcSelf(), &processUserStart, &processKernelStart, &processTotalStart); if (RT_FAILURE(rc)) { RTPrintf("tstCollector: getRawProcessCpuLoad() -> %Rrc\n", rc); return 1; } RTThreadSleep(5000); // Sleep for 5 seconds rc = collector->preCollect(hints, 0); if (RT_FAILURE(rc)) { RTPrintf("tstCollector: preCollect() -> %Rrc\n", rc); return 1; } rc = collector->getRawHostCpuLoad(&hostUserStop, &hostKernelStop, &hostIdleStop); if (RT_FAILURE(rc)) { RTPrintf("tstCollector: getRawHostCpuLoad() -> %Rrc\n", rc); return 1; } rc = collector->getRawProcessCpuLoad(RTProcSelf(), &processUserStop, &processKernelStop, &processTotalStop); if (RT_FAILURE(rc)) { RTPrintf("tstCollector: getRawProcessCpuLoad() -> %Rrc\n", rc); return 1; } hostTotal = hostUserStop - hostUserStart + hostKernelStop - hostKernelStart + hostIdleStop - hostIdleStart; /*printf("tstCollector: host cpu user = %f sec\n", (hostUserStop - hostUserStart) / 10000000.); printf("tstCollector: host cpu kernel = %f sec\n", (hostKernelStop - hostKernelStart) / 10000000.); printf("tstCollector: host cpu idle = %f sec\n", (hostIdleStop - hostIdleStart) / 10000000.); printf("tstCollector: host cpu total = %f sec\n", hostTotal / 10000000.);*/ RTPrintf("tstCollector: host cpu user = %u.%u %%\n", (unsigned)((hostUserStop - hostUserStart) * 100 / hostTotal), (unsigned)((hostUserStop - hostUserStart) * 10000 / hostTotal % 100)); RTPrintf("tstCollector: host cpu kernel = %u.%u %%\n", (unsigned)((hostKernelStop - hostKernelStart) * 100 / hostTotal), (unsigned)((hostKernelStop - hostKernelStart) * 10000 / hostTotal % 100)); RTPrintf("tstCollector: host cpu idle = %u.%u %%\n", (unsigned)((hostIdleStop - hostIdleStart) * 100 / hostTotal), (unsigned)((hostIdleStop - hostIdleStart) * 10000 / hostTotal % 100)); RTPrintf("tstCollector: process cpu user = %u.%u %%\n", (unsigned)((processUserStop - processUserStart) * 100 / (processTotalStop - processTotalStart)), (unsigned)((processUserStop - processUserStart) * 10000 / (processTotalStop - processTotalStart) % 100)); RTPrintf("tstCollector: process cpu kernel = %u.%u %%\n\n", (unsigned)((processKernelStop - processKernelStart) * 100 / (processTotalStop - processTotalStart)), (unsigned)((processKernelStop - processKernelStart) * 10000 / (processTotalStop - processTotalStart) % 100)); RTPrintf("tstCollector: TESTING - CPU load, looping for 5 sec\n"); rc = collector->preCollect(hints, 0); if (RT_FAILURE(rc)) { RTPrintf("tstCollector: preCollect() -> %Rrc\n", rc); return 1; } rc = collector->getRawHostCpuLoad(&hostUserStart, &hostKernelStart, &hostIdleStart); if (RT_FAILURE(rc)) { RTPrintf("tstCollector: getRawHostCpuLoad() -> %Rrc\n", rc); return 1; } rc = collector->getRawProcessCpuLoad(RTProcSelf(), &processUserStart, &processKernelStart, &processTotalStart); if (RT_FAILURE(rc)) { RTPrintf("tstCollector: getRawProcessCpuLoad() -> %Rrc\n", rc); return 1; } start = RTTimeMilliTS(); while(RTTimeMilliTS() - start < 5000) ; // Loop for 5 seconds rc = collector->preCollect(hints, 0); if (RT_FAILURE(rc)) { RTPrintf("tstCollector: preCollect() -> %Rrc\n", rc); return 1; } rc = collector->getRawHostCpuLoad(&hostUserStop, &hostKernelStop, &hostIdleStop); if (RT_FAILURE(rc)) { RTPrintf("tstCollector: getRawHostCpuLoad() -> %Rrc\n", rc); return 1; } rc = collector->getRawProcessCpuLoad(RTProcSelf(), &processUserStop, &processKernelStop, &processTotalStop); if (RT_FAILURE(rc)) { RTPrintf("tstCollector: getRawProcessCpuLoad() -> %Rrc\n", rc); return 1; } hostTotal = hostUserStop - hostUserStart + hostKernelStop - hostKernelStart + hostIdleStop - hostIdleStart; RTPrintf("tstCollector: host cpu user = %u.%u %%\n", (unsigned)((hostUserStop - hostUserStart) * 100 / hostTotal), (unsigned)((hostUserStop - hostUserStart) * 10000 / hostTotal % 100)); RTPrintf("tstCollector: host cpu kernel = %u.%u %%\n", (unsigned)((hostKernelStop - hostKernelStart) * 100 / hostTotal), (unsigned)((hostKernelStop - hostKernelStart) * 10000 / hostTotal % 100)); RTPrintf("tstCollector: host cpu idle = %u.%u %%\n", (unsigned)((hostIdleStop - hostIdleStart) * 100 / hostTotal), (unsigned)((hostIdleStop - hostIdleStart) * 10000 / hostTotal % 100)); RTPrintf("tstCollector: process cpu user = %u.%u %%\n", (unsigned)((processUserStop - processUserStart) * 100 / (processTotalStop - processTotalStart)), (unsigned)((processUserStop - processUserStart) * 10000 / (processTotalStop - processTotalStart) % 100)); RTPrintf("tstCollector: process cpu kernel = %u.%u %%\n\n", (unsigned)((processKernelStop - processKernelStart) * 100 / (processTotalStop - processTotalStart)), (unsigned)((processKernelStop - processKernelStart) * 10000 / (processTotalStop - processTotalStart) % 100)); RTPrintf("tstCollector: TESTING - Memory usage\n"); ULONG total, used, available, processUsed; rc = collector->getHostMemoryUsage(&total, &used, &available); if (RT_FAILURE(rc)) { RTPrintf("tstCollector: getHostMemoryUsage() -> %Rrc\n", rc); return 1; } rc = collector->getProcessMemoryUsage(RTProcSelf(), &processUsed); if (RT_FAILURE(rc)) { RTPrintf("tstCollector: getProcessMemoryUsage() -> %Rrc\n", rc); return 1; } RTPrintf("tstCollector: host mem total = %lu kB\n", total); RTPrintf("tstCollector: host mem used = %lu kB\n", used); RTPrintf("tstCollector: host mem available = %lu kB\n", available); RTPrintf("tstCollector: process mem used = %lu kB\n\n", processUsed); #endif #if 1 rc = testNetwork(collector); #endif #if 1 rc = testFsUsage(collector); #endif #if 1 rc = testDisk(collector); #endif #if 1 RTPrintf("tstCollector: TESTING - Performance\n\n"); measurePerformance(collector, argv[0], 100); #endif delete collector; printf ("\ntstCollector FINISHED.\n"); return rc; }
RTDECL(uint64_t) RTTimeSystemMilliTS(void) { return RTTimeMilliTS(); }
/** * Gets the current TMCLOCK_REAL time. * * @returns Real time. * @param pVM Pointer to the VM. */ VMM_INT_DECL(uint64_t) TMRealGet(PVM pVM) { NOREF(pVM); return RTTimeMilliTS(); }
static void tstTraffic(unsigned cThreads, unsigned cSecs) { RTTestSubF(g_hTest, "Traffic - %u threads per direction, %u sec", cThreads, cSecs); /* * Create X worker threads which drives in the south/north direction and Y * worker threads which drives in the west/east direction. Let them drive * in a loop for 15 seconds with slight delays between some of the runs and * then check the numbers. */ /* init */ RTTHREAD ahThreadsX[8]; for (unsigned i = 0; i < RT_ELEMENTS(ahThreadsX); i++) ahThreadsX[i] = NIL_RTTHREAD; AssertRelease(RT_ELEMENTS(ahThreadsX) >= cThreads); RTTHREAD ahThreadsY[8]; for (unsigned i = 0; i < RT_ELEMENTS(ahThreadsY); i++) ahThreadsY[i] = NIL_RTTHREAD; AssertRelease(RT_ELEMENTS(ahThreadsY) >= cThreads); g_cNSCrossings = 0; g_cEWCrossings = 0; g_cSecs = cSecs; g_u64StartMilliTS = RTTimeMilliTS(); /* create */ RTTEST_CHECK_RC_RETV(g_hTest, RTSemXRoadsCreate(&g_hXRoads), VINF_SUCCESS); int rc = VINF_SUCCESS; for (unsigned i = 0; i < cThreads && RT_SUCCESS(rc); i++) { rc = RTThreadCreateF(&ahThreadsX[i], tstTrafficNSThread, (void *)(uintptr_t)i, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "NS-%u", i); RTTEST_CHECK_RC_OK(g_hTest, rc); } for (unsigned i = 0; i < cThreads && RT_SUCCESS(rc); i++) { rc = RTThreadCreateF(&ahThreadsX[i], tstTrafficEWThread, (void *)(uintptr_t)i, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "NS-%u", i); RTTEST_CHECK_RC_OK(g_hTest, rc); } /* wait */ for (unsigned i = 0; i < RT_ELEMENTS(ahThreadsX); i++) if (ahThreadsX[i] != NIL_RTTHREAD) { int rc2 = RTThreadWaitNoResume(ahThreadsX[i], (60 + cSecs) * 1000, NULL); RTTEST_CHECK_RC_OK(g_hTest, rc2); } for (unsigned i = 0; i < RT_ELEMENTS(ahThreadsY); i++) if (ahThreadsY[i] != NIL_RTTHREAD) { int rc2 = RTThreadWaitNoResume(ahThreadsY[i], (60 + cSecs) * 1000, NULL); RTTEST_CHECK_RC_OK(g_hTest, rc2); } RTTEST_CHECK_MSG_RETV(g_hTest, g_cEWCrossings > 10 && g_cNSCrossings, (g_hTest, "cEWCrossings=%u g_cNSCrossings=%u\n", g_cEWCrossings, g_cNSCrossings)); RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "cNSCrossings=%u\n", g_cNSCrossings); RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "cEWCrossings=%u\n", g_cEWCrossings); }
/** * Thread function waiting for credentials to arrive. * * @return IPRT status code. * @param hThreadSelf Thread handle. * @param pvUser Pointer to a PAMVBOXTHREAD structure providing * required data used / set by the thread. */ static DECLCALLBACK(int) pam_vbox_wait_thread(RTTHREAD hThreadSelf, void *pvUser) { RT_NOREF1(hThreadSelf); PPAMVBOXTHREAD pUserData = (PPAMVBOXTHREAD)pvUser; AssertPtr(pUserData); int rc = VINF_SUCCESS; /* Get current time stamp to later calculate rest of timeout left. */ uint64_t u64StartMS = RTTimeMilliTS(); #ifdef VBOX_WITH_GUEST_PROPS uint32_t uClientID = 0; rc = VbglR3GuestPropConnect(&uClientID); if (RT_FAILURE(rc)) { pam_vbox_error(pUserData->hPAM, "pam_vbox_wait_thread: Unable to connect to guest property service, rc=%Rrc\n", rc); } else { pam_vbox_log(pUserData->hPAM, "pam_vbox_wait_thread: clientID=%u\n", uClientID); #endif for (;;) { #ifdef VBOX_WITH_GUEST_PROPS if (uClientID) { rc = pam_vbox_wait_prop(pUserData->hPAM, uClientID, "/VirtualBox/GuestAdd/PAM/CredsWaitAbort", 500 /* Wait 500ms, same as VBoxGINA/VBoxCredProv. */); switch (rc) { case VINF_SUCCESS: /* Somebody (guest/host) wants to abort waiting for credentials. */ break; case VERR_INTERRUPTED: pam_vbox_error(pUserData->hPAM, "pam_vbox_wait_thread: The abort notification request timed out or was interrupted\n"); break; case VERR_TIMEOUT: /* We did not receive an abort message within time. */ break; case VERR_TOO_MUCH_DATA: pam_vbox_error(pUserData->hPAM, "pam_vbox_wait_thread: Temporarily unable to get abort notification\n"); break; default: pam_vbox_error(pUserData->hPAM, "pam_vbox_wait_thread: The abort notification request failed with rc=%Rrc\n", rc); break; } if (RT_SUCCESS(rc)) /* Abort waiting. */ { pam_vbox_log(pUserData->hPAM, "pam_vbox_wait_thread: Got notification to abort waiting\n"); rc = VERR_CANCELLED; break; } } #endif if ( RT_SUCCESS(rc) || rc == VERR_TIMEOUT) { rc = pam_vbox_check_creds(pUserData->hPAM); if (RT_SUCCESS(rc)) { /* Credentials retrieved. */ break; /* Thread no longer is required, bail out. */ } else if (rc == VERR_NOT_FOUND) { /* No credentials found, but try next round (if there's * time left for) ... */ #ifndef VBOX_WITH_GUEST_PROPS RTThreadSleep(500); /* Wait 500 ms. */ #endif } else break; /* Something bad happend ... */ } else break; /* Calculate timeout value left after process has been started. */ uint64_t u64Elapsed = RTTimeMilliTS() - u64StartMS; /* Is it time to bail out? */ if (pUserData->uTimeoutMS < u64Elapsed) { pam_vbox_log(pUserData->hPAM, "pam_vbox_wait_thread: Waiting thread has reached timeout (%dms), exiting ...\n", pUserData->uTimeoutMS); rc = VERR_TIMEOUT; break; } } #ifdef VBOX_WITH_GUEST_PROPS } VbglR3GuestPropDisconnect(uClientID); #endif /* Save result. */ pUserData->rc = rc; /** @todo Use ASMAtomicXXX? */ int rc2 = RTThreadUserSignal(RTThreadSelf()); AssertRC(rc2); pam_vbox_log(pUserData->hPAM, "pam_vbox_wait_thread: Waiting thread returned with rc=%Rrc\n", rc); return rc; }
int main() { /* * Init runtime */ unsigned cErrors = 0; int rc = RTR3InitExeNoArguments(0); if (RT_FAILURE(rc)) return RTMsgInitFailure(rc); /* * Check that the clock is reliable. */ RTPrintf("tstTimer: TESTING - RTTimeNanoTS() for 2sec\n"); uint64_t uTSMillies = RTTimeMilliTS(); uint64_t uTSBegin = RTTimeNanoTS(); uint64_t uTSLast = uTSBegin; uint64_t uTSDiff; uint64_t cIterations = 0; do { uint64_t uTS = RTTimeNanoTS(); if (uTS < uTSLast) { RTPrintf("tstTimer: FAILURE - RTTimeNanoTS() is unreliable. uTS=%RU64 uTSLast=%RU64\n", uTS, uTSLast); cErrors++; } if (++cIterations > (2*1000*1000*1000)) { RTPrintf("tstTimer: FAILURE - RTTimeNanoTS() is unreliable. cIterations=%RU64 uTS=%RU64 uTSBegin=%RU64\n", cIterations, uTS, uTSBegin); return 1; } uTSLast = uTS; uTSDiff = uTSLast - uTSBegin; } while (uTSDiff < (2*1000*1000*1000)); uTSMillies = RTTimeMilliTS() - uTSMillies; if (uTSMillies >= 2500 || uTSMillies <= 1500) { RTPrintf("tstTimer: FAILURE - uTSMillies=%RI64 uTSBegin=%RU64 uTSLast=%RU64 uTSDiff=%RU64\n", uTSMillies, uTSBegin, uTSLast, uTSDiff); cErrors++; } if (!cErrors) RTPrintf("tstTimer: OK - RTTimeNanoTS()\n"); /* * Tests. */ static struct { unsigned uMicroInterval; unsigned uMilliesWait; unsigned cLower; unsigned cUpper; } aTests[] = { { 32000, 2000, 0, 0 }, { 20000, 2000, 0, 0 }, { 10000, 2000, 0, 0 }, { 8000, 2000, 0, 0 }, { 2000, 2000, 0, 0 }, { 1000, 2000, 0, 0 }, { 500, 5000, 0, 0 }, { 200, 5000, 0, 0 }, { 100, 5000, 0, 0 } }; unsigned i = 0; for (i = 0; i < RT_ELEMENTS(aTests); i++) { aTests[i].cLower = (aTests[i].uMilliesWait*1000 - aTests[i].uMilliesWait*100) / aTests[i].uMicroInterval; aTests[i].cUpper = (aTests[i].uMilliesWait*1000 + aTests[i].uMilliesWait*100) / aTests[i].uMicroInterval; gu64Norm = aTests[i].uMicroInterval*1000; RTPrintf("\n" "tstTimer: TESTING - %d us interval, %d ms wait, expects %d-%d ticks.\n", aTests[i].uMicroInterval, aTests[i].uMilliesWait, aTests[i].cLower, aTests[i].cUpper); /* * Start timer which ticks every 10ms. */ gcTicks = 0; PRTTIMER pTimer; gu64Max = 0; gu64Min = UINT64_MAX; gu64Prev = 0; RT_ZERO(cFrequency); #ifdef RT_OS_WINDOWS if (aTests[i].uMicroInterval < 1000) continue; rc = RTTimerCreate(&pTimer, aTests[i].uMicroInterval / 1000, TimerCallback, NULL); #else rc = RTTimerCreateEx(&pTimer, aTests[i].uMicroInterval * (uint64_t)1000, 0, TimerCallback, NULL); #endif if (RT_FAILURE(rc)) { RTPrintf("tstTimer: FAILURE - RTTimerCreateEx(,%u*1M,,,) -> %Rrc\n", aTests[i].uMicroInterval, rc); cErrors++; continue; } /* * Start the timer and active waiting for the requested test period. */ uTSBegin = RTTimeNanoTS(); #ifndef RT_OS_WINDOWS rc = RTTimerStart(pTimer, 0); if (RT_FAILURE(rc)) { RTPrintf("tstTimer: FAILURE - RTTimerStart(,0) -> %Rrc\n", rc); cErrors++; } #endif while (RTTimeNanoTS() - uTSBegin < (uint64_t)aTests[i].uMilliesWait * 1000000) /* nothing */; /* destroy the timer */ uint64_t uTSEnd = RTTimeNanoTS(); uTSDiff = uTSEnd - uTSBegin; rc = RTTimerDestroy(pTimer); if (RT_FAILURE(rc)) { RTPrintf("tstTimer: FAILURE - RTTimerDestroy() -> %d gcTicks=%d\n", rc, gcTicks); cErrors++; } RTPrintf("tstTimer: uTS=%RI64 (%RU64 - %RU64)\n", uTSDiff, uTSBegin, uTSEnd); unsigned cTicks = gcTicks; RTThreadSleep(aTests[i].uMicroInterval/1000 * 3); if (gcTicks != cTicks) { RTPrintf("tstTimer: FAILURE - RTTimerDestroy() didn't really stop the timer! gcTicks=%d cTicks=%d\n", gcTicks, cTicks); cErrors++; continue; } /* * Check the number of ticks. */ if (gcTicks < aTests[i].cLower) { RTPrintf("tstTimer: FAILURE - Too few ticks gcTicks=%d (expected %d-%d)", gcTicks, aTests[i].cUpper, aTests[i].cLower); cErrors++; } else if (gcTicks > aTests[i].cUpper) { RTPrintf("tstTimer: FAILURE - Too many ticks gcTicks=%d (expected %d-%d)", gcTicks, aTests[i].cUpper, aTests[i].cLower); cErrors++; } else RTPrintf("tstTimer: OK - gcTicks=%d", gcTicks); RTPrintf(" min=%RU64 max=%RU64\n", gu64Min, gu64Max); for (int j = 0; j < (int)RT_ELEMENTS(cFrequency); j++) { uint32_t len = cFrequency[j] * 70 / gcTicks; uint32_t deviation = j - RT_ELEMENTS(cFrequency) / 2; uint64_t u64FreqPercent = (uint64_t)cFrequency[j] * 10000 / gcTicks; uint64_t u64FreqPercentFrac = u64FreqPercent % 100; u64FreqPercent = u64FreqPercent / 100; RTPrintf("%+4d%c %6u %3llu.%02llu%% ", deviation, deviation == 0 ? ' ' : '%', cFrequency[j], u64FreqPercent, u64FreqPercentFrac); for (unsigned k = 0; k < len; k++) RTPrintf("*"); RTPrintf("\n"); } } /* * Summary. */ if (!cErrors) RTPrintf("tstTimer: SUCCESS\n"); else RTPrintf("tstTimer: FAILURE %d errors\n", cErrors); return !!cErrors; }
Console::teleporterSrcThreadWrapper(RTTHREAD hThread, void *pvUser) { TeleporterStateSrc *pState = (TeleporterStateSrc *)pvUser; /* * Console::teleporterSrc does the work, we just grab onto the VM handle * and do the cleanups afterwards. */ SafeVMPtr ptrVM(pState->mptrConsole); HRESULT hrc = ptrVM.rc(); if (SUCCEEDED(hrc)) hrc = pState->mptrConsole->teleporterSrc(pState); /* Close the connection ASAP on so that the other side can complete. */ if (pState->mhSocket != NIL_RTSOCKET) { RTTcpClientClose(pState->mhSocket); pState->mhSocket = NIL_RTSOCKET; } /* Aaarg! setMachineState trashes error info on Windows, so we have to complete things here on failure instead of right before cleanup. */ if (FAILED(hrc)) pState->mptrProgress->notifyComplete(hrc); /* We can no longer be canceled (success), or it doesn't matter any longer (failure). */ pState->mptrProgress->setCancelCallback(NULL, NULL); /* * Write lock the console before resetting mptrCancelableProgress and * fixing the state. */ AutoWriteLock autoLock(pState->mptrConsole COMMA_LOCKVAL_SRC_POS); pState->mptrConsole->mptrCancelableProgress.setNull(); VMSTATE const enmVMState = VMR3GetStateU(pState->mpUVM); MachineState_T const enmMachineState = pState->mptrConsole->mMachineState; if (SUCCEEDED(hrc)) { /* * Automatically shut down the VM on success. * * Note! We have to release the VM caller object or we'll deadlock in * powerDown. */ AssertLogRelMsg(enmVMState == VMSTATE_SUSPENDED, ("%s\n", VMR3GetStateName(enmVMState))); AssertLogRelMsg(enmMachineState == MachineState_TeleportingPausedVM, ("%s\n", Global::stringifyMachineState(enmMachineState))); ptrVM.release(); pState->mptrConsole->mVMIsAlreadyPoweringOff = true; /* (Make sure we stick in the TeleportingPausedVM state.) */ hrc = pState->mptrConsole->powerDown(); pState->mptrConsole->mVMIsAlreadyPoweringOff = false; pState->mptrProgress->notifyComplete(hrc); } else { /* * Work the state machinery on failure. * * If the state is no longer 'Teleporting*', some other operation has * canceled us and there is nothing we need to do here. In all other * cases, we've failed one way or another. */ if ( enmMachineState == MachineState_Teleporting || enmMachineState == MachineState_TeleportingPausedVM ) { if (pState->mfUnlockedMedia) { ErrorInfoKeeper Oak; HRESULT hrc2 = pState->mptrConsole->mControl->LockMedia(); if (FAILED(hrc2)) { uint64_t StartMS = RTTimeMilliTS(); do { RTThreadSleep(2); hrc2 = pState->mptrConsole->mControl->LockMedia(); } while ( FAILED(hrc2) && RTTimeMilliTS() - StartMS < 2000); } if (SUCCEEDED(hrc2)) pState->mfUnlockedMedia = true; else LogRel(("FATAL ERROR: Failed to re-take the media locks. hrc2=%Rhrc\n", hrc2)); } switch (enmVMState) { case VMSTATE_RUNNING: case VMSTATE_RUNNING_LS: case VMSTATE_DEBUGGING: case VMSTATE_DEBUGGING_LS: case VMSTATE_POWERING_OFF: case VMSTATE_POWERING_OFF_LS: case VMSTATE_RESETTING: case VMSTATE_RESETTING_LS: Assert(!pState->mfSuspendedByUs); Assert(!pState->mfUnlockedMedia); pState->mptrConsole->setMachineState(MachineState_Running); break; case VMSTATE_GURU_MEDITATION: case VMSTATE_GURU_MEDITATION_LS: pState->mptrConsole->setMachineState(MachineState_Stuck); break; case VMSTATE_FATAL_ERROR: case VMSTATE_FATAL_ERROR_LS: pState->mptrConsole->setMachineState(MachineState_Paused); break; default: AssertMsgFailed(("%s\n", VMR3GetStateName(enmVMState))); case VMSTATE_SUSPENDED: case VMSTATE_SUSPENDED_LS: case VMSTATE_SUSPENDING: case VMSTATE_SUSPENDING_LS: case VMSTATE_SUSPENDING_EXT_LS: if (!pState->mfUnlockedMedia) { pState->mptrConsole->setMachineState(MachineState_Paused); if (pState->mfSuspendedByUs) { autoLock.release(); int rc = VMR3Resume(VMR3GetVM(pState->mpUVM)); AssertLogRelMsgRC(rc, ("VMR3Resume -> %Rrc\n", rc)); autoLock.acquire(); } } else { /* Faking a guru meditation is the best I can think of doing here... */ pState->mptrConsole->setMachineState(MachineState_Stuck); } break; } } } autoLock.release(); /* * Cleanup. */ Assert(pState->mhSocket == NIL_RTSOCKET); delete pState; return VINF_SUCCESS; /* ignored */ }
/* The function checks the URB queue for completed URBs. Also if the client * has requested URB polling, the function will send URB poll requests. */ static DECLCALLBACK(int) iface_ReapURB(PREMOTEUSBDEVICE pDevice, uint32_t u32Millies, void **ppvURB, uint32_t *pu32Len, uint32_t *pu32Err) { int rc = VINF_SUCCESS; LogFlow(("RemoteUSBBackend::iface_ReapURB %d ms\n", u32Millies)); if (pDevice->fFailed) { return VERR_VUSB_DEVICE_NOT_ATTACHED; } RemoteUSBBackend *pThis = pDevice->pOwner; /* Wait for transaction completion. */ uint64_t u64StartTime = RTTimeMilliTS(); if (pThis->pollingEnabledURB()) { VRDE_USB_REQ_REAP_URB_PARM parm; parm.code = VRDE_USB_REQ_REAP_URB; pThis->VRDPServer()->SendUSBRequest(pDevice->u32ClientId, &parm, sizeof(parm)); } REMOTEUSBQURB *qurb = NULL; for (;;) { uint32_t u32ClientId; if (ASMAtomicXchgBool(&pDevice->fWokenUp, false)) break; /* Scan queued URBs, look for completed. */ requestDevice(pDevice); u32ClientId = pDevice->u32ClientId; qurb = pDevice->pHeadQURBs; while (qurb) { if (qurb->fCompleted) { /* Remove this completed urb from the queue. */ if (qurb->prev) { qurb->prev->next = qurb->next; } else { pDevice->pHeadQURBs = qurb->next; } if (qurb->next) { qurb->next->prev = qurb->prev; } else { pDevice->pTailQURBs = qurb->prev; } qurb->next = NULL; qurb->prev = NULL; break; } qurb = qurb->next; } releaseDevice(pDevice); if ( qurb || !pDevice->pHeadQURBs || u32Millies == 0 || pDevice->fFailed || (RTTimeMilliTS() - u64StartTime >= (uint64_t)u32Millies)) { /* Got an URB or do not have to wait for an URB. */ break; } LogFlow(("RemoteUSBBackend::iface_ReapURB iteration.\n")); RTThreadSleep(10); if (pThis->pollingEnabledURB()) { VRDE_USB_REQ_REAP_URB_PARM parm; parm.code = VRDE_USB_REQ_REAP_URB; pThis->VRDPServer()->SendUSBRequest(u32ClientId, &parm, sizeof(parm)); } } LogFlow(("RemoteUSBBackend::iface_ReapURB completed in %lld ms, qurb = %p\n", RTTimeMilliTS () - u64StartTime, qurb)); if (!qurb) { *ppvURB = NULL; *pu32Len = 0; *pu32Err = VUSBSTATUS_OK; } else { *ppvURB = qurb->pvURB; *pu32Len = qurb->u32Len; *pu32Err = qurb->u32Err; #ifdef LOG_ENABLED Log(("URB len = %d, data = %p\n", qurb->u32Len, qurb->pvURB)); if (qurb->u32Len) { Log(("Received URB content:\n%.*Rhxd\n", qurb->u32Len, qurb->pvData)); } #endif qurbFree(qurb); } return rc; }
int USBProxyBackendUsbIp::wait(RTMSINTERVAL aMillies) { int rc = VINF_SUCCESS; bool fDeviceListChangedOrWokenUp = false; /* Try to reconnect once when we enter if we lost the connection earlier. */ if (m->hSocket == NIL_RTSOCKET) rc = reconnect(); /* Query a new device list upon entering. */ if (m->enmRecvState == kUsbIpRecvState_None) { rc = startListExportedDevicesReq(); if (RT_FAILURE(rc)) disconnect(); } /* * Because the USB/IP protocol doesn't specify a way to get notified about * new or removed exported devices we have to poll the host periodically for * a new device list and compare it with the previous one notifying the proxy * service about changes. */ while ( !fDeviceListChangedOrWokenUp && (aMillies == RT_INDEFINITE_WAIT || aMillies > 0) && RT_SUCCESS(rc)) { RTMSINTERVAL msWait = aMillies; uint64_t msPollStart = RTTimeMilliTS(); uint32_t uIdReady = 0; uint32_t fEventsRecv = 0; /* Limit the waiting time to 1sec so we can either reconnect or get a new device list. */ if (m->hSocket == NIL_RTSOCKET || m->enmRecvState == kUsbIpRecvState_None) msWait = RT_MIN(1000, aMillies); rc = RTPoll(m->hPollSet, msWait, &fEventsRecv, &uIdReady); if (RT_SUCCESS(rc)) { if (uIdReady == USBIP_POLL_ID_PIPE) { /* Drain the wakeup pipe. */ char bRead = 0; size_t cbRead = 0; rc = RTPipeRead(m->hWakeupPipeR, &bRead, 1, &cbRead); Assert(RT_SUCCESS(rc) && cbRead == 1); fDeviceListChangedOrWokenUp = true; } else if (uIdReady == USBIP_POLL_ID_SOCKET) { if (fEventsRecv & RTPOLL_EVT_ERROR) rc = VERR_NET_SHUTDOWN; else rc = receiveData(); if (RT_SUCCESS(rc)) { /* * If we are in the none state again we received the previous request * and have a new device list to compare the old against. */ if (m->enmRecvState == kUsbIpRecvState_None) { if (hasDevListChanged(m->pHead)) fDeviceListChangedOrWokenUp = true; /* Update to the new list in any case now that we have it anyway. */ RTSemFastMutexRequest(m->hMtxDevices); freeDeviceList(m->pUsbDevicesCur); m->cUsbDevicesCur = m->cDevicesCur; m->pUsbDevicesCur = m->pHead; RTSemFastMutexRelease(m->hMtxDevices); m->pHead = NULL; resetRecvState(); } } else if (rc == VERR_NET_SHUTDOWN || rc == VERR_BROKEN_PIPE) { LogRelMax(10, ("USB/IP: Lost connection to host \"%s\", trying to reconnect...\n", m->pszHost)); disconnect(); rc = VINF_SUCCESS; } } else { AssertMsgFailed(("Invalid poll ID returned\n")); rc = VERR_INVALID_STATE; } aMillies -= (RTTimeMilliTS() - msPollStart); } else if (rc == VERR_TIMEOUT) { aMillies -= msWait; if (aMillies) { /* Try to reconnect and start a new request if we lost the connection before. */ if (m->hSocket == NIL_RTSOCKET) rc = reconnect(); if (RT_SUCCESS(rc)) rc = startListExportedDevicesReq(); } } } return rc; }
/** * Get an entry from an mbox. */ u32_t sys_arch_mbox_fetch(sys_mbox_t mbox, void **msg, u32_t timeout) { int rc; RTMSINTERVAL cMillies; uint64_t tsStart, tsEnd; Assert(mbox != NULL); tsStart = RTTimeMilliTS(); if (timeout == 0) cMillies = RT_INDEFINITE_WAIT; else cMillies = timeout; rc = LWIPMutexRequest(mbox->mutex, cMillies); if (rc == VERR_TIMEOUT) return SYS_ARCH_TIMEOUT; AssertRC(rc); while (mbox->head == mbox->tail) { /* mbox is empty, have to wait until a slot is filled. */ rc = LWIPMutexRelease(mbox->mutex); AssertRC(rc); if (timeout != 0) { tsEnd = RTTimeMilliTS(); if (tsEnd - tsStart >= cMillies) return SYS_ARCH_TIMEOUT; cMillies -= tsEnd - tsStart; } rc = RTSemEventMultiWait(mbox->nonempty, cMillies); if (rc == VERR_TIMEOUT) return SYS_ARCH_TIMEOUT; AssertRC(rc); if (timeout != 0) { tsEnd = RTTimeMilliTS(); if (tsEnd - tsStart >= cMillies) return SYS_ARCH_TIMEOUT; cMillies -= tsEnd - tsStart; } rc = LWIPMutexRequest(mbox->mutex, cMillies); if (rc == VERR_TIMEOUT) return SYS_ARCH_TIMEOUT; AssertRC(rc); } if ((mbox->head + 1) % MBOX_ENTRIES_MAX == mbox->tail) { rc = RTSemEventMultiSignal(mbox->nonfull); AssertRC(rc); } if (msg != NULL) *msg = mbox->apvEntries[mbox->tail]; mbox->tail++; mbox->tail %= MBOX_ENTRIES_MAX; rc = RTSemEventMultiSignal(mbox->nonfull); if (mbox->head == mbox->tail) { rc = RTSemEventMultiReset(mbox->nonempty); AssertRC(rc); } rc = LWIPMutexRelease(mbox->mutex); AssertRC(rc); tsEnd = RTTimeMilliTS(); return tsEnd - tsStart; }
RTDECL(int) RTPipeSelectOne(RTPIPE hPipe, RTMSINTERVAL cMillies) { RTPIPEINTERNAL *pThis = hPipe; AssertPtrReturn(pThis, VERR_INVALID_HANDLE); AssertReturn(pThis->u32Magic == RTPIPE_MAGIC, VERR_INVALID_HANDLE); uint64_t const StartMsTS = RTTimeMilliTS(); int rc = RTCritSectEnter(&pThis->CritSect); if (RT_FAILURE(rc)) return rc; for (unsigned iLoop = 0;; iLoop++) { HANDLE hWait = INVALID_HANDLE_VALUE; if (pThis->fRead) { if (pThis->fIOPending) hWait = pThis->Overlapped.hEvent; else { /* Peek at the pipe buffer and see how many bytes it contains. */ DWORD cbAvailable; if ( PeekNamedPipe(pThis->hPipe, NULL, 0, NULL, &cbAvailable, NULL) && cbAvailable > 0) { rc = VINF_SUCCESS; break; } /* Start a zero byte read operation that we can wait on. */ if (cMillies == 0) { rc = VERR_TIMEOUT; break; } AssertBreakStmt(pThis->cUsers == 0, rc = VERR_INTERNAL_ERROR_5); rc = ResetEvent(pThis->Overlapped.hEvent); Assert(rc == TRUE); DWORD cbRead = 0; if (ReadFile(pThis->hPipe, pThis->abBuf, 0, &cbRead, &pThis->Overlapped)) { rc = VINF_SUCCESS; if (iLoop > 10) RTThreadYield(); } else if (GetLastError() == ERROR_IO_PENDING) { pThis->cUsers++; pThis->fIOPending = true; pThis->fZeroByteRead = true; hWait = pThis->Overlapped.hEvent; } else rc = RTErrConvertFromWin32(GetLastError()); } } else { if (pThis->fIOPending) { rc = rtPipeWriteCheckCompletion(pThis); if (RT_FAILURE(rc)) break; } if (pThis->fIOPending) hWait = pThis->Overlapped.hEvent; else { FILE_PIPE_LOCAL_INFORMATION Info; if (rtPipeQueryInfo(pThis, &Info)) { /* Check for broken pipe. */ if (Info.NamedPipeState == FILE_PIPE_CLOSING_STATE) { rc = VERR_BROKEN_PIPE; break; } /* Check for available write buffer space. */ else if (Info.WriteQuotaAvailable > 0) { pThis->fPromisedWritable = false; rc = VINF_SUCCESS; break; } /* delayed buffer alloc or timeout: phony promise later: See if we still can associate a semaphore with the pipe, like on OS/2. */ else if ( Info.OutboundQuota == 0 || cMillies) { pThis->fPromisedWritable = true; rc = VINF_SUCCESS; break; } } else { pThis->fPromisedWritable = true; rc = VINF_SUCCESS; break; } } } if (RT_FAILURE(rc)) break; /* * Check for timeout. */ DWORD cMsMaxWait = INFINITE; if ( cMillies != RT_INDEFINITE_WAIT && ( hWait != INVALID_HANDLE_VALUE || iLoop > 10) ) { uint64_t cElapsed = RTTimeMilliTS() - StartMsTS; if (cElapsed >= cMillies) { rc = VERR_TIMEOUT; break; } cMsMaxWait = cMillies - (uint32_t)cElapsed; } /* * Wait. */ if (hWait != INVALID_HANDLE_VALUE) { RTCritSectLeave(&pThis->CritSect); DWORD dwRc = WaitForSingleObject(hWait, cMsMaxWait); if (dwRc == WAIT_OBJECT_0) rc = VINF_SUCCESS; else if (dwRc == WAIT_TIMEOUT) rc = VERR_TIMEOUT; else if (dwRc == WAIT_ABANDONED) rc = VERR_INVALID_HANDLE; else rc = RTErrConvertFromWin32(GetLastError()); if ( RT_FAILURE(rc) && pThis->u32Magic != RTPIPE_MAGIC) return rc; RTCritSectEnter(&pThis->CritSect); if (pThis->fZeroByteRead) { pThis->cUsers--; pThis->fIOPending = false; if (rc != VINF_SUCCESS) CancelIo(pThis->hPipe); DWORD cbRead = 0; GetOverlappedResult(pThis->hPipe, &pThis->Overlapped, &cbRead, TRUE /*fWait*/); } if (RT_FAILURE(rc)) break; } } if (rc == VERR_BROKEN_PIPE) pThis->fBrokenPipe = true; RTCritSectLeave(&pThis->CritSect); return rc; }