diff --git a/Cargo.lock b/Cargo.lock index 94da0a14..63a92736 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -166,15 +166,6 @@ dependencies = [ "windows-targets", ] -[[package]] -name = "convert_case" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" -dependencies = [ - "unicode-segmentation", -] - [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -211,7 +202,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" dependencies = [ - "convert_case", "proc-macro2", "quote", "syn", @@ -391,17 +381,17 @@ dependencies = [ [[package]] name = "hbbytecode" version = "0.1.0" -source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#e8a5027cab7ce008dbb0964fe0522c8fef585979" +source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#67b8ffe2f223629850c293858abbb0cc5337a850" [[package]] name = "hbbytecode" version = "0.1.0" -source = "git+https://git.ablecorp.us/ableos/holey-bytes#e8a5027cab7ce008dbb0964fe0522c8fef585979" +source = "git+https://git.ablecorp.us/ableos/holey-bytes#67b8ffe2f223629850c293858abbb0cc5337a850" [[package]] name = "hblang" version = "0.1.0" -source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#e8a5027cab7ce008dbb0964fe0522c8fef585979" +source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#67b8ffe2f223629850c293858abbb0cc5337a850" dependencies = [ "hbvm 0.1.0 (git+https://git.ablecorp.us/AbleOS/holey-bytes.git)", ] @@ -409,7 +399,7 @@ dependencies = [ [[package]] name = "hbvm" version = "0.1.0" -source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#e8a5027cab7ce008dbb0964fe0522c8fef585979" +source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#67b8ffe2f223629850c293858abbb0cc5337a850" dependencies = [ "hbbytecode 0.1.0 (git+https://git.ablecorp.us/AbleOS/holey-bytes.git)", ] @@ -417,7 +407,7 @@ dependencies = [ [[package]] name = "hbvm" version = "0.1.0" -source = "git+https://git.ablecorp.us/ableos/holey-bytes#e8a5027cab7ce008dbb0964fe0522c8fef585979" +source = "git+https://git.ablecorp.us/ableos/holey-bytes#67b8ffe2f223629850c293858abbb0cc5337a850" dependencies = [ "hbbytecode 0.1.0 (git+https://git.ablecorp.us/ableos/holey-bytes)", ] @@ -507,9 +497,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cde7055719c54e36e95e8719f95883f22072a48ede39db7fc17a4e1d5281e9b9" +checksum = "da62f120a8a37763efb0cf8fdf264b884c7b8b9ac8660b900c8661030c00e6ba" dependencies = [ "bytes", "futures-channel", @@ -594,16 +584,14 @@ name = "kernel" version = "0.2.0" dependencies = [ "crossbeam-queue", + "crossbeam-utils", "derive_more", "embedded-graphics", "hashbrown", "hbvm 0.1.0 (git+https://git.ablecorp.us/ableos/holey-bytes)", - "kiam", "limine", "log", - "rdrand", "sbi", - "slab", "spin", "uart_16550", "versioning", @@ -613,12 +601,6 @@ dependencies = [ "xml", ] -[[package]] -name = "kiam" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb0fc32485e41ae5e9dedd1442f36dec998431adc9f321224c2c5d645f38fdcb" - [[package]] name = "lazy_static" version = "1.5.0" @@ -907,15 +889,6 @@ dependencies = [ "bitflags 1.3.2", ] -[[package]] -name = "rdrand" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d92195228612ac8eed47adbc2ed0f04e513a4ccb98175b6f2bd04d963b533655" -dependencies = [ - "rand_core", -] - [[package]] name = "regex-syntax" version = "0.8.4" @@ -1046,9 +1019,9 @@ checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" [[package]] name = "rustls-webpki" -version = "0.102.7" +version = "0.102.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84678086bd54edf2b415183ed7a94d0efb049f1b646a33e22a36f3794be6ae56" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" dependencies = [ "ring", "rustls-pki-types", @@ -1389,12 +1362,6 @@ dependencies = [ "tinyvec", ] -[[package]] -name = "unicode-segmentation" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" - [[package]] name = "unicode-xid" version = "0.2.5" diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index 59e964fb..be0aa8a6 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -9,13 +9,11 @@ embedded-graphics = "0.8" hbvm.git = "https://git.ablecorp.us/ableos/holey-bytes" log = "0.4" spin = "0.9" -uart_16550 = "0.3" -slab = { version = "0.4", default-features = false } +uart_16550 = { version = "0.3", features = ["nightly"] } xml.git = "https://git.ablecorp.us/ableos/ableos_userland" versioning.git = "https://git.ablecorp.us/ableos/ableos_userland" # able_graphics_library.git = "https://git.ablecorp.us/ableos/ableos_userland" -hashbrown = "0.14" -kiam = "0.1" +hashbrown = { version = "0.14", features = ["nightly"] } [dependencies.limine] version = "0.1" @@ -24,7 +22,11 @@ version = "0.1" [dependencies.crossbeam-queue] version = "0.3" default-features = false -features = ["alloc"] +features = ["alloc", "nightly"] + +[dependencies.crossbeam-utils] +version = "0.8" +default-features = false # [dependencies.clparse] # git = "https://git.ablecorp.us/ableos/ableos_userland" @@ -51,9 +53,6 @@ features = [ x86_64 = "0.15" x2apic = "0.4" virtio-drivers = "0.7" -# rdrand = "*" -rdrand = { version = "0.8", default-features = false } - [target.'cfg(target_arch = "riscv64")'.dependencies] sbi = "0.2.0" diff --git a/kernel/src/arch/riscv64/memory.rs b/kernel/src/arch/riscv64/memory.rs index b6411d73..a4859aec 100644 --- a/kernel/src/arch/riscv64/memory.rs +++ b/kernel/src/arch/riscv64/memory.rs @@ -1,8 +1,10 @@ use core::num; -use alloc::boxed::Box; -use spin::{Mutex, Once}; -use crate::memory::{MemoryManager, PhysicalAddress, VirtualAddress}; +use { + crate::memory::{MemoryManager, PhysicalAddress, VirtualAddress}, + alloc::boxed::Box, + spin::{Mutex, Once}, +}; use super::PAGE_SIZE; @@ -28,7 +30,7 @@ impl PageSize { } pub struct PageTable { - entries: [PageEntry; 512] + entries: [PageEntry; 512], } impl PageTable { @@ -72,8 +74,14 @@ impl PageTable { /// flags MUST include one or more of the following: /// Read, Write, Execute /// The valid bit automatically gets added - pub fn map(&mut self, vaddr: VirtualAddress, paddr: PhysicalAddress, flags: PageEntryFlags, page_size: PageSize) { - assert!(flags as usize & 0xe != 0); + pub fn map( + &mut self, + vaddr: VirtualAddress, + paddr: PhysicalAddress, + flags: PageEntryFlags, + page_size: PageSize, + ) { + assert!(flags as usize & 0xE != 0); let vpn = vaddr.vpns(); let ppn = paddr.ppns(); @@ -91,7 +99,7 @@ impl PageTable { } let entry = v.addr().as_mut_ptr::(); - v = unsafe { entry.add(vpn[i]).as_mut().unwrap() }; + v = unsafe { entry.add(vpn[i]).as_mut().unwrap() }; } // When we get here, we should be at VPN[0] and v should be pointing to our entry. @@ -105,14 +113,24 @@ impl PageTable { } /// Identity maps a page of memory - pub fn identity_map(&mut self, addr: PhysicalAddress, flags: PageEntryFlags, page_size: PageSize) { + pub fn identity_map( + &mut self, + addr: PhysicalAddress, + flags: PageEntryFlags, + page_size: PageSize, + ) { // log::debug!("identity mapped {addr}"); self.map(addr.as_addr().into(), addr, flags, page_size); } /// Identity maps a range of contiguous memory /// This assumes that start <= end - pub fn identity_map_range(&mut self, start: PhysicalAddress, end: PhysicalAddress, flags: PageEntryFlags) { + pub fn identity_map_range( + &mut self, + start: PhysicalAddress, + end: PhysicalAddress, + flags: PageEntryFlags, + ) { log::debug!("start: {start}, end: {end}"); let mut mem_addr = start.as_addr() & !(PAGE_SIZE - 1); let num_pages = (align_val(end.as_addr(), 12) - mem_addr - 1) / PAGE_SIZE + 1; @@ -142,7 +160,7 @@ impl PageTable { } let entry = v.addr().as_mut_ptr::(); - v = unsafe { entry.add(vpn[i]).as_mut().unwrap() }; + v = unsafe { entry.add(vpn[i]).as_mut().unwrap() }; } // If we're here this is an unmapped page @@ -182,7 +200,7 @@ pub enum PageEntryFlags { Global = 1 << 5, Access = 1 << 6, Dirty = 1 << 7, - + // for convenience ReadWrite = Self::Read as usize | Self::Write as usize, ReadExecute = Self::Read as usize | Self::Execute as usize, @@ -228,7 +246,7 @@ impl PageEntry { } fn addr(&self) -> PhysicalAddress { - ((self.entry() as usize & !0x3ff) << 2).into() + ((self.entry() as usize & !0x3FF) << 2).into() } fn destroy(&mut self) { diff --git a/kernel/src/arch/x86_64/mod.rs b/kernel/src/arch/x86_64/mod.rs index 7451f297..be68b5f7 100644 --- a/kernel/src/arch/x86_64/mod.rs +++ b/kernel/src/arch/x86_64/mod.rs @@ -1,4 +1,6 @@ -use {crate::bootmodules::BootModule, core::arch::asm, log::warn, rdrand::RdSeed}; +use core::arch::x86_64::{_rdrand32_step, _rdrand64_step, _rdseed32_step, _rdseed64_step}; + +use {crate::bootmodules::BootModule, core::arch::asm, log::warn}; pub mod memory; mod cpuid; @@ -189,62 +191,43 @@ unsafe extern "C" fn start() -> ! { ) } +use crossbeam_utils::Backoff; + /// Spin loop pub fn spin_loop() -> ! { + let backoff = Backoff::new(); loop { - x86_64::instructions::hlt(); + core::hint::spin_loop(); + // x86_64::instructions::hlt(); + backoff.spin() } } pub fn hardware_random_u64() -> u64 { - use {log::trace, rdrand::RdRand}; - let gen = RdRand::new(); - match gen { - Ok(gen) => { - let ret = gen.try_next_u64().unwrap(); - trace!("Random {}", ret); - return ret; - } - Err(_) => { + let mut out: u64 = 0; + match unsafe { _rdrand64_step(&mut out) } { + 1 => out, + _ => { warn!("RDRand not supported."); // Try rdseed - let gen = RdSeed::new(); - match gen { - Ok(gen) => { - let ret = gen.try_next_u64().unwrap(); - trace!("Random {}", ret); - return ret; - } - Err(_) => { - panic!("Neither RDRand or RDSeed are supported") - } + match unsafe { _rdseed64_step(&mut out) } { + 1 => out, + _ => panic!("Neither RDRand or RDSeed are supported"), } } } } pub fn hardware_random_u32() -> u32 { - use {log::trace, rdrand::RdRand}; - let gen = RdRand::new(); - match gen { - Ok(gen) => { - let ret = gen.try_next_u32().unwrap(); - trace!("Random {}", ret); - return ret; - } - Err(_) => { + let mut out: u32 = 0; + match unsafe { _rdrand32_step(&mut out) } { + 1 => out, + _ => { warn!("RDRand not supported."); // Try rdseed - let gen = RdSeed::new(); - match gen { - Ok(gen) => { - let ret = gen.try_next_u32().unwrap(); - trace!("Random {}", ret); - return ret; - } - Err(_) => { - panic!("Neither RDRand or RDSeed are supported") - } + match unsafe { _rdseed32_step(&mut out) } { + 1 => out, + _ => panic!("Neither RDRand or RDSeed are supported"), } } } diff --git a/kernel/src/holeybytes/mod.rs b/kernel/src/holeybytes/mod.rs index a8d31b9b..77dad395 100644 --- a/kernel/src/holeybytes/mod.rs +++ b/kernel/src/holeybytes/mod.rs @@ -65,7 +65,7 @@ impl<'p> Drop for ExecThread<'p> { impl<'p> Future for ExecThread<'p> { type Output = Result<(), VmRunError>; - + #[inline(always)] fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { match self.vm.run() { Err(err) => { @@ -110,10 +110,12 @@ impl HandlePageFault for PageFaultHandler { } } +#[inline(always)] const fn stack_layout() -> Layout { unsafe { Layout::from_size_align_unchecked(STACK_SIZE, 4096) } } +#[inline(always)] fn allocate_stack() -> NonNull { let layout = stack_layout(); NonNull::new(unsafe { alloc::alloc::alloc_zeroed(layout) }) diff --git a/kernel/src/kmain.rs b/kernel/src/kmain.rs index f385b31c..7543345d 100644 --- a/kernel/src/kmain.rs +++ b/kernel/src/kmain.rs @@ -66,7 +66,7 @@ pub fn kmain(_cmdline: &str, boot_modules: BootModules) -> ! { fb1.address.as_ptr().unwrap() as *const u8 ); - let mut executor = crate::task::Executor::default(); + let mut executor = crate::task::Executor::new(256); let bm_take = boot_modules.len(); unsafe { for module in boot_modules.into_iter().take(bm_take) { @@ -80,16 +80,17 @@ pub fn kmain(_cmdline: &str, boot_modules: BootModules) -> ! { log::info!("Spawning {} with arguments \"{}\"", module.path, cmd); - executor.spawn(async move { - let mut thr = ExecThread::new(&module.bytes, Address::new(0)); - if cmd_len > 0 { - thr.set_arguments(cmd.as_bytes().as_ptr() as u64, cmd_len); - } - - if let Err(e) = thr.await { - log::error!("{e:?}"); - } - }); + executor + .spawn(async move { + let mut thr = ExecThread::new(&module.bytes, Address::new(0)); + if cmd_len > 0 { + thr.set_arguments(cmd.as_bytes().as_ptr() as u64, cmd_len); + } + if let Err(e) = thr.await { + log::error!("{e:?}"); + } + }) + .unwrap(); } info!("Random number: {}", hardware_random_u64()); diff --git a/kernel/src/task.rs b/kernel/src/task.rs index 59600652..8db84d1b 100644 --- a/kernel/src/task.rs +++ b/kernel/src/task.rs @@ -1,23 +1,23 @@ -#![allow(unused)] - use { alloc::{boxed::Box, sync::Arc, task::Wake}, core::{ future::Future, pin::Pin, + sync::atomic::{AtomicUsize, Ordering}, task::{Context, Poll, Waker}, }, crossbeam_queue::SegQueue, - hashbrown::HashMap, - slab::Slab, - spin::Mutex, + crossbeam_utils::CachePadded, }; +use alloc::vec::Vec; + pub fn yield_now() -> impl Future { struct YieldNow(bool); impl Future for YieldNow { type Output = (); + #[inline(always)] fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { if self.0 { Poll::Ready(()) @@ -34,86 +34,168 @@ pub fn yield_now() -> impl Future { #[derive(Default)] pub struct Executor { - tasks: Slab, - queue: Arc>, - wakers: HashMap, // Keeping HashMap as it is more performant for lookups. + tasks: Vec>, + task_queue: Arc, + max_tasks: usize, } impl Executor { - pub fn new() -> Self { + pub fn new(max_tasks: usize) -> Self { Self { - tasks: Slab::new(), - queue: Arc::new(SegQueue::new()), - wakers: HashMap::new(), + tasks: (0..max_tasks) + .map(|_| CachePadded::new(TaskSlot::default())) + .collect(), + task_queue: Arc::new(TaskQueue::new(max_tasks)), + max_tasks, } } - pub fn spawn(&mut self, future: impl Future + Send + 'static) { - let task_id = TaskId(self.tasks.insert(Task::new(future))); - self.queue.push(task_id); + pub fn spawn(&mut self, future: impl Future + Send + 'static) -> Result<(), ()> { + let task_id = self.task_queue.allocate_task_id().ok_or(())?; + self.tasks[task_id.0].lock.replace(Task::new(future)); + self.task_queue.push(task_id); + Ok(()) } pub fn run(&mut self) { + let mut task_batch = Vec::with_capacity(16); + loop { - while let Some(id) = self.queue.pop() { - if let Some(task) = self.tasks.get_mut(id.0) { - let waker = self.wakers.entry(id).or_insert_with(|| { - Waker::from(Arc::new(TaskWaker { - id, - queue: Arc::clone(&self.queue), - })) - }); - - let mut cx = Context::from_waker(waker); - - if let Poll::Ready(()) = task.poll(&mut cx) { - self.tasks.remove(id.0); - self.wakers.remove(&id); - } + self.task_queue.batch_pop(&mut task_batch); + if task_batch.is_empty() { + if self.task_queue.is_empty() { + break; } else { - panic!("Attempted to get task from empty slot: {}", id.0); + continue; } } - if self.tasks.is_empty() { - break; + for id in task_batch.drain(..) { + let task_slot = &mut self.tasks[id.0]; + + let mut task_opt = task_slot.lock.take(); + if let Some(task) = &mut task_opt { + let waker = task_slot.waker.get_or_insert_with(|| { + Arc::new(TaskWaker::new(id, Arc::clone(&self.task_queue))) + }); + + let waker = Waker::from(Arc::clone(waker)); + let mut cx = Context::from_waker(&waker); + + if let Poll::Ready(()) = task.poll(&mut cx) { + task_slot.waker = None; + self.task_queue.free_task_id(id); + } else { + task_slot.lock.replace(task_opt.take().unwrap()); + } + } } } } } +#[derive(Default)] +struct TaskSlot { + lock: Option, + waker: Option>, +} + struct Task { future: Pin + Send>>, } impl Task { + #[inline(always)] pub fn new(future: impl Future + Send + 'static) -> Self { - log::trace!("New task scheduled"); Self { future: Box::pin(future), } } + #[inline(always)] fn poll(&mut self, cx: &mut Context) -> Poll<()> { self.future.as_mut().poll(cx) } } -#[derive(Hash, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] struct TaskId(usize); struct TaskWaker { - id: TaskId, - queue: Arc>, + id: TaskId, + task_queue: Arc, +} + +impl TaskWaker { + #[inline(always)] + pub fn new(id: TaskId, task_queue: Arc) -> Self { + Self { id, task_queue } + } } impl Wake for TaskWaker { + #[inline(always)] fn wake(self: Arc) { - log::trace!("Woke Task-{:?}", self.id); - self.queue.push(self.id); + self.task_queue.push(self.id); } + #[inline(always)] fn wake_by_ref(self: &Arc) { - self.queue.push(self.id); + self.task_queue.push(self.id); + } +} + +#[derive(Default)] +struct TaskQueue { + queue: SegQueue, + next_task: AtomicUsize, + max_tasks: usize, + free_tasks: SegQueue, +} + +impl TaskQueue { + fn new(max_tasks: usize) -> Self { + Self { + queue: SegQueue::new(), + next_task: AtomicUsize::new(0), + max_tasks, + free_tasks: SegQueue::new(), + } + } + + fn allocate_task_id(&self) -> Option { + self.free_tasks.pop().or_else(|| { + let id = self.next_task.fetch_add(1, Ordering::Relaxed); + if id < self.max_tasks { + Some(TaskId(id)) + } else { + None + } + }) + } + + #[inline(always)] + fn free_task_id(&self, id: TaskId) { + self.free_tasks.push(id); + } + + #[inline(always)] + fn push(&self, id: TaskId) { + self.queue.push(id); + } + + #[inline(always)] + fn batch_pop(&self, output: &mut Vec) { + while let Some(id) = self.queue.pop() { + output.push(id); + if output.len() >= output.capacity() { + break; + } + } + } + + #[inline(always)] + fn is_empty(&self) -> bool { + self.queue.is_empty() } } diff --git a/repbuild/Cargo.toml b/repbuild/Cargo.toml index 693031a7..a082573a 100644 --- a/repbuild/Cargo.toml +++ b/repbuild/Cargo.toml @@ -5,7 +5,18 @@ edition = "2021" [dependencies] str-reader = "0.1" -derive_more = { version = "1", features = ["full"] } +derive_more = { version = "1", default-features = false, features = [ + "add", + "add_assign", + "constructor", + "display", + "from", + "into", + "mul", + "mul_assign", + "not", + "sum", +] } error-stack = "0.5" fatfs = "0.3" toml = "0.8" diff --git a/repbuild/src/main.rs b/repbuild/src/main.rs index 58f0451b..3e3ad95b 100644 --- a/repbuild/src/main.rs +++ b/repbuild/src/main.rs @@ -1,4 +1,4 @@ -#![allow(unused)] +// #![allow(unused)] mod dev; @@ -195,7 +195,7 @@ TERM_BACKDROP={} let modules = value.get_mut("modules").unwrap().as_table_mut().unwrap(); // let mut real_modules = modules.clone(); - modules.into_iter().for_each(|(key, value)| { + modules.into_iter().for_each(|(_, value)| { if value.is_table() { let path = get_path_without_boot_prefix( value.get("path").expect("You must have `path` as a value"), @@ -244,7 +244,7 @@ TERM_BACKDROP={} let bootdir = fs.root_dir().create_dir("efi")?.create_dir("boot")?; let mut f = fs.root_dir().create_file("limine.cfg")?; - let a = f.write(limine_str.as_bytes())?; + let _ = f.write(limine_str.as_bytes())?; drop(f); io::copy( @@ -446,6 +446,7 @@ enum Target { Aarch64, } +#[allow(unused)] #[derive(Debug, Display)] enum Error { #[display("Failed to build the kernel")] @@ -466,6 +467,7 @@ enum Error { impl Context for Error {} +#[allow(dead_code)] fn fmt_qemu_err(e: Option) -> impl Display { struct W(Option); impl Display for W { diff --git a/sysdata/libraries/render/src/software.hb b/sysdata/libraries/render/src/software.hb index da15e5cb..6a082455 100644 --- a/sysdata/libraries/render/src/software.hb +++ b/sysdata/libraries/render/src/software.hb @@ -23,7 +23,7 @@ fb_width := 1024 fb_height := 768 fb_pixels := fb_width * fb_height fb_bytes := fb_pixels << 2 -copy_pixels := math.min(0x1800, fb_bytes) >> 2 +copy_pixels := math.min(0xC000, fb_bytes) >> 2 partitions := fb_pixels / copy_pixels total_pages := 1 + fb_bytes >> 12 @@ -51,12 +51,22 @@ create_back_buffer := fn(): ^Color { clear := fn(color: Color): void { n := 0 - loop if n >= copy_pixels break else { + loop if n == 512 break else { *(back_buffer + n) = color n += 1 } n = 1 - loop if n >= partitions break else { + loop if n == 8 break else { + *(@as(^[Color; 512], @bitcast(back_buffer)) + n) = *@as(^[Color; 512], @bitcast(back_buffer)) + n += 1 + } + n = 1 + loop if n == copy_pixels >> 12 break else { + *(@as(^[Color; 4096], @bitcast(back_buffer)) + n) = *@as(^[Color; 4096], @bitcast(back_buffer)) + n += 1 + } + n = 1 + loop if n == partitions break else { *(@as(^[Color; copy_pixels], @bitcast(back_buffer)) + n) = *@as(^[Color; copy_pixels], @bitcast(back_buffer)) n += 1 } @@ -65,7 +75,7 @@ clear := fn(color: Color): void { sync := fn(): void { n := 0 - loop if n >= partitions break else { + loop if n == partitions break else { *(@as(^[Color; copy_pixels], @bitcast(front_buffer)) + n) = *(@as(^[Color; copy_pixels], @bitcast(back_buffer)) + n) n += 1 } diff --git a/sysdata/programs/render_example/src/main.hb b/sysdata/programs/render_example/src/main.hb index 63d63909..35b2706e 100644 --- a/sysdata/programs/render_example/src/main.hb +++ b/sysdata/programs/render_example/src/main.hb @@ -1,4 +1,4 @@ -.{example} := @use("./examples/lines.hb") +.{example} := @use("./examples/amogus.hb") main := fn(): void { @inline(example)