summaryrefslogtreecommitdiff
path: root/Kernel/Thread.h
diff options
context:
space:
mode:
authorIdan Horowitz <idan.horowitz@gmail.com>2021-12-12 01:01:42 +0200
committerIdan Horowitz <idan.horowitz@gmail.com>2021-12-12 08:34:19 +0200
commit762e047ec9c4d1dad7c8f72099fa59f1fdf0ab50 (patch)
tree985edfb22020bde85069a7a886e93b0b0153ad3f /Kernel/Thread.h
parent13d98999b76aaac16d77e7b0e80fdd2922f48fd7 (diff)
downloadserenity-762e047ec9c4d1dad7c8f72099fa59f1fdf0ab50.zip
Kernel+LibC: Implement sigtimedwait()
This includes a new Thread::Blocker called SignalBlocker which blocks until a signal of a matching type is pending. The current Blocker implementation in the Kernel is very complicated, but cleaning it up is a different yak for a different day.
Diffstat (limited to 'Kernel/Thread.h')
-rw-r--r--Kernel/Thread.h37
1 files changed, 37 insertions, 0 deletions
diff --git a/Kernel/Thread.h b/Kernel/Thread.h
index a225191ca5..d085790203 100644
--- a/Kernel/Thread.h
+++ b/Kernel/Thread.h
@@ -292,6 +292,7 @@ public:
Queue,
Routing,
Sleep,
+ Signal,
Wait
};
virtual ~Blocker();
@@ -698,6 +699,41 @@ public:
bool m_did_unblock { false };
};
+ class SignalBlocker final : public Blocker {
+ public:
+ explicit SignalBlocker(sigset_t pending_set, siginfo_t& result);
+ virtual StringView state_string() const override { return "Pending Signal"sv; }
+ virtual Type blocker_type() const override { return Type::Signal; }
+ void will_unblock_immediately_without_blocking(UnblockImmediatelyReason) override;
+ virtual bool setup_blocker() override;
+ bool check_pending_signals(bool from_add_blocker);
+
+ private:
+ sigset_t m_pending_set { 0 };
+ siginfo_t& m_result;
+ bool m_did_unblock { false };
+ };
+
+ class SignalBlockerSet final : public BlockerSet {
+ public:
+ void unblock_all_blockers_whose_conditions_are_met()
+ {
+ BlockerSet::unblock_all_blockers_whose_conditions_are_met([&](auto& b, void*, bool&) {
+ VERIFY(b.blocker_type() == Blocker::Type::Signal);
+ auto& blocker = static_cast<Thread::SignalBlocker&>(b);
+ return blocker.check_pending_signals(false);
+ });
+ }
+
+ private:
+ bool should_add_blocker(Blocker& b, void*) override
+ {
+ VERIFY(b.blocker_type() == Blocker::Type::Signal);
+ auto& blocker = static_cast<Thread::SignalBlocker&>(b);
+ return !blocker.check_pending_signals(true);
+ }
+ };
+
class WaitBlocker final : public Blocker {
public:
enum class UnblockFlags {
@@ -1302,6 +1338,7 @@ private:
u32 m_signal_mask { 0 };
FlatPtr m_alternative_signal_stack { 0 };
FlatPtr m_alternative_signal_stack_size { 0 };
+ SignalBlockerSet m_signal_blocker_set;
FlatPtr m_kernel_stack_base { 0 };
FlatPtr m_kernel_stack_top { 0 };
OwnPtr<Memory::Region> m_kernel_stack_region;