[kernel] Add locking to endpoint

Endpoints could previously crash if two senders were concurrently
writing to them, so this change adds a spinlock and protects functions
that touch the signals and blocked list.
This commit is contained in:
Justin C. Miller
2022-01-23 19:42:37 -08:00
parent 0394f29f70
commit 3f8dfbd5b2
2 changed files with 18 additions and 0 deletions

View File

@@ -1,3 +1,4 @@
#include "assert.h"
#include "clock.h"
#include "device_manager.h"
#include "objects/endpoint.h"
@@ -22,6 +23,8 @@ endpoint::close()
{
kobject::close();
util::scoped_lock lock {m_lock};
for (auto &data : m_blocked) {
if (data.th)
data.th->wake_on_result(this, j6_status_closed);
@@ -37,9 +40,13 @@ endpoint::send(j6_tag_t tag, const void *data, size_t data_len)
sender.len = data_len;
sender.tag = tag;
util::scoped_lock lock {m_lock};
if (!check_signal(j6_signal_endpoint_can_send)) {
assert_signal(j6_signal_endpoint_can_recv);
m_blocked.append(sender);
lock.release();
sender.th->wait_on_object(this);
// we woke up having already finished the send
@@ -68,9 +75,13 @@ endpoint::receive(j6_tag_t *tag, void *data, size_t *data_len, uint64_t timeout)
if (timeout)
timeout += clock::get().value();
util::scoped_lock lock {m_lock};
if (!check_signal(j6_signal_endpoint_can_recv)) {
assert_signal(j6_signal_endpoint_can_send);
m_blocked.append(receiver);
lock.release();
receiver.th->wait_on_object(this, timeout);
// we woke up having already finished the recv
@@ -96,6 +107,8 @@ endpoint::signal_irq(unsigned irq)
{
j6_tag_t tag = j6_tag_from_irq(irq);
util::scoped_lock lock {m_lock};
if (!check_signal(j6_signal_endpoint_can_send)) {
assert_signal(j6_signal_endpoint_can_recv);
@@ -110,6 +123,9 @@ endpoint::signal_irq(unsigned irq)
}
thread_data receiver = m_blocked.pop_front();
kassert(receiver.len_p && receiver.tag_p,
"endpoint had can_send but m_blocked was empty");
if (m_blocked.count() == 0)
deassert_signal(j6_signal_endpoint_can_send);

View File

@@ -3,6 +3,7 @@
/// Definition of endpoint kobject types
#include <j6/signals.h>
#include <util/spinlock.h>
#include <util/vector.h>
#include "objects/kobject.h"
@@ -72,6 +73,7 @@ private:
j6_status_t do_message_copy(const thread_data &sender, thread_data &receiver);
util::spinlock m_lock;
util::vector<thread_data> m_blocked;
};