mirror of
https://github.com/justinian/jsix.git
synced 2025-12-09 16:04:32 -08:00
[kernel] Use the hpet clock source in scheduler
There has been a global clock object for a while now, but scheduler was never using it, instead still using its simple increment clock. Now it uses the hpet clock.
This commit is contained in:
@@ -333,10 +333,11 @@ device_manager::probe_pci()
|
|||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t
|
static uint64_t
|
||||||
fake_clock_source(void*)
|
tsc_clock_source(void*)
|
||||||
{
|
{
|
||||||
static uint64_t value = 0;
|
uint32_t lo = 0, hi = 0;
|
||||||
return value++;
|
asm volatile ("rdtsc" : "=a" (lo), "=d" (hi));
|
||||||
|
return ((uint64_t)hi << 32) | lo;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -367,7 +368,7 @@ device_manager::init_drivers()
|
|||||||
log::info(logs::clock, "Created master clock using HPET 0: Rate %d", h.rate());
|
log::info(logs::clock, "Created master clock using HPET 0: Rate %d", h.rate());
|
||||||
} else {
|
} else {
|
||||||
//TODO: Other clocks, APIC clock?
|
//TODO: Other clocks, APIC clock?
|
||||||
master_clock = new clock(5000, fake_clock_source, nullptr);
|
master_clock = new clock(5000, tsc_clock_source, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
kassert(master_clock, "Failed to allocate master clock");
|
kassert(master_clock, "Failed to allocate master clock");
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
|
#include "clock.h"
|
||||||
#include "device_manager.h"
|
#include "device_manager.h"
|
||||||
#include "objects/endpoint.h"
|
#include "objects/endpoint.h"
|
||||||
#include "objects/process.h"
|
#include "objects/process.h"
|
||||||
#include "objects/thread.h"
|
#include "objects/thread.h"
|
||||||
#include "scheduler.h"
|
|
||||||
#include "vm_space.h"
|
#include "vm_space.h"
|
||||||
|
|
||||||
endpoint::endpoint() :
|
endpoint::endpoint() :
|
||||||
@@ -64,7 +64,7 @@ endpoint::receive(j6_tag_t *tag, void *data, size_t *data_len, uint64_t timeout)
|
|||||||
|
|
||||||
// Timeout is a duration, but wait_on_* calls need a time
|
// Timeout is a duration, but wait_on_* calls need a time
|
||||||
if (timeout)
|
if (timeout)
|
||||||
timeout += scheduler::get().clock();
|
timeout += clock::get().value();
|
||||||
|
|
||||||
if (!check_signal(j6_signal_endpoint_can_recv)) {
|
if (!check_signal(j6_signal_endpoint_can_recv)) {
|
||||||
assert_signal(j6_signal_endpoint_can_send);
|
assert_signal(j6_signal_endpoint_can_send);
|
||||||
|
|||||||
@@ -36,8 +36,7 @@ struct run_queue
|
|||||||
};
|
};
|
||||||
|
|
||||||
scheduler::scheduler(unsigned cpus) :
|
scheduler::scheduler(unsigned cpus) :
|
||||||
m_next_pid {1},
|
m_next_pid {1}
|
||||||
m_clock {0}
|
|
||||||
{
|
{
|
||||||
kassert(!s_instance, "Created multiple schedulers!");
|
kassert(!s_instance, "Created multiple schedulers!");
|
||||||
if (!s_instance)
|
if (!s_instance)
|
||||||
@@ -242,11 +241,13 @@ scheduler::schedule()
|
|||||||
lapic &apic = *cpu.apic;
|
lapic &apic = *cpu.apic;
|
||||||
uint32_t remaining = apic.stop_timer();
|
uint32_t remaining = apic.stop_timer();
|
||||||
|
|
||||||
|
uint64_t now = clock::get().value();
|
||||||
|
|
||||||
// Only one CPU can be stealing at a time
|
// Only one CPU can be stealing at a time
|
||||||
if (m_steal_turn == cpu.index &&
|
if (m_steal_turn == cpu.index &&
|
||||||
m_clock - queue.last_steal > steal_frequency) {
|
now - queue.last_steal > steal_frequency) {
|
||||||
steal_work(cpu);
|
steal_work(cpu);
|
||||||
queue.last_steal = m_clock;
|
queue.last_steal = now;
|
||||||
m_steal_turn = (m_steal_turn + 1) % m_run_queues.count();
|
m_steal_turn = (m_steal_turn + 1) % m_run_queues.count();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -283,9 +284,9 @@ scheduler::schedule()
|
|||||||
}
|
}
|
||||||
|
|
||||||
clock::get().update();
|
clock::get().update();
|
||||||
prune(queue, ++m_clock);
|
prune(queue, now);
|
||||||
if (m_clock - queue.last_promotion > promote_frequency)
|
if (now - queue.last_promotion > promote_frequency)
|
||||||
check_promotions(queue, m_clock);
|
check_promotions(queue, now);
|
||||||
|
|
||||||
priority = 0;
|
priority = 0;
|
||||||
while (queue.ready[priority].empty()) {
|
while (queue.ready[priority].empty()) {
|
||||||
@@ -293,10 +294,10 @@ scheduler::schedule()
|
|||||||
kassert(priority < num_priorities, "All runlists are empty");
|
kassert(priority < num_priorities, "All runlists are empty");
|
||||||
}
|
}
|
||||||
|
|
||||||
queue.current->last_ran = m_clock;
|
queue.current->last_ran = now;
|
||||||
|
|
||||||
auto *next = queue.ready[priority].pop_front();
|
auto *next = queue.ready[priority].pop_front();
|
||||||
next->last_ran = m_clock;
|
next->last_ran = now;
|
||||||
apic.reset_timer(next->time_left);
|
apic.reset_timer(next->time_left);
|
||||||
|
|
||||||
if (next == queue.current) {
|
if (next == queue.current) {
|
||||||
@@ -313,7 +314,7 @@ scheduler::schedule()
|
|||||||
log::debug(logs::sched, "CPU%02x switching threads %llx->%llx",
|
log::debug(logs::sched, "CPU%02x switching threads %llx->%llx",
|
||||||
cpu.index, th->koid(), next_thread->koid());
|
cpu.index, th->koid(), next_thread->koid());
|
||||||
log::debug(logs::sched, " priority %d time left %d @ %lld.",
|
log::debug(logs::sched, " priority %d time left %d @ %lld.",
|
||||||
next->priority, next->time_left, m_clock);
|
next->priority, next->time_left, now);
|
||||||
log::debug(logs::sched, " PML4 %llx", next->pml4);
|
log::debug(logs::sched, " PML4 %llx", next->pml4);
|
||||||
|
|
||||||
queue.lock.release(&waiter);
|
queue.lock.release(&waiter);
|
||||||
|
|||||||
@@ -72,8 +72,6 @@ public:
|
|||||||
/// \arg t The new thread's TCB
|
/// \arg t The new thread's TCB
|
||||||
void add_thread(TCB *t);
|
void add_thread(TCB *t);
|
||||||
|
|
||||||
uint64_t clock() const { return m_clock; }
|
|
||||||
|
|
||||||
/// Get a reference to the scheduler
|
/// Get a reference to the scheduler
|
||||||
/// \returns A reference to the global system scheduler
|
/// \returns A reference to the global system scheduler
|
||||||
static scheduler & get() { return *s_instance; }
|
static scheduler & get() { return *s_instance; }
|
||||||
@@ -95,9 +93,6 @@ private:
|
|||||||
|
|
||||||
util::vector<run_queue> m_run_queues;
|
util::vector<run_queue> m_run_queues;
|
||||||
|
|
||||||
// TODO: lol a real clock
|
|
||||||
uint64_t m_clock = 0;
|
|
||||||
|
|
||||||
unsigned m_steal_turn = 0;
|
unsigned m_steal_turn = 0;
|
||||||
static scheduler *s_instance;
|
static scheduler *s_instance;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -160,7 +160,7 @@ main(int argc, const char **argv)
|
|||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
uint64_t tag = 0;
|
uint64_t tag = 0;
|
||||||
result = j6_endpoint_receive(endp, &tag, nullptr, &len, 10);
|
result = j6_endpoint_receive(endp, &tag, nullptr, &len, 10000);
|
||||||
if (result == j6_err_timed_out) {
|
if (result == j6_err_timed_out) {
|
||||||
com1.handle_interrupt();
|
com1.handle_interrupt();
|
||||||
com2.handle_interrupt();
|
com2.handle_interrupt();
|
||||||
|
|||||||
Reference in New Issue
Block a user