summaryrefslogtreecommitdiff
path: root/kernel/src/arch/x86_64/schedule_timer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/src/arch/x86_64/schedule_timer.cpp')
-rw-r--r--kernel/src/arch/x86_64/schedule_timer.cpp58
1 files changed, 58 insertions, 0 deletions
diff --git a/kernel/src/arch/x86_64/schedule_timer.cpp b/kernel/src/arch/x86_64/schedule_timer.cpp
new file mode 100644
index 0000000..97882c7
--- /dev/null
+++ b/kernel/src/arch/x86_64/schedule_timer.cpp
@@ -0,0 +1,58 @@
+#include <arch/x86_64/schedule_timer.hpp>
+#include <arch/x86_64/cpu/idt.hpp>
+#include <arch/x86_64/cpu/xapic.hpp>
+#include <arch/x86_64/cpu_local.hpp>
+#include <generic/scheduling.hpp>
+#include <klibc/stdio.hpp>
+#include <generic/mp.hpp>
+#include <generic/time.hpp>
+#include <generic/lock/spinlock.hpp>
+#include <atomic>
+
+extern "C" void scheduler_timer_asm();
+
+int is_timer_off = 0;
+std::atomic<int> stfu_cpus = 0;
+
+extern "C" void timer_tick(x86_64::idt::int_frame_t* ctx) {
+
+ if(is_timer_off) {
+ stfu_cpus++;
+ arch::hcf();
+ }
+
+ process::schedule((void*)ctx);
+ static std::atomic<int> i = 0;
+ klibc::printf("timer tick %lli %d\r", i++,x86_64::cpu_data()->cpu);
+ x86_64::apic::eoi();
+}
+
+void x86_64::schedule_timer::off() {
+ is_timer_off = 1;
+
+ if(mp::cpu_count() <= 1)
+ return;
+
+ std::uint32_t timeout = 10;
+
+ klibc::printf("Poweroff: Waiting for all cpus to done work\r\n"); // used from poweroff so
+ while(stfu_cpus != (std::int32_t)(mp::cpu_count() - 1)) {
+ arch::memory_barrier();
+
+ if(--timeout == 0) {
+ klibc::printf("Poweroff: Can't wait longer, forching them to be disabled\r\n");
+ x86_64::lapic::off();
+ return;
+ }
+
+ if(time::timer) {
+ time::timer->sleep(50000);
+ } else {
+ arch::pause();
+ }
+ }
+}
+
+void x86_64::schedule_timer::init() {
+ x86_64::idt::set_entry((std::uint64_t)scheduler_timer_asm,32, 0x8E, 2);
+} \ No newline at end of file