mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-18 02:40:08 +00:00
vbox5-nova: avoid Blocking_canceled exception
using pthread primitives to implement block/wakeup of EMT thread Fixes #3810
This commit is contained in:
parent
ed4594c76b
commit
641679f7e7
@ -340,9 +340,6 @@ int SUPR3CallVMMR0Ex(PVMR0 pVMR0, VMCPUID idCpu, unsigned uOperation,
|
||||
if (!ns_diff)
|
||||
return VINF_SUCCESS;
|
||||
|
||||
uint64_t const tsc_offset = genode_cpu_hz() * ns_diff / (1000*1000*1000);
|
||||
uint64_t const tsc_abs = Genode::Trace::timestamp() + tsc_offset;
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
if (ns_diff > RT_NS_1SEC)
|
||||
@ -350,7 +347,7 @@ int SUPR3CallVMMR0Ex(PVMR0 pVMR0, VMCPUID idCpu, unsigned uOperation,
|
||||
|
||||
Vcpu_handler *vcpu_handler = lookup_vcpu_handler(idCpu);
|
||||
Assert(vcpu_handler);
|
||||
vcpu_handler->halt(tsc_abs);
|
||||
vcpu_handler->halt(ns_diff);
|
||||
|
||||
return VINF_SUCCESS;
|
||||
}
|
||||
|
@ -88,7 +88,9 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<Genode::Thread>,
|
||||
X86FXSTATE _guest_fpu_state __attribute__((aligned(0x10)));
|
||||
X86FXSTATE _emt_fpu_state __attribute__((aligned(0x10)));
|
||||
|
||||
pthread _pthread;
|
||||
pthread _pthread;
|
||||
pthread_cond_t _cond_wait;
|
||||
pthread_mutex_t _mutex;
|
||||
|
||||
Vmm::Vcpu_other_pd _vcpu;
|
||||
|
||||
@ -125,6 +127,29 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<Genode::Thread>,
|
||||
INTERRUPT_STATE_NONE = 0U,
|
||||
};
|
||||
|
||||
timespec add_timespec_ns(timespec a, uint64_t ns) const
|
||||
{
|
||||
enum { NSEC_PER_SEC = 1'000'000'000ull };
|
||||
|
||||
long sec = a.tv_sec;
|
||||
|
||||
while (a.tv_nsec >= NSEC_PER_SEC) {
|
||||
a.tv_nsec -= NSEC_PER_SEC;
|
||||
sec++;
|
||||
}
|
||||
while (ns >= NSEC_PER_SEC) {
|
||||
ns -= NSEC_PER_SEC;
|
||||
sec++;
|
||||
}
|
||||
|
||||
long nsec = a.tv_nsec + ns;
|
||||
while (nsec >= NSEC_PER_SEC) {
|
||||
nsec -= NSEC_PER_SEC;
|
||||
sec++;
|
||||
}
|
||||
return timespec { sec, nsec };
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
void _fpu_save()
|
||||
@ -834,7 +859,16 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<Genode::Thread>,
|
||||
_vcpu(cpu_connection, location, pd_vcpu),
|
||||
_ec_sel(Genode::cap_map().insert()),
|
||||
_cpu_id(cpu_id)
|
||||
{ }
|
||||
{
|
||||
pthread_mutexattr_t _attr;
|
||||
pthread_mutexattr_init(&_attr);
|
||||
|
||||
pthread_cond_init(&_cond_wait, nullptr);
|
||||
|
||||
pthread_mutexattr_settype(&_attr, PTHREAD_MUTEX_ERRORCHECK);
|
||||
pthread_mutex_init(&_mutex, &_attr);
|
||||
|
||||
}
|
||||
|
||||
pthread &pthread_obj() { return _pthread; }
|
||||
|
||||
@ -880,24 +914,24 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<Genode::Thread>,
|
||||
#endif
|
||||
}
|
||||
|
||||
void halt(Genode::uint64_t tsc_abs)
|
||||
void halt(Genode::uint64_t const wait_ns)
|
||||
{
|
||||
Assert(utcb() == Thread::myself()->utcb());
|
||||
/* calculate timeout */
|
||||
timespec ts { 0, 0 };
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
ts = add_timespec_ns(ts, wait_ns);
|
||||
|
||||
Genode::addr_t sem = native_thread().exc_pt_sel + Nova::SM_SEL_EC;
|
||||
Nova::sm_ctrl(sem, Nova::SEMAPHORE_DOWNZERO, tsc_abs);
|
||||
/* wait for condition or timeout */
|
||||
pthread_mutex_lock(&_mutex);
|
||||
pthread_cond_timedwait(&_cond_wait, &_mutex, &ts);
|
||||
pthread_mutex_unlock(&_mutex);
|
||||
}
|
||||
|
||||
void wake_up()
|
||||
{
|
||||
/*
|
||||
* Note: the following 'SEMAPHORE_UP' call can cause a
|
||||
* 'Blocking_canceled' exception in the target thread
|
||||
* if it is currently blocking on a Genode lock, because
|
||||
* the same NOVA semaphore is used.
|
||||
*/
|
||||
Genode::addr_t sem = native_thread().exc_pt_sel + Nova::SM_SEL_EC;
|
||||
Nova::sm_ctrl(sem, Nova::SEMAPHORE_UP);
|
||||
pthread_mutex_lock(&_mutex);
|
||||
pthread_cond_signal(&_cond_wait);
|
||||
pthread_mutex_unlock(&_mutex);
|
||||
}
|
||||
|
||||
int run_hw(PVMR0 pVMR0)
|
||||
|
Loading…
Reference in New Issue
Block a user