dde_linux: preserve Io_signal_handler for IRQs

Do not construct/destruct signal handlers for interrupts dynamically,
but only the Irq session to prevent a deadlock.

Fix #4272
This commit is contained in:
Stefan Kalkowski 2021-09-29 16:32:47 +02:00 committed by Norman Feske
parent 6ae55d490b
commit f4cb5cc299
3 changed files with 37 additions and 55 deletions

View File

@ -59,39 +59,19 @@ class Lx_kit::Device : List<Device>::Element
: idx{idx}, addr(addr), size(size) {}
};
struct Irq_handler
{
private:
Irq_handler(Irq_handler const &);
Irq_handler &operator = (Irq_handler const &);
Platform::Device::Irq _irq;
Io_signal_handler<Irq_handler> _handler;
unsigned _number;
void _handle();
public:
Irq_handler(Platform::Device & dev,
Platform::Device::Irq::Index idx,
unsigned number);
void ack() { _irq.ack(); }
};
struct Irq : List<Irq>::Element
{
using Index = Platform::Device::Irq::Index;
Index idx;
unsigned number;
Index idx;
unsigned number;
Io_signal_handler<Irq> handler;
Constructible<Irq_handler> handler {};
Constructible<Platform::Device::Irq> session {};
Irq(unsigned idx, unsigned number)
: idx{idx}, number(number) {}
Irq(Entrypoint & ep, unsigned idx, unsigned number);
void handle();
};
struct Clock : List<Clock>::Element
@ -104,7 +84,8 @@ class Lx_kit::Device : List<Device>::Element
: idx(idx), name(name), lx_clock{0} {}
};
Device(Platform::Connection & plat,
Device(Entrypoint & ep,
Platform::Connection & plat,
Xml_node & xml,
Heap & heap);
@ -156,7 +137,9 @@ class Lx_kit::Device_list : List<Device>
void for_each(FN const & fn) {
for (Device * d = first(); d; d = d->next()) fn(*d); }
Device_list(Heap & heap, Platform::Connection & platform);
Device_list(Entrypoint & ep,
Heap & heap,
Platform::Connection & platform);
};
#endif /* _LX_KIT__DEVICE_H_ */

View File

@ -48,7 +48,7 @@ struct Lx_kit::Env
Mem_allocator memory { env, heap, platform, CACHED };
Mem_allocator uncached_memory { env, heap, platform, UNCACHED };
Scheduler scheduler { };
Device_list devices { heap, platform };
Device_list devices { env.ep(), heap, platform };
Lx_kit::Timeout timeout { timer, scheduler };
unsigned int last_irq { 0 };

View File

@ -27,29 +27,23 @@ bool Device::Io_mem::match(addr_t addr, size_t size)
}
/*************************
** Device::Irq_handler **
*************************/
/****************
** Device::Irq**
****************/
void Device::Irq_handler::_handle()
void Device::Irq::handle()
{
env().last_irq = _number;
env().last_irq = number;
env().scheduler.unblock_irq_handler();
env().scheduler.schedule();
}
Device::Irq_handler::Irq_handler(Platform::Device & dev,
Platform::Device::Irq::Index idx,
unsigned number)
Device::Irq::Irq(Entrypoint & ep, unsigned idx, unsigned number)
:
_irq(dev, idx),
_handler(Lx_kit::env().env.ep(), *this, &Irq_handler::_handle),
_number(number)
{
_irq.sigh_omit_initial_signal(_handler);
_irq.ack();
}
idx{idx},
number(number),
handler(ep, *this, &Irq::handle) { }
/************
@ -132,13 +126,15 @@ bool Device::irq_unmask(unsigned number)
if (irq.number != number)
return;
ret = true;
enable();
if (irq.handler.constructed())
if (irq.session.constructed())
return;
irq.handler.construct(*_pdev, irq.idx, number);
ret = true;
irq.session.construct(*_pdev, irq.idx);
irq.session->sigh_omit_initial_signal(irq.handler);
irq.session->ack();
});
return ret;
@ -153,7 +149,7 @@ void Device::irq_mask(unsigned number)
_for_each_irq([&] (Irq & irq) {
if (irq.number != number)
return;
irq.handler.destruct();
irq.session.destruct();
});
}
@ -165,9 +161,9 @@ void Device::irq_ack(unsigned number)
return;
_for_each_irq([&] (Irq & irq) {
if (irq.number != number)
if (irq.number != number || !irq.session.constructed())
return;
irq.handler->ack();
irq.session->ack();
});
}
@ -196,7 +192,8 @@ void Device::enable()
}
Device::Device(Platform::Connection & plat,
Device::Device(Entrypoint & ep,
Platform::Connection & plat,
Xml_node & xml,
Heap & heap)
:
@ -213,7 +210,7 @@ Device::Device(Platform::Connection & plat,
i = 0;
xml.for_each_sub_node("irq", [&] (Xml_node node) {
_irqs.insert(new (heap) Irq(i++, node.attribute_value("number", 0U)));
_irqs.insert(new (heap) Irq(ep, i++, node.attribute_value("number", 0U)));
});
i = 0;
@ -228,13 +225,15 @@ Device::Device(Platform::Connection & plat,
** Device_list **
*****************/
Device_list::Device_list(Heap & heap, Platform::Connection & platform)
Device_list::Device_list(Entrypoint & ep,
Heap & heap,
Platform::Connection & platform)
:
_platform(platform)
{
_platform.with_xml([&] (Xml_node & xml) {
xml.for_each_sub_node("device", [&] (Xml_node node) {
insert(new (heap) Device(_platform, node, heap));
insert(new (heap) Device(ep, _platform, node, heap));
});
});
}