mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-31 00:24:51 +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)
|
if (!ns_diff)
|
||||||
return VINF_SUCCESS;
|
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;
|
using namespace Genode;
|
||||||
|
|
||||||
if (ns_diff > RT_NS_1SEC)
|
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);
|
Vcpu_handler *vcpu_handler = lookup_vcpu_handler(idCpu);
|
||||||
Assert(vcpu_handler);
|
Assert(vcpu_handler);
|
||||||
vcpu_handler->halt(tsc_abs);
|
vcpu_handler->halt(ns_diff);
|
||||||
|
|
||||||
return VINF_SUCCESS;
|
return VINF_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -88,7 +88,9 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<Genode::Thread>,
|
|||||||
X86FXSTATE _guest_fpu_state __attribute__((aligned(0x10)));
|
X86FXSTATE _guest_fpu_state __attribute__((aligned(0x10)));
|
||||||
X86FXSTATE _emt_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;
|
Vmm::Vcpu_other_pd _vcpu;
|
||||||
|
|
||||||
@ -125,6 +127,29 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<Genode::Thread>,
|
|||||||
INTERRUPT_STATE_NONE = 0U,
|
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:
|
protected:
|
||||||
|
|
||||||
void _fpu_save()
|
void _fpu_save()
|
||||||
@ -834,7 +859,16 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<Genode::Thread>,
|
|||||||
_vcpu(cpu_connection, location, pd_vcpu),
|
_vcpu(cpu_connection, location, pd_vcpu),
|
||||||
_ec_sel(Genode::cap_map().insert()),
|
_ec_sel(Genode::cap_map().insert()),
|
||||||
_cpu_id(cpu_id)
|
_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; }
|
pthread &pthread_obj() { return _pthread; }
|
||||||
|
|
||||||
@ -880,24 +914,24 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<Genode::Thread>,
|
|||||||
#endif
|
#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;
|
/* wait for condition or timeout */
|
||||||
Nova::sm_ctrl(sem, Nova::SEMAPHORE_DOWNZERO, tsc_abs);
|
pthread_mutex_lock(&_mutex);
|
||||||
|
pthread_cond_timedwait(&_cond_wait, &_mutex, &ts);
|
||||||
|
pthread_mutex_unlock(&_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void wake_up()
|
void wake_up()
|
||||||
{
|
{
|
||||||
/*
|
pthread_mutex_lock(&_mutex);
|
||||||
* Note: the following 'SEMAPHORE_UP' call can cause a
|
pthread_cond_signal(&_cond_wait);
|
||||||
* 'Blocking_canceled' exception in the target thread
|
pthread_mutex_unlock(&_mutex);
|
||||||
* 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int run_hw(PVMR0 pVMR0)
|
int run_hw(PVMR0 pVMR0)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user