/** * Try to get an entry from an mbox. */ u32_t sys_arch_mbox_tryfetch(sys_mbox_t *pvMbox, void **msg) { int rc; struct sys_mbox *mbox = NULL; if (!pvMbox || !*pvMbox) return SYS_MBOX_EMPTY; mbox = (struct sys_mbox*)*pvMbox; rc = LWIPMutexRequest((mbox)->mutex); AssertRC(rc); if ((mbox)->head == (mbox)->tail) { /* (mbox) is empty, don't wait */ rc = LWIPMutexRelease((mbox)->mutex); AssertRC(rc); return SYS_MBOX_EMPTY; } 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); return 0; }
/** * Try to place an entry in an mbox if there is a free slot. */ err_t sys_mbox_trypost(sys_mbox_t *pvMbox, void *msg) { int rc; struct sys_mbox *mbox = NULL; AssertReturn(pvMbox && *pvMbox, ERR_ARG); mbox = (struct sys_mbox*)*pvMbox; rc = LWIPMutexRequest((mbox)->mutex); AssertRC(rc); if (((mbox)->head + 1) % MBOX_ENTRIES_MAX == (mbox)->tail) { /* (mbox) is full */ rc = LWIPMutexRelease((mbox)->mutex); AssertRC(rc); return ERR_MEM; } if ((mbox)->head == (mbox)->tail) { rc = RTSemEventMultiSignal((mbox)->nonempty); AssertRC(rc); } (mbox)->apvEntries[(mbox)->head] = msg; (mbox)->head++; (mbox)->head %= MBOX_ENTRIES_MAX; if (((mbox)->head + 1) % MBOX_ENTRIES_MAX == (mbox)->tail) { rc = RTSemEventMultiReset((mbox)->nonfull); AssertRC(rc); } rc = LWIPMutexRelease((mbox)->mutex); AssertRC(rc); return ERR_OK; }
SUPDECL(int) SUPSemEventMultiSignal(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti) { int rc; uint32_t h32; PSUPDRVOBJ pObj; /* * Input validation. */ AssertReturn(SUP_IS_SESSION_VALID(pSession), VERR_INVALID_PARAMETER); h32 = (uint32_t)(uintptr_t)hEventMulti; if (h32 != (uintptr_t)hEventMulti) return VERR_INVALID_HANDLE; pObj = (PSUPDRVOBJ)RTHandleTableLookupWithCtx(pSession->hHandleTable, h32, SUPDRV_HANDLE_CTX_EVENT_MULTI); if (!pObj) return VERR_INVALID_HANDLE; /* * Do the job. */ rc = RTSemEventMultiSignal((RTSEMEVENTMULTI)pObj->pvUser1); SUPR0ObjRelease(pObj, pSession); return rc; }
/** * Signals that the current operation is successfully completed and advances to * the next operation. The operation percentage is reset to 0. * * @param aOperationDescription Description of the next operation. * * @note The current operation must not be the last one. */ HRESULT Progress::setNextOperation(const com::Utf8Str &aNextOperationDescription, ULONG aNextOperationsWeight) { AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); if (mCanceled) return E_FAIL; AssertReturn(!mCompleted, E_FAIL); AssertReturn(m_ulCurrentOperation + 1 < m_cOperations, E_FAIL); ++m_ulCurrentOperation; m_ulOperationsCompletedWeight += m_ulCurrentOperationWeight; m_operationDescription = aNextOperationDescription; m_ulCurrentOperationWeight = aNextOperationsWeight; m_ulOperationPercent = 0; Log(("Progress::setNextOperation(%s): aNextOperationsWeight = %d; m_ulCurrentOperation is now %d, m_ulOperationsCompletedWeight is now %d\n", m_operationDescription.c_str(), aNextOperationsWeight, m_ulCurrentOperation, m_ulOperationsCompletedWeight)); /* wake up all waiting threads */ if (mWaitersCount > 0) RTSemEventMultiSignal(mCompletedSem); return S_OK; }
static void test1(void) { RTTestISub("Three threads"); /* * Create the threads and let them block on the event multi semaphore. */ RTSEMEVENTMULTI hSem; RTTESTI_CHECK_RC_RETV(RTSemEventMultiCreate(&hSem), VINF_SUCCESS); RTTHREAD hThread2; RTTESTI_CHECK_RC_RETV(RTThreadCreate(&hThread2, test1Thread2, &hSem, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "test2"), VINF_SUCCESS); RTThreadSleep(100); RTTHREAD hThread1; RTTESTI_CHECK_RC_RETV(RTThreadCreate(&hThread1, test1Thread1, &hSem, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "test1"), VINF_SUCCESS); /* Force first thread (which has a timeout of 1 second) to timeout in the * first wait, and the second wait will succeed. */ RTTESTI_CHECK_RC(RTThreadSleep(1500), VINF_SUCCESS); RTTESTI_CHECK_RC(RTSemEventMultiSignal(hSem), VINF_SUCCESS); RTTESTI_CHECK_RC(RTThreadWait(hThread1, 5000, NULL), VINF_SUCCESS); RTTESTI_CHECK_RC(RTThreadWait(hThread2, 5000, NULL), VINF_SUCCESS); RTTESTI_CHECK_RC(RTSemEventMultiDestroy(hSem), VINF_SUCCESS); }
/** * Signals that the current operation is successfully completed and advances to * the next operation. The operation percentage is reset to 0. * * @param aOperationDescription Description of the next operation. * * @note The current operation must not be the last one. */ STDMETHODIMP Progress::SetNextOperation(IN_BSTR bstrNextOperationDescription, ULONG ulNextOperationsWeight) { AssertReturn(bstrNextOperationDescription, E_INVALIDARG); AutoCaller autoCaller(this); AssertComRCReturnRC(autoCaller.rc()); AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); if (mCanceled) return E_FAIL; AssertReturn(!mCompleted, E_FAIL); AssertReturn(m_ulCurrentOperation + 1 < m_cOperations, E_FAIL); ++m_ulCurrentOperation; m_ulOperationsCompletedWeight += m_ulCurrentOperationWeight; m_bstrOperationDescription = bstrNextOperationDescription; m_ulCurrentOperationWeight = ulNextOperationsWeight; m_ulOperationPercent = 0; Log(("Progress::setNextOperation(%ls): ulNextOperationsWeight = %d; m_ulCurrentOperation is now %d, m_ulOperationsCompletedWeight is now %d\n", m_bstrOperationDescription.raw(), ulNextOperationsWeight, m_ulCurrentOperation, m_ulOperationsCompletedWeight)); /* wake up all waiting threads */ if (mWaitersCount > 0) RTSemEventMultiSignal(mCompletedSem); return S_OK; }
/** * Terminates the thread. * Called by the thread wrapper function when the thread terminates. * * @param pThread The thread structure. * @param rc The thread result code. */ DECLHIDDEN(void) rtThreadTerminate(PRTTHREADINT pThread, int rc) { Assert(pThread->cRefs >= 1); #ifdef IPRT_WITH_GENERIC_TLS /* * Destroy TLS entries. */ rtThreadTlsDestruction(pThread); #endif /* IPRT_WITH_GENERIC_TLS */ /* * Set the rc, mark it terminated and signal anyone waiting. */ pThread->rc = rc; rtThreadSetState(pThread, RTTHREADSTATE_TERMINATED); ASMAtomicOrU32(&pThread->fIntFlags, RTTHREADINT_FLAGS_TERMINATED); if (pThread->EventTerminated != NIL_RTSEMEVENTMULTI) RTSemEventMultiSignal(pThread->EventTerminated); /* * Remove the thread from the tree so that there will be no * key clashes in the AVL tree and release our reference to ourself. */ rtThreadRemove(pThread); rtThreadRelease(pThread); }
/** * Does the wakeup call. * * @returns VBox status code. Already asserted on failure. * @param pThread The PDM thread. */ static DECLCALLBACK(int) pdmR3ThreadWakeUp(PPDMTHREAD pThread) { RTSemEventMultiSignal(pThread->Internal.s.SleepEvent); int rc; switch (pThread->Internal.s.enmType) { case PDMTHREADTYPE_DEVICE: rc = pThread->u.Dev.pfnWakeUp(pThread->u.Dev.pDevIns, pThread); break; case PDMTHREADTYPE_USB: rc = pThread->u.Usb.pfnWakeUp(pThread->u.Usb.pUsbIns, pThread); break; case PDMTHREADTYPE_DRIVER: rc = pThread->u.Drv.pfnWakeUp(pThread->u.Drv.pDrvIns, pThread); break; case PDMTHREADTYPE_INTERNAL: rc = pThread->u.Int.pfnWakeUp(pThread->Internal.s.pVM, pThread); break; case PDMTHREADTYPE_EXTERNAL: rc = pThread->u.Ext.pfnWakeUp(pThread); break; default: AssertMsgFailed(("%d\n", pThread->Internal.s.enmType)); rc = VERR_PDM_THREAD_IPE_1; break; } AssertRC(rc); return rc; }
/** * Place an entry in an mbox. */ void sys_mbox_post(sys_mbox_t mbox, void *msg) { int rc; Assert(mbox != NULL); rc = LWIPMutexRequest(mbox->mutex, RT_INDEFINITE_WAIT); AssertRC(rc); while ((mbox->head + 1) % MBOX_ENTRIES_MAX == mbox->tail) { /* mbox is full, have to wait until a slot becomes available. */ rc = LWIPMutexRelease(mbox->mutex); AssertRC(rc); rc = RTSemEventMultiWait(mbox->nonfull, RT_INDEFINITE_WAIT); AssertRC(rc); rc = LWIPMutexRequest(mbox->mutex, RT_INDEFINITE_WAIT); AssertRC(rc); } if (mbox->head == mbox->tail) { rc = RTSemEventMultiSignal(mbox->nonempty); AssertRC(rc); } mbox->apvEntries[mbox->head] = msg; mbox->head++; mbox->head %= MBOX_ENTRIES_MAX; if ((mbox->head + 1) % MBOX_ENTRIES_MAX == mbox->tail) { rc = RTSemEventMultiReset(mbox->nonfull); AssertRC(rc); } rc = LWIPMutexRelease(mbox->mutex); AssertRC(rc); }
/** * Uninitializes the instance and sets the ready flag to FALSE. * * Called either from FinalRelease() or by the parent when it gets destroyed. */ void Progress::uninit() { LogFlowThisFunc(("\n")); /* Enclose the state transition Ready->InUninit->NotReady */ AutoUninitSpan autoUninitSpan(this); if (autoUninitSpan.uninitDone()) return; /* wake up all threads still waiting on occasion */ if (mWaitersCount > 0) { LogFlow(("WARNING: There are still %d threads waiting for '%s' completion!\n", mWaitersCount, mDescription.c_str())); RTSemEventMultiSignal(mCompletedSem); } RTSemEventMultiDestroy(mCompletedSem); /* release initiator (effective only if mInitiator has been assigned in * * init()) */ unconst(mInitiator).setNull(); #if !defined(VBOX_COM_INPROC) if (mParent) { /* remove the added progress on failure to complete the initialization */ if (autoUninitSpan.initFailed() && mId.isValid() && !mId.isZero()) mParent->i_removeProgress(mId.ref()); unconst(mParent) = NULL; } #endif }
/** * Time constrained test with and unlimited N threads. */ static void tst3(uint32_t cThreads, uint32_t cbObject, int iMethod, uint32_t cSecs) { RTTestISubF("Benchmark - %u threads, %u bytes, %u secs, %s", cThreads, cbObject, cSecs, iMethod == 0 ? "RTMemCache" : "RTMemAlloc"); /* * Create a cache with unlimited space, a start semaphore and line up * the threads. */ RTTESTI_CHECK_RC_RETV(RTMemCacheCreate(&g_hMemCache, cbObject, 0 /*cbAlignment*/, UINT32_MAX, NULL, NULL, NULL, 0 /*fFlags*/), VINF_SUCCESS); RTSEMEVENTMULTI hEvt; RTTESTI_CHECK_RC_OK_RETV(RTSemEventMultiCreate(&hEvt)); TST3THREAD aThreads[64]; RTTESTI_CHECK_RETV(cThreads < RT_ELEMENTS(aThreads)); ASMAtomicWriteBool(&g_fTst3Stop, false); for (uint32_t i = 0; i < cThreads; i++) { aThreads[i].hThread = NIL_RTTHREAD; aThreads[i].cIterations = 0; aThreads[i].fUseCache = iMethod == 0; aThreads[i].cbObject = cbObject; aThreads[i].hEvt = hEvt; RTTESTI_CHECK_RC_OK_RETV(RTThreadCreateF(&aThreads[i].hThread, tst3Thread, &aThreads[i], 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "tst3-%u", i)); } /* * Start the race. */ RTTimeNanoTS(); /* warmup */ uint64_t uStartTS = RTTimeNanoTS(); RTTESTI_CHECK_RC_OK_RETV(RTSemEventMultiSignal(hEvt)); RTThreadSleep(cSecs * 1000); ASMAtomicWriteBool(&g_fTst3Stop, true); for (uint32_t i = 0; i < cThreads; i++) RTTESTI_CHECK_RC_OK_RETV(RTThreadWait(aThreads[i].hThread, 60*1000, NULL)); uint64_t cElapsedNS = RTTimeNanoTS() - uStartTS; /* * Sum up the counts. */ uint64_t cIterations = 0; for (uint32_t i = 0; i < cThreads; i++) cIterations += aThreads[i].cIterations; RTTestIPrintf(RTTESTLVL_ALWAYS, "%'8u iterations per second, %'llu ns on avg\n", (unsigned)((long double)cIterations * 1000000000.0 / cElapsedNS), cElapsedNS / cIterations); /* clean up */ RTTESTI_CHECK_RC(RTMemCacheDestroy(g_hMemCache), VINF_SUCCESS); RTTESTI_CHECK_RC_OK(RTSemEventMultiDestroy(hEvt)); }
/** * Signals the event so that a re-enumeration of VM-specific * information (like logged in users) can happen. * * @return IPRT status code. */ int VBoxServiceVMInfoSignal(void) { /* Trigger a re-enumeration of all logged-in users by unblocking * the multi event semaphore of the VMInfo thread. */ if (g_hVMInfoEvent) return RTSemEventMultiSignal(g_hVMInfoEvent); return VINF_SUCCESS; }
/** @copydoc VBOXSERVICE::pfnStop */ static DECLCALLBACK(void) VBoxServiceAutoMountStop(void) { /* * We need this check because at the moment our auto-mount * thread really is a one-timer which destroys the event itself * after running. */ if (g_AutoMountEvent != NIL_RTSEMEVENTMULTI) RTSemEventMultiSignal(g_AutoMountEvent); }
static void testBasics(void) { RTTestISub("Basics"); RTSEMEVENTMULTI hSem; RTTESTI_CHECK_RC_RETV(RTSemEventMultiCreate(&hSem), VINF_SUCCESS); /* The semaphore is created in a reset state, calling reset explicitly shouldn't make any difference. */ testBasicsWaitTimeout(hSem, 0); RTTESTI_CHECK_RC_RETV(RTSemEventMultiReset(hSem), VINF_SUCCESS); testBasicsWaitTimeout(hSem, 1); if (RTTestIErrorCount()) return; /* When signalling the semaphore all successive wait calls shall succeed, signalling it again should make no difference. */ RTTESTI_CHECK_RC_RETV(RTSemEventMultiSignal(hSem), VINF_SUCCESS); testBasicsWaitSuccess(hSem, 2); if (RTTestIErrorCount()) return; /* After resetting it we should time out again. */ RTTESTI_CHECK_RC_RETV(RTSemEventMultiReset(hSem), VINF_SUCCESS); testBasicsWaitTimeout(hSem, 3); if (RTTestIErrorCount()) return; /* The number of resets or signal calls shouldn't matter. */ RTTESTI_CHECK_RC_RETV(RTSemEventMultiReset(hSem), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTSemEventMultiReset(hSem), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTSemEventMultiReset(hSem), VINF_SUCCESS); testBasicsWaitTimeout(hSem, 4); RTTESTI_CHECK_RC_RETV(RTSemEventMultiSignal(hSem), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTSemEventMultiSignal(hSem), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTSemEventMultiSignal(hSem), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTSemEventMultiSignal(hSem), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTSemEventMultiSignal(hSem), VINF_SUCCESS); testBasicsWaitSuccess(hSem, 5); RTTESTI_CHECK_RC_RETV(RTSemEventMultiReset(hSem), VINF_SUCCESS); testBasicsWaitTimeout(hSem, 6); /* Destroy it. */ RTTESTI_CHECK_RC_RETV(RTSemEventMultiDestroy(hSem), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTSemEventMultiDestroy(NIL_RTSEMEVENTMULTI), VINF_SUCCESS); /* Whether it is reset (above), signalled or not used shouldn't matter. */ RTTESTI_CHECK_RC_RETV(RTSemEventMultiCreate(&hSem), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTSemEventMultiSignal(hSem), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTSemEventMultiDestroy(hSem), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTSemEventMultiCreate(&hSem), VINF_SUCCESS); RTTESTI_CHECK_RC_RETV(RTSemEventMultiDestroy(hSem), VINF_SUCCESS); RTTestISubDone(); }
/** * Signal the user event. * * @returns iprt status code. */ RTDECL(int) RTThreadUserSignal(RTTHREAD Thread) { int rc; PRTTHREADINT pThread = rtThreadGet(Thread); if (pThread) { rc = RTSemEventMultiSignal(pThread->EventUser); rtThreadRelease(pThread); } else rc = VERR_INVALID_HANDLE; return rc; }
/** * @interface_method_impl{PDMDEVREG,pfnDestruct} */ static DECLCALLBACK(int) gimdevR3Destruct(PPDMDEVINS pDevIns) { PGIMDEV pThis = PDMINS_2_DATA(pDevIns, PGIMDEV); PVM pVM = PDMDevHlpGetVM(pDevIns); uint32_t cRegions = 0; PGIMMMIO2REGION pCur = GIMR3GetMmio2Regions(pVM, &cRegions); for (uint32_t i = 0; i < cRegions; i++, pCur++) { int rc = PDMDevHlpMMIOExDeregister(pDevIns, NULL, pCur->iRegion); if (RT_FAILURE(rc)) return rc; } /* * Signal and wait for the debug thread to terminate. */ if (pThis->hDbgRecvThread != NIL_RTTHREAD) { pThis->fDbgRecvThreadShutdown = true; if (pThis->Dbg.hDbgRecvThreadSem != NIL_RTSEMEVENT) RTSemEventMultiSignal(pThis->Dbg.hDbgRecvThreadSem); int rc = RTThreadWait(pThis->hDbgRecvThread, 20000, NULL /*prc*/); if (RT_SUCCESS(rc)) pThis->hDbgRecvThread = NIL_RTTHREAD; else { LogRel(("GIMDev: Debug thread did not terminate, rc=%Rrc!\n", rc)); return VERR_RESOURCE_BUSY; } } /* * Now clean up the semaphore & buffer now that the thread is gone. */ if (pThis->Dbg.hDbgRecvThreadSem != NIL_RTSEMEVENT) { RTSemEventMultiDestroy(pThis->Dbg.hDbgRecvThreadSem); pThis->Dbg.hDbgRecvThreadSem = NIL_RTSEMEVENTMULTI; } if (pThis->Dbg.pvDbgRecvBuf) { RTMemFree(pThis->Dbg.pvDbgRecvBuf); pThis->Dbg.pvDbgRecvBuf = NULL; } return VINF_SUCCESS; }
/** * Marks the operation as complete and attaches full error info. * * See VirtualBoxBase::setError(HRESULT, const GUID &, const wchar_t * *, const char *, ...) for more info. * * @param aResultCode Operation result (error) code, must not be S_OK. * @param aIID IID of the interface that defines the error. * @param aComponent Name of the component that generates the error. * @param aText Error message (must not be null), an RTStrPrintf-like * format string in UTF-8 encoding. * @param va List of arguments for the format string. */ HRESULT Progress::i_notifyCompleteV(HRESULT aResultCode, const GUID &aIID, const char *pcszComponent, const char *aText, va_list va) { Utf8Str text(aText, va); AutoCaller autoCaller(this); AssertComRCReturnRC(autoCaller.rc()); AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); AssertReturn(mCompleted == FALSE, E_FAIL); if (mCanceled && SUCCEEDED(aResultCode)) aResultCode = E_FAIL; mCompleted = TRUE; mResultCode = aResultCode; AssertReturn(FAILED(aResultCode), E_FAIL); ComObjPtr<VirtualBoxErrorInfo> errorInfo; HRESULT rc = errorInfo.createObject(); AssertComRC(rc); if (SUCCEEDED(rc)) { errorInfo->init(aResultCode, aIID, pcszComponent, text); errorInfo.queryInterfaceTo(mErrorInfo.asOutParam()); } #if !defined VBOX_COM_INPROC /* remove from the global collection of pending progress operations */ if (mParent) mParent->i_removeProgress(mId.ref()); #endif /* wake up all waiting threads */ if (mWaitersCount > 0) RTSemEventMultiSignal(mCompletedSem); return rc; }
/** * Resumes the thread. * * This can be called the power on / resume notifications to resume the * PDM thread a bit early. The thread will be automatically resumed upon * return from these two notification callbacks (devices/drivers). * * The caller is responsible for serializing the control operations on the * thread. That basically means, always do these calls from the EMT. * * @returns VBox status code. * @param pThread The PDM thread. */ VMMR3DECL(int) PDMR3ThreadResume(PPDMTHREAD pThread) { /* * Assert sanity. */ AssertPtrReturn(pThread, VERR_INVALID_POINTER); AssertReturn(pThread->u32Version == PDMTHREAD_VERSION, VERR_INVALID_MAGIC); Assert(pThread->Thread != RTThreadSelf()); /* * Change the state to resuming and kick the thread. */ int rc = RTThreadUserReset(pThread->Thread); if (RT_SUCCESS(rc)) { rc = VERR_WRONG_ORDER; if (pdmR3AtomicCmpXchgState(pThread, PDMTHREADSTATE_RESUMING, PDMTHREADSTATE_SUSPENDED)) { rc = RTSemEventMultiSignal(pThread->Internal.s.BlockEvent); if (RT_SUCCESS(rc)) { /* * Wait for the thread to reach the running state. */ rc = RTThreadUserWait(pThread->Thread, 60*1000); if ( RT_SUCCESS(rc) && pThread->enmState != PDMTHREADSTATE_RUNNING) rc = VERR_PDM_THREAD_IPE_2; if (RT_SUCCESS(rc)) return rc; } } } /* * Something failed, initialize termination. */ AssertMsgFailed(("PDMR3ThreadResume -> rc=%Rrc enmState=%d\n", rc, pThread->enmState)); pdmR3ThreadBailOut(pThread); return rc; }
/** * Place an entry in an mbox, waiting for a free slot if necessary. */ void sys_mbox_post(sys_mbox_t *pvMbox, void *msg) { int rc; struct sys_mbox *mbox = NULL; Assert(pvMbox && *pvMbox); mbox = (struct sys_mbox*)*pvMbox; rc = LWIPMutexRequest((mbox)->mutex); AssertRC(rc); while (((mbox)->head + 1) % MBOX_ENTRIES_MAX == (mbox)->tail) { /* (mbox) is full, have to wait until a slot becomes available. */ rc = LWIPMutexRelease((mbox)->mutex); AssertRC(rc); rc = RTSemEventMultiWait((mbox)->nonfull, RT_INDEFINITE_WAIT); AssertRC(rc); rc = LWIPMutexRequest((mbox)->mutex); AssertRC(rc); } if ((mbox)->head == (mbox)->tail) { rc = RTSemEventMultiSignal((mbox)->nonempty); AssertRC(rc); } (mbox)->apvEntries[(mbox)->head] = msg; (mbox)->head++; (mbox)->head %= MBOX_ENTRIES_MAX; if (((mbox)->head + 1) % MBOX_ENTRIES_MAX == (mbox)->tail) { rc = RTSemEventMultiReset((mbox)->nonfull); AssertRC(rc); } rc = LWIPMutexRelease((mbox)->mutex); AssertRC(rc); }
/** * Initiate termination of the thread because something failed in a bad way. * * @param pThread The PDM thread. */ static void pdmR3ThreadBailOut(PPDMTHREAD pThread) { for (;;) { PDMTHREADSTATE enmState = pThread->enmState; switch (enmState) { case PDMTHREADSTATE_SUSPENDING: case PDMTHREADSTATE_SUSPENDED: if (!pdmR3AtomicCmpXchgState(pThread, PDMTHREADSTATE_TERMINATING, enmState)) continue; RTSemEventMultiSignal(pThread->Internal.s.BlockEvent); break; case PDMTHREADSTATE_RESUMING: if (!pdmR3AtomicCmpXchgState(pThread, PDMTHREADSTATE_TERMINATING, enmState)) continue; break; case PDMTHREADSTATE_RUNNING: if (!pdmR3AtomicCmpXchgState(pThread, PDMTHREADSTATE_TERMINATING, enmState)) continue; pdmR3ThreadWakeUp(pThread); break; case PDMTHREADSTATE_TERMINATING: case PDMTHREADSTATE_TERMINATED: break; case PDMTHREADSTATE_INITIALIZING: default: AssertMsgFailed(("enmState=%d\n", enmState)); break; } break; } }
/** * Marks the whole task as complete and sets the result code. * * If the result code indicates a failure (|FAILED(@a aResultCode)|) then this * method will import the error info from the current thread and assign it to * the errorInfo attribute (it will return an error if no info is available in * such case). * * If the result code indicates a success (|SUCCEEDED(@a aResultCode)|) then * the current operation is set to the last. * * Note that this method may be called only once for the given Progress object. * Subsequent calls will assert. * * @param aResultCode Operation result code. */ HRESULT Progress::i_notifyComplete(HRESULT aResultCode) { AutoCaller autoCaller(this); AssertComRCReturnRC(autoCaller.rc()); AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); AssertReturn(mCompleted == FALSE, E_FAIL); LogFunc(("aResultCode=%d\n", aResultCode)); if (mCanceled && SUCCEEDED(aResultCode)) aResultCode = E_FAIL; HRESULT rc = i_setResultCode(aResultCode); mCompleted = TRUE; if (!FAILED(aResultCode)) { m_ulCurrentOperation = m_cOperations - 1; /* last operation */ m_ulOperationPercent = 100; } #if !defined VBOX_COM_INPROC /* remove from the global collection of pending progress operations */ if (mParent) mParent->i_removeProgress(mId.ref()); #endif /* wake up all waiting threads */ if (mWaitersCount > 0) RTSemEventMultiSignal(mCompletedSem); 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; }
/** @copydoc VBOXSERVICE::pfnStop */ static DECLCALLBACK(void) VBoxServiceVMStatsStop(void) { RTSemEventMultiSignal(g_VMStatEvent); }
RTDECL(int) RTSemRWCreateEx(PRTSEMRW phRWSem, uint32_t fFlags, RTLOCKVALCLASS hClass, uint32_t uSubClass, const char *pszNameFmt, ...) { AssertReturn(!(fFlags & ~RTSEMRW_FLAGS_NO_LOCK_VAL), VERR_INVALID_PARAMETER); /* * Allocate memory. */ int rc; struct RTSEMRWINTERNAL *pThis = (struct RTSEMRWINTERNAL *)RTMemAlloc(sizeof(struct RTSEMRWINTERNAL)); if (pThis) { /* * Create the semaphores. */ rc = RTSemEventCreateEx(&pThis->WriteEvent, RTSEMEVENT_FLAGS_NO_LOCK_VAL, NIL_RTLOCKVALCLASS, NULL); if (RT_SUCCESS(rc)) { rc = RTSemEventMultiCreateEx(&pThis->ReadEvent, RTSEMEVENT_FLAGS_NO_LOCK_VAL, NIL_RTLOCKVALCLASS, NULL); if (RT_SUCCESS(rc)) { rc = RTCritSectInitEx(&pThis->CritSect, RTCRITSECT_FLAGS_NO_LOCK_VAL, NIL_RTLOCKVALCLASS, RTLOCKVAL_SUB_CLASS_NONE, NULL); if (RT_SUCCESS(rc)) { /* * Signal the read semaphore and initialize other variables. */ rc = RTSemEventMultiSignal(pThis->ReadEvent); if (RT_SUCCESS(rc)) { pThis->u32Padding = UINT32_C(0xa5a55a5a); pThis->cReads = 0; pThis->cWrites = 0; pThis->cWriterReads = 0; pThis->cWritesWaiting = 0; pThis->hWriter = NIL_RTNATIVETHREAD; pThis->fNeedResetReadEvent = true; pThis->u32Magic = RTSEMRW_MAGIC; #ifdef RTSEMRW_STRICT bool const fLVEnabled = !(fFlags & RTSEMRW_FLAGS_NO_LOCK_VAL); if (!pszNameFmt) { static uint32_t volatile s_iSemRWAnon = 0; uint32_t i = ASMAtomicIncU32(&s_iSemRWAnon) - 1; RTLockValidatorRecExclInit(&pThis->ValidatorWrite, hClass, uSubClass, pThis, fLVEnabled, "RTSemRW-%u", i); RTLockValidatorRecSharedInit(&pThis->ValidatorRead, hClass, uSubClass, pThis, false /*fSignaller*/, fLVEnabled, "RTSemRW-%u", i); } else { va_list va; va_start(va, pszNameFmt); RTLockValidatorRecExclInitV(&pThis->ValidatorWrite, hClass, uSubClass, pThis, fLVEnabled, pszNameFmt, va); va_end(va); va_start(va, pszNameFmt); RTLockValidatorRecSharedInitV(&pThis->ValidatorRead, hClass, uSubClass, pThis, false /*fSignaller*/, fLVEnabled, pszNameFmt, va); va_end(va); } RTLockValidatorRecMakeSiblings(&pThis->ValidatorWrite.Core, &pThis->ValidatorRead.Core); #endif *phRWSem = pThis; return VINF_SUCCESS; } RTCritSectDelete(&pThis->CritSect); } RTSemEventMultiDestroy(pThis->ReadEvent); } RTSemEventDestroy(pThis->WriteEvent); } RTMemFree(pThis); } else rc = VERR_NO_MEMORY; return rc; }
/** @copydoc VBOXSERVICE::pfnStop */ static DECLCALLBACK(void) VBoxServiceVMInfoStop(void) { RTSemEventMultiSignal(g_hVMInfoEvent); }
/** * Service control handler (extended). * * @returns Windows status (see HandlerEx). * @retval NO_ERROR if handled. * @retval ERROR_CALL_NOT_IMPLEMENTED if not handled. * * @param dwControl The control code. * @param dwEventType Event type. (specific to the control?) * @param pvEventData Event data, specific to the event. * @param pvContext The context pointer registered with the handler. * Currently not used. */ static DWORD WINAPI supSvcWinServiceCtrlHandlerEx(DWORD dwControl, DWORD dwEventType, LPVOID pvEventData, LPVOID pvContext) { LogFlow(("supSvcWinServiceCtrlHandlerEx: dwControl=%#x dwEventType=%#x pvEventData=%p\n", dwControl, dwEventType, pvEventData)); switch (dwControl) { /* * Interrogate the service about it's current status. * MSDN says that this should just return NO_ERROR and does * not need to set the status again. */ case SERVICE_CONTROL_INTERROGATE: return NO_ERROR; /* * Request to stop the service. */ case SERVICE_CONTROL_STOP: { /* * Check if the real services can be stopped and then tell them to stop. */ supSvcWinSetServiceStatus(SERVICE_STOP_PENDING, 3000, NO_ERROR); int rc = supSvcTryStopServices(); if (RT_SUCCESS(rc)) { /* * Notify the main thread that we're done, it will wait for the * real services to stop, destroy them, and finally set the windows * service status to SERVICE_STOPPED and return. */ rc = RTSemEventMultiSignal(g_hSupSvcWinEvent); if (RT_FAILURE(rc)) supSvcLogError("SERVICE_CONTROL_STOP: RTSemEventMultiSignal failed, %Rrc\n", rc); } return NO_ERROR; } case SERVICE_CONTROL_PAUSE: case SERVICE_CONTROL_CONTINUE: case SERVICE_CONTROL_SHUTDOWN: case SERVICE_CONTROL_PARAMCHANGE: case SERVICE_CONTROL_NETBINDADD: case SERVICE_CONTROL_NETBINDREMOVE: case SERVICE_CONTROL_NETBINDENABLE: case SERVICE_CONTROL_NETBINDDISABLE: case SERVICE_CONTROL_DEVICEEVENT: case SERVICE_CONTROL_HARDWAREPROFILECHANGE: case SERVICE_CONTROL_POWEREVENT: case SERVICE_CONTROL_SESSIONCHANGE: #ifdef SERVICE_CONTROL_PRESHUTDOWN /* vista */ case SERVICE_CONTROL_PRESHUTDOWN: #endif default: return ERROR_CALL_NOT_IMPLEMENTED; } NOREF(dwEventType); NOREF(pvEventData); NOREF(pvContext); return NO_ERROR; }
/** * @interface_method_impl{VBOXSERVICE,pfnStop} */ static DECLCALLBACK(void) vgsvcVMStatsStop(void) { RTSemEventMultiSignal(g_VMStatEvent); }
int main() { RTR3InitExeNoArguments(0); /* * Just a simple testcase. */ RTPrintf("tstOnce: TESTING - smoke...\n"); RTONCE Once1 = RTONCE_INITIALIZER; g_fOnceCB1 = false; int rc = RTOnce(&Once1, Once1CB, (void *)1); if (rc != VINF_SUCCESS) RTPrintf("tstOnce: ERROR - Once1, 1 failed, rc=%Rrc\n", rc); g_fOnceCB1 = false; rc = RTOnce(&Once1, Once1CB, (void *)1); if (rc != VINF_SUCCESS) RTPrintf("tstOnce: ERROR - Once1, 2 failed, rc=%Rrc\n", rc); /* * Throw a bunch of threads up against a init once thing. */ RTPrintf("tstOnce: TESTING - bunch of threads...\n"); /* create the semaphore they'll be waiting on. */ rc = RTSemEventMultiCreate(&g_hEventMulti); if (RT_FAILURE(rc)) { RTPrintf("tstOnce: FATAL ERROR - RTSemEventMultiCreate returned %Rrc\n", rc); return 1; } /* create the threads */ RTTHREAD aThreads[32]; for (unsigned i = 0; i < RT_ELEMENTS(aThreads); i++) { char szName[16]; RTStrPrintf(szName, sizeof(szName), "ONCE2-%d\n", i); rc = RTThreadCreate(&aThreads[i], Once2Thread, NULL, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, szName); if (RT_FAILURE(rc)) { RTPrintf("tstOnce: ERROR - failed to create thread #%d\n", i); g_cErrors++; } } /* kick them off and yield */ rc = RTSemEventMultiSignal(g_hEventMulti); if (RT_FAILURE(rc)) { RTPrintf("tstOnce: FATAL ERROR - RTSemEventMultiSignal returned %Rrc\n", rc); return 1; } RTThreadYield(); /* wait for all of them to finish up, 30 seconds each. */ for (unsigned i = 0; i < RT_ELEMENTS(aThreads); i++) if (aThreads[i] != NIL_RTTHREAD) { int rc2; rc = RTThreadWait(aThreads[i], 30*1000, &rc2); if (RT_FAILURE(rc)) { RTPrintf("tstOnce: ERROR - RTThreadWait on thread #%u returned %Rrc\n", i, rc); g_cErrors++; } else if (RT_FAILURE(rc2)) { RTPrintf("tstOnce: ERROR - Thread #%u returned %Rrc\n", i, rc2); g_cErrors++; } } /* * Summary. */ if (!g_cErrors) RTPrintf("tstOnce: SUCCESS\n"); else RTPrintf("tstOnce: FAILURE - %d errors\n", g_cErrors); return !!g_cErrors; }
/** * @interface_method_impl{VBOXSERVICE,pfnStop} */ static DECLCALLBACK(void) vgsvcTimeSyncStop(void) { RTSemEventMultiSignal(g_TimeSyncEvent); }
/** @copydoc VBOXSERVICE::pfnStop */ static DECLCALLBACK(void) VBoxServiceTimeSyncStop(void) { RTSemEventMultiSignal(g_TimeSyncEvent); }