1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 20:18:12 +00:00

Kernel: Move block condition evaluation out of the Scheduler

This makes the Scheduler a lot leaner by not having to evaluate
block conditions every time it is invoked. Instead evaluate them as
the states change, and unblock threads at that point.

This also implements some more waitid/waitpid/wait features and
behavior. For example, WUNTRACED and WNOWAIT are now supported. And
wait will now not return EINTR when SIGCHLD is delivered at the
same time.
This commit is contained in:
Tom 2020-11-29 16:05:27 -07:00 committed by Andreas Kling
parent 6a620562cc
commit 046d6855f5
53 changed files with 2027 additions and 930 deletions

View file

@ -68,38 +68,86 @@ public:
private:
Plan9FS(FileDescription&);
struct ReceiveCompletion {
Plan9FS& fs;
Message& message;
KResult& result;
Atomic<bool> completed;
class Blocker;
class Plan9FSBlockCondition : public Thread::BlockCondition {
public:
Plan9FSBlockCondition(Plan9FS& fs)
: m_fs(fs)
{
}
void unblock_completed(u16);
void unblock_all();
void try_unblock(Blocker&);
protected:
virtual bool should_add_blocker(Thread::Blocker&, void*) override;
private:
Plan9FS& m_fs;
mutable SpinLock<u8> m_lock;
};
struct ReceiveCompletion : public RefCounted<ReceiveCompletion> {
mutable SpinLock<u8> lock;
bool completed { false };
const u16 tag;
OwnPtr<Message> message;
KResult result { KSuccess };
ReceiveCompletion(u16 tag);
~ReceiveCompletion();
};
class Blocker final : public Thread::Blocker {
public:
Blocker(ReceiveCompletion& completion)
: m_completion(completion)
Blocker(Plan9FS& fs, Message& message, NonnullRefPtr<ReceiveCompletion> completion)
: m_fs(fs)
, m_message(message)
, m_completion(move(completion))
{
set_block_condition(fs.m_completion_blocker);
}
virtual bool should_unblock(Thread&) override;
virtual const char* state_string() const override { return "Waiting"; }
virtual Type blocker_type() const override { return Type::Plan9FS; }
virtual void not_blocking(bool) override;
const NonnullRefPtr<ReceiveCompletion>& completion() const { return m_completion; }
u16 tag() const { return m_completion->tag; }
bool is_completed() const;
bool unblock()
{
unblock_from_blocker();
return true;
}
bool unblock(u16 tag);
private:
ReceiveCompletion& m_completion;
Plan9FS& m_fs;
Message& m_message;
NonnullRefPtr<ReceiveCompletion> m_completion;
bool m_did_unblock { false };
};
friend class Blocker;
virtual const char* class_name() const override { return "Plan9FS"; }
KResult post_message(Message&);
bool is_complete(const ReceiveCompletion&);
KResult post_message(Message&, RefPtr<ReceiveCompletion>);
KResult do_read(u8* buffer, size_t);
KResult read_and_dispatch_one_message();
KResult wait_for_specific_message(u16 tag, Message& out_message);
KResult post_message_and_wait_for_a_reply(Message&, bool auto_convert_error_reply_to_error = true);
KResult post_message_and_wait_for_a_reply(Message&);
KResult post_message_and_explicitly_ignore_reply(Message&);
ProtocolVersion parse_protocol_version(const StringView&) const;
ssize_t adjust_buffer_size(ssize_t size) const;
void thread_main();
void ensure_thread();
RefPtr<Plan9FSInode> m_root_inode;
Atomic<u16> m_next_tag { (u16)-1 };
Atomic<u32> m_next_fid { 1 };
@ -108,9 +156,13 @@ private:
size_t m_max_message_size { 4 * KiB };
Lock m_send_lock { "Plan9FS send" };
Atomic<bool> m_someone_is_reading { false };
HashMap<u16, ReceiveCompletion*> m_completions;
HashTable<u16> m_tags_to_ignore;
Plan9FSBlockCondition m_completion_blocker;
HashMap<u16, NonnullRefPtr<ReceiveCompletion>> m_completions;
SpinLock<u8> m_thread_lock;
RefPtr<Thread> m_thread;
Atomic<bool> m_thread_running { false };
Atomic<bool> m_thread_shutdown { false };
};
class Plan9FSInode final : public Inode {