From 5d152811b213d2f0436489971c024228bee6fcc4 Mon Sep 17 00:00:00 2001
From: kodin <kodin@yourmoms.house>
Date: Tue, 26 Nov 2024 15:53:50 -0600
Subject: [PATCH] Interrupt Forwarding (#22)

Co-authored-by: Talha Qamar <qamartalha@proton.me>
Reviewed-on: https://git.ablecorp.us/AbleOS/ableos/pulls/22
Co-authored-by: kodin <kodin@yourmoms.house>
Co-committed-by: kodin <kodin@yourmoms.house>
---
 kernel/src/arch/x86_64/interrupts.rs    |  7 ++++++-
 kernel/src/holeybytes/ecah.rs           | 11 ++++++++++
 kernel/src/task.rs                      | 28 ++++++++++++++++++++++---
 sysdata/libraries/stn/src/sleep.hb      |  1 +
 sysdata/programs/timer_test/meta.toml   | 11 ++++++++++
 sysdata/programs/timer_test/src/main.hb |  8 +++++++
 sysdata/system_config.toml              | 27 +++++++++++++-----------
 7 files changed, 77 insertions(+), 16 deletions(-)
 create mode 100644 sysdata/programs/timer_test/meta.toml
 create mode 100644 sysdata/programs/timer_test/src/main.hb

diff --git a/kernel/src/arch/x86_64/interrupts.rs b/kernel/src/arch/x86_64/interrupts.rs
index 4bd3c8a..28b432c 100644
--- a/kernel/src/arch/x86_64/interrupts.rs
+++ b/kernel/src/arch/x86_64/interrupts.rs
@@ -62,7 +62,7 @@ extern "x86-interrupt" fn page_fault(
 }
 
 extern "x86-interrupt" fn timer(_isf: InterruptStackFrame) {
-    // interrupt(Interrupt::Timer);
+    interrupt(Interrupt::Timer);
 
     unsafe {
         LAPIC.end_of_interrupt();
@@ -85,6 +85,7 @@ extern "x86-interrupt" fn spurious(_: InterruptStackFrame) {
 
 fn interrupt(interrupt_type: Interrupt) {
     use crate::arch::INTERRUPT_LIST;
+    use crate::kmain::EXECUTOR;
     let il = INTERRUPT_LIST.lock();
     let val = il.list.get(&interrupt_type).unwrap();
 
@@ -107,4 +108,8 @@ fn interrupt(interrupt_type: Interrupt) {
 
         // log::info!("{}", buffer);
     }
+
+    unsafe{
+        EXECUTOR.send_interrupt(interrupt_type as u8);
+    }
 }
diff --git a/kernel/src/holeybytes/ecah.rs b/kernel/src/holeybytes/ecah.rs
index a34f683..b1561f9 100644
--- a/kernel/src/holeybytes/ecah.rs
+++ b/kernel/src/holeybytes/ecah.rs
@@ -1,5 +1,7 @@
 //! Environment call handling routines
 
+use log::log;
+
 use {alloc::boxed::Box, core::cell::LazyCell, hbvm::mem::Address};
 
 use crate::{
@@ -242,6 +244,15 @@ pub fn handler(vm: &mut Vm, pid: &usize) {
                 vm.registers[3] = x
             }
         }
+        6 => { // Wait till interrupt
+            use crate::kmain::EXECUTOR;
+            let interrupt_type = vm.registers[3].cast::<u8>();
+            info!("Interrupt subscribled: {}", interrupt_type);
+            unsafe{
+                EXECUTOR.pause(pid.clone());
+                LazyCell::<Executor>::get_mut(&mut EXECUTOR).unwrap().interrupt_subscribe(pid.clone(), interrupt_type);
+            }
+        }
         _ => {
             log::error!("Syscall unknown {:?}{:?}", ecall_number, vm.registers);
         }
diff --git a/kernel/src/task.rs b/kernel/src/task.rs
index 01c6688..c79140f 100644
--- a/kernel/src/task.rs
+++ b/kernel/src/task.rs
@@ -35,6 +35,7 @@ impl<T: Future<Output = ()> + Send> Process for T {}
 pub struct Executor {
     tasks:      Slab<Task>,
     task_queue: Arc<SegQueue<usize>>,
+    interrupt_lookup: [Option<usize>; u8::MAX as usize],
 }
 
 impl Executor {
@@ -42,6 +43,7 @@ impl Executor {
         Self {
             tasks:      Slab::new(),
             task_queue: Arc::new(SegQueue::new()),
+            interrupt_lookup: [None; u8::MAX as usize],
         }
     }
 
@@ -52,19 +54,23 @@ impl Executor {
         id
     }
 
-    pub fn pause(&mut self, id: usize) {
+    pub fn pause(&self, id: usize) {
         if let Some(task) = self.tasks.get(id) {
             task.set_paused(true);
         }
     }
 
-    pub fn unpause(&mut self, id: usize) {
+    pub fn unpause(&self, id: usize) {
         if let Some(task) = self.tasks.get(id) {
             task.set_paused(false);
             self.task_queue.push(id);
         }
     }
 
+    pub fn interrupt_subscribe(&mut self, pid : usize, interrupt_type: u8){
+        self.interrupt_lookup[interrupt_type as usize] = Some(pid);
+    }
+
     pub fn run(&mut self) {
         let mut task_batch = [0; 32];
         loop {
@@ -79,7 +85,8 @@ impl Executor {
             }
 
             if batch_len == 0 {
-                break;
+                //break;
+                continue;
             }
 
             for &(mut id) in &task_batch[..batch_len] {
@@ -93,11 +100,26 @@ impl Executor {
 
                     if let Poll::Ready(()) = task.poll(&mut cx) {
                         self.tasks.remove(id);
+                        self.interrupt_lookup.map(|pid|{
+                            if let Some(pid) = pid{
+                                if pid == id {
+                                    return None;
+                                }
+                            }
+                            return pid;
+                        });
                     }
                 }
             }
         }
     }
+
+    pub fn send_interrupt(&self, interrupt : u8){
+        let id = self.interrupt_lookup[interrupt as usize];
+        if let Some(id) = id{
+            self.unpause(id);
+        }
+    }
 }
 
 struct Task {
diff --git a/sysdata/libraries/stn/src/sleep.hb b/sysdata/libraries/stn/src/sleep.hb
index d323267..5aeaf14 100644
--- a/sysdata/libraries/stn/src/sleep.hb
+++ b/sysdata/libraries/stn/src/sleep.hb
@@ -3,4 +3,5 @@ subscribe_to_interrupt := fn(interrupt_number: u8): bool {
 }
 // Pauses execution until the interrupt occures
 sleep_until_interrupt := fn(interrupt_number: u8): void {
+	@eca(6, interrupt_number)
 }
\ No newline at end of file
diff --git a/sysdata/programs/timer_test/meta.toml b/sysdata/programs/timer_test/meta.toml
new file mode 100644
index 0000000..c05908d
--- /dev/null
+++ b/sysdata/programs/timer_test/meta.toml
@@ -0,0 +1,11 @@
+[package]
+name = "timer_test"
+authors = ["Talha Qamar"]
+
+[dependants.libraries]
+
+[dependants.binaries]
+hblang.version = "1.0.0"
+
+[build]
+command = "hblang src/main.hb"
diff --git a/sysdata/programs/timer_test/src/main.hb b/sysdata/programs/timer_test/src/main.hb
new file mode 100644
index 0000000..b2142ea
--- /dev/null
+++ b/sysdata/programs/timer_test/src/main.hb
@@ -0,0 +1,8 @@
+sleep := @use("../../../libraries/stn/src/sleep.hb")
+log := @use("../../../libraries/stn/src/log.hb")
+
+main := fn(): int {
+	log.info("BEFORE\0")
+	sleep.sleep_until_interrupt(32)
+	log.info("AFTER\0")
+}
\ No newline at end of file
diff --git a/sysdata/system_config.toml b/sysdata/system_config.toml
index a63f170..34ab790 100644
--- a/sysdata/system_config.toml
+++ b/sysdata/system_config.toml
@@ -28,23 +28,26 @@ resolution = "1024x768x24"
 # [boot.limine.ableos.modules.horizon]
 # path = "boot:///horizon.hbf"
 
-[boot.limine.ableos.modules.ps2_mouse_driver]
-path = "boot:///ps2_mouse_driver.hbf"
+# path = "boot:///ps2_mouse_driver.hbf"
+# [boot.limine.ableos.modules.ps2_mouse_driver]
 
 # [boot.limine.ableos.modules.ps2_keyboard_driver]
 # path = "boot:///ps2_keyboard_driver.hbf"
 
-[boot.limine.ableos.modules.sunset_client]
-path = "boot:///sunset_client.hbf"
+[boot.limine.ableos.modules.timer_test]
+path = "boot:///timer_test.hbf"
 
-[boot.limine.ableos.modules.sunset_client_2]
-path = "boot:///sunset_client_2.hbf"
-
-[boot.limine.ableos.modules.sdoom]
-path = "boot:///sdoom.hbf"
-
-[boot.limine.ableos.modules.sunset_server]
-path = "boot:///sunset_server.hbf"
+# [boot.limine.ableos.modules.sunset_client]
+# path = "boot:///sunset_client.hbf"
+# 
+# [boot.limine.ableos.modules.sunset_client_2]
+# path = "boot:///sunset_client_2.hbf"
+# 
+# [boot.limine.ableos.modules.sdoom]
+# path = "boot:///sdoom.hbf"
+# 
+# [boot.limine.ableos.modules.sunset_server]
+# path = "boot:///sunset_server.hbf"
 
 # [boot.limine.ableos.modules.pcspkr]
 # path = "boot:///pcspkr.hbf"