#Nyaux

1 messages · Page 20 of 1

flat nymph
#

You can also test my OS now that I've fixed it sunflush

wide nexus
#

you can also test my OS (I dont have an OS)

flat nymph
#

Please don't abandon Nyaux again

surreal path
#

:)

flat nymph
#

(smp is kinda complicated)

surreal path
#

how

flat nymph
#

Race conditions (Rust kinda makes it easier) and cache-coherency (TLB issues)

surreal path
#

i have locks on everything that is unsafe

flat nymph
#

The goal is to have no locks

#

Also my kernel was full of reference counting pointers, and I'm getting rid of them since they become very anoying quite quickly

flat nymph
surreal path
molten grotto
#

its not worth completely avoiding locks either, making everything lockless can also kill performance

flat nymph
flat nymph
molten grotto
#

yeah

flat nymph
#

like having locks on objects is fine

#

Or whatever

flat nymph
molten grotto
#

I just realized some day that I have accidentally effectively serialized interrupts on my kernel meme I have global random pools that are locked inside the irqs and then also a global lock protecting the irq handler list that is locked inside the irq handler trolol (I should really get rid of that because removing/adding irq handler is very rare and I can just make making sure that the irq is not getting triggered anymore when deregistering the handler the caller's responsibility)

#

and the random pools should just be cpu local

surreal path
#

idk what yall are saying

#

:)

flat nymph
#

Just ignore us, you will feel the pain later

flat nymph
#

(in kernel)

surreal path
#

where in the sdm does it take abt getting the cpuid using the cpuid instruction

#

which chapter

flat nymph
#

Huh?

#

Just take lapic id from lapic...

#

Wait

#

cpuid?

surreal path
#

the core

#

what core number

flat nymph
surreal path
#

for funny prints

#

also cause more information = pro

#

its fine i just wont have that

molten grotto
surreal path
#

ok lol

molten grotto
#

giving the cores numbers starting at 0

#

because the lapic id's may not be contiguous

flat nymph
#

and may not start at 0

#

and may be different from cpuid

#

or msr

#

(one of two I don't remember)

surreal path
#

hehehaha

#

ummmm

#

why is the lapic address the exact same

#

im using read msr

#

to get the lapic addr

flat nymph
#

It's per-CPU

#

Like it's normal

cinder plinth
surreal path
cinder plinth
#

the default flanterm one is good enough

surreal path
#

why is it 0

molten grotto
#

where do you get it from

surreal path
#

the lapic

flat nymph
#

Oh, that is not normal

finite summit
surreal path
cinder plinth
#

I need to steal some

finite summit
flat nymph
surreal path
#

whats wrong

cinder plinth
flat nymph
#

Didn't someone say it was UB?

#

Maybe nothing

molten grotto
#

no its not ub

cinder plinth
#

where is it from

finite summit
#

I think I stole it from ubuntu

#

months ago

surreal path
#

help

flat nymph
#

What is lapic_addr?

#

(where does it come from?)

surreal path
#

rdmsr

finite summit
#

nyaux thread is almsot at 20000 messages

surreal path
#

lol

finite summit
#

and you mask the bits

surreal path
#

yes

finite summit
#

first 12 iirc

#

and they are...

#

the value of the msr

cinder plinth
surreal path
#

what i do

#
let addr = rdmsr(0x1b);

        let shit = (addr & 0xfffff000) + HDDM_OFFSET.get_response().unwrap().offset();
surreal path
cinder plinth
#

no

#

i mean

#

my github

#

is rdmsr

#

lol

surreal path
#

lol

finite summit
#

isn't there an iretq in this server

#

@thorn bramble

#

iretq

surreal path
#

yes

finite summit
#

iretd

cinder plinth
#

idk if his github is iretq

surreal path
flat nymph
#

It looks normal

surreal path
#

thats hex

finite summit
#

it is

#

and it looks fine

flat nymph
surreal path
#

LMAO

#

😭

#

i forgot

#

im doing this on the bootstrap cpu

flat nymph
#

Then 0 is normal

#

usually

surreal path
#

yea

flat nymph
#

(except when it's not (I had a bug in my kernel because of that))

surreal path
#

we got smp!

finite summit
#

where scheduler

surreal path
#

lol

#

i need smp before scheduler

finite summit
#

lies

surreal path
#

(im scared of scheduler cause now hardmode with smp)

flat nymph
#

Time has the same frequency on all CPUs btw

surreal path
#

doesnt matter i calculatae it

#

lol

finite summit
#

for reference, the first commit was april 29

#

and this one was may 3rd

flat nymph
#

but it's a rewrite

finite summit
finite summit
#

without any code copied

surreal path
#

ur scheduler looks extremely hard mode lol

finite summit
#

I only started copying code in june

finite summit
surreal path
#

thread starvation

#

im gonna starve u

cinder plinth
#

I think the code is just messy

finite summit
#

my code indeed is messy

flat nymph
#

I have a realtime scheduler coolmeme

#

(and it's a giant mess and I don't wanna touch it)

finite summit
#

((my scheduler is as well))

flat nymph
#

(((oh)))

finite summit
#

((((I have barely modified it since the day it was committed)

#

(((((only reason I did is because of api changes and bug fixes)))))

surreal path
#

anyone have GOOD scheduler code thats simple and supports smp i can read?

finite summit
#

can probably look at like any project here and find that

cinder plinth
#

good code or good scheduler

surreal path
#

like something easy to read

#

and simple

cinder plinth
#

good scheduler look at freebsd's ULE

surreal path
#

that is not simple

#

💀

cinder plinth
#

for now just do round robin on each cpu

cinder plinth
flat nymph
#

just do round robin

surreal path
#

how does round robin work with smo

#

smp

flat nymph
#

global lock

finite summit
#

round robin with per-cpu queues

#

or that

flat nymph
#

or per-cpu queues

cinder plinth
#

nah no need for global locks

flat nymph
#

or both

cinder plinth
#

pre-cpu queues are better

#

yea

#

choose a cpu sequentially at first

#

then in the future you can do load balancing

flat nymph
#

Like you probably don't need more than that for most uses

surreal path
#

how should a process and thread struct look like

#

what should it store

finite summit
#
// choose a cpu to run
// todo: better
int cpu = rand() % cpu_count;
flat nymph
cinder plinth
#

curr_cpu++;

#

if curr_cpu >= cpu_len-1 { curr_cpu = 0}

molten grotto
surreal path
finite summit
#

table of handles

surreal path
#

??

molten grotto
#

a handle table == a table that maps eg. fd's to actual kernel objects

surreal path
#

what is an fd again

molten grotto
#

an opaque integer handle to a open file

surreal path
#

should it map to

cinder plinth
#

can be an array

#

no need for a hashmap

#

FDs are allocated first-free

surreal path
#

i like hashmaps they are easy :)

molten grotto
flat nymph
surreal path
#

should it be a dyn vnode or smthin

cinder plinth
#

an enum

surreal path
#

oh

#

so fds can point to not just files

cinder plinth
#

no this is not for just fds

#

you don't even need an "handle table"

surreal path
#

oh

cinder plinth
#

just a fd table

cinder plinth
surreal path
#

what handles also exist

#

other then fds

cinder plinth
#

in UNIX, nothing

surreal path
#

lmao

#

what about NT

#

i plan to add NT subsystem maybe

cinder plinth
#

any resource

surreal path
#

i see

cinder plinth
surreal path
#

can there be multiple handles to the same thing

cinder plinth
#

handles are actually a much better design but don't tell that to unix people

surreal path
#

or only one

cinder plinth
#

yea

#

two different fds can refer to the same file

surreal path
#

but they are the same handle id or no

#

oh okay

#

so if its an fd

#

it should be pointing to a dyn vnode

#

which can be whatever

cinder plinth
#

nah

surreal path
#

huh

cinder plinth
#

likely you want something like posix::File

#

which keeps track of the cursor

surreal path
#

whats posix::file??

molten grotto
#

an open file ™️

surreal path
#

cursor?

molten grotto
#

the write/read position within the file

surreal path
#

wheres the

#

um

#

struct actual defination

#

not the documentation lol

surreal path
#

Vnode *vnode;
VnodeStream stream;
int flags, status;?

#

vnode stream?

#

sorry

cinder plinth
#

that's just a class which implements the Stream 'trait', meaning you can read, write and seek on it

surreal path
#

and that contains the offset in file?

cinder plinth
#

yea

surreal path
#

i see

cinder plinth
#

I forgot why I have a stream trait but it's useful

#

oh yeah

#

I remember now

#

for loading elfs for example

#

you can pass a Stream&

#

meaning you could pass a byte stream or a vnode stream and it'd work the same

surreal path
#
trait Stream {
  fn read
  fn write
  fn seek
}
struct VNodeStream {offset: usize};
impl Stream for VNodeStream{...};
struct PosixFile {
vnode: Rc<RefCell<dyn vnode>>,
flags: VNODEFLAGS,
stream: VNodeStream
}
#

something like this?

cinder plinth
#

yeah but you don't need that

#

I just do it

surreal path
#

i will do it cause rust way

cinder plinth
#

rust has std traits for that

#

std::io::Seek

#

Read

#

and Write

surreal path
#

yea but thats in stsd

#

ill implment my own

surreal path
surreal path
#

thanks

#
enum HandleType {
File(*mut PosixFile)
}
struct cpu_context {
  frame: *mut Registers,
  // fpu_state: todo!
}
struct perthreadcpuinfo {
  kernel_stack_ptr *mut u8,
  user_stack_ptr: *mut u8,
  }
struct process {
  vfs: *mut vfs,
  pagemap: u64,
  cwd: Rc<RefCell<dyn vnode>>,
  pid: u64,
  handles: HashMap<usize, HandleType>,
  name: String,
  threads: Vec<Thread>
}
struct Thread {
  name: String,
  tid: u64,
  gs_base: *mut perthreadcpuinfo,
  context: *mut cpu_context
  
}

tell me if theres anything else i need to add

#

?

finite summit
#

*context info

surreal path
#

perthreadcpuinfo

molten grotto
#

tbh you don't really need that inside the thread

surreal path
#

okay i added

molten grotto
#

well it depends on how your scheduler works, if you eg. use the irq handler to save the user regs and your scheduler only switches between kernel mode threads (and saves the callee saved registers on the stack) then you might not need it inside the thread struct

cinder plinth
#

You need it for syscall

surreal path
molten grotto
#

though ig if you don't want to pass the context ptr around manually then it might be nice

#

but like you usually don't have to pass the whole context that deep anyway

#

(unless you like store the syscall context inside the thread itself instead of the thread's kernel stack or smth)

cinder plinth
molten grotto
#

how does that affect it tho

cinder plinth
#

yeah nvm

thorn bramble
surreal path
#

what is whence

#

lol

#

what is this

#

@cinder plinth mr

cinder plinth
#

adverb
From where; from what place.
"Whence came this traveler?"
From what origin or source.
"Whence comes this splendid feast?"

surreal path
#

😭

#

but actually what is this for

#

what is Whence for

cinder plinth
#

have you never used seek

#

man seek

surreal path
#

okay

surreal path
#

for some reason

#

im probs missing a package but i dont know what it is

#

im on popos

#

sooo

cinder plinth
#

man fseek

surreal path
#

okay there

surreal path
cinder plinth
#

yes

#

well from where to do that

surreal path
#

but why size + offset????

molten grotto
#

because its from the end of the file

surreal path
#

what

molten grotto
#

Whence::END

#

means that its an offset from the end of the file

#

and end of the file == size of the file

surreal path
#

why would u want that

cinder plinth
#

to get the file size?

#

or to write at the end of a file

surreal path
#

no to add an offset to the end of the file

molten grotto
#

the offset can be zero

surreal path
#

ohhhhh

#

make sense

#

then

cinder plinth
#

can also be negative

surreal path
#

i see

surreal path
#

or how is it gonna get the vnode

cinder plinth
#

yeah

#

vnode is not in posix file

surreal path
#

okay makes sense

cinder plinth
#

nvm it is

#

well it can be

surreal path
#

why

cinder plinth
#

doesn't matter really

surreal path
#

eh alr

#

wait @cinder plinth if u call open on a dir what should u do

elder shoal
#

Open it

#

Opening a directory is a valid operation because you can then use getdents or whatever

surreal path
#

okay so thats valid

#

right

#

what is openat

#

oh it takes in another PosixFile

elder shoal
#

Open a file using a path relative to that directory

surreal path
#

yea i see

thorn bramble
#

or using a sentinel value to represent the current working directory

surreal path
#

whats a sentinel

#

like sential from valorant

surreal path
#

@cinder plinth what is this code for

#

why are you setting nbyte to attr.size - off

cinder plinth
#

if off>attr.size then resize

surreal path
#

uh huh

#

i see

#

is this check good

#

my brain is farting

cinder plinth
#

no

surreal path
#

why is this not good

cinder plinth
#

count will be negative

#

do offset-self.data.len()

#

instead

surreal path
#

okay

#

i did that

#

is that good

#

also

#

why do u do tn->attr.size

#

that wasnt modified?

#

so why are you reallocing the exact same size

cinder plinth
#

oh this is in read

surreal path
#

???

#

yea

cinder plinth
#

i have no idea why I even realloc there

surreal path
#

lmao

cinder plinth
#

i think I mustve copy pasted write

surreal path
#

😭

cinder plinth
#

remove that realloc thing

#

and it's fine

surreal path
#

alr

surreal path
# cinder plinth remove that realloc thing
fn read(&self, buf: &mut [u8], offset: isize) -> Result<usize, UNIXERROR> {
        let mut count = buf.len();
        if buf.len() == 1 {
            return Err(UNIXERROR::EINVAL);
        }
        if (offset + buf.len() as isize) as usize >= self.data.len() {
            if self.data.len() <= offset as usize {
                count = (offset - self.data.len() as isize) as usize
            }
        }
        if self.data.len() == 0 {
            return Err(UNIXERROR::EPERM);
        }
        let dest = unsafe {buf.as_mut_ptr().offset(offset)};
        let src: *const u8 = self.data.as_ptr();
        unsafe {
            core::ptr::copy_nonoverlapping(src, dest, count)
        }
        return Ok(count);
    }
    fn write(&mut self, buf: &[u8], offset: isize) -> Result<usize, UNIXERROR> {
        let size = (offset + buf.len() as isize) as usize;
        
        if (offset + buf.len() as isize) as usize > self.data.len() as usize {
            
            self.data.resize((offset + buf.len() as isize) as usize, 0);
        }
        if self.data.len() == 0 {
            return Err(UNIXERROR::EPERM);
        }
        self.data.resize(size, 0);
        let src = buf.as_ptr();
        let dest = unsafe {self.data.as_mut_ptr().offset(offset)};
        unsafe {
            core::ptr::copy_nonoverlapping(src, dest, size);
        }
        // SO EASY
        return Ok(size);
    }

these 2 funcitions look good?

cinder plinth
#

idk try them

surreal path
#

yea they dont work

#

yea i have no idea why it is not working

#

😭

flat nymph
#

Shouldn't you follow symlinks in a loop?

surreal path
#

this is read and write

#

what

flat nymph
#

In Vnode::Type::LINK

surreal path
#

this is in tmpfs

#
fn read(&self, buf: &mut [u8], offset: isize) -> Result<usize, UNIXERROR> {
        let mut count = buf.len();
        if buf.len() == 1 {
            return Err(UNIXERROR::EINVAL);
        }
        if (offset + buf.len() as isize) as usize >= self.data.len() {
            if self.data.len() <= offset as usize {
                count = (offset - self.data.len() as isize) as usize;
                
            }
        }
        if self.data.len() == 0 {
            return Err(UNIXERROR::EPERM);
        }
        let dest = unsafe {buf.as_mut_ptr().offset(offset)};
        let src: *const u8 = self.data.as_ptr();
        unsafe {
            core::ptr::copy_nonoverlapping(src, dest, count)
        }
        return Ok(count);
    }
    fn write(&mut self, buf: &[u8], offset: isize) -> Result<usize, UNIXERROR> {
        let count = buf.len();
        
        if (offset + buf.len() as isize) as usize > self.data.len() as usize {
            
            self.data.resize((offset + buf.len() as isize) as usize, 0);
        }
        if self.data.len() == 0 {
            return Err(UNIXERROR::EPERM);
        }
        
        let src = buf.as_ptr();
        let dest = unsafe {self.data.as_mut_ptr().offset(offset)};
        unsafe {
            core::ptr::copy_nonoverlapping(src, dest, count);
        }
        // SO EASY
        return Ok(count);
    }
#

i dont know what im doing wrong

#

to be honest

#

im trying to read it but it seems fine

#

like if offset is anything other then 0

#

no data is given

surreal path
cinder plinth
#

if offset >= is wrong

#

should be >

surreal path
#

oh

#

that solved nothing

#

assertion left == right failed
left: "ello world!\n"
right: ""

cinder plinth
#

also read should take a count

surreal path
#

really?

cinder plinth
cinder plinth
surreal path
#

okay sec

#

read and write take count?

#

or only read

cinder plinth
#

yes?

#

have you like

#

never used any unix api

surreal path
#

bru

#

😭

#

stop flaming me

cinder plinth
#

mhm well I guess if you can get the size of &[u8] then its fine

#

but then that won't work for syscalls

#

because you can't take a &[u8] from syscalls

surreal path
#

okay so i should take count

#

alright

cinder plinth
#

also on read you don't want to allow reads on greater than length

#

like

surreal path
#

still fails

cinder plinth
surreal path
cinder plinth
#

like

#

if you read at offset 20 on a 10 byte buffer

#

return 10 bytes

surreal path
#

so if offset is bigger then data.len

#

what do i do

#

like im so confused rn lol

#
fn read(&self, buf: &mut [u8], offset: isize, count: usize) -> Result<usize, UNIXERROR> {
        let mut count = count;
        if buf.len() == 1 {
            return Err(UNIXERROR::EINVAL);
        }
        if (offset + buf.len() as isize) as usize > self.data.len() {
            if self.data.len() <= offset as usize {
                count = (offset - self.data.len() as isize) as usize;
                
            }
        }
        if self.data.len() == 0 {
            return Err(UNIXERROR::EPERM);
        }
        let dest = unsafe {buf.as_mut_ptr().offset(offset)};
        let src: *const u8 = self.data.as_ptr();
        unsafe {
            core::ptr::copy_nonoverlapping(src, dest, count)
        }
        return Ok(count);
    }

like

#

this is my read function rn

cinder plinth
#

run the function in your head with some values

#

thats how you figure it out

surreal path
#

okay

cinder plinth
#

if self.data.len() <= offset as usize { that's wrong

surreal path
#

i see

cinder plinth
#

apart from that no idea

surreal path
#

what should it be then

cinder plinth
#

nothing

#

remove that line

surreal path
#

okay

cinder plinth
#

this isnt a very complex function lmao

surreal path
#
if (offset + buf.len() as isize) as usize > self.data.len() {
            
            count = (offset - self.data.len() as isize) as usize;
                
            
        }
cinder plinth
#

buf.len() == 1 is also wrong, what if I want to read 1 byte

surreal path
#

something like this

cinder plinth
#

yes try it

surreal path
#

okay

cinder plinth
#

if self.data.len() == 0 {
return Err(UNIXERROR::EPERM);
}
shouldnt be an error

#

just return 0

surreal path
cinder plinth
#

bro

#

buf+offset

#

that's wrong

#

you read N bytes from file at offset O

#

why are you putting N bytes in buffer at offset O

surreal path
#

what

cinder plinth
#

at this point im not gonna spoonfeed

surreal path
#

dont spoonfeed then

#

i dont want you to spoonfeed

#

im trying to understand

cinder plinth
#

does it make sense to write data from the beginning of the file to a buffer + offset?

surreal path
#

no

cinder plinth
#

when what you really want is to read bytes from file+offset?

surreal path
#

yes

cinder plinth
#

then fix that

surreal path
cinder plinth
#

what is offset

surreal path
#

1

cinder plinth
#

is there a copy_unaligned

surreal path
#

lemme check

cinder plinth
#

can you print those

surreal path
#

let mut buf = "hello world!\n".as_bytes();

#

thats src

#

i cannot print dest

#

as this is running in a test

#

so an std enviroment

cinder plinth
#

idk can't you do println!("{} {}", dest src)

surreal path
#

no

surreal path
cinder plinth
#

what does your code look like now

#

read

#

that is

surreal path
#

here

#
fn read(&self, buf: &mut [u8], offset: isize, count: usize) -> Result<usize, UNIXERROR> {
        let mut count = count;
        if buf.len() == 0 {
            return Err(UNIXERROR::EINVAL);
        }
        if (offset + buf.len() as isize) as usize > self.data.len() {
            
            count = (offset - self.data.len() as isize) as usize;
                
            
        }
        if self.data.len() == 0 {
            return Ok(0)
        }
        let dest = unsafe {buf.as_mut_ptr()};
        let src: *const u8 = unsafe {self.data.as_ptr().offset(offset)};
        unsafe {
            core::ptr::copy_nonoverlapping(src, dest, count)
        }
        return Ok(count);
    }
cinder plinth
#

no clue then

surreal path
#

any rust gods know

#

😎

#

guess no nooo

cinder plinth
#

I shall ask mr.gpt

surreal path
#

lmao

cinder plinth
#

// Copy the data safely using slices
let src = &self.data[offset..offset + read_len];
buf[..read_len].copy_from_slice(src);

#

try this

#

I actually did think of that but i wasn't sure if slices worked

surreal path
#

you cannot index slices with isize

cinder plinth
#

well

#

you can do

#

offset as usize...(offset + read_len) as usize

#

or something

#

that won't work for negative offsets yet but it's a start

surreal path
#

yea clearly not

#

there gotta be a way

#

mr gpt told me

cinder plinth
#

well negative offsets wont work if you dont have a cursor anyway

surreal path
#

i have a cursor

#

tho

cinder plinth
#

I don't see you modifying it

surreal path
#

im implementing that

cinder plinth
#

well then easy

surreal path
#

its not pushed

cinder plinth
#

(self.cursor + offset) as usize...(size)

surreal path
#

yea but

#

i only have access to the cursor

#

in the impl for the Stream

cinder plinth
#

ah then offset is never gonna be negative

#

in your read()

#

can be usize

surreal path
#

okay and how do i make negative reads working

cinder plinth
#

well cursor+offset is always going to be positive

#

if you check for it ofc

#

you can't do a read at absolute -10

#

it's always relative to the cursor

surreal path
#

i dont have access

#

to the

#

offset

#

in the stream impl

cinder plinth
#

you do though?

#

your offset is cursor

surreal path
#

yes but

cinder plinth
#

when you get read(-10) then you do cursor+-10

surreal path
#

oh

#

so this shangains was pointless lol

cinder plinth
#

idk what a shangain is

cinder plinth
#

it'll work

#

you can make offset usize

surreal path
#
fn read(&self, buf: &mut [u8], offset: usize) -> Result<usize, UNIXERROR> {
        let mut size = offset + buf.len() as usize;
        if buf.len() == 0 {
            return Err(UNIXERROR::EINVAL);
        }
        if (offset + buf.len()) >= self.data.len() {
            size = self.data.len();
        }
        if self.data.len() == 0 {
            return Err(UNIXERROR::EPERM);
        }
        let pro = &self.data[offset..size];
        buf[..pro.len()].copy_from_slice(pro);
        return Ok(size);
    }
cinder plinth
#

yes should be fine

#

..pro.len() is useless though but sure

surreal path
cinder plinth
#

you can just do size-offset

surreal path
#

size..offset?

#

or [..size - offset]

cinder plinth
#

yea

surreal path
#

okay

cinder plinth
#

same as (offset..size).len()

surreal path
# cinder plinth same as (offset..size).len()
fn read(&self, buf: &mut [u8], offset: usize, count: usize) -> Result<usize, UNIXERROR> {
        let mut size = offset + buf.len() as usize;
        if buf.len() == 0 {
            return Err(UNIXERROR::EINVAL);
        }
        if (offset + buf.len()) >= self.data.len() {
            size = self.data.len();
        }
        if self.data.len() == 0 {
            return Err(UNIXERROR::EPERM);
        }
        let pro = &self.data[offset..count];
        buf[..count - offset].copy_from_slice(pro);
        return Ok(count);
    }

does THIS function look good now

cinder plinth
#

try it

surreal path
#

wait i think i fixed a bug

#
fn read(&self, buf: &mut [u8], offset: usize, count: usize) -> Result<usize, UNIXERROR> {
        let mut size = offset + count as usize;
        if buf.len() == 0 {
            return Err(UNIXERROR::EINVAL);
        }
        if (offset + count) >= self.data.len() {
            size = self.data.len();
        }
        if self.data.len() == 0 {
            return Err(UNIXERROR::EPERM);
        }
        let pro = &self.data[offset..size];
        buf[..(size) - offset].copy_from_slice(pro);
        return Ok(size);
    }
#

yea this is better

#

wait no i did not

#

sec

surreal path
#

@cinder plinth

cinder plinth
#

no that's wrong

surreal path
#

yea

surreal path
cinder plinth
#

size should be count

surreal path
#

just

size = count;

?

cinder plinth
#

nvm

cinder plinth
surreal path
#

like what if size was 1

#

and offset is 1

#

it would be 0

#

and you would be indexing 0

#

which makes sense.?

#

i suppose it does

#

no cause

#

if size is 2

#

and offset is 1

#

it will index 1 of the slice

#

so not good

#

what should i do then

cinder plinth
#

do + 1

#

(size-offset)+1

#

no nvm that wont work

surreal path
#

lmao

#

why are we

#

even indexing the slice

#

of the buf

cinder plinth
#

true

surreal path
#

lma

cinder plinth
#

dont do it then

surreal path
#

yea

cinder plinth
#

mr.gpt was wrong

surreal path
#

clearly

#

mr gpt is stupid

#
fn write(&mut self, buf: &[u8], offset: usize, count: usize) -> Result<usize, UNIXERROR> {
        let size = count;
        if buf.len() == 0 {
            return Err(UNIXERROR::EINVAL)
        }
        if offset + buf.len() > self.data.len() as usize {
            
            self.data.resize((offset + buf.len()), 0);
        }
        if self.data.len() == 0 {
            return Err(UNIXERROR::EPERM);
        }
        let pro = &buf[offset..size];
        self.data.copy_from_slice(pro);

        // SO EASY
        return Ok(size);
    }
#

i think this is also correct

cinder plinth
#

does read work

#

do read first

#

then do write

surreal path
#

@cinder plinth tests pass

cinder plinth
#

great

surreal path
#

yep

#

time to do the things for posix file

surreal path
#

one sec

#

for WHENCE::END what should i do

#
trait Stream {
    fn read<T>(&self, buf: &mut [u8], sizeofbut: usize) -> Result<usize, UNIXERROR>;
    fn write<T>(&self, buf: &mut [u8], sizeofbut: usize) -> Result<usize, UNIXERROR>;
    fn seek(&mut self, offset: isize, wh: WHENCE) -> Result<usize, UNIXERROR>;
  }
struct VNodeStream {
    offset: usize,
    vnode: Rc<RefCell<dyn vnode>>
}
enum VNODEFLAGS {
    None,
    DIR,
    SYMLINK,
    FILE
}
enum WHENCE {
    CURRENT,
    SET,
    END
}
  impl Stream for VNodeStream{
    fn read<T>(&self, buf: &mut [u8], sizeofbut: usize) -> Result<usize, UNIXERROR> {
        let res = self.vnode.borrow_mut().read(buf, self.offset, sizeofbut);
        return res;
    }
    fn seek(&mut self, offset: isize, wh: WHENCE) -> Result<usize, UNIXERROR> {
        match wh {
            WHENCE::CURRENT => {
                self.offset = (self.offset as isize + offset) as usize;
                
            },
            WHENCE::SET => {
                self.offset = (self.offset as usize)
            },
            WHENCE::END => {
                self.offset = (self.vnode.borrow_mut().get_attrib().unwrap().size as isize + offset) as usize
            }
        }
        Ok(self.offset)
    }
    fn write<T>(&self, buf: &mut [u8], sizeofbut: usize) -> Result<usize, UNIXERROR> {
        let res = self.vnode.borrow_mut().read(buf, self.offset, sizeofbut);
        return res;
    }
  }
  struct PosixFile {
  vnode: Rc<RefCell<dyn vnode>>,
  flags: VNODEFLAGS,
  stream: VNodeStream
  }
#

is this good

#

i think it looks good

#

okay so now we have a PosixFile

cinder plinth
#

yk you can

#

self.offset = match wh {...}

surreal path
#

eh its fine

surreal path
#

i finished implmenting PosixFile

#

its time...

#

for the scheduler

#

BUM BUM BUM

#

yall ready?

edgy pilot
#

write a completely fair scheduler implementation from linux

surreal path
#

lmao

cinder plinth
#

nah ULE ftw

#

better than cfs

elder shoal
#

once I get to rewriting my scheduler I will likely make it inspirted by ULE

surreal path
#

will you be proud of me

#

😎

cinder plinth
#

i doubt you will

surreal path
#

watch me

cinder plinth
#

you need to implement a scheduler, syscalls, tty, port mlibc

#

you cant do that at the time it is atm

surreal path
#

im not sleeping

#

:)

#

so um

#

hahah

#

idc if i have school tmrw to be honest

#

i just do my classes and get home

#

then go sleep

#

then work

elder shoal
surreal path
#

ill just work what i can

surreal path
cinder plinth
#

nooo vec

#

no

surreal path
#

why

cinder plinth
#

ideally you'd use a linked list

#

but rust

surreal path
#

Box exists lol

#

:)

cinder plinth
surreal path
#

fair

#

rust has a linked list built in omg

surreal path
#

linked list

surreal path
#

:)

#

do yall think i should get dev devices working before scheduler

#

or like xsave and friends

surreal path
#

okay we got something

molten grotto
molten grotto
#

and tbh even if you don't you can create a slice from userspace ptr + size

cinder plinth
#

True

surreal path
#

how do they even work lol

edgy pilot
#

I'm not very good at explaining things

molten grotto
surreal path
#

you would just create a struct that implments the vnode ops and have that deal with the driver

#

?

edgy pilot
#

A better example would be disk access

surreal path
#
struct PS2Driver;

impl vnodeops for PS2Driver {
...
}
edgy pilot
#

read from it, you are directly reading from the storage

surreal path
#

i see

#

what dev device should i create

#

what do i need

edgy pilot
#

tty

surreal path
#

right

#

i heard tty is complicated

#

no idea where to start for tty lol

elder shoal
#

Tty demistified

surreal path
#

thank u

#

okay before i implment tty lets implment /dev/null

#

:)

#
fn read()
{
  // we do nothing :)
}

is this how /dev/null works

elder shoal
#

bytes read = 0
return success

surreal path
molten grotto
#

and for write just return the amount of data that it tried to write

surreal path
#

should i make a dev fs init function

surreal path
#

or how should i structure this

elder shoal
#

Im planning on putting all filesystems in a special section that gets initialised in vfs_init

#

But for now a devfs_init works

surreal path
#

should a devfs have a directory like tmpfs

molten grotto
#

yes that would work

elder shoal
#

Yeah you can have subdirs like pts

surreal path
#

i see

#

so just same implmentation as tmpfs

#

for directorys ig?

#

also im gonna need some way to get drivers to hook into the read() write() functions

molten grotto
#

you already have the trait?

surreal path
#

fair

molten grotto
#

just make a function to register a trait object to the devfs

surreal path
molten grotto
#

as in a function that the driver can use to create a file in the devtmpfs with a file that contains its own ops

surreal path
molten grotto
#
fn devtmpfs_register(parent_dir: &Arc<Mutex<Box<dyn VNodeOps>>>, file: Arc<Mutex<Box<dyn VNodeOps>>>) {
    // ...
}

struct Ps2Device;

impl VNodeOps for Ps2Device {
    fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
        buf.fill(0xFF);
        Ok(buf.len())
    }
}
``` something like this I'd imagine
surreal path
#

why under an arc

#

why a reference to an arc

#

lol

#

??? 😭

molten grotto
#

well yeah it could also just be a plain arc lol

molten grotto
# surreal path why under an arc

that's not the important part, but you have to protect the vnode against concurrent access somewhere, either within the higher level or in the vnode fns itself

surreal path
molten grotto
#

you make a new op to create a file?

surreal path
#

wait create() exists nvm

molten grotto
#

you need that anyway

#

yeah

surreal path
#

yea makes sense

#
fn create(&mut self, name: &str) -> Result<Rc<RefCell<dyn vfs::vnode>>, UNIXERROR> {
        let dir = &mut self.files;
        let ifeelsick = Rc::new(RefCell::new(tmpfsfile::default()));
        dir.insert(name.to_string(), ifeelsick.clone());
        return Ok(ifeelsick);
    }

how my create looks anyway

molten grotto
#

though idk if that's what you would use in this case because you don't want to create a new vnode for every on-disk file you create right away or you are going to be running out of ram

surreal path
#

okay should i add a new op or smthin

#

create_from_file or smthin

#

idfk

molten grotto
molten grotto
#

I just had to stop thinking about what happens for a second lol

surreal path
surreal path
#

or idfk

molten grotto
#

you could probably proxy the ops like astral does, as in the devfsfile would contains a field with devfsops trait object that the vnodeops fns would then call

surreal path
#
struct devfsfile {
ops: Rc<RefCell<dyn devfsops>>
}
#

something like this?

#

also should i replace all my usage of rc with arc?

#

and refcell with mutex?

#

or no

#

because i have smp now and like im gonna be implmenting scheduler soon ™️

molten grotto
#

maybe it could be a good idea then yeah

surreal path
molten grotto
#

yeah with everything

surreal path
#

okay

molten grotto
#

you don't need to lock twice

surreal path
#

Arc<dyn devfs>?

molten grotto
#

Box<dyn devfsops> would probably do

surreal path
#

okay

surreal path
molten grotto
#

wdym

surreal path
#

like, theres no function to attach ops to a devfsfile

#

its initally none

#

its wrapped in an option

molten grotto
#

the devfsfile create function can take the ops?

surreal path
#

but that wont follow the vnodeops trait

molten grotto
#

follow in what way

surreal path
#

fn create(&mut self, name: &str) -> Result<Arc<Mutex<dyn vfs::vnode>>, UNIXERROR>

i cant just add another parameter

#

because in vnode ops ive defined fn create as that

#

and if i add an ops field thats like really dumb

#

cause most fs's wont use that parameter

molten grotto
#

ah

#

I'd probably just make a new separate create function specifically for the devfs that can take the ops

surreal path
#

but most fs's wont use that lol

#

thats gonna be rlly dumb

molten grotto
#

it doesn't have to be inside vnodeops at all

surreal path
#

wym

molten grotto
#

well like you could do the create stuff directly inside the function that's used to register something to the devtmpfs and that function doesn't have to be a part of the vnode trait

#

and I don't see why you couldn't make it work using the existing create fn as well, call that inside the devtmpfs create wrapper function and then assign the ops

#
fn devtmpfs_register(parent_dir: &Arc<Mutex<Box<dyn VNodeOps>>>, name: &str, ops: Box<dyn DevFsOps>) {
    let mut node = parent_dir.create(name);
    node.ops = Some(Box::new(DevFsNode::new(ops))));
}
``` if this is how it works (?) (idk if you actually have ops as a box but you get the idea anyway)
surreal path
#

thanks qwinci :)

surreal path
#

its not

#

in create i return a arc mutex dyn vnodeops

#

fn create(&mut self, name: &str) -> Result<Arc<Mutex<dyn vfs::vnode>>, UNIXERROR> {
return Err(UNIXERROR::EISFILE);
}

#

so like

#

😭

#

yea i have no idea either

#

😭

#

how we should design this like

molten grotto
#

ig the devfsnode could have a member function for the creation of a new file and then you have the logic there

molten grotto
#
impl devfsnode {
    fn dev_create(&mut self, name: &str, ops: Box<dyn devfsops> {}
}
#

then you do the hashmap stuff in there inserting a new vnode to the map

surreal path
#

but like

#

wait lemme think

#

okay got it

#

yea

#

but what

#

but wait

#

wait no

surreal path
#

ik 😭

molten grotto
surreal path
#

:)

thorn bramble
#

a reference to one*

surreal path
#

for some reason

molten grotto
#

oh yeah

thorn bramble
#

reference to a reference

surreal path
#

lmao

molten grotto
#

I mean it can avoid one refcount increment/decrement trolol

surreal path
#

still wont work

molten grotto
#

what did you try

surreal path
#

one sec

surreal path
molten grotto
#

and what is the problem

surreal path
#

i cant get ops

#

lol

molten grotto
#

oh yeah its the ops itself that are returned from create lol

surreal path
#

again that breaks vnodeops

#

okay actually wait i have an idea

#

i know how to do it lol

#

dwdwdw

molten grotto
#

well you could have the devfs ops field as none initially and otherwise populate the ops inside create() and then inside that dev_create downcast the vnode

surreal path
#

downcast

#

??

molten grotto
#

you can downcast a trait object to the actual underlying object (like to a reference to an actual struct) though you do need a little helper method for that

surreal path
#

so i need to wrap everything under a box?

molten grotto
#

no it doesn't matter where its stored

#

but anyway there are probably other solutions in this case

surreal path
#

it wont let call downcast

molten grotto
#

yeah because you need a helper method inside the trait that returns &mut dyn Any

surreal path
#

how to do implment that

molten grotto
#

and the impl for that can be self

surreal path
#

oh i see

molten grotto
#

then you can do let a: &mut mystruct = node.as_any_mut().downcast_mut().unwrap() or whatever

surreal path
#

gotcha

surreal path
#
impl ? for Self
molten grotto
#

well it depends in what trait you put that method into

surreal path
#

i put vnode

molten grotto
#

like if you want to be able to cast a vnodeops then its in vnodeops

surreal path
#

so vnodeops for Self?

molten grotto
#

you probably already have an impl block for vnodeops

surreal path
#

i do

#

im so confused

#

lmao

molten grotto
#

just put it there

surreal path
molten grotto
#

ah yeah you literally created a new trait for it

#

probably best to just move the decl inside vnodeops

surreal path
#

what

molten grotto
#
trait vnodeops {
    // ...
    fn as_any_mut(&mut self) -> &mut dyn Any;
}
thorn bramble
#

oh hell naw

surreal path
#

oh hell yes :)

molten grotto
#
impl vnodeops for devfsfile {
    // ...
    fn as_any_mut(&mut self) -> &mut dyn Any {
        self
    }
}
surreal path
#

i see

molten grotto
#

but yeah I am pretty sure there would be ways to do what you want without needing to do it like this

surreal path
thorn bramble
#

this is just

#

no

surreal path
#

yes

#

:)

thorn bramble
#

im not even joking

#

this is just

#

you dont write codel ike this

#

if you do

#

you fucked up terriblyu

surreal path
#

broski u have any other ideas

thorn bramble
#

no i cbf reading all of ur code

molten grotto
#

I already said one idea to you, you could just move the logic from inside create to that fn

thorn bramble
#

but everyone does it somehow

#

so u should be able to too

molten grotto
#

you wouldn't need downcast if you'd move the logic there as you'd have access to the new devfsnode object you create

surreal path
#

but that cant take ops

molten grotto
#

its why I said that move the code from the create function to the devfs_register or whatever fn

surreal path
#

OHHHH

#

LMAO

#

yea that makes sense

#

im sorry qwinci

#

im really sorry

#

😭

molten grotto
#

though then it also means that the parent dir vnode would have to not be a trait object and instead it would be a complete type (and you'd need a new non-vnodeops lookup fn that returns that complete type), though then you could reuse that to implement the vnodeops lookup fn

surreal path
#

yk whats ill just use downcast

#

its fine

thorn bramble
#

no tis not

#

but whatever

surreal path
#

:)

thorn bramble
#

its not a pointer cast

surreal path
#

what is it then

thorn bramble
#

its cancer

#

idek why its a language feature

surreal path
#

how is it cancer

thorn bramble
#

this turns rust into python

surreal path
#

like explain why

#

what

#

this?

thorn bramble
#

also literally qwinci gave u the solution

#

and u said u understand

surreal path
#
downcast_as_mut::<tmpfsdir>()
#

this bad?

surreal path
thorn bramble
#

yes this is bad

#

but whatever

#

works for u i guess

surreal path
#

theres no performance hit anyway

thorn bramble
#

yes there is

#

lol

surreal path
#

wait what

thorn bramble
#

what the fuck did you think it was doing?

surreal path
#

how big is the perfomance hit

thorn bramble
#

well it has to check that the object is actually what youre trying to cast it to?

#

and if not then panic

#

lol

surreal path
#

and that is a lot of perfomance loss?

thorn bramble
#

every time you call the downcast method

edgy pilot
#

I don't think that's "a lot of performance loss"

#

but if the rust masters say it's bad, do it the correct way

surreal path
#

for making devfs

thorn bramble
#

ah i thought

#

u were calling it

#

on every like

#

idk devfs operation

#

or whatever

#

but still this is bad lol

#

fix it

surreal path
#

devfs_registerfile

#

UGHHH Fine

#

ill do it qwincis way

thorn bramble
#

nah it works for u

#

thats what matters

#

just downcast it

surreal path
#

no cause i want this to be a good kernel so

#

im not gonna downcast it

thorn bramble
#

i mean.. yes it is bad lol

#

langauges are typed for a reason

#

statically typed*

edgy pilot
#

I don't type my languages
I just speak them and computer executes

edgy pilot
#

the thing he's doing

thorn bramble
#

well c++ has std::any

molten grotto
#

I mean ofc its still a little even if its just a single if but its not like that bad

surreal path
molten grotto
#

I meant that the devfs_register function would take in a parent as an Arc<Mutex<Box<devfsnode>>> or whatever so then you cna directly insert the new node into the parent's hashmap

#

but if you already got it working then it works™️

edgy pilot
#

I understand Mutex but what's Arc or Box

molten grotto
#

arc is an atomically reference counted object and box is just a heap allocated object

edgy pilot
#

so is that like atomic shared_ptr with a lock on it

molten grotto
#

arc is basically like std::shared_ptr from c++

molten grotto
surreal path
#
threads: Vec<Arc<Thread>>,
#

bad idea?

#

fighting with borrow checker

#

i just

molten grotto
#

why does it have to be an arc

surreal path
#

is that bad

molten grotto
#

why does it have to be an rc either? wouldn't a box do?

surreal path
#

cause borrow rules

#

wont let me

molten grotto
#

what are you doing that needs this

surreal path
#

nvm a box works fine

#

alright

surreal path
#

i need this to be per cpu

#

im unsure of how to do that

flat nymph
#

Too much messages; do you have TLS already?

surreal path
#

tls?

flat nymph
#

Thread local storage

#

(cpu local storage)

surreal path
#

i dont know

#

i dont think so?

#

how do i set that up

flat nymph
#

"it depends"