Index: src/VBox/Runtime/r0drv/freebsd/semevent-r0drv-freebsd.c =================================================================== --- src/VBox/Runtime/r0drv/freebsd/semevent-r0drv-freebsd.c (revision 22051) +++ src/VBox/Runtime/r0drv/freebsd/semevent-r0drv-freebsd.c (working copy) @@ -75,7 +75,7 @@ pEventInt->cWaiters = 0; pEventInt->cWaking = 0; pEventInt->fSignaled = 0; - mtx_init(&pEventInt->Mtx, "IPRT Event Semaphore", NULL, 0); + mtx_init(&pEventInt->Mtx, "IPRT Event Semaphore", NULL, MTX_SPIN); *pEventSem = pEventInt; return VINF_SUCCESS; } @@ -93,21 +93,21 @@ ("pEventInt=%p u32Magic=%#x\n", pEventInt, pEventInt->u32Magic), VERR_INVALID_HANDLE); - mtx_lock(&pEventInt->Mtx); + mtx_lock_spin(&pEventInt->Mtx); ASMAtomicIncU32(&pEventInt->u32Magic); /* make the handle invalid */ if (pEventInt->cWaiters > 0) { /* abort waiting thread, last man cleans up. */ ASMAtomicXchgU32(&pEventInt->cWaking, pEventInt->cWaking + pEventInt->cWaiters); wakeup(pEventInt); - mtx_unlock(&pEventInt->Mtx); + mtx_unlock_spin(&pEventInt->Mtx); } else if (pEventInt->cWaking) /* the last waking thread is gonna do the cleanup */ - mtx_unlock(&pEventInt->Mtx); + mtx_unlock_spin(&pEventInt->Mtx); else { - mtx_unlock(&pEventInt->Mtx); + mtx_unlock_spin(&pEventInt->Mtx); mtx_destroy(&pEventInt->Mtx); RTMemFree(pEventInt); } @@ -124,7 +124,7 @@ ("pEventInt=%p u32Magic=%#x\n", pEventInt, pEventInt->u32Magic), VERR_INVALID_HANDLE); - mtx_lock(&pEventInt->Mtx); + mtx_lock_spin(&pEventInt->Mtx); if (pEventInt->cWaiters > 0) { @@ -135,7 +135,7 @@ else ASMAtomicXchgU8(&pEventInt->fSignaled, true); - mtx_unlock(&pEventInt->Mtx); + mtx_unlock_spin(&pEventInt->Mtx); return VINF_SUCCESS; } @@ -149,7 +149,7 @@ ("pEventInt=%p u32Magic=%#x\n", pEventInt, pEventInt->u32Magic), VERR_INVALID_HANDLE); - mtx_lock(&pEventInt->Mtx); + mtx_lock_spin(&pEventInt->Mtx); if (pEventInt->fSignaled) { @@ -172,17 +172,23 @@ ASMAtomicIncU32(&pEventInt->cWaiters); - /** @todo r=bird: This doesn't handle cMillies == 0 correctly, it will assert - * and or sleep for ever according to r47861. (That's probably an old bug - * of my making.) - */ - rc = mtx_sleep(pEventInt, /* block id */ - &pEventInt->Mtx, /* mtx */ - fInterruptible ? PZERO | PCATCH : PZERO, - "iprtev", /* max 6 chars */ - cMillies == RT_INDEFINITE_WAIT - ? 0 - : tvtohz(&tv)); + mtx_unlock_spin(&pEventInt->Mtx); +/** @todo r=bird: This doesn't handle cMillies == 0 correctly, it will assert + * and or sleep for ever according to r47861. (That's probably an old bug + * of my making.) + * + * And it really looks like it's racing signalling on MP systems. (It + * *looks* like you leave the lock and then tries to go to sleep on a + * block id, someone spinning on the lock attempt to wake us up before we + * go to sleep. That's why the code was originally trying to use msleep + * here.). */ + rc = tsleep(pEventInt, /* block id */ + fInterruptible ? PZERO | PCATCH : PZERO, + "iprtev", /* max 6 chars */ + cMillies == RT_INDEFINITE_WAIT + ? 0 + : tvtohz(&tv)); + mtx_lock_spin(&pEventInt->Mtx); switch (rc) { @@ -200,7 +206,7 @@ { /* The event was destroyed, as the last thread do the cleanup. we don't actually know whether */ - mtx_unlock(&pEventInt->Mtx); + mtx_unlock_spin(&pEventInt->Mtx); mtx_destroy(&pEventInt->Mtx); RTMemFree(pEventInt); return rc; @@ -230,7 +236,7 @@ } } - mtx_unlock(&pEventInt->Mtx); + mtx_unlock_spin(&pEventInt->Mtx); return rc; }