mirror of
https://github.com/genodelabs/genode.git
synced 2025-03-28 14:49:58 +00:00
nova: don't wait for workers in cpu_session::pause
If a local thread is attempted to be 'pause'd via cpu_session, don't wait until it gets into the recalled state. If the caller is lucky it is, if not return only the stack pointer. Avoids deadlocking of the gdb when attached to a process running a server. Issue #478
This commit is contained in:
parent
d8cf17687e
commit
73cff5c996
@ -135,6 +135,7 @@ namespace Genode {
|
|||||||
/**
|
/**
|
||||||
* Set initial stack pointer used by the startup handler
|
* Set initial stack pointer used by the startup handler
|
||||||
*/
|
*/
|
||||||
|
addr_t initial_esp() { return _initial_esp; }
|
||||||
void initial_esp(addr_t esp) { _initial_esp = esp; }
|
void initial_esp(addr_t esp) { _initial_esp = esp; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -183,14 +184,14 @@ namespace Genode {
|
|||||||
/**
|
/**
|
||||||
* Copy thread state of recalled thread.
|
* Copy thread state of recalled thread.
|
||||||
*/
|
*/
|
||||||
int copy_thread_state(Thread_state * state_dst)
|
bool copy_thread_state(Thread_state * state_dst)
|
||||||
{
|
{
|
||||||
if (!state_dst || !_state.is_valid())
|
if (!state_dst || !_state.is_valid())
|
||||||
return -1;
|
return false;
|
||||||
|
|
||||||
*state_dst = _state.thread;
|
*state_dst = _state.thread;
|
||||||
|
|
||||||
return 0;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -37,13 +37,24 @@ namespace Genode {
|
|||||||
addr_t _id_base;
|
addr_t _id_base;
|
||||||
addr_t _sel_exc_base;
|
addr_t _sel_exc_base;
|
||||||
Affinity::Location _location;
|
Affinity::Location _location;
|
||||||
bool _is_main_thread;
|
|
||||||
bool _is_vcpu;
|
enum {
|
||||||
|
MAIN_THREAD = 0x1U,
|
||||||
|
VCPU = 0x2U,
|
||||||
|
WORKER = 0x4U,
|
||||||
|
};
|
||||||
|
uint8_t _features;
|
||||||
|
|
||||||
char _name[Thread_base::Context::NAME_LEN];
|
char _name[Thread_base::Context::NAME_LEN];
|
||||||
|
|
||||||
addr_t _sel_ec() const { return _id_base; }
|
addr_t _sel_ec() const { return _id_base; }
|
||||||
addr_t _sel_sc() const { return _id_base + 1; }
|
addr_t _sel_sc() const { return _id_base + 1; }
|
||||||
|
|
||||||
|
/* convenience function to access _feature variable */
|
||||||
|
inline bool is_main_thread() { return _features & MAIN_THREAD; }
|
||||||
|
inline bool is_vcpu() { return _features & VCPU; }
|
||||||
|
inline bool is_worker() { return _features & WORKER; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/* invalid thread number */
|
/* invalid thread number */
|
||||||
@ -144,9 +155,11 @@ namespace Genode {
|
|||||||
/**
|
/**
|
||||||
* Associate thread with protection domain
|
* Associate thread with protection domain
|
||||||
*/
|
*/
|
||||||
void bind_to_pd(Platform_pd *pd, bool is_main_thread)
|
void bind_to_pd(Platform_pd *pd, bool main_thread)
|
||||||
{
|
{
|
||||||
_pd = pd, _is_main_thread = is_main_thread;
|
_pd = pd;
|
||||||
|
|
||||||
|
if (main_thread) _features |= MAIN_THREAD;
|
||||||
}
|
}
|
||||||
|
|
||||||
void single_step(bool on);
|
void single_step(bool on);
|
||||||
|
@ -63,9 +63,9 @@ int Platform_thread::start(void *ip, void *sp)
|
|||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_is_main_thread) {
|
if (!is_main_thread()) {
|
||||||
addr_t initial_sp = reinterpret_cast<addr_t>(sp);
|
addr_t initial_sp = reinterpret_cast<addr_t>(sp);
|
||||||
addr_t utcb = _is_vcpu ? 0 : round_page(initial_sp);
|
addr_t utcb = is_vcpu() ? 0 : round_page(initial_sp);
|
||||||
|
|
||||||
if (_sel_exc_base == Native_thread::INVALID_INDEX) {
|
if (_sel_exc_base == Native_thread::INVALID_INDEX) {
|
||||||
PERR("exception base not specified");
|
PERR("exception base not specified");
|
||||||
@ -82,6 +82,13 @@ int Platform_thread::start(void *ip, void *sp)
|
|||||||
return -4;
|
return -4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!thread_global) {
|
||||||
|
_features |= WORKER;
|
||||||
|
|
||||||
|
/* local/worker threads do not require a startup portal */
|
||||||
|
revoke(Obj_crd(_pager->exc_pt_sel_client() + PT_SEL_STARTUP, 0));
|
||||||
|
}
|
||||||
|
|
||||||
_pager->initial_eip((addr_t)ip);
|
_pager->initial_eip((addr_t)ip);
|
||||||
_pager->initial_esp(initial_sp);
|
_pager->initial_esp(initial_sp);
|
||||||
_pager->client_set_ec(_sel_ec());
|
_pager->client_set_ec(_sel_ec());
|
||||||
@ -181,18 +188,20 @@ int Platform_thread::start(void *ip, void *sp)
|
|||||||
|
|
||||||
Native_capability Platform_thread::pause()
|
Native_capability Platform_thread::pause()
|
||||||
{
|
{
|
||||||
if (!_pager)
|
if (!_pager) return Native_capability();
|
||||||
return Native_capability::invalid_cap();
|
|
||||||
|
|
||||||
Native_capability notify_sm = _pager->notify_sm();
|
Native_capability notify_sm = _pager->notify_sm();
|
||||||
if (!notify_sm.valid()) return notify_sm;
|
if (!notify_sm.valid()) return notify_sm;
|
||||||
|
|
||||||
if (_pager->client_recall() != Nova::NOVA_OK)
|
if (_pager->client_recall() != Nova::NOVA_OK)
|
||||||
return Native_capability::invalid_cap();
|
return Native_capability();
|
||||||
|
|
||||||
/* If the thread is blocked in the its own SM, get him out */
|
/* If the thread is blocked in its own SM, get him out */
|
||||||
cancel_blocking();
|
cancel_blocking();
|
||||||
|
|
||||||
|
/* local thread may never get be canceled if it doesn't receive an IPC */
|
||||||
|
if (is_worker()) return Native_capability();
|
||||||
|
|
||||||
return notify_sm;
|
return notify_sm;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,8 +210,10 @@ void Platform_thread::resume()
|
|||||||
{
|
{
|
||||||
using namespace Nova;
|
using namespace Nova;
|
||||||
|
|
||||||
uint8_t res = create_sc(_sel_sc(), _pd->pd_sel(), _sel_ec(), Qpd());
|
if (!is_worker()) {
|
||||||
if (res == NOVA_OK) return;
|
uint8_t res = create_sc(_sel_sc(), _pd->pd_sel(), _sel_ec(), Qpd());
|
||||||
|
if (res == NOVA_OK) return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!_pager) return;
|
if (!_pager) return;
|
||||||
|
|
||||||
@ -213,9 +224,15 @@ void Platform_thread::resume()
|
|||||||
|
|
||||||
Thread_state Platform_thread::state()
|
Thread_state Platform_thread::state()
|
||||||
{
|
{
|
||||||
Thread_state s;
|
|
||||||
if (!_pager) throw Cpu_session::State_access_failed();
|
if (!_pager) throw Cpu_session::State_access_failed();
|
||||||
_pager->copy_thread_state(&s);
|
|
||||||
|
Thread_state s;
|
||||||
|
if (_pager->copy_thread_state(&s))
|
||||||
|
return s;
|
||||||
|
|
||||||
|
if (is_worker())
|
||||||
|
s.sp = _pager->initial_esp();
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,20 +240,20 @@ Thread_state Platform_thread::state()
|
|||||||
void Platform_thread::state(Thread_state s)
|
void Platform_thread::state(Thread_state s)
|
||||||
{
|
{
|
||||||
/* not permitted for main thread */
|
/* not permitted for main thread */
|
||||||
if (_is_main_thread) throw Cpu_session::State_access_failed();
|
if (is_main_thread()) throw Cpu_session::State_access_failed();
|
||||||
|
|
||||||
/* you can do it only once */
|
/* you can do it only once */
|
||||||
if (_sel_exc_base != Native_thread::INVALID_INDEX)
|
if (_sel_exc_base != Native_thread::INVALID_INDEX)
|
||||||
throw Cpu_session::State_access_failed();
|
throw Cpu_session::State_access_failed();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* _sel_exc_base exception base of thread in caller
|
* s.sel_exc_base exception base of thread in caller
|
||||||
* protection domain - not in Core !
|
* protection domain - not in Core !
|
||||||
* _is_vcpu If true it will run as vCPU,
|
* s.is_vcpu If true it will run as vCPU,
|
||||||
* otherwise it will be a thread.
|
* otherwise it will be a thread.
|
||||||
*/
|
*/
|
||||||
_sel_exc_base = s.sel_exc_base;
|
_sel_exc_base = s.sel_exc_base;
|
||||||
_is_vcpu = s.is_vcpu;
|
if (s.is_vcpu) _features |= VCPU;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -272,7 +289,7 @@ Platform_thread::Platform_thread(const char *name, unsigned, int thread_id)
|
|||||||
:
|
:
|
||||||
_pd(0), _pager(0), _id_base(cap_selector_allocator()->alloc(1)),
|
_pd(0), _pager(0), _id_base(cap_selector_allocator()->alloc(1)),
|
||||||
_sel_exc_base(Native_thread::INVALID_INDEX), _location(boot_cpu(), 0),
|
_sel_exc_base(Native_thread::INVALID_INDEX), _location(boot_cpu(), 0),
|
||||||
_is_main_thread(false), _is_vcpu(false)
|
_features(0)
|
||||||
{
|
{
|
||||||
strncpy(_name, name, sizeof(_name));
|
strncpy(_name, name, sizeof(_name));
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user