From 9142c02da04e6ab5befa10430d90655c835880f1 Mon Sep 17 00:00:00 2001
From: koniifer <koniifer@proton.me>
Date: Thu, 30 Jan 2025 21:17:00 +0000
Subject: [PATCH] implement stn.process.fork, also various bug fixes, update
 dependencies

---
 Cargo.lock                                    | 68 ++++++++---------
 kernel/src/holeybytes/ecah.rs                 | 76 ++++++++++++-------
 kernel/src/holeybytes/mem.rs                  |  3 +-
 kernel/src/holeybytes/mod.rs                  | 11 ++-
 kernel/src/kmain.rs                           |  7 +-
 sysdata/libraries/horizon_api/src/lib.hb      |  2 +-
 .../libraries/stn/src/alloc/block_alloc.hb    |  2 +-
 sysdata/libraries/stn/src/dt.hb               |  2 +-
 sysdata/libraries/stn/src/log.hb              |  4 +-
 sysdata/libraries/stn/src/process.hb          |  3 +-
 sysdata/programs/horizon/src/main.hb          |  2 +-
 sysdata/programs/serial_driver/src/main.hb    |  2 +-
 sysdata/programs/test/src/main.hb             |  5 +-
 .../programs/test/src/tests/stn/process.hb    | 29 ++++++-
 14 files changed, 129 insertions(+), 87 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 7f3bc80..87da907 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -61,9 +61,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
 
 [[package]]
 name = "bitflags"
-version = "2.6.0"
+version = "2.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
+checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36"
 
 [[package]]
 name = "byteorder"
@@ -73,9 +73,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
 
 [[package]]
 name = "cc"
-version = "1.2.6"
+version = "1.2.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8d6dbb628b8f8555f86d0323c2eb39e3ec81901f4b83e091db8a6a76d316a333"
+checksum = "13208fcbb66eaeffe09b99fffbe1af420f00a7b35aa99ad683dfc1aa76145229"
 dependencies = [
  "shlex",
 ]
@@ -213,12 +213,12 @@ dependencies = [
 [[package]]
 name = "hbbytecode"
 version = "0.1.0"
-source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#d1bc70892b442376138e854450b0f423302962ef"
+source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#18e8a831ab6b710dbdd9b0d6a0880c67df0cec26"
 
 [[package]]
 name = "hblang"
 version = "0.1.0"
-source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#d1bc70892b442376138e854450b0f423302962ef"
+source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#18e8a831ab6b710dbdd9b0d6a0880c67df0cec26"
 dependencies = [
  "hashbrown",
  "hbbytecode",
@@ -229,7 +229,7 @@ dependencies = [
 [[package]]
 name = "hbvm"
 version = "0.1.0"
-source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#d1bc70892b442376138e854450b0f423302962ef"
+source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#18e8a831ab6b710dbdd9b0d6a0880c67df0cec26"
 dependencies = [
  "hbbytecode",
 ]
@@ -375,9 +375,9 @@ dependencies = [
 
 [[package]]
 name = "indexmap"
-version = "2.7.0"
+version = "2.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f"
+checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652"
 dependencies = [
  "equivalent",
  "hashbrown",
@@ -449,9 +449,9 @@ dependencies = [
 
 [[package]]
 name = "log"
-version = "0.4.22"
+version = "0.4.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
+checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f"
 
 [[package]]
 name = "logos"
@@ -512,9 +512,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.92"
+version = "1.0.93"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
+checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99"
 dependencies = [
  "unicode-ident",
 ]
@@ -539,11 +539,11 @@ dependencies = [
 
 [[package]]
 name = "raw-cpuid"
-version = "11.2.0"
+version = "11.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1ab240315c661615f2ee9f0f2cd32d5a7343a84d5ebcccb99d46e6637565e7b0"
+checksum = "c6928fa44c097620b706542d428957635951bade7143269085389d42c8a4927e"
 dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.8.0",
 ]
 
 [[package]]
@@ -561,7 +561,7 @@ dependencies = [
  "fatfs",
  "hblang",
  "log",
- "raw-cpuid 11.2.0",
+ "raw-cpuid 11.3.0",
  "str-reader",
  "toml",
  "ureq",
@@ -593,9 +593,9 @@ dependencies = [
 
 [[package]]
 name = "rustls"
-version = "0.23.20"
+version = "0.23.22"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5065c3f250cbd332cd894be57c40fa52387247659b14a2d6041d121547903b1b"
+checksum = "9fb9263ab4eb695e42321db096e3b8fbd715a59b154d5c88d82db2175b681ba7"
 dependencies = [
  "log",
  "once_cell",
@@ -608,9 +608,9 @@ dependencies = [
 
 [[package]]
 name = "rustls-pki-types"
-version = "1.10.1"
+version = "1.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d2bf47e6ff922db3825eb750c4e2ff784c6ff8fb9e13046ef6a1d1c5401b0b37"
+checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c"
 
 [[package]]
 name = "rustls-webpki"
@@ -643,9 +643,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
 
 [[package]]
 name = "semver"
-version = "1.0.24"
+version = "1.0.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba"
+checksum = "f79dfe2d285b0488816f30e700a7438c5a73d816b5b7d3ac72fbc48b0d185e03"
 
 [[package]]
 name = "serde"
@@ -726,9 +726,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
 
 [[package]]
 name = "syn"
-version = "2.0.93"
+version = "2.0.96"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c786062daee0d6db1132800e623df74274a0a87322d8e183338e01b3d98d058"
+checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -785,9 +785,9 @@ dependencies = [
 
 [[package]]
 name = "toml_edit"
-version = "0.22.22"
+version = "0.22.23"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5"
+checksum = "02a8b472d1a3d7c18e2d61a489aee3453fd9031c33e4f55bd533f4a7adca1bee"
 dependencies = [
  "indexmap",
  "serde",
@@ -802,16 +802,16 @@ version = "0.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e492212ac378a5e00da953718dafb1340d9fbaf4f27d6f3c5cab03d931d1c049"
 dependencies = [
- "bitflags 2.6.0",
+ "bitflags 2.8.0",
  "rustversion",
  "x86",
 ]
 
 [[package]]
 name = "unicode-ident"
-version = "1.0.14"
+version = "1.0.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
+checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034"
 
 [[package]]
 name = "unicode-xid"
@@ -967,9 +967,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
 
 [[package]]
 name = "winnow"
-version = "0.6.21"
+version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e6f5bb5257f2407a5425c6e749bfd9692192a73e70a6060516ac04f889087d68"
+checksum = "7e49d2d35d3fad69b39b94139037ecfb4f359f08958b9c11e7315ce770462419"
 dependencies = [
  "memchr",
 ]
@@ -1017,7 +1017,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c101112411baafbb4bf8d33e4c4a80ab5b02d74d2612331c61e8192fc9710491"
 dependencies = [
  "bit_field",
- "bitflags 2.6.0",
+ "bitflags 2.8.0",
  "rustversion",
  "volatile",
 ]
@@ -1029,7 +1029,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0f042214de98141e9c8706e8192b73f56494087cc55ebec28ce10f26c5c364ae"
 dependencies = [
  "bit_field",
- "bitflags 2.6.0",
+ "bitflags 2.8.0",
  "rustversion",
  "volatile",
 ]
diff --git a/kernel/src/holeybytes/ecah.rs b/kernel/src/holeybytes/ecah.rs
index ab540d6..05bf41b 100644
--- a/kernel/src/holeybytes/ecah.rs
+++ b/kernel/src/holeybytes/ecah.rs
@@ -8,14 +8,13 @@ use crate::{
             block_read, dt_msg_handler::dt_msg_handler, logging_service::log_msg_handler,
             service_definition_service::sds_msg_handler,
         },
-        ExecThread,
+        ExecThread, STACK_SIZE,
     },
     kmain::EXECUTOR,
     task::Executor,
 };
 
 use {
-    super::Vm,
     crate::{arch, ipc::buffer::IpcBuffer, kmain::IPC_BUFFERS},
     hbvm::value::Value,
     log::{debug, error, info, trace},
@@ -33,21 +32,21 @@ unsafe fn x86_in<T: x86_64::instructions::port::PortRead>(address: u16) -> T {
 }
 
 #[inline(always)]
-pub fn handler(vm: &mut Vm, pid: &usize) {
-    let ecall_number = vm.registers[2].cast::<u64>();
+pub fn handler(thr: &mut ExecThread, pid: &usize) {
+    let ecall_number = thr.vm.registers[2].cast::<u64>();
 
     match ecall_number {
         0 => {
             // TODO: explode computer
             // hello world ecall
             for x in 0u64..=255 {
-                vm.registers[x as usize] = x.into();
+                thr.vm.registers[x as usize] = x.into();
             }
         }
         1 => {
             // Make buffer
 
-            let bounded = match vm.registers[3] {
+            let bounded = match thr.vm.registers[3] {
                 Value(0) => false,
                 Value(1) => true,
                 _ => {
@@ -55,7 +54,7 @@ pub fn handler(vm: &mut Vm, pid: &usize) {
                 }
             };
 
-            let length = vm.registers[4].cast::<u64>();
+            let length = thr.vm.registers[4].cast::<u64>();
 
             let mut buffs = IPC_BUFFERS.lock();
 
@@ -67,7 +66,7 @@ pub fn handler(vm: &mut Vm, pid: &usize) {
                     true => IpcBuffer::new(true, length),
                 },
             );
-            vm.registers[1] = hbvm::value::Value(buff_id);
+            thr.vm.registers[1] = hbvm::value::Value(buff_id);
         }
         2 => {
             log::error!("Oops, deleting buffers is not implemented.")
@@ -75,9 +74,9 @@ pub fn handler(vm: &mut Vm, pid: &usize) {
         }
         3 => {
             // Send a message to a buffer
-            let buffer_id = vm.registers[3].cast::<u64>();
-            let mem_addr = vm.registers[4].cast::<u64>();
-            let length = vm.registers[5].cast::<u64>() as usize;
+            let buffer_id = thr.vm.registers[3].cast::<u64>();
+            let mem_addr = thr.vm.registers[4].cast::<u64>();
+            let length = thr.vm.registers[5].cast::<u64>() as usize;
             trace!("IPC address: {:?}", mem_addr);
 
             unsafe { LazyCell::<Executor>::get_mut(&mut EXECUTOR) }
@@ -85,17 +84,17 @@ pub fn handler(vm: &mut Vm, pid: &usize) {
                 .send_buffer(buffer_id as usize);
 
             match buffer_id {
-                0 => match sds_msg_handler(vm, mem_addr, length) {
+                0 => match sds_msg_handler(&mut thr.vm, mem_addr, length) {
                     Ok(()) => {}
                     Err(err) => log::error!("Improper sds format: {err:?}"),
                 },
-                1 => match log_msg_handler(vm, mem_addr, length) {
+                1 => match log_msg_handler(&mut thr.vm, mem_addr, length) {
                     Ok(()) => {}
                     Err(_) => log::error!("Improper log format"),
                 },
                 2 => {
                     use crate::holeybytes::kernel_services::mem_serve::memory_msg_handler;
-                    match memory_msg_handler(vm, mem_addr, length) {
+                    match memory_msg_handler(&mut thr.vm, mem_addr, length) {
                         Ok(_) => {}
                         Err(_) => {}
                     }
@@ -116,7 +115,7 @@ pub fn handler(vm: &mut Vm, pid: &usize) {
                                 _ => panic!("Trying to read size other than: 8, 16, 32 from port."),
                             };
                             // info!("Read the value {} from address {}", value, addr);
-                            vm.registers[1] = hbvm::value::Value(value);
+                            thr.vm.registers[1] = hbvm::value::Value(value);
                         },
                         1 => unsafe {
                             let size = msg_vec[1];
@@ -150,9 +149,9 @@ pub fn handler(vm: &mut Vm, pid: &usize) {
                             &crate::arch::hardware_random_u64().to_le_bytes()[..chunk.len()],
                         );
                     });
-                    vm.registers[1] = hbvm::value::Value(mem_addr);
+                    thr.vm.registers[1] = hbvm::value::Value(mem_addr);
                 }
-                5 => match dt_msg_handler(vm, mem_addr, length) {
+                5 => match dt_msg_handler(&mut thr.vm, mem_addr, length) {
                     Ok(()) => {}
                     Err(_) => log::error!("Improper dt query"),
                 },
@@ -181,18 +180,39 @@ pub fn handler(vm: &mut Vm, pid: &usize) {
                     let end = (code_length + data_length) as usize;
                     log::debug!("{code_length} + {data_length} = {end}");
 
-                    let thr = ExecThread::new(&program[offset..end], Address::new(0));
-                    vm.registers[1] = Value(
+                    let thr2 = ExecThread::new(program[offset..end].into(), Address::new(0));
+                    thr.vm.registers[1] = Value(
                         LazyCell::<Executor>::get_mut(&mut EXECUTOR)
                             .unwrap()
                             .spawn(Box::pin(async move {
-                                if let Err(e) = thr.await {
+                                if let Err(e) = thr2.await {
                                     log::error!("{e:?}");
                                 }
                             })) as u64,
                     );
                     log::debug!("spawned a process");
                 },
+                7 => unsafe {
+                    let mut thr2 = ExecThread::new(
+                        thr.program,
+                        thr.vm.pc.wrapping_sub(thr.program.as_ptr() as u64),
+                    );
+                    thr.stack_bottom
+                        .copy_to_nonoverlapping(thr2.stack_bottom, STACK_SIZE);
+                    thr2.vm.registers = thr.vm.registers;
+                    thr2.vm.registers[1] = Value(0);
+
+                    thr.vm.registers[1] = Value(
+                        LazyCell::<Executor>::get_mut(&mut EXECUTOR)
+                            .unwrap()
+                            .spawn(Box::pin(async move {
+                                if let Err(e) = thr2.await {
+                                    log::error!("{e:?}");
+                                }
+                            })) as u64,
+                    );
+                    log::debug!("forked a process")
+                },
 
                 buffer_id => {
                     let mut buffs = IPC_BUFFERS.lock();
@@ -210,9 +230,9 @@ pub fn handler(vm: &mut Vm, pid: &usize) {
             }
         }
         4 => {
-            let buffer_id = vm.registers[3].cast::<u64>();
-            let map_ptr = vm.registers[4].cast::<u64>();
-            let max_length = vm.registers[5].cast::<u64>();
+            let buffer_id = thr.vm.registers[3].cast::<u64>();
+            let map_ptr = thr.vm.registers[4].cast::<u64>();
+            let max_length = thr.vm.registers[5].cast::<u64>();
             let mut buffs = IPC_BUFFERS.lock();
             let buff: &mut IpcBuffer = match buffs.get_mut(&buffer_id) {
                 Some(buff) => buff,
@@ -240,16 +260,16 @@ pub fn handler(vm: &mut Vm, pid: &usize) {
         5 => {
             #[cfg(target_arch = "x86_64")]
             {
-                let r2 = vm.registers[2].cast::<u64>();
+                let r2 = thr.vm.registers[2].cast::<u64>();
                 let x = hbvm::value::Value(unsafe { x86_in::<u8>(r2 as u16) } as u64);
                 // info!("Read {:?} from Port {:?}", x, r2);
-                vm.registers[3] = x
+                thr.vm.registers[3] = x
             }
         }
         6 => {
             // Wait till interrupt
             use crate::kmain::EXECUTOR;
-            let interrupt_type = vm.registers[3].cast::<u8>();
+            let interrupt_type = thr.vm.registers[3].cast::<u8>();
             debug!("Interrupt subscribed: {}", interrupt_type);
             unsafe {
                 LazyCell::<Executor>::get_mut(&mut EXECUTOR)
@@ -260,7 +280,7 @@ pub fn handler(vm: &mut Vm, pid: &usize) {
         7 => {
             // Wait till buffer
             use crate::kmain::EXECUTOR;
-            let buffer_id = vm.registers[3].cast::<u64>() as usize;
+            let buffer_id = thr.vm.registers[3].cast::<u64>() as usize;
             debug!("Buffer subscribed: {}", buffer_id);
             unsafe {
                 LazyCell::<Executor>::get_mut(&mut EXECUTOR)
@@ -269,7 +289,7 @@ pub fn handler(vm: &mut Vm, pid: &usize) {
             }
         }
         _ => {
-            log::error!("Syscall unknown {:?}{:?}", ecall_number, vm.registers);
+            log::error!("Syscall unknown {:?}{:?}", ecall_number, thr.vm.registers);
         }
     }
 }
diff --git a/kernel/src/holeybytes/mem.rs b/kernel/src/holeybytes/mem.rs
index 887ef02..5b1a07d 100644
--- a/kernel/src/holeybytes/mem.rs
+++ b/kernel/src/holeybytes/mem.rs
@@ -60,7 +60,8 @@ impl hbvm::mem::Memory for Memory {
     }
 
     #[inline(always)]
-    fn log_instr(&mut self, _at: Address, _regs: &[hbvm::value::Value]) {
+    #[allow(unused)]
+    fn log_instr(&mut self, at: Address, regs: &[hbvm::value::Value]) {
         // log::debug!("exec: [{:02x}] {}", at.get(), unsafe {
         //     self.logger.display_instr(at, regs)
         // });
diff --git a/kernel/src/holeybytes/mod.rs b/kernel/src/holeybytes/mod.rs
index c670d89..4ea3430 100644
--- a/kernel/src/holeybytes/mod.rs
+++ b/kernel/src/holeybytes/mod.rs
@@ -24,6 +24,7 @@ type Vm = hbvm::Vm<mem::Memory, TIMER_QUOTIENT>;
 pub struct ExecThread {
     vm: Vm,
     stack_bottom: *mut u8,
+    program: &'static [u8],
 }
 
 unsafe impl Send for ExecThread {}
@@ -34,7 +35,7 @@ impl ExecThread {
         self.vm.registers[2] = hbvm::value::Value(length);
     }
 
-    pub unsafe fn new(program: &[u8], entrypoint: Address) -> Self {
+    pub unsafe fn new(program: &'static [u8], entrypoint: Address) -> Self {
         let mut vm = Vm::new(
             mem::Memory::default(),
             Address::new(program.as_ptr() as u64 + entrypoint.get()),
@@ -44,7 +45,11 @@ impl ExecThread {
 
         vm.write_reg(254, (stack_bottom as usize + STACK_SIZE - 1) as u64);
 
-        ExecThread { vm, stack_bottom }
+        ExecThread {
+            vm,
+            stack_bottom,
+            program,
+        }
     }
 }
 
@@ -66,7 +71,7 @@ impl<'p> Future for ExecThread {
             }
             Ok(VmRunOk::End) => return Poll::Ready(Ok(())),
             Ok(VmRunOk::Ecall) => ecah::handler(
-                &mut self.vm,
+                &mut self,
                 cx.ext()
                     .downcast_ref()
                     .expect("PID did not exist in Context"),
diff --git a/kernel/src/kmain.rs b/kernel/src/kmain.rs
index 8d9d398..c92cdb4 100644
--- a/kernel/src/kmain.rs
+++ b/kernel/src/kmain.rs
@@ -19,15 +19,12 @@ use {
     spin::{Lazy, Mutex},
 };
 
-pub fn kmain(_cmdline: &str, boot_modules: BootModules) -> ! {
+pub fn kmain(_cmdline: &str, boot_modules: BootModules<'static>) -> ! {
     debug!("Entered kmain");
 
     #[cfg(feature = "ktest")]
     {
-        use {
-			crate::ktest,
-			log::info,
-		};
+        use {crate::ktest, log::info};
         info!("Running tests");
         ktest::test_main();
 
diff --git a/sysdata/libraries/horizon_api/src/lib.hb b/sysdata/libraries/horizon_api/src/lib.hb
index 2acd07f..f11a406 100644
--- a/sysdata/libraries/horizon_api/src/lib.hb
+++ b/sysdata/libraries/horizon_api/src/lib.hb
@@ -21,7 +21,7 @@ create_window := fn(channel: uint): ^render.Surface {
 	// wait to recieve a message
 
 	windowing_system_buffer := buffer.search("XHorizon")
-	mem_buf := memory.request_page(1)
+	mem_buf := memory.request_page(1, false)
 
 	if windowing_system_buffer == 0 {
 		return @as(^render.Surface, idk)
diff --git a/sysdata/libraries/stn/src/alloc/block_alloc.hb b/sysdata/libraries/stn/src/alloc/block_alloc.hb
index 801cb04..9db24fb 100644
--- a/sysdata/libraries/stn/src/alloc/block_alloc.hb
+++ b/sysdata/libraries/stn/src/alloc/block_alloc.hb
@@ -10,7 +10,7 @@ BlockAlloc := struct {
 	ptr: ?^u8,
 
 	$init := fn(): Self {
-		alloc_page_ptr := memory.request_page(1)
+		alloc_page_ptr := memory.request_page(1, false)
 		state := 0xFFFFFFFFFFFFFFFF
 		return .(state, alloc_page_ptr)
 	}
diff --git a/sysdata/libraries/stn/src/dt.hb b/sysdata/libraries/stn/src/dt.hb
index d7f03c7..47437a1 100644
--- a/sysdata/libraries/stn/src/dt.hb
+++ b/sysdata/libraries/stn/src/dt.hb
@@ -1,3 +1,3 @@
 $get := fn($Expr: type, query: []u8): Expr {
-	return @eca(3, 5, query, query.len)
+	return @eca(3, 5, query.ptr, query.len)
 }
\ No newline at end of file
diff --git a/sysdata/libraries/stn/src/log.hb b/sysdata/libraries/stn/src/log.hb
index 50e23e8..79ee112 100644
--- a/sysdata/libraries/stn/src/log.hb
+++ b/sysdata/libraries/stn/src/log.hb
@@ -24,7 +24,7 @@ print_buffer := memory.dangling(u8)
 
 print := fn(v: @Any(), opts: fmt.FormatOptions): void {
 	if print_buffer == memory.dangling(u8) {
-		print_buffer = memory.request_page(1)
+		print_buffer = memory.request_page(1, false)
 	}
 	len := @inline(fmt.format, v, print_buffer[0..memory.PAGE_SIZE], opts)
 	@eca(3, 1, LogMsg.(opts.log, print_buffer, len), @sizeof(LogMsg))
@@ -33,7 +33,7 @@ print := fn(v: @Any(), opts: fmt.FormatOptions): void {
 
 printf := fn(str: []u8, v: @Any(), opts: fmt.FormatOptions): void {
 	if print_buffer == memory.dangling(u8) {
-		print_buffer = memory.request_page(1)
+		print_buffer = memory.request_page(1, false)
 	}
 	len := @inline(fmt.format_with_str, v, str, print_buffer[0..memory.PAGE_SIZE], opts)
 	@eca(3, 1, LogMsg.(opts.log, print_buffer, len), @sizeof(LogMsg))
diff --git a/sysdata/libraries/stn/src/process.hb b/sysdata/libraries/stn/src/process.hb
index 918067b..23bc4f1 100644
--- a/sysdata/libraries/stn/src/process.hb
+++ b/sysdata/libraries/stn/src/process.hb
@@ -1,9 +1,10 @@
-// ! will be rewritten to take a file object when filesystem is exist
 // returns PID
 $spawn := fn(proc_exe: ^u8, length: uint): uint {
 	return @eca(3, 6, proc_exe, length)
 }
 
+$fork := fn(): uint return @eca(3, 7)
+
 /* TODO:
 - Spawn an empty process
 - Call a function to load bytes into that process from a function
diff --git a/sysdata/programs/horizon/src/main.hb b/sysdata/programs/horizon/src/main.hb
index 59d440e..7436c90 100644
--- a/sysdata/programs/horizon/src/main.hb
+++ b/sysdata/programs/horizon/src/main.hb
@@ -39,7 +39,7 @@ main := fn(): int {
 
 	window := render.Surface.new(screen.width / 3, screen.height / 3)
 
-	mem_buf := memory.request_page(1)
+	mem_buf := memory.request_page(1, false)
 	color := random.any(render.Color)
 	side := window.width / 8
 
diff --git a/sysdata/programs/serial_driver/src/main.hb b/sysdata/programs/serial_driver/src/main.hb
index a754547..6de0a01 100644
--- a/sysdata/programs/serial_driver/src/main.hb
+++ b/sysdata/programs/serial_driver/src/main.hb
@@ -23,7 +23,7 @@ main := fn(): int {
 	a := buffer.create("XNumber")
 	serial_println("Starting Serial Driver.")
 
-	mem := memory.request_page(1)[1..memory.PAGE_SIZE]
+	mem := memory.request_page(1, true)[1..memory.PAGE_SIZE]
 
 	loop {
 		ptr := @as(^u8, @eca(4, a, mem, 0x1000))
diff --git a/sysdata/programs/test/src/main.hb b/sysdata/programs/test/src/main.hb
index 3b3bc21..d3f1546 100644
--- a/sysdata/programs/test/src/main.hb
+++ b/sysdata/programs/test/src/main.hb
@@ -1,7 +1,4 @@
 stn := @use("./tests/stn/lib.hb")
 serial_driver := @use("./tests/serial_driver.hb")
 
-main := fn(): uint {
-	// return serial_driver.test()
-	return stn.process.test()
-}
\ No newline at end of file
+main := stn.process.test
\ No newline at end of file
diff --git a/sysdata/programs/test/src/tests/stn/process.hb b/sysdata/programs/test/src/tests/stn/process.hb
index 96b879b..86a7bfa 100644
--- a/sysdata/programs/test/src/tests/stn/process.hb
+++ b/sysdata/programs/test/src/tests/stn/process.hb
@@ -1,9 +1,30 @@
-.{process, log} := @use("stn")
+.{process, log, memory} := @use("stn")
 
-// src: https://git.ablecorp.us/koniifer/lily
-exe := @embed("./assets/lily.axe")
+/*
+ * extract to un-inlined function so the compiler doesnt
+ * assume that `*a` never changes (program doesnt work otherwise)
+ * (this is a reason why memory sharing is bad)
+ */
+opaque := fn(ptr: ^bool): bool {
+	return *ptr
+}
 
 test := fn(): uint {
-	process.spawn(@bitcast(&exe), @sizeof(@TypeOf(exe)))
+	a: ^bool = @bitcast(memory.request_page(1, true))
+	x := process.fork()
+	log.info("both will print this")
+	// (x == 0) => child process
+	// (x == N) => N is PID of new child process (in theory)
+	if x == 0 {
+		// ! NOTE: NEVER DO THIS!!! USE BUFFERS INSTEAD!!! :)
+		// acts as a lock. when parent is done, this can go ahead.
+		loop if opaque(a) break else {
+		};
+		log.info("child done.")
+	} else {
+		*a = true
+		log.info("parent done.")
+	}
+
 	return 0
 }
\ No newline at end of file