Kernel: Semaphores and Threads can now be blocked with timeout
This commit is contained in:
parent
534b3e6a9a
commit
ed0b1a86aa
|
@ -19,9 +19,9 @@ namespace Kernel
|
||||||
void reschedule();
|
void reschedule();
|
||||||
void reschedule_if_idling();
|
void reschedule_if_idling();
|
||||||
|
|
||||||
void set_current_thread_sleeping(uint64_t);
|
void set_current_thread_sleeping(uint64_t wake_time);
|
||||||
|
|
||||||
void block_current_thread(Semaphore*);
|
void block_current_thread(Semaphore*, uint64_t wake_time);
|
||||||
void unblock_threads(Semaphore*);
|
void unblock_threads(Semaphore*);
|
||||||
// Makes sleeping or blocked thread with tid active.
|
// Makes sleeping or blocked thread with tid active.
|
||||||
void unblock_thread(pid_t tid);
|
void unblock_thread(pid_t tid);
|
||||||
|
@ -36,6 +36,8 @@ namespace Kernel
|
||||||
private:
|
private:
|
||||||
Scheduler() = default;
|
Scheduler() = default;
|
||||||
|
|
||||||
|
void set_current_thread_sleeping_impl(uint64_t wake_time);
|
||||||
|
|
||||||
void wake_threads();
|
void wake_threads();
|
||||||
[[nodiscard]] bool save_current_thread();
|
[[nodiscard]] bool save_current_thread();
|
||||||
void remove_and_advance_current_thread();
|
void remove_and_advance_current_thread();
|
||||||
|
@ -50,18 +52,14 @@ namespace Kernel
|
||||||
: thread(thread)
|
: thread(thread)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
Thread* thread;
|
Thread* thread;
|
||||||
union
|
uint64_t wake_time;
|
||||||
{
|
Semaphore* semaphore;
|
||||||
uint64_t wake_time;
|
|
||||||
Semaphore* semaphore;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Thread* m_idle_thread { nullptr };
|
Thread* m_idle_thread { nullptr };
|
||||||
BAN::LinkedList<SchedulerThread> m_active_threads;
|
BAN::LinkedList<SchedulerThread> m_active_threads;
|
||||||
BAN::LinkedList<SchedulerThread> m_sleeping_threads;
|
BAN::LinkedList<SchedulerThread> m_sleeping_threads;
|
||||||
BAN::LinkedList<SchedulerThread> m_blocking_threads;
|
|
||||||
|
|
||||||
BAN::LinkedList<SchedulerThread>::iterator m_current_thread;
|
BAN::LinkedList<SchedulerThread>::iterator m_current_thread;
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,9 @@ namespace Kernel
|
||||||
class Semaphore
|
class Semaphore
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void block();
|
void block_indefinite();
|
||||||
|
void block_with_timeout(uint64_t timeout_ms);
|
||||||
|
void block_with_wake_time(uint64_t wake_time_ms);
|
||||||
void unblock();
|
void unblock();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -47,8 +47,10 @@ namespace Kernel
|
||||||
void handle_signal(int signal = 0);
|
void handle_signal(int signal = 0);
|
||||||
bool add_signal(int signal);
|
bool add_signal(int signal);
|
||||||
|
|
||||||
// blocks semaphore and returns either on unblock, eintr or spuriously
|
// blocks semaphore and returns either on unblock, eintr, spuriously or after timeout
|
||||||
BAN::ErrorOr<void> block_or_eintr(Semaphore&);
|
BAN::ErrorOr<void> block_or_eintr_indefinite(Semaphore& semaphore);
|
||||||
|
BAN::ErrorOr<void> block_or_eintr_or_timeout(Semaphore& semaphore, uint64_t timeout_ms, bool etimedout);
|
||||||
|
BAN::ErrorOr<void> block_or_eintr_or_waketime(Semaphore& semaphore, uint64_t wake_time_ms, bool etimedout);
|
||||||
|
|
||||||
void set_return_rsp(uintptr_t& rsp) { m_return_rsp = &rsp; }
|
void set_return_rsp(uintptr_t& rsp) { m_return_rsp = &rsp; }
|
||||||
void set_return_rip(uintptr_t& rip) { m_return_rip = &rip; }
|
void set_return_rip(uintptr_t& rip) { m_return_rip = &rip; }
|
||||||
|
|
|
@ -64,9 +64,8 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
while (!s_instance->m_should_sync)
|
while (!s_instance->m_should_sync)
|
||||||
{
|
{
|
||||||
s_instance->m_device_lock.unlock();
|
LockFreeGuard _(s_instance->m_device_lock);
|
||||||
s_instance->m_sync_semaphore.block();
|
s_instance->m_sync_semaphore.block_indefinite();
|
||||||
s_instance->m_device_lock.lock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& device : s_instance->m_devices)
|
for (auto& device : s_instance->m_devices)
|
||||||
|
@ -105,7 +104,7 @@ namespace Kernel
|
||||||
m_sync_semaphore.unblock();
|
m_sync_semaphore.unblock();
|
||||||
}
|
}
|
||||||
if (should_block)
|
if (should_block)
|
||||||
m_sync_done.block();
|
m_sync_done.block_indefinite();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DevFileSystem::add_device(BAN::RefPtr<Device> device)
|
void DevFileSystem::add_device(BAN::RefPtr<Device> device)
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include <kernel/FS/Pipe.h>
|
#include <kernel/FS/Pipe.h>
|
||||||
#include <kernel/LockGuard.h>
|
#include <kernel/LockGuard.h>
|
||||||
|
#include <kernel/Thread.h>
|
||||||
#include <kernel/Timer/Timer.h>
|
#include <kernel/Timer/Timer.h>
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
|
@ -46,9 +47,8 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
if (m_writing_count == 0)
|
if (m_writing_count == 0)
|
||||||
return 0;
|
return 0;
|
||||||
m_lock.unlock();
|
LockFreeGuard lock_free(m_lock);
|
||||||
m_semaphore.block();
|
TRY(Thread::current().block_or_eintr_indefinite(m_semaphore));
|
||||||
m_lock.lock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t to_copy = BAN::Math::min<size_t>(buffer.size(), m_buffer.size());
|
size_t to_copy = BAN::Math::min<size_t>(buffer.size(), m_buffer.size());
|
||||||
|
|
|
@ -195,7 +195,7 @@ namespace Kernel::Input
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (m_event_queue.empty())
|
if (m_event_queue.empty())
|
||||||
TRY(Thread::current().block_or_eintr(m_semaphore));
|
TRY(Thread::current().block_or_eintr_indefinite(m_semaphore));
|
||||||
|
|
||||||
CriticalScope _;
|
CriticalScope _;
|
||||||
if (m_event_queue.empty())
|
if (m_event_queue.empty())
|
||||||
|
|
|
@ -179,7 +179,7 @@ namespace Kernel::Input
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (m_event_queue.empty())
|
if (m_event_queue.empty())
|
||||||
TRY(Thread::current().block_or_eintr(m_semaphore));
|
TRY(Thread::current().block_or_eintr_indefinite(m_semaphore));
|
||||||
|
|
||||||
CriticalScope _;
|
CriticalScope _;
|
||||||
if (m_event_queue.empty())
|
if (m_event_queue.empty())
|
||||||
|
|
|
@ -155,7 +155,7 @@ namespace Kernel
|
||||||
|
|
||||||
if (!pending.has_value())
|
if (!pending.has_value())
|
||||||
{
|
{
|
||||||
m_pending_semaphore.block();
|
m_pending_semaphore.block_indefinite();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -239,7 +239,7 @@ namespace Kernel
|
||||||
|
|
||||||
if (!pending.has_value())
|
if (!pending.has_value())
|
||||||
{
|
{
|
||||||
m_pending_semaphore.block();
|
m_pending_semaphore.block_indefinite();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -65,7 +65,7 @@ namespace Kernel
|
||||||
BAN::ErrorOr<size_t> UDPSocket::read_packet(BAN::ByteSpan buffer, sockaddr_in* sender_addr)
|
BAN::ErrorOr<size_t> UDPSocket::read_packet(BAN::ByteSpan buffer, sockaddr_in* sender_addr)
|
||||||
{
|
{
|
||||||
while (m_packets.empty())
|
while (m_packets.empty())
|
||||||
TRY(Thread::current().block_or_eintr(m_packet_semaphore));
|
TRY(Thread::current().block_or_eintr_indefinite(m_packet_semaphore));
|
||||||
|
|
||||||
LockGuard _(m_packet_lock);
|
LockGuard _(m_packet_lock);
|
||||||
if (m_packets.empty())
|
if (m_packets.empty())
|
||||||
|
|
|
@ -66,7 +66,7 @@ namespace Kernel
|
||||||
return BAN::Error::from_errno(EINVAL);
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
|
||||||
while (connection_info.pending_connections.empty())
|
while (connection_info.pending_connections.empty())
|
||||||
TRY(Thread::current().block_or_eintr(connection_info.pending_semaphore));
|
TRY(Thread::current().block_or_eintr_indefinite(connection_info.pending_semaphore));
|
||||||
|
|
||||||
BAN::RefPtr<UnixDomainSocket> pending;
|
BAN::RefPtr<UnixDomainSocket> pending;
|
||||||
|
|
||||||
|
@ -158,7 +158,7 @@ namespace Kernel
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TRY(Thread::current().block_or_eintr(target_info.pending_semaphore));
|
TRY(Thread::current().block_or_eintr_indefinite(target_info.pending_semaphore));
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!connection_info.connection_done)
|
while (!connection_info.connection_done)
|
||||||
|
@ -234,7 +234,7 @@ namespace Kernel
|
||||||
while (m_packet_sizes.full() || m_packet_size_total + packet.size() > s_packet_buffer_size)
|
while (m_packet_sizes.full() || m_packet_size_total + packet.size() > s_packet_buffer_size)
|
||||||
{
|
{
|
||||||
LockFreeGuard _(m_lock);
|
LockFreeGuard _(m_lock);
|
||||||
TRY(Thread::current().block_or_eintr(m_packet_semaphore));
|
TRY(Thread::current().block_or_eintr_indefinite(m_packet_semaphore));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t* packet_buffer = reinterpret_cast<uint8_t*>(m_packet_buffer->vaddr() + m_packet_size_total);
|
uint8_t* packet_buffer = reinterpret_cast<uint8_t*>(m_packet_buffer->vaddr() + m_packet_size_total);
|
||||||
|
@ -321,7 +321,7 @@ namespace Kernel
|
||||||
while (m_packet_size_total == 0)
|
while (m_packet_size_total == 0)
|
||||||
{
|
{
|
||||||
LockFreeGuard _(m_lock);
|
LockFreeGuard _(m_lock);
|
||||||
TRY(Thread::current().block_or_eintr(m_packet_semaphore));
|
TRY(Thread::current().block_or_eintr_indefinite(m_packet_semaphore));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t* packet_buffer = reinterpret_cast<uint8_t*>(m_packet_buffer->vaddr());
|
uint8_t* packet_buffer = reinterpret_cast<uint8_t*>(m_packet_buffer->vaddr());
|
||||||
|
|
|
@ -568,7 +568,7 @@ namespace Kernel
|
||||||
return BAN::Error::from_errno(ECHILD);
|
return BAN::Error::from_errno(ECHILD);
|
||||||
|
|
||||||
while (!target->m_exit_status.exited)
|
while (!target->m_exit_status.exited)
|
||||||
TRY(Thread::current().block_or_eintr(target->m_exit_status.semaphore));
|
TRY(Thread::current().block_or_eintr_indefinite(target->m_exit_status.semaphore));
|
||||||
|
|
||||||
int exit_status = target->m_exit_status.exit_code;
|
int exit_status = target->m_exit_status.exit_code;
|
||||||
target->m_exit_status.waiting--;
|
target->m_exit_status.waiting--;
|
||||||
|
|
|
@ -278,12 +278,9 @@ namespace Kernel
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scheduler::set_current_thread_sleeping(uint64_t wake_time)
|
void Scheduler::set_current_thread_sleeping_impl(uint64_t wake_time)
|
||||||
{
|
{
|
||||||
VERIFY_STI();
|
VERIFY_CLI();
|
||||||
DISABLE_INTERRUPTS();
|
|
||||||
|
|
||||||
ASSERT(m_current_thread);
|
|
||||||
|
|
||||||
if (save_current_thread())
|
if (save_current_thread())
|
||||||
{
|
{
|
||||||
|
@ -310,42 +307,37 @@ namespace Kernel
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scheduler::block_current_thread(Semaphore* semaphore)
|
void Scheduler::set_current_thread_sleeping(uint64_t wake_time)
|
||||||
{
|
{
|
||||||
VERIFY_STI();
|
VERIFY_STI();
|
||||||
DISABLE_INTERRUPTS();
|
DISABLE_INTERRUPTS();
|
||||||
|
|
||||||
ASSERT(m_current_thread);
|
ASSERT(m_current_thread);
|
||||||
|
|
||||||
if (save_current_thread())
|
m_current_thread->semaphore = nullptr;
|
||||||
{
|
set_current_thread_sleeping_impl(wake_time);
|
||||||
ENABLE_INTERRUPTS();
|
}
|
||||||
return;
|
|
||||||
}
|
void Scheduler::block_current_thread(Semaphore* semaphore, uint64_t wake_time)
|
||||||
|
{
|
||||||
|
VERIFY_STI();
|
||||||
|
DISABLE_INTERRUPTS();
|
||||||
|
|
||||||
|
ASSERT(m_current_thread);
|
||||||
|
|
||||||
m_current_thread->semaphore = semaphore;
|
m_current_thread->semaphore = semaphore;
|
||||||
m_active_threads.move_element_to_other_linked_list(
|
set_current_thread_sleeping_impl(wake_time);
|
||||||
m_blocking_threads,
|
|
||||||
m_blocking_threads.end(),
|
|
||||||
m_current_thread
|
|
||||||
);
|
|
||||||
|
|
||||||
m_current_thread = {};
|
|
||||||
advance_current_thread();
|
|
||||||
|
|
||||||
execute_current_thread();
|
|
||||||
ASSERT_NOT_REACHED();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scheduler::unblock_threads(Semaphore* semaphore)
|
void Scheduler::unblock_threads(Semaphore* semaphore)
|
||||||
{
|
{
|
||||||
CriticalScope critical;
|
CriticalScope critical;
|
||||||
|
|
||||||
for (auto it = m_blocking_threads.begin(); it != m_blocking_threads.end();)
|
for (auto it = m_sleeping_threads.begin(); it != m_sleeping_threads.end();)
|
||||||
{
|
{
|
||||||
if (it->semaphore == semaphore)
|
if (it->semaphore == semaphore)
|
||||||
{
|
{
|
||||||
it = m_blocking_threads.move_element_to_other_linked_list(
|
it = m_sleeping_threads.move_element_to_other_linked_list(
|
||||||
m_active_threads,
|
m_active_threads,
|
||||||
m_active_threads.end(),
|
m_active_threads.end(),
|
||||||
it
|
it
|
||||||
|
@ -362,19 +354,6 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
CriticalScope _;
|
CriticalScope _;
|
||||||
|
|
||||||
for (auto it = m_blocking_threads.begin(); it != m_blocking_threads.end(); it++)
|
|
||||||
{
|
|
||||||
if (it->thread->tid() == tid)
|
|
||||||
{
|
|
||||||
m_blocking_threads.move_element_to_other_linked_list(
|
|
||||||
m_active_threads,
|
|
||||||
m_active_threads.end(),
|
|
||||||
it
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto it = m_sleeping_threads.begin(); it != m_sleeping_threads.end(); it++)
|
for (auto it = m_sleeping_threads.begin(); it != m_sleeping_threads.end(); it++)
|
||||||
{
|
{
|
||||||
if (it->thread->tid() == tid)
|
if (it->thread->tid() == tid)
|
||||||
|
|
|
@ -1,12 +1,23 @@
|
||||||
#include <kernel/Scheduler.h>
|
#include <kernel/Scheduler.h>
|
||||||
#include <kernel/Semaphore.h>
|
#include <kernel/Semaphore.h>
|
||||||
|
#include <kernel/Timer/Timer.h>
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
|
||||||
void Semaphore::block()
|
void Semaphore::block_indefinite()
|
||||||
{
|
{
|
||||||
Scheduler::get().block_current_thread(this);
|
Scheduler::get().block_current_thread(this, ~(uint64_t)0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Semaphore::block_with_timeout(uint64_t timeout_ms)
|
||||||
|
{
|
||||||
|
Scheduler::get().block_current_thread(this, SystemTimer::get().ms_since_boot() + timeout_ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Semaphore::block_with_wake_time(uint64_t wake_time)
|
||||||
|
{
|
||||||
|
Scheduler::get().block_current_thread(this, wake_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Semaphore::unblock()
|
void Semaphore::unblock()
|
||||||
|
|
|
@ -67,13 +67,12 @@ namespace Kernel
|
||||||
|
|
||||||
while (SystemTimer::get().ms_since_boot() < start_time + s_nvme_command_timeout_ms)
|
while (SystemTimer::get().ms_since_boot() < start_time + s_nvme_command_timeout_ms)
|
||||||
{
|
{
|
||||||
if (!m_done)
|
if (m_done)
|
||||||
{
|
{
|
||||||
m_semaphore.block();
|
m_done = false;
|
||||||
continue;
|
return m_status;
|
||||||
}
|
}
|
||||||
m_done = false;
|
m_semaphore.block_with_wake_time(start_time + s_nvme_command_timeout_ms);
|
||||||
return m_status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0xFFFF;
|
return 0xFFFF;
|
||||||
|
|
|
@ -92,7 +92,7 @@ namespace Kernel
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
while (!TTY::current()->m_tty_ctrl.receive_input)
|
while (!TTY::current()->m_tty_ctrl.receive_input)
|
||||||
TTY::current()->m_tty_ctrl.semaphore.block();
|
TTY::current()->m_tty_ctrl.semaphore.block_indefinite();
|
||||||
|
|
||||||
Input::KeyEvent event;
|
Input::KeyEvent event;
|
||||||
size_t read = MUST(inode->read(0, BAN::ByteSpan::from(event)));
|
size_t read = MUST(inode->read(0, BAN::ByteSpan::from(event)));
|
||||||
|
@ -323,7 +323,7 @@ namespace Kernel
|
||||||
uint32_t depth = m_lock.lock_depth();
|
uint32_t depth = m_lock.lock_depth();
|
||||||
for (uint32_t i = 0; i < depth; i++)
|
for (uint32_t i = 0; i < depth; i++)
|
||||||
m_lock.unlock();
|
m_lock.unlock();
|
||||||
auto eintr = Thread::current().block_or_eintr(m_output.semaphore);
|
auto eintr = Thread::current().block_or_eintr_indefinite(m_output.semaphore);
|
||||||
for (uint32_t i = 0; i < depth; i++)
|
for (uint32_t i = 0; i < depth; i++)
|
||||||
m_lock.lock();
|
m_lock.lock();
|
||||||
if (eintr.is_error())
|
if (eintr.is_error())
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include <kernel/Process.h>
|
#include <kernel/Process.h>
|
||||||
#include <kernel/Scheduler.h>
|
#include <kernel/Scheduler.h>
|
||||||
#include <kernel/Thread.h>
|
#include <kernel/Thread.h>
|
||||||
|
#include <kernel/Timer/Timer.h>
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
@ -30,7 +31,6 @@ namespace Kernel
|
||||||
void Thread::terminate()
|
void Thread::terminate()
|
||||||
{
|
{
|
||||||
CriticalScope _;
|
CriticalScope _;
|
||||||
ASSERT(this == &Thread::current());
|
|
||||||
m_state = Thread::State::Terminated;
|
m_state = Thread::State::Terminated;
|
||||||
if (this == &Thread::current())
|
if (this == &Thread::current())
|
||||||
Scheduler::get().execute_current_thread();
|
Scheduler::get().execute_current_thread();
|
||||||
|
@ -343,16 +343,34 @@ namespace Kernel
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<void> Thread::block_or_eintr(Semaphore& semaphore)
|
BAN::ErrorOr<void> Thread::block_or_eintr_indefinite(Semaphore& semaphore)
|
||||||
{
|
{
|
||||||
if (is_interrupted_by_signal())
|
if (is_interrupted_by_signal())
|
||||||
return BAN::Error::from_errno(EINTR);
|
return BAN::Error::from_errno(EINTR);
|
||||||
semaphore.block();
|
semaphore.block_indefinite();
|
||||||
if (is_interrupted_by_signal())
|
if (is_interrupted_by_signal())
|
||||||
return BAN::Error::from_errno(EINTR);
|
return BAN::Error::from_errno(EINTR);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<void> Thread::block_or_eintr_or_timeout(Semaphore& semaphore, uint64_t timeout_ms, bool etimedout)
|
||||||
|
{
|
||||||
|
uint64_t wake_time_ms = SystemTimer::get().ms_since_boot() + timeout_ms;
|
||||||
|
return block_or_eintr_or_waketime(semaphore, wake_time_ms, etimedout);
|
||||||
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<void> Thread::block_or_eintr_or_waketime(Semaphore& semaphore, uint64_t wake_time_ms, bool etimedout)
|
||||||
|
{
|
||||||
|
if (is_interrupted_by_signal())
|
||||||
|
return BAN::Error::from_errno(EINTR);
|
||||||
|
semaphore.block_with_wake_time(wake_time_ms);
|
||||||
|
if (is_interrupted_by_signal())
|
||||||
|
return BAN::Error::from_errno(EINTR);
|
||||||
|
if (etimedout && SystemTimer::get().ms_since_boot() >= wake_time_ms)
|
||||||
|
return BAN::Error::from_errno(ETIMEDOUT);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
void Thread::validate_stack() const
|
void Thread::validate_stack() const
|
||||||
{
|
{
|
||||||
if (stack_base() <= m_rsp && m_rsp <= stack_base() + stack_size())
|
if (stack_base() <= m_rsp && m_rsp <= stack_base() + stack_size())
|
||||||
|
|
Loading…
Reference in New Issue