#Nyaux
1 messages · Page 21 of 1
i already do that
okay
Yeah probably Arc if you don't have RCU
#[repr(C, packed)]
pub struct perthreadcpuinfo {
kernel_stack_ptr: *mut u8,
user_stack_ptr: *mut u8,
current_thread: *mut Thread
}
something like this?
what
Arc<Mutex<Box<dyn
Or a bunch of unsafe code
can i even store an arc in a repr c struct
in gs
Why can't you?
oh okay
Also it doesn't have to be repr c
Just store a pointer to normal struct
okay, does it have to be packed?
CPU loads it for you already
no
From tss
in syscall
Oh
Ignore this probably (I need sleep)
pub fn scheduletask(mut regs: *mut Registers_Exception) {
// pick a queue
let que: &mut Vec<cpu_queue> = unsafe {
&mut ITIS.as_mut().unwrap().queue
};
let mut got_you = que.pop();
if got_you.is_none() {
return;
}
let mut r = got_you.unwrap().queue;
if r.is_none() {
return;
}
let mut new_process = r.as_mut().unwrap().pop();
if new_process.is_none() {
return;
}
let mut new_thread = new_process.as_mut().unwrap().lock().threads.pop();
if new_thread.is_none() {
return;
}
let info = unsafe {
let e = rdmsr(0xC0000102) as *mut perthreadcpuinfo;
e
};
// get current thread
let thr = unsafe {
(*info).current_thread.clone()
};
save_context(regs, thr.lock().context);
let fs = rdmsr(0xC0000100);
thr.lock().fs = fs;
switch_context(regs, new_thread.as_mut().unwrap().lock().context);
wrmsr(0xC0000100, new_thread.as_ref().unwrap().lock().fs);
wrmsr(0xC0000102, new_thread.as_ref().unwrap().lock().gs_base as u64);
let o = thr;
new_process.as_mut().unwrap().lock().threads.insert(0, o);
r.as_mut().unwrap().insert(0, unsafe {(*info).current_thread.lock().process.clone()});
}
i think this is good
i was forced to um
use Arc<Mutex>>
its fine whatever
20002th message
20003th message
20004th message
20005th message
20006th message
200007th message
2000008th message
hard at work on scheduler
also lol
okay im having issues
trying to create the queues and shit its proving difficult
using arcs and mutexes everywhere doesnt help
i might just have to go with raw pointers
unless yall have a better idea
??
chat i do not know how to implment the scheduler in safe rust with SMP

just do it™️
bro i did
wanna see my first shitty implmentation that page faulted INSTANTLY
:3
I mean you are even using a physical address directly in it again 
yea but I had ABSTRACTION over it
like a ton of shit
boxes and what not
no like
theres only one time
i used a physical address
how does that cause insta page fault
😭
well it would cause a page fault when you'd switch to that new thread
and then it would also fault after that thread has printed hi
the first one because you are using a physical address as the sp for the new thread
second because there is nothing that the thread would return to
right
extern "C" fn lol()
{
println!("hi")
}
what do you think will happen when it will return from that
well in that case yeah but the gist literally had this
i see
SO CLOSE
rayan@pop-os:~/NyauxKT$ addr2line -e kernel/kernel ffffffff8001b9c2
/rustc/9c01301c52df5d2d7b6fe337707a74e011d68d6f/library/core/src/ptr/non_null.rs:366
rayan@pop-os:~/NyauxKT$
what does that mean
null deref?
CR2=0000000000000010
cr2 is 10
i added the hhdm offset
so why is it page fault
hmmmmmmmmmmmmmmmmmm
gdb
yeaye ik
pulling up gdb now
btw qwinci do you think i rlly needed all that arc mutex bull shit
on the vecs
well like on the cpu frame struct
*cpu_context
no need for it to be a raw pointer inside a box
either store it as frame: Registers_Exception or make new return a non boxed cpu_context
okay fine
ill make non boxed cpu_context
I mean not that this really matters, its just weird
same kinda goes for the queues being in a vector instead of being in your struct cpu or whatever
but eh
okay
what else
idk
alr
I could go over it and tell you all the non idiomatic things that it does but I don't feel like that rn 
okay i fixed that
still page faults
but gdb time ig
yall want a stream in #voice-0 or nah
guess not lol
#0 core::ptr::non_null::NonNull<alloc::sync::ArcInner<spin::mutex::Mutex<NyauxKT::fs::devfs::devfsfile, spin::relax::Spin>>>::as_ref<alloc::sync::ArcInner<spin::mutex::Mutex<NyauxKT::fs::devfs::devfsfile, spin::relax::Spin>>> (
self=0xffff80007bba0358) at /rustc/9c01301c52df5d2d7b6fe337707a74e011d68d6f/library/core/src/ptr/non_null.rs:366
#1 alloc::sync::Arc<spin::mutex::Mutex<NyauxKT::fs::devfs::devfsfile, spin::relax::Spin>, alloc::alloc::Global>::inner<spin::mutex::Mutex<NyauxKT::fs::devfs::devfsfile, spin::relax::Spin>, alloc::alloc::Global> (self=0xffff80007bba0358)
at /rustc/9c01301c52df5d2d7b6fe337707a74e011d68d6f/library/alloc/src/sync.rs:1823
#2 alloc::sync::{impl#28}::clone<spin::mutex::Mutex<NyauxKT::fs::devfs::devfsfile, spin::relax::Spin>, alloc::alloc::Global> (self=0xffff80007bba0358) at /rustc/9c01301c52df5d2d7b6fe337707a74e011d68d6f/library/alloc/src/sync.rs:2102
#3 0xffffffff8000dba1 in NyauxKT::fs::devfs::{impl#2}::create (self=0xffff80007ff0c2c0, name=...)
at src/fs/devfs/mod.rs:55
#4 0xffffffff8000e29a in NyauxKT::fs::devfs::{impl#4}::dev_create (self=0xffff80007ff0c2c0, name=..., ops=...)
at src/fs/devfs/mod.rs:122
#5 0xffffffff8000eecf in NyauxKT::fs::devfs::devfs_init () at src/fs/devfs/mod.rs:153
#6 0xffffffff80000a36 in NyauxKT::kmain () at src/main.rs:90
huh???
devfs is panicking
wha
lemme comment out sched init
WTF IS GOING ON
AAAAAAAA
i cannot debug wtf is going on

it doenst fault
when sched init is not happening
when sched init happens
boom
fault
page fault !!!!
can anyone help im kinda stuck
wait lemme debug sched init
one sec

GALAXY BRAIN IDEA

LUCKY
chat does that make my thread
the most messages
????
😭
are you building your kernel in debug mode?
also
miriiiii
i think miri would have a stroke on nyaux :^)
right miri
rayan@pop-os:~/NyauxKT/kernel$ cargo miri build
fatal error: cargo miri supports the following subcommands: run, test, nextest, clean, and setup.
rayan@pop-os:~/NyauxKT/kernel$
i cant
o
or cargo miri test or whatever
its only complaining about the tests
miri is dynamic analysis so duh
what about my other code
like the scheduler code
its not complaining about that
test fs::USTAR::populate_vfs ... error: unsupported operation: `open` not available when isolation is enabled
--> /home/rayan/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/pal/unix/fs.rs:1175:36
|
1175 | let fd = cvt_r(|| unsafe { open64(path.as_ptr(), flags, opts.mode as c_int) })?;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `open` not available when isolatio
theres an env var to turn it off lol
whats the env var
Running `/home/rayan/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/bin/cargo-miri runner target/miri/x86_64-unknown-linux-gnu/debug/NyauxKT`
error: no global memory allocator found but one is required; link to std or add `#[global_allocator]` to a static item that implements the GlobalAlloc trait
error: unwinding panics are not supported without std
|
= help: using nightly cargo, use -Zbuild-std with panic="abort" to avoid unwinding
= note: since the core library is usually precompiled with panic="unwind", rebuilding your crate with panic="abort" may not be enough to fix the problem
error: aborting due to 2 previous errors
ummm
its using x86_64-unknown-linux-gnu????
ummm
trying to do the ocmmand gives this
rayan@pop-os:~/NyauxKT/kernel$ cargo -Zbuild-std with panic="abort" miri run
error: no such command: `with`
Did you mean `fetch`?
View all installed commands with `cargo --list`
Find a package to install `with` with `cargo search cargo-with`
rayan@pop-os:~/NyauxKT/kernel$ cargo -Zbuild-std with panic="abort" miri run
oh my fucking god
i did MIRIFLAGS=-Zmiri-disable-isolation on cargo miri test
all passed
okay
You would typically use intrusive lists (?)
I don't know how that would look with Rust
There is a crate for it...
they work incorrectly
Alternatively, at some point I just had sched queues with intrusive lists with shared_ptr in my kernel
pitust how to use mmap
in rust
wihtout any crate
???
otherwise i cannot write this test
without 1 SINGULAR
page
you can just extern "C" fn mmap lol
Typical Rust
the test run just fine
the sched init
ran fine under miri too

do you still have the same issue
yea
what did gdb say
^
and not having sched init it runs fine
.
well then ig you do something weird in the sched init, can't really tell what
what more does the real thing do
i literarly let the cpus schedule their shit
hmm
@molten grotto
fn sched_queuetest() {
extern crate libc;
use std::io;
use std::ptr;
use libc::{mmap, munmap, sysconf, _SC_PAGESIZE, PROT_READ, PROT_WRITE, MAP_PRIVATE, MAP_ANONYMOUS, MAP_FAILED};
use std::println;
use std::thread;
let mut fake = cpu_queue {queue: Some(Vec::new()), lapic_id: 0};
let mut process = Arc::new(Mutex::new(process::new(None, unsafe {None}, "hi".to_string())));
// Map one page of memory into the process (anonymous memory, not backed by a file)
let addr = unsafe {mmap(
ptr::null_mut(), // Let the OS choose the address
4096, // Size of the mapping (one page)
PROT_READ | PROT_WRITE, // Read/write access
MAP_PRIVATE | MAP_ANONYMOUS, // Private anonymous mapping (not backed by a file)
-1, // No file descriptor (since this is anonymous memory)
0, // Offset (ignored for anonymous mapping)
)};
// Check if mmap failed
if addr == MAP_FAILED {
assert_eq!(1, 2);
}
// Cast the returned address to a mutable u8 pointer
let data = addr as *mut u8;
let kstack = data;
let mut context = cpu_context::new(lol as u64, false, unsafe {kstack.offset(4096) as u64});
let mut thre = Arc::new(Mutex::new(Thread::new(process.clone(), context, "kthread".to_string())));
let per = perthreadcpuinfo::new(unsafe {kstack.offset(4096)}, 0 as *mut u8, thre.clone());
thre.lock().gs_base = Box::into_raw(per);
unsafe {
let o = fake.queue.unwrap();
let mut j = o;
process.lock().threads.insert(0, thre);
j.push(process);
}
unsafe {munmap(
addr as *mut _,
4096
)};
}
what about you try switching to the some other thread in the test
though miri probably doesn't like that to be fair
how tf am i supposed to do that
its in an std enviroment
you can still switch contexts around in the same priv ring
as long as you don't use iret or smth to do it
how
the same way as in the kernel?
just dont use iret?
yeah you'd have to do it with normal ret
yes
and push them
yes
Who do Rust kernels do though?
I know Linux just ships stuff like RCU to C
none of them are particularly great afaik
but also you can write linked lists that, while incorrect, do always produce correct code
all hail rust btw
But then "who is the owner"
well yeah it would be unsafe
unless the objects are actually owned by the list
which ig would work as long as an object is part of only one list
If you pin threads to CPUs that may work...
well ofc you could still take them out of the list and move to other but like at the same time
But like it's inevitable to be referencing them on other processors
im gonna breakpoint the sched tick function
foudn the issue @molten grotto
let thr = unsafe {
(*info).current_thread.clone()
};
dereference info
cause a page fault
nice
yep
null deref
let info = unsafe {
let e = rdmsr(0xC0000102) as *mut perthreadcpuinfo;
e
};
hmmm
yea so
theres nothing in the kernel base msr
that's the inactive one
the kernel base msr always contains the currently inactive gsbase (and the currently used one is in the gsbase msr)
gotcha
okay it fixed that but
now a new issue
the entry function isnt executing
and it panics on non kvm
lovely
page faults*
yea i dont know whats going on
info is still 0x0 lol
do you actually write something to the msr
yes
#[no_mangle]
pub fn scheduletask(regs: *mut Registers_Exception) -> Option<*mut Registers_Exception>{
// pick a queue
let que = unsafe {
&mut ITIS.as_mut().unwrap().queue
};
let mut got_you = que.pop();
if got_you.is_none() {
return None;
}
let mut r = got_you;
if r.is_none() {
return None;
}
let mut new_process = r.as_mut().unwrap().lock().queue.as_mut().unwrap().pop();
if new_process.is_none() {
return None;
}
let mut new_thread = new_process.as_mut().unwrap().lock().threads.pop();
if new_thread.is_none() {
return None;
}
let info = unsafe {
let e = rdmsr(0xC0000101) as *mut perthreadcpuinfo;
e
};
// get current thread
let thr = unsafe {
(*info).current_thread.clone()
};
save_context(regs, &mut thr.lock().context);
let fs = rdmsr(0xC0000100);
thr.lock().fs = fs;
let cc = switch_context(regs, &mut new_thread.as_mut().unwrap().lock().context);
wrmsr(0xC0000100, new_thread.as_ref().unwrap().lock().fs);
wrmsr(0xC0000102, new_thread.as_ref().unwrap().lock().gs_base as u64);
let o = thr;
new_process.as_mut().unwrap().lock().threads.insert(0, o.clone());
r.as_mut().unwrap().lock().queue.as_mut().unwrap().insert(0, o.lock().process.clone());
Some(cc)
}
oh wait i havent written gs_base into
the msr on init
right
okay @molten grotto i do this now
wrmsr(0xC0000102, thre.lock().gs_base as u64);
yet it still pages faults fun
you write to the inactive msr
oh
no i think im getting it confused now
on init
should i write to which msr
the kernel
or the gs base
cause clearly
somethings not working
very likely to the gsbase
no you read both from the same gsbase msr
they don't change around unless you swapgs
to start with no if you write to the gsbase
let info = unsafe {
let e = rdmsr(0xC0000101) as *mut perthreadcpuinfo;
e
};
i read from gs_base
0xC0000101
its 0x0
gdb tells me
is it also zero if you read it back directly after you write it there
let me check
no its not
where is
wtf
where is gs base
bro wtf
you added the code into a test
yea something funky is going on @molten grotto
i think i know whats going on
still crashes
im unsure whats going on

gdb didnt give me much
WHY IS SMP SO DIFFICULT TO DEBUG
AAA
just do it on a single core to start with?
okay
yea so
on one core
it doesnt crash but rather
doesnt execute the thread
like at all
wtf
i give up debugging this 
hi im back from school
will work on scheduler later
im tired atm i have homework
dev fs created!
from rip 0xffffffff80000be4
switching context to 0xffffffff80000be4
returning it at rip 0xffffffff80000be4
from rip 0xffffffff80000be4
yea thats not right
0xffffffff80000be4 um
is the lol function at that address?
lets check with object dump
rayan@pop-os:~/NyauxKT$ objdump -d kernel/kernel --demangle | grep ffffffff80000be4
ffffffff80000be4: eb fd jmp ffffffff80000be3 <NyauxKT::hcf+0x3>
rayan@pop-os:~/NyauxKT$ objdump -d kernel/kernel --demangle | grep ffffffff80000be4
what????
bro what
yea something is very wrong
either the compiler hates me or my code is SO bad that
it makes rust want to kill itself
i say the second option
nyauxmaster try not to make shitty code

im dying chat
chat i might just rewrite the entire scheduler
good plan?
what do yall think
i think the scheduler is just too shitty
i have changed the design of the structs
#[repr(C, packed(8))]
pub struct perthreadcpuinfo {
kernel_stack_ptr: *mut u8,
user_stack_ptr: *mut u8,
current_thread: Box<Thread>
}
pub struct process {
vfs: Option<*mut vfs>,
pagemap: Option<*mut PageMap>,
cwd: Option<Arc<Mutex<dyn vnode>>>,
pid: u64,
handles: HashMap<usize, HandleType>,
name: String,
threads: Option<Box<Thread>>
}
struct Thread {
name: String,
tid: u64,
gs_base: Box<perthreadcpuinfo>,
fs: u64,
context: cpu_context,
process: Arc<Mutex<process>>,
next: Option<Box<Thread>>
}
struct cpu_queue {
next: Option<Box<cpu_queue>>,
lapic_id: u32,
process: Option<Box<process>>
}
pub struct CpuSQueue {
queue: Option<Box<cpu_queue>>
}
using less raw pointers
and less arc mutex bullshit
and not using vectors
and using a linked list instead
tell me if theres any issues with it
is there any issues with it?
i really wanna make sure i get this right before proceeding
the real question is why does the scheduler have to deal with processes? the scheduler queue should just be a list of threads
and each cpu can have its own queue of threads
buttttt we need to store the pagemap PER process
yes but other than that
like don't modify the thread list inside the process struct in the scheduler
wym
like at least in the old scheduler code you got the next thread to run from the thread list inside the process
yes?
so what abt that
im so confused lol
???
that its not a good idea
the scheduler queue would just be a list of threads and then it accesses the process using the thread's field when it needs to swap the pagemap
i see
so like the thread would point to the process struct, the queue is just a list of threads
makes sense
yeah
#[repr(C, packed(8))]
pub struct perthreadcpuinfo {
kernel_stack_ptr: *mut u8,
user_stack_ptr: *mut u8,
current_thread: Box<Thread>
}
pub struct process {
vfs: Option<*mut vfs>,
pagemap: Option<*mut PageMap>,
cwd: Option<Arc<Mutex<dyn vnode>>>,
pid: u64,
handles: HashMap<usize, HandleType>,
name: String,
}
struct Thread {
name: String,
tid: u64,
gs_base: Box<perthreadcpuinfo>,
fs: u64,
context: cpu_context,
process: Arc<Mutex<process>>,
next: Option<Box<Thread>>
}
struct cpu_queue {
lapic_id: u32,
thread_list: Option<Box<Thread>>
}
pub struct CpuSQueue {
queue: Vec<cpu_queue>
}
impl CpuSQueue {
pub fn create_queue(&mut self, lapic_id: u32) {
let queu = cpu_queue { lapic_id: lapic_id , thread_list: None};
serial_println!("created queue with lapic id {}", queu.lapic_id);
self.queue.push(queu);
}
}
improved version
the thread is a linked list
or actually should it be a vec
would that be easier or slower
okay
so
the lapic timer
is firing when it shouldnt
i cli'd the boot cpu
and the other cpus
idk whats fucking going on
does anyone kno
w
speedruning osdev was a bad idea from the beginning
im not speedrunning
im taking my time
this is speedrunning
you're just trying to implement things without fully understanding them or the language you are using first
i understand what im implmenting
maybe i could learn about the language more
but
i understand what im doing
^
it shouldnt happen
the cli instruction disabled ALL external interrupts
i understand what im doing
im gonna have to do the hacky solution of masking the lapic timer manually
by writing to the register
Or find out why the interrupts arent being actually disabled. Hint: flags register is what has the interrupt flag
okay then
WHY IS IT STILL ENABLED
WTF
WHY ISNT THIS INSTRUCTION EXECUTING
@elder shoal i think the compiler is optimizing out the asm function
well gg
oh my fucking god
you should only sti if the interrupts were originally disabled
Lmao
A scheduler queue shouldn't be aware of arch implementation details like lapic id
i mean yea but
i plan on supporting just x86

Still incorrect level of abstraction
check_exception old: 0xffffffff new 0xe
160: v=0e e=0002 i=0 cpl=0 IP=0028:ffffffff8000ba93 pc=ffffffff8000ba93 SP=0030:ffff80007a24ddd0 CR2=ffff80049077b358
RAX=ffffffff80068068 RBX=0000000000000000 RCX=0000000000000011 RDX=ffff80049077b330
RSI=000000000000000d RDI=ffff80007a24de68 RBP=0000000000000000 RSP=ffff80007a24ddd0
R8 =0000000000000000 R9 =0000000000000002 R10=0000000000000000 R11=0000000000000000
R12=0000000000000000 R13=0000000000000000 R14=0000000000000000 R15=0000000000000000
yo wtf
the rip is just garbage
ummm
CR2=ffff80049077b358
nyuax might just be more cursed than obos
yea i dont know whats fucking going on
i uncovered at least 10 memory corruption bugs by writing an xhci driver
time to try and get a backtrace
from missing ists through (accidentally) shared kernel stacks
told ya
it was smp
.rs
new issue tho
my ENTRY FUNCTION ISNT EXECUTING

what
0xffff80007febb438
0xffffffff80011e70
wtf
we got threads but
its only from cpu 0???
huh??????
wtf
i have 10 cpus
and ive inited the lapic for all of them
its coming from only one cpu huh???
wtf
i did info lapic on the other cpus
and the all work fine so wtffff
dying chat
nvm forgot to switch page maps
okay deadlocking issues now
!!!
lovely
yea this isnt going well

helppp

i hate smp
i hate smp
you know you don't HAVE to do smp
i gotta have it 
also btw i think its because i have a mutex around my thread and process
pub struct Thread {
name: String,
tid: u64,
gs_base: u64,
fs: u64,
context: cpu_context,
process: Arc<Mutex<process>>,
}
pub struct cpu_queue {
lapic_id: u32,
thread_list: Vec<Arc<Mutex<Thread>>>,
cur_idx: Option<usize>
}
i think this is causing a deadlock issue
so maybe i should remove the mutex all together in favour for a refcell<T>
what do yall think
either that or i should put a mutex on the cpu queues
i have no idea why
it deadlocks
i thought rust prevents these things lmao
yea i do not have a mutex on the global queue
there is no way it can prevent eg. you locking a mutex in normal code and then again in an interrupt handler that happens to occur when the mutex is locked in the normal code with interrupts enabled
Wrap it in Mutex<>
will do
fair
its eg. why you should disable interrupts when holding a spinlock that can be taken from an interrupt handler too
If you drop the references as you're supposed to, you shouldn't have deadlocks
fair
ill just disable interrupts on entry to my scheduler interrupt
and reenable them on exit
they are already disabled if its within an interrupt
so no point in doing that manually
oh i see
or have a nonpreemptive microkernel and don't worry about interrupts
I have a counter in my spinlocks
Which counts to like 100 million
And prints a stack trace when that is reached
To diagnose deadlocks
yea im having a lot of weird issues now
yea its still only cpu id 0
idk whats fucking going on
lol
but i mean
theres only one thread
maybe if i spawn another thread or smthin
its still only cpu id 0
...
bro
Are you sure theyre even getting scheduled on the other cpu and put on the other cpu's queue?
wdym
You have per cpu queues, you could start by checking if the thread is actually put there lol
i just have it so on schedule task a cpu picks a random queue to execute its thread
A cpu looks in another cpu's queue to execute it?
yea
it picks at random
WHA
is that bad 😭 ??
did it not cross your mind
That beats the whole point of having per cpu queues
it's called a per cpu queue for a reason?
right
yea right man
dont be mean i just got confused 😭
man don't get confused like THAT
well just don't 😭
😭
What the fuck
😭 😭
okay it works now!!!!!
we have scheduler chat
!!!!!
i need a rand function now
based
to randomly pick a cpu queue to assign a thread to

int rand()
{
return 4;
}
lmao
it's random
very random 
Rdrand
does qemu support rdrand?
Ofc
uhhh idk
Qemu supports everything with the right flags
idk I remember something about qemu and rdrand
theres a good crate that implments this functionality
i can use this and have it work with the rand crate
giving me random numbers
there's truly a crate for everything
yea i get u
second good thing about rust
there is a reason there is a crate registry...
U know its one x86 instruction right
lmao
arent u a rustie
Urdrand incoming
yeah but im not LIKE that
okay fine ill implment my own rdrand
bro its one (1) instruction
i know
3 lines of rust code
you can even fit it on one single line
no im talking 3 lines of normal rust code
one line for the out variable, one line for the core::arch::asm! and one line for the return
who needs \n
whats the difference
im using kvm
okay it works now
cool
rand seed 653978260621011362
pro
just gotta stick this into rand and
we got random numbers
😎
yea
nice
is this actually random or just happens to be a random number
reboot and try
nice
LETS GO IT WORKS NOW
😎
okay scheduler is done
whats next chat
userland time?
ITS USERLAND TIME
WEEEEEEEE
ITS USERLAND TIME
shit i do not have mlibc
uhhhhh
what do i do hmmm
also what happens when a thread returns
what will the scheduler do
lol
lmao
oh right thats a syscall
exit()
to which i do not have syscalls
i should probs set that up
i do not know what to start with
elf loader or get build system working or what
or syscalls or what
xsave? fpu setup?
idk
I was just going to say "hah this looks like the Cell architecture (the PPE coordinates the SPEs) and then ilobilo literally put the ECDSA breach meme for the PS3 here
about this
i think that's a reference to xkcd/221
chosen by fair dice roll, guaranteed to be random
yall know what i should do first?
syscall, setup fpu, elf loader, or build system?
was that an actual thing tho?
if so funny thanks for telling me
I had this on my phone for some reason
let's gooo
my discord bugged out
I was seeing multiple images of this in the chat
those kinds of things are nice tbh (not for sony tho, fuck sony)
well now we can install Linux on PS3 again
and that because Sony removed that feature in the first place
which lead to the previous problem
also reminded me that I should try ps4linux again now that there is a jb for 11.00
or ps4managarm
would be funny
ps4nyaux when qwinci

I mean why not, though idk if you'd have to use the terrible linux boot protocol
fyi the PS4 is an 8 core machine sooo
the way you execute linux on it is with a kexec like thing anyway so eh
though ig you could still make some kind of modified bootloader that would be booted that way

Assertion failed: '!"wtf are you doing"'
Same idea as uefi lol
now with custom firmware patches you can automatically boot in otherOS on the PS3
Astral on ps4 when?
assertation os
When astral itself works good enough 
don't worry. The PS4 OS itself does not work properly anyways
is nyaux better then astral 

Then astral should be good enough
You have per cpu queues so instantly better than astral 

i call the kernel the KT kernel
cause funy
kernel toes
cwd: unsafe {(*vf).vnode.clone()},
dear lord
why is this man passing around raw pointers everywehre
i have a problem
because rust is **
also Option<*mut ?> lets me pass a Some(core::ptr::null_mut()) lol

use Option<NonNull<?>> instead
I like my pointers medium rare
^
use hzlibc
and implement the ~200 sysdep fns

dont give him ideas
you'll be stuck here answering questions for the next 20h
yeah I don't think you actually need like a ton (at least not as much as nyauxkt with its c like code)
and linked lists + other things like that probably
lol
im definitely not writing my own pairing heap
A priority queue implemented with a binary heap.
yay
insertion and popping is O(log(n))
i dont think thats bad, but idk data structures so 
well with a pairing heap popping from the top is O(1) afaik
qookie hiii
hi
ok so i probably want to find something better than that
pairing heap isn't so hard to implement
x86-64 crate
what's it to be used for? a timer queue?

i suppose it's probably not that bad if you have some global value that stores the nearest timestamp for something in the heap that you check before checking the heap
i found this
Operation Time Complexity
append O(1)
peek O(1)
pop O(log n) (amortized)
push O(1)
push_pop O(log n) (amortized)
replace O(log n) (amortized)
this looks much better
I am in that you shouldn't use my libc because I don't even know whether things like xorg work on it without potentially crappy sysdep impls, that's on my todo list (and to actually write the posix compat syscalls in my kernel), and I know that cmake doesn't properly work when using it (as in when using the libc on the build system)
cats > dogs
^
lol
are you making a kernel all your own or refactoring nyaux kernel?
i wouldnt dare touch that code
one wrong move and it all falls apart
i dont think nyaux even has timers lol
i have the hpet
that is not a timer in the sense we are talking about
what timer are u talking abt then
what, like a ticker?
yeah iirc nyaux just sets up the lapic timer to fire continously
every 10ms or whatever
and that drives the scheduler
eg. having a thread sleep for 2s or having a function run after x ns
yea
nothing
i have the hpet for that
thats how everyone starts
it's not unreasonable, it's how most kernels were until fairly recently
if i need to use it
have something happen after eg. 2s without having the cpu spin
while hpet.read() < deadline { wait(); } is what you're trying to avoid
solution: base your whole kernel around coroutines
solution: make event objects, profit
you eg. keep a list of timer objects and then in your timer irq you check the list for the ones that expired and execute their actions
that's what I do
oh easy i have the lapic timer
easy
😎
and i can reuse my handle system for this
I look for expired timers and call their handlers
thats already in the process struct
im still unsure how that interacts with the scheduler, i dont have a mental map of that just yet
you could have it wait on an event
to be set
as in the thread
blocked on the timer object
basically:
timer_irq userdata:
set_event(userdata);```
we still far off lol
i still have a bunch of shit to do
like
an elf loader
or
then you:
.... setup timer object ....
wait_on_object(event);```
getting ze fpu working
in the thread
Do tickless smh
i forgot what the difference between tickless vs tickful even is lol
solution: dont worry about this until its needed later
someone explained it to me but im dumb
lmao
no ive been there already
i need better now
all my efforts end with my code being shit and me wanting it to be better
with tickless if you have an event that should happen in 10ms, you set the timer to fire in 10ms (assuming there are no events that should happen earlier)
so i want to write good stuff once and be done with it
This
without the timer ticking regularly
ah so basically have the scheduler be driven by the "timer subsystem"
I do tickless in astral even if it has some rough edges™️
i will do timer objects later
im not having nyaux be tickless cause im lazy
lol
ill just have working timer object,
it's like < 300 lines
struct Thread {
handles: HashMap<usize, HandleType>
}
enum HandleType {
...
TimerEvent(struct TimerEventObject)
...
}
struct TimerEventObject {
handler: Box<dyn timereventhandler>,
time_to_expire: usize
}
tickless for scheduling is nice since the scheduler just says "fire this event in N ms" where N is the current thread's quantum
what if there isnt another thread to run
assuming no other timed events are pending, no timer ticks will happen
you're waiting for some other device in the system to raise an irq
elves 
e.g. the hard drive or usb controller
what if my userspace program is a 1: jmp 1b
get build system workin
and no other threads are running
so i actually have elfs to run
would the cpu just spin until an irq happens?
that brings it to the isr, it does its thing, and returns back to the scheduler
which schedules my jmp 1b again?
anyways im gonna go distro hop rq brb
since that isnt blocked on anything or whatever
you could probably avoid entering the scheduler if there is only one running thread
and any scheduler timer ticks
yeah i was kind of tryihng to get a mental map of how it all works together
so when i go and implement it i dont end up being confused
yep that was it lol
you could also not treat the single thread case in a special way and just schedule the timer to fire in N ms anyway
and just find out no other threads are runnable
i think with modern timers that are 64-bits wide or near-enough (lapic with tsc deadline, stime* on riscv, aarch64 generic timers) it's even the easiest thing to do to go tickless, or dynamic tick
i think if no other threads are running i shouldnt queue the timer
and for older timers without that probably worth emulating
shouldnt be that much additional code
yeah with timers that only do deadline it's extra effort to have periodic ticks instead of tickless
and it seems that that's a trend with modern timers
literally if (new_thread is null) { return; }
else save current thread context, load new thread context, arm timer and return
also put old thread back on run queue probably
fadanoid whats ur opinion on progress wit nyaux kernel
i am pleased with the progress and look forward to seeing it go further
i see no reason why you shouldn't have bash running in due course
i dont think i will be rescheduling a thread that is blocked, that would go through a different route probably called yield, which saves the thread context, picks a new thread (or the idle thread) and switches to that
then when whatever the thread was blocked on is signaled i can reschedule again to that thread?
idk
i shouldnt talk about it there ig
one thing that helps with latency, giving a thread newly made runnable by (for example) it's reading from the keyboard device and there's now data available to read, give the thread a little help to run soon
so e.g. preempt a currently running thread on some core to get it immediately going, if its priority agrees
i have no idea how thread priorities work (yet) but i dont think that would be too hard
i guess every thread has a baseline priority it starts with
then when a thread is woken up, because of io completion for example, it gets a priority boost?
and that allows it to preempt a thread on another core
or the core it has affinity for
it can, there are a few schools of thought
i guess i should try the core it has affinity for first, then other cores
in my book, the core it has affinity for is the core it was last run on, so idk if that its right, just clarifying
one school is that the scheduler itself should include heuristics to identify what threads are I/O bound v.s. compute bound, usually by considering how much of its timeslice the thread uses up v.s. how much remains (lots used = compute bound little used = I/O bound)
and then the scheduler dynamically adjusts the priority based on that
the other school is explicitly temporarily boosting the priority of a thread woken up by I/O completion
that's the best way to go, migrating between cores is expensive to varying degrees
i think i could do both, or start with the 2nd and move to 1st at some point in time when im confident that my scheduler needs to be improved
with SMT you can fairly move a thread between two hyperthreads, hyperthreads share a lot; on the other extreme, moving a thread from one NUMA node to another is a hateful business
its about caches, tlb and all that i assume?
yeah, and numa then adds on top inequality in latency of memory access to other ndoes
What I do is that I lower the priority of a thread if it uses its full timeslice and if it blocks then I raise its priority (and the lower the priority the bigger the timeslice is)
and it has worked mostly fine™️ so far
you mean the higher the priority?
if a thread uses it's timeslice fully i dont think it should get even more cpu time
for low priority paradoxically it is often better to have a larger timeslice
really? damn
as the low priority threads are hopefully compute-bound, and the high priority are I/O-bound, and when a high priority thread becomes runnable it should preempt the low priority one
so while the i/o-bound threads are not ready, let the compute-bound ones grill
ah right, preemption exists
is preemption literally just "get out of here, its my time to run"
yes, if someone higher priority turns up, then the lower priority one typically gets punted
the scheduler always takes the next thread to run from the high priority queue (with the smallest timeslice) and only if there are no runnable threads in there it considers the lower priority ones with bigger slices
so would low priority threads never run if there were more than cores available to scheduler threads on?
but i assume scheduler would bring their priority down if that happened
to let low priority threads run
assuming they turned from io-bound to compute-bound ones
otherwise they would do io and let lower priority threads run again
that makes sense
low priority threads don't run until there are no more runnable high priority threads (which is guaranteed to happen as they either block or get turned into low priority ones themself)
ah yeah
gives me confidence in actually being able to implement it properly 
i think im going to do temporary priority boosts for now because i dont feel like trying to figure out how to do automatic priority stuff just yet, mainly because im not sure i can do it properly lol
im just playing minecraft, ill work on the elf loader later
minecraft: the procrastiation tool
I have not updated my PS4 in a long time 
Wasn't it 4 core bulldozer?
I checked rn and it says 8 cores, with 2 4 core modules
Also, PS4 isn't a PC (?)
I need to get obos running on a ps4
I've heard it doesn't have BIOS/UEFI, south bridge and a lot of stuff like that
So it's x86, but not a PC
the most reputable source of information
quora
i mean even if they arent half wrong
its still not a deal breaker
you can write drivers around this whole thing no problem
didnt people get linux to run on the ps4?
yes
whats stopping you from getting your os to run on the ps4 too?
well, not you
but anyone in general
not at all
even if its not a standard pc its not any harder
security features
Fair
@kind root when hyper for ps4

