From 1f7fd647daf86acd462c9d5b7beb44dcf7476986 Mon Sep 17 00:00:00 2001 From: Christian Prochaska Date: Thu, 5 Mar 2015 19:31:41 +0100 Subject: [PATCH] vbox: wait longer for stable timer state Some functions in the time manager, for example 'TMTimerSet()' and 'TMTimerStop()' let VirtualBox abort with a failed assertion if the timer does not change to a 'stable' state after 1000 calls of a mixture of 'yield' and 'sleep'. On Genode, this happens sometimes when the 'EMT' thread is executing 'TMTimerSet()' and gets interrupted by the 'TAP' thread, which calls 'TMTimerStop()' and waits for the 'EMT' thread to finish setting the timer. Since the 'EMT' thread has the lowest priority, 1000 retries can be too few. Without the assertion, these functions would return an error code, which is often ignored by the caller, so it seems safer to keep retrying until the function can return successfully. Fixes #1437 --- repos/ports/ports/virtualbox.hash | 2 +- repos/ports/ports/virtualbox.port | 2 +- .../src/virtualbox/patches/tm_retries.patch | 88 +++++++++++++++++++ 3 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 repos/ports/src/virtualbox/patches/tm_retries.patch diff --git a/repos/ports/ports/virtualbox.hash b/repos/ports/ports/virtualbox.hash index 86af65a21..b261ef6b6 100644 --- a/repos/ports/ports/virtualbox.hash +++ b/repos/ports/ports/virtualbox.hash @@ -1 +1 @@ -372dfd49bf530d54f766b4a206c58bebee9a4bc7 +21c8fc5eade0a7bc64c3a494b53228a57cbfe995 diff --git a/repos/ports/ports/virtualbox.port b/repos/ports/ports/virtualbox.port index f135c8ed2..e8ec1d42a 100644 --- a/repos/ports/ports/virtualbox.port +++ b/repos/ports/ports/virtualbox.port @@ -10,7 +10,7 @@ SHA(virtualbox) := e4c23b713e8715b8e0172fa066f2197756e901fe PATCHES_LIST := acpi_drv dev_e1000 eminternal fake_pci_vendor iconv mouse PATCHES_LIST += pdm_driver poke sharedfolder_pagelist -PATCHES_LIST += time-log-deadlock vbox_inc vbox_main network +PATCHES_LIST += time-log-deadlock tm_retries vbox_inc vbox_main network PATCHES_LIST += vga_fb vga_vbva vmdk vmmdev avoid_yield serial rem_irq usb PATCHES := $(addsuffix .patch, $(PATCHES_LIST)) diff --git a/repos/ports/src/virtualbox/patches/tm_retries.patch b/repos/ports/src/virtualbox/patches/tm_retries.patch new file mode 100644 index 000000000..0b81bc3e9 --- /dev/null +++ b/repos/ports/src/virtualbox/patches/tm_retries.patch @@ -0,0 +1,88 @@ +Wait longer for stable timer state + +Some functions in the time manager, for example 'TMTimerSet()' and +'TMTimerStop()' let VirtualBox abort with a failed assertion if the timer +does not change to a 'stable' state after 1000 calls of a mixture of +'yield' and 'sleep'. On Genode, this happens sometimes when the 'EMT' +thread is executing 'TMTimerSet()' and gets interrupted by the 'TAP' +thread, which calls 'TMTimerStop()' and waits for the 'EMT' thread to +finish setting the timer. Since the 'EMT' thread has the lowest priority, +1000 retries can be too few. Without the assertion, these functions would +return an error code, which is often ignored by the caller, so it seems +safer to keep retrying until the function can return successfully. + +Issue #1437 + +diff --git src/app/virtualbox/src/VBox/VMM/VMMAll/TMAll.cpp src/app/virtualbox/src/VBox/VMM/VMMAll/TMAll.cpp +index a1167a1..fbf95e2 100644 +--- src/app/virtualbox/src/VBox/VMM/VMMAll/TMAll.cpp ++++ src/app/virtualbox/src/VBox/VMM/VMMAll/TMAll.cpp +@@ -1334,6 +1334,12 @@ VMMDECL(int) TMTimerSet(PTMTIMER pTimer, uint64_t u64Expire) + AssertMsgFailed(("Unknown timer state %d (%s)\n", enmState, R3STRING(pTimer->pszDesc))); + return VERR_TM_UNKNOWN_STATE; + } ++ ++ if (cRetries == 0) { ++ RTLogPrintf("TMTimerSet(): Failed waiting for stable state. state=%d (%s), keeping trying...\n", pTimer->enmState, R3STRING(pTimer->pszDesc)); ++ cRetries = 1000; ++ } ++ + } while (cRetries-- > 0); + + AssertMsgFailed(("Failed waiting for stable state. state=%d (%s)\n", pTimer->enmState, R3STRING(pTimer->pszDesc))); +@@ -1683,10 +1689,8 @@ VMMDECL(int) TMTimerSetRelative(PTMTIMER pTimer, uint64_t cTicksToNext, uint64_t + } + if (cRetries <= 0) + { +- AssertMsgFailed(("Failed waiting for stable state. state=%d (%s)\n", pTimer->enmState, R3STRING(pTimer->pszDesc))); +- rc = VERR_TM_TIMER_UNSTABLE_STATE; +- tmTimerSetRelativeNowWorker(pVM, enmClock, pu64Now); +- break; ++ RTLogPrintf("TMTimerSetRelative(): Failed waiting for stable state. state=%d (%s), keeping trying...\n", pTimer->enmState, R3STRING(pTimer->pszDesc)); ++ cRetries = 1000; + } + + /* +@@ -1909,6 +1913,12 @@ VMMDECL(int) TMTimerStop(PTMTIMER pTimer) + AssertMsgFailed(("Unknown timer state %d (%s)\n", enmState, R3STRING(pTimer->pszDesc))); + return VERR_TM_UNKNOWN_STATE; + } ++ ++ if (cRetries == 0) { ++ RTLogPrintf("TMTimerStop(): Failed waiting for stable state. state=%d (%s), keeping trying...\n", pTimer->enmState, R3STRING(pTimer->pszDesc)); ++ cRetries = 1000; ++ } ++ + } while (cRetries-- > 0); + + AssertMsgFailed(("Failed waiting for stable state. state=%d (%s)\n", pTimer->enmState, R3STRING(pTimer->pszDesc))); +@@ -2027,6 +2037,12 @@ VMMDECL(uint64_t) TMTimerGetExpire(PTMTIMER pTimer) + AssertMsgFailed(("Unknown timer state %d (%s)\n", enmState, R3STRING(pTimer->pszDesc))); + return ~(uint64_t)0; + } ++ ++ if (cRetries == 0) { ++ RTLogPrintf("TMTimerGetExpire(): Failed waiting for stable state. state=%d (%s), keeping trying...\n", pTimer->enmState, R3STRING(pTimer->pszDesc)); ++ cRetries = 1000; ++ } ++ + } while (cRetries-- > 0); + + AssertMsgFailed(("Failed waiting for stable state. state=%d (%s)\n", pTimer->enmState, R3STRING(pTimer->pszDesc))); +diff --git src/app/virtualbox/src/VBox/VMM/VMMR3/TM.cpp src/app/virtualbox/src/VBox/VMM/VMMR3/TM.cpp +index f6f6c8e..c3bc22d 100644 +--- src/app/virtualbox/src/VBox/VMM/VMMR3/TM.cpp ++++ src/app/virtualbox/src/VBox/VMM/VMMR3/TM.cpp +@@ -1617,8 +1617,10 @@ VMMR3DECL(int) TMR3TimerDestroy(PTMTIMER pTimer) + TM_UNLOCK_TIMERS(pVM); + if (!RTThreadYield()) + RTThreadSleep(1); +- AssertMsgReturn(cRetries > 0, ("Failed waiting for stable state. state=%d (%s)\n", pTimer->enmState, pTimer->pszDesc), +- VERR_TM_UNSTABLE_STATE); ++ if (cRetries == 0) { ++ RTLogPrintf("TMR3TimerDestroy(): Failed waiting for stable state. state=%d (%s), keeping trying...\n", pTimer->enmState, pTimer->pszDesc); ++ cRetries = 1000; ++ } + TM_LOCK_TIMERS(pVM); + continue; +