diff options
author | Idan Horowitz <idan.horowitz@gmail.com> | 2021-12-12 01:01:42 +0200 |
---|---|---|
committer | Idan Horowitz <idan.horowitz@gmail.com> | 2021-12-12 08:34:19 +0200 |
commit | 762e047ec9c4d1dad7c8f72099fa59f1fdf0ab50 (patch) | |
tree | 985edfb22020bde85069a7a886e93b0b0153ad3f /Kernel/Thread.h | |
parent | 13d98999b76aaac16d77e7b0e80fdd2922f48fd7 (diff) | |
download | serenity-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.h | 37 |
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; |