[kernel] Add an IPI to tell a CPU to run the scheduler

When waking another thread, if that thread has a more urgent priority
than the current thread on the same CPU, send that CPU an IPI to tell it
to run its scheduler.

Related changes in this commit:

- Addition of the ipiSchedule isr (vector 0xe4) and its handler in
  isr_handler().
- Change the APIC's send_ipi* functions to take an isr enum and not an
  int for their vector parameter
- Thread TCBs now contain a pointer to their current CPU's cpu_data
  structure
- Add the maybe_schedule() call to the scheduler, which sends the
  schedule IPI to the given thread's CPU only when that CPU is running a
  less-urgent thread.
- Move the locking of a run queue lock earlier in schedule() instead of
  taking the lock in steal_work() and again in schedule().
This commit is contained in:
Justin C. Miller
2022-02-26 14:04:14 -08:00
parent 40274f5fac
commit 982442eb00
10 changed files with 73 additions and 36 deletions

View File

@@ -53,7 +53,17 @@ thread::block()
void
thread::wake(uint64_t value)
{
if (has_state(state::ready))
return;
m_wake_value = value;
wake_only();
scheduler::get().maybe_schedule(tcb());
}
void
thread::wake_only()
{
m_wake_timeout = 0;
set_state(state::ready);
}

View File

@@ -9,6 +9,7 @@
#include "objects/kobject.h"
struct cpu_data;
struct page_table;
namespace obj {
@@ -37,6 +38,7 @@ struct TCB
uint64_t last_ran;
uintptr_t kernel_stack;
cpu_data *cpu;
};
using tcb_list = util::linked_list<TCB>;
@@ -45,15 +47,6 @@ using tcb_node = tcb_list::item_type;
namespace obj {
enum class wait_type : uint8_t
{
none = 0x00,
signal = 0x01,
time = 0x02,
object = 0x04,
};
is_bitfield(wait_type);
class process;
class thread :
@@ -109,6 +102,10 @@ public:
/// \arg value The value that block() should return
void wake(uint64_t value = 0);
/// Set this thread as awake, but do not call the scheduler
/// or set the wake value.
void wake_only();
/// Set a timeout to unblock this thread
/// \arg time The clock time at which to wake. 0 for no timeout.
inline void set_wake_timeout(uint64_t time) { m_wake_timeout = time; }