#Zinnia

1 messages ยท Page 13 of 1

near tartan
#

i do that too

autumn jasper
#

I have a real array because I don't have that many chunks but you could do a virtually sparse one where it's backing is transient (or do it nothing like this at all)

near tartan
#

i keep a ref to the mapped node in the pfndb

autumn jasper
#

pfndb of what

#

pfn entry of what I mean

near tartan
#

of ever page where the node is mapped

#

so if i fault on phys 0x10000, i just look up the struct page for it and am at the node

near tartan
#

this shit is making me reconsider my life choices

#

:(

#

rust is slowing me down so much

uncut jackal
#

wrong

#

rust is making u go brrr ๐Ÿš€

#

/s

fast mirage
eternal wharf
#

RIIC++

fast mirage
#

real

marble salmon
#

i don't think we use any object relationship in our vfs and/or memory subsystem that can't be modelled in rust

near tartan
#

i just made the cursed thing ever

#

i love gnu extensions

grave peak
#

Are you finally dumping rust

near tartan
#

not yet

#

i need to make up my mind

#

because if i'm going to rewrite YET AGAIN

#

i'm going to lose it

grave peak
near tartan
grave peak
#

Damn

near tartan
#

(of course a gnu extension)

near tartan
#

eh i'll take a break for now

#

this is doing my head in

#

i'll come back to this in a few weeks

uncut jackal
#

when I rewrote my kernel in C++ it slowed me down because I was reimplementing everything that would be in core/alloc in Rust

#

idk tho it's your choice

near tartan
#

yea i wont

#

idk this my premature optimization urge kicking in

idle flower
#

maybe you are thinking to complex? or still a c like mindset?

#

but i only followed Menix Progress sparesely

near tartan
#

im currently doing page caching for inodes

#

i don't know how to properly expose it to the kernel

#

mmapping is easy enough, but actually doing file IO on it is my issue

idle flower
#

what exactly is the issue there?

near tartan
#

well, a page cache is basically a scatter gather list, right?

#

so if i map it into the kernel for a single write, would that not be slow?

#

similarly, how do i handle writes past the current file/cache size

#

that would require me to remap everything

#

the other idea is to traverse the sglist myself and just split the data up into and then write it page wise via hhdm

idle flower
#

the purpose of the page cache is to cache block io in your case? or file level io?

near tartan
#

i use it to store the in-memory representation of an inode

#

which can be mmapd

idle flower
#

the inodes are your way of storing file level metadata?

near tartan
#

yes

#

like linux' struct inode or bsd's vnode

#

it's literally the last piece I'm missing

idle flower
#

the inodes are used by the vfs to build and maintain the file/folder tree?

near tartan
#

no

#

i have dentries

#

inodes keep track of the id, stat, some ops and reference to their owning fs instance

idle flower
#

so inodes are fs local?

distant cypress
idle flower
#

dunno?

#

i am just confused why there are inodes and dentrys

near tartan
#

inodes are the actual files, dentries give them a name

#

and structure

distant cypress
marble salmon
#

Conceptually the page cache in Managarm works like this (but the implementation is a bit more complicated):

  • There is a memory object that stores a vector of (possibly absent) pages + their states (absent, in initialization, clean, dirty, in writeback etc.)
  • The memory object is mapped into userspace on mmap()
  • If an absent page is needed (e.g., due to a page fault), the kernel sends a notification (in Rust terms, think of a tokio mpsc channel) to the FS driver to make the page available
  • The FS driver reads the contents from disk and writes them to a newly allocated physical page
  • The FS driver tells the kernel that the page has been loaded
  • The kernel completes the page fault
#

If i wanted to implement this in Rust in a monolithic kernel, I'd just let the inode store an Arc<MemoryObject> and use a channel for communication from MemoryObject -> Inode

near tartan
marble salmon
#

it's stored as a radix tree but that's an implementation detail

near tartan
#

ah

#

so how does the kernel execute e.g. read()?

marble salmon
#

basically, like i stated above

#

as far as the memory object in concerned, it's the same code path as a page fault

#

but instead of mapping the page, it copies out of it

near tartan
#

now this is the part where i got stuck

#

do i map the pages into an array, or do i just walk the radix tree

#

and use the hhdm

marble salmon
#

it probably doesn't really matter

#

a mapping is better if the kernel needs to access file pages a lot

#

which is not true in Managarm so we don't do mappings of files into kernel space

#

we do use mappings in the (userspace) fs driver though

#

for some operations

near tartan
#

well the issue isn't really mapping the pages itself, but what happens when there are more pages than before

#

i.e. write with SEEK_END

#

with hhdm i can just add a new page to the tree and access it

#

with a mapping id have to unmap and remap again

marble salmon
#

using the hddm vs a mapping are not really conflicting either

#

you could use the hddm for most operations and a mapping when you really need it

#

but yeah, keeping permanent mappings of all files sounds like a bad idea

#

that'd also potentially exhaust the available virtual address space

near tartan
#

true

#

is it a stupid idea to use inodes for anonymous mappings as well

#

instead of having a separate memoryobject

marble salmon
autumn jasper
#

and you recycle them

#

as needed

marble salmon
#

yeah that makes much more sense

pine rock
marble salmon
#

i guess you can do that, depends on your kernel design

#

in general it's usually easier to reason about individual parts

near tartan
#

well, i'm unsure if it's worth the extra hassle

#

I'll take a look at the managarm impl though

pine rock
#

do the bare minimum and make it better once you actually have problems with the current implementation

marble salmon
#

I'm not sure if the Managarm implementation is instructive or not

#

It's probably more complicated than it needs to be for a monolithic kernel

near tartan
#

hmm

#

so just to summarize so i have the facts right. when i want to e.g. write a 16kb block to an empty tmpfs regular file, i:

  • call File::write(), which calls the generic callback impl
  • check if i have enough pages for the write, which in this case i do not
  • allocate 4 pages to fit the new data and assign them to that memory object
  • write the first 4kb to the first page
  • write the second 4kb to the second page, etc...
hybrid island
fast mirage
#

hows userspace

near tartan
#

close

#

current diff is 1k lines

fast mirage
#

nice

near tartan
#

yeah, that's a bit

hybrid island
#

Do you already have GPT parsing? If so, what do you use to check the CRC32?

near tartan
#

i do not

hybrid island
#

Ah

#

Well the crc32 crate doesn't work in freestanding, so that's a bit sadge

near tartan
#

cringe

hybrid island
#

The crc crate does work freestanding (there's like 6 different crates that do CRC checksums for some reason)

fickle elbow
#

Just use crc32fast

hoary cave
#

it's literally a table and a for loop

#

why would anyone need a crate for that

#

oh right.. rust

grave peak
#

Lol

hybrid island
hoary cave
#

it's not called reinventing

#

also, it takes negative effort to do that

#

it takes more time to find a crate that works with no_std than to copy the table from wikipedia

near tartan
near tartan
mental tinsel
#

type shit

near tartan
#

i'm getting my shit together

near tartan
#

AAAAAAAAAAAAAHRRG i'm going insane

#

rust atomic function pointer handling is the most aids thing ever

#

@sick flax

#

interpreter parsing is going well

#

now i just need to fix the stack and it works

sick flax
#

Still no userspace

#

Damn

near tartan
#

look at pc

sick flax
#

Yes

#

But

#

Where mlibc hello world

#

That was the deal

near tartan
#

tonight

sick flax
#

Youโ€™ve been saying tonight for 3 weeks plus bro ๐Ÿ˜‚๐Ÿ˜‚

#

literal trolling here

near tartan
#

im meming

sick flax
#

As one does

near tartan
#

but i got more time on my hands now

sick flax
#

So hello world or ban????

near tartan
#

may god strike my balls if not tonight

sick flax
#

God might not but the ban hammer is primed

near tartan
#

vc can happen starting at like 3pm or 4

sick flax
#

If I were to do something then I might be able to join for an hour maybe 2 ish?

near tartan
#

pog

#

i saw you're going on vacation?

sick flax
#

Yeah

#

So VC limited for the next 3 weeks ish

near tartan
#

๐Ÿป

sick flax
#

You bet

marble salmon
near tartan
#

interior mutability

#

but i just replaced it with a OnceInit

near tartan
#

huge

#

i got mlibc to start loading shared libraries

hybrid island
#

niiice

near tartan
#

now it's just a matter of connecting the kernel functions to the syscall dispatch table

#

most posix functions i have already implemented

#

i'll be working on this until i get the openrc welcome message

#

then i can finally merge the dev branch again

mental tinsel
#

mlibrust

near tartan
#

i should make a proper pty impl

nocturne rampart
near tartan
#

no

#

actually, i should probably fix my driver build system issues first

#

this is aids

nocturne rampart
#

Lmao

near tartan
#

a basic tty should be fine for now

marble salmon
near tartan
#

i need a way to make certain modules regular rlibs instead of dylibs

#

i haven't found a clean way to do that with vanilla cargo

#

i want a tree of crates, like subdir() in meson

#

because otherwise i'd have to specify every single driver in the cargo workspace

#

right now i have this bullshit but that only produces dynamic modules

near tartan
#

that's not good if i have like 40 mini drivers and is only 1 part of the problem

#

the other is still with actually linking built-in drivers into the kernel

#

i wish cargo wasn't dogshit

marble salmon
#

like cfg(ps2_builtin)

near tartan
#

hm

#

can you link crates together via build.rs?

marble salmon
#

probably not without massive hacks

#

sounds cursed

#

I'd just focus on what cargo does well instead of fighting against cargo

near tartan
#

well cargo does nothing well

#

:D

#

the thing that you recommend is needlessly verbose and doesn't scale at all

#

i'll try some shit

#

maybe i can get it to work without big hacks

grave peak
#

the main issue is rust wasnt designed for this use case

#

its a userspace lang idk

near tartan
#

rust was

#

cargo wasn't

grave peak
#

wellll

#

with how it handles OOMs

#

and stuff

near tartan
#

you have allocator_api

#

but that's hacked on top

marble salmon
#

it's unstable

#

but it exists

near tartan
#

well a kernel without unstable is impossible at the moment

#

you need so much stuff that is nightly only

marble salmon
#

I'd just make all drivers dylib and list them all in the workspace Cargo.toml

grave peak
#

i wonder how they solved this in linux

grave peak
#

ah wait they dont use cargo at all there

near tartan
#

yep

marble salmon
near tartan
#

no built-in drivers

#

if i could get the few crates i'm using to work with meson i'd 100% just use that instead

marble salmon
#
[features]
ps2_in_kernel = ["dep:ps2"]

[dependencies]
ps2 = { path = "../drivers/ps2", optional = true }

?

grave peak
#

i thought it was a meme

near tartan
#

clippy has a safety lint on unsafe functions

grave peak
#

ohh lol

near tartan
#

i have configured it to fail if you are missing it

grave peak
#

thats a lot of comments KEKW

near tartan
marble salmon
grave peak
marble salmon
#

UB is much easier to trigger in unsafe Rust than in C++

grave peak
#

like you have to explain yourself

marble salmon
#

so the safety comments make sense

near tartan
marble salmon
#

and it's also quite easy to produce unsound code when dealing with unsafe

#

= code that can trigger UB from safe code

near tartan
grave peak
#

also i wonder why their alloc calls into realloc

#

is it some rust thing?

near tartan
#

not as far as i know

eternal wharf
near tartan
#

oh damn i might be able to do this with build.rs

near tartan
#

i can make a builtin feature that causes the lib to be linked statically

grave peak
#

Is pub unsafe trait Allocator what u meant by the unstable allocator thing?

near tartan
#

no

#

allocator_api

#

fallible allocations

grave peak
#

ah

near tartan
#

i use it in many places

marble salmon
#

if you set the crate type to ["rlib", "dylib"], it should do the right thing โ„ข

#

if you need a build.rs to build pure rust code, you're probably doing something strange halfmemeleft

hoary cave
#

i think the problem with built in modules is that they depend on the kernel for the kernel api l, so the kernel canโ€™t depend on them, because that would be a cyclic dependency

near tartan
#

not even that

#

i don't need to reference them by symbol

#

just need a pointer to the init function on the kernel side

#

it worked in the C version

hoary cave
near tartan
#

wdym

hoary cave
#

what is the problem here

#

with bullt in modules

#

is it the build system?

near tartan
#

yes

hoary cave
#

idโ€™d do what korona said

near tartan
#

i'm trying

#

this is fucking bullshit

#

@marble salmon i can't do it in the way you suggested

#

it causes a cyclic dep

#

because i somehow need to builtin drivers in the kernel binary

marble salmon
#

i said this in the past already but I'd do a kernel-core crate for the basic APIs

#

and a kernel-full for everything

near tartan
#

i'm not doing that, that's just silly at this point

#

maybe i can do it via staticlib

marble salmon
#

I don't think it's silly at all

near tartan
#

it's more effort than just doing it with the proper linker commands

marble salmon
#

you'd face the same issue with dynamic libs in C as well

near tartan
#

no you don't

#

it literally worked in the C version

#

because the linker takes care of this

marble salmon
#

your kernel-full can be an almost empty crate that just calls the init functions of all other crates

near tartan
#

i don't understand the point of this

#

modules will need stuff from all of the kernel

#

and like i said, the way i did it before worked flawlessly

#

i will die trying

marble salmon
#

But that's no different from avoiding cycles in the dep graph of a userspace program etc

near tartan
#

the kernel doesn't really "depend" on builtin, it just needs to be linked together with it

marble salmon
#

but then there are no cycles anyway

near tartan
#

i know that, but how do i express this in cargo meme

marble salmon
#

Because the deps always go from module to kernel-core

near tartan
#

i need the code to get linked to the kernel binary

#

and i don't see any way to do that except for cargo dependencies

#

tbh i don't even know if that would even work without cargo

#

for generics or some bullshit

marble salmon
#

I'm pretty sure what i described above just works

#

you have deps

kernel-full -> ps2 -> kernel-core
kernel-full -> ahci -> kernel-core
...
#

and no cycles

near tartan
#

wait i might've misunderstood your idea

marble salmon
#

kernel-full is a binary, kernel-core is an rlib (+ dylib?)

near tartan
#

when you said "basic API" i thought you meant split the kernel into essential and non-essential

#

that's my bad

near tartan
#

i need to see what happens if i link two modules

grave peak
#

me when 71 commit VFS

near tartan
#

i may have done other things

#

shit depends on everything

hybrid island
#

I'm 73 commits into "driver refactor" and not close to merging

near tartan
#

@marble salmon lol

#

now it basically generated an empty binary with a sole dependency on kernel.kso

near tartan
#

okay koronas idea doesn't work properly unfortunately

#

it does build, but i can't find a way to make rustc only link dynamically against the kernel when building the dynamic modules

#

because it either links everything dynamically (even the actual kernel library) or it links the kernel functions into the modules statically

#

the latter actually boots, but then that defeats the purpose of modules

#

man shit like this makes me want to go back to C

#

where i'm safe from this brain damage

marble salmon
#

Hm

#

I guess this is expected

#

It has to do that to deal with monomorphization

near tartan
#

true

#

i'd need more fine grained control

marble salmon
#

I guess you have to expose an ffi in the kernel lib that the modules use to avoid that

near tartan
#

I'd rather switch back to C

hoary cave
#

dont be a pussy

#

what you can still do is the kernel_core crate that drivers can link against and a kernel crate that links it into an executable with optional statically linked drivers

hoary cave
#

oh the rlib thing

#

right

near tartan
#

and not doing either builtin or dynamic modules is an L move

hoary cave
#

then all you can do is a custom build system

grave peak
near tartan
#

opinionated language ecosystems suck

hybrid island
#

Why are you trying to make the kernel link depend on your modules? Shouldn't you have it only the other way around?

near tartan
#

how do you get builtin modules into the kernel binary

hybrid island
#

By compiling them directly in the kernel source tree, but even then the kernel doesn't link depend on them.

#

They register themselves early in startup

near tartan
#

and you do that in cargo how?

hybrid island
#

By putting them into a section, and adding some symbols around that section in my linker script. Keep in mind that I have a primarily C kernel so far.

near tartan
#

that's not what i mean

#

sure you can put them directly in the kernel tree

#

but how does that resolve the problem

#

cargo can't include any external crates even if it just needs it a linktime

hybrid island
#

Like I said: using the special section solves it

near tartan
#

no it doesn't

#

you can't link the resulting lib to the kernel

#

not with cargo

hybrid island
#

Sure it does, so long as it's in the same crate as the kernel

near tartan
#

but it's not

#

it's a dylib or an rlib

hybrid island
#

Then you need -Wl,--whole-archive

near tartan
#

you cannot specify that with cargo

#

like -l and -L

#

this isn't an issue with rust, it's with cargo being unflexible

hybrid island
#

I fixed this by making the kernel crate an rlib, still building with cargo, but linking my way after the fact.

near tartan
#

this approach also doesn't work in this case

#

because i need the kernel to also be a dylib

hybrid island
#

Couldn't you do your final link step into a dynamic object? It wouldn't be controlled by cargo in this case anyway.

near tartan
#

wdym not controlled

hybrid island
#

I just proposed taking manual control of the final kernel link step by making the core kernel an rlib and linking built-in modules not into the kernel via cargo but via this final link step.

near tartan
hybrid island
#

Oh totally

#

But didn't I basically say to do so earlier too?

near tartan
#

not sure

#

mightve missed it

hybrid island
#

IMO you can't compile kernels correctly without a custom build system.

near tartan
#

@hoary cave is a hater of !cargo for some reason

hoary cave
#

what no

#

i was the first one to suggest gc which was a spin on gn

#

generate cargo :^)

near tartan
#

๐Ÿ’€

hybrid island
#

I like cargo but it can't do everything I need, so I have cmake

hoary cave
#

i mean tbf how often do you change up kernel configuration

#

all you need to test every once in a while is all builtin and all dynamic

near tartan
#

during dev not at all

#

i really like meson tho

hybrid island
#

Then go use it

near tartan
#

the only issue i have realistically is build-std

#

idfk how cargo does it

hybrid island
#

FWIW, I nostd my entire kernel

near tartan
#

that's not what i mean

#

build-std includes core + alloc

hybrid island
#

Oh that

#

I think those are just crates?

marble salmon
near tartan
marble salmon
#

so you have a kernel_api crate that exposes extern functions and deps

module -> kernel_api

and at runtime your kernel provides all the extern functions

#

or you could just not bother with modules at all and link everything statically halfmemeleft

hybrid island
#

That's probably best yes

marble salmon
#

i don't think this is a cargo problem btw

hybrid island
#

Also true

marble salmon
#

this is a "language with monomorphization" problem

#

it would also happen in C++

#

if you tried to expose a C++ interface between the kernel and kernel modules (and not just a C interface)

near tartan
#

then i should use a language that doesn't have these issues flobsh

#

this is pissing me off

marble salmon
near tartan
#

sure, but in C this is done automatically galaxybrain

hybrid island
#

What is?

near tartan
#

headers provide this ffi

hybrid island
#

You'll still need an object with the dynamic symbols in or your linker won't allow it.

near tartan
#

im trying to convince myself to not give up because of a slight inconvenience

#

it's not going well

marble salmon
#

why do you value modules that highly anyway?

near tartan
#

cuz its more or less the reason why i even started the project

hybrid island
#

Sounds like what you actually need to do right now is take a break?

near tartan
#

probably

#

rust has its niceties but i'm missing C so much at a lot of times

#

i was way more productive and faster

spark surge
#

use C

#

C23, simple as

near tartan
#

i wonder how much one can do with gnu23 extensions

#

like auto cleanup or stuff like that

grave peak
#

probably tons of shit

#

u can basically have C++ RAII without cancer

#

also auto

marble salmon
grave peak
#

it only works for classes

#

its not as nice as defer in other languages

#

u can make like a ScopeGuard wrapper class and stuff ofc

#

but its still less fluid than just inline defer

marble salmon
#

you can forget defer but you can't forget a destructor

#

and yes, scope_exit is equivalent to defer, so you can still defer

near tartan
#

i was already able to do self unlocking spinlocks like in rust

#

with the cleanup attribute

grave peak
#

yeah linux already uses it in the latest versions for RCU and stuff

near tartan
#

v nice

marble salmon
#

did you check if there are rust to rust ffi crates?

near tartan
#

yes

#

none are very usable

#

tons of dead projects

marble salmon
#

i'd probably just not do kernel modules if i was doing a monolithic rust kernel

near tartan
#

yeah fair

marble salmon
#

do a microkernel so that you don't need modules ultrameme

near tartan
#

i wonder how hard that is

#

i know nothing about microkernel implementations

#

is there a reason why managarm has so much logic in mlibc?

hybrid island
marble salmon
#

wdym by "so much logic"?

near tartan
#

like, the managarm sysdep has so much code

#

in comparison

marble salmon
#

it's mostly protocol related code

near tartan
#

mind you, i know nothing about best practices when it comes to this

#

couldn't you do something like a supercall? i.e. server id OR'd with the server command?

#

something like

#
#define SUPERCALL(server, func, ...) syscall(((u32)server << 32) | (u32)func, #__VA_ARGS)

u32 posix_id = ...;

int sys_read(int fd, char *buf, size_t len) {
    SUPERCALL(posix_id, POSIX_READ, id, buf, len)
    ...
#

@marble salmon

marble salmon
#

A synchronous OS could do that yeah

idle flower
#

the downside is that for a microkernel the cost of sync io is higher (user1-kernel-driver-kernel-user1) than async io (given sufficient core/process ratio)

near tartan
#

is minix a synchronous OS?

uncut jackal
uncut jackal
#

preprocessed target json with the necessary linker flags lol :3

#

like, target.json.m5 or something

uncut jackal
#

possibly unstable but I last checked whether rustc's CLI was stabilised like 2 years ago (it wasn't

#

maybe it got stabilised

#

cuz linux needs that

marble salmon
near tartan
marble salmon
#

well, Managarm needs to translate the call into a posix protocol request

near tartan
#

hm

#

i don't really need this protocol stuff right?

idle flower
near tartan
#

with an unnecessary amount of overhead trl

uncut jackal
#

i like the kernel_api solution but

#

why the hell would your kernel depend on dynamically loaded modules

#

make every dependency static and optional

#

then make it so that they can be built as a dylib separately

near tartan
#

it doesn't

near tartan
uncut jackal
#

hm?

uncut jackal
#

ok so like

#

ohh

#

wait

#

i understand

near tartan
#

it's whatever

uncut jackal
#

i don't have a solution but i understand

#

and i see why it does that

#

rustc alone would do the same i guess?

#

without cargo

near tartan
#

maybe not

uncut jackal
#

you could still use cargo but don't make anything depend on anything

#

then link them together with an extra build step

#

would that pull in kernel functions into the modules?

#

like can you get modules built with no kernel functions pulled in

#

or, you can make packages for kernel modules which have a dylib output AND a rlib output

#

and vendor the prebuilt rlibs into the kernel build kinda like how portage builds rust stuff AIUI

fast mirage
#

we are so fucking close to menix hello world mlibc userspace

#

i wanna see that shit vrol

uncut jackal
#

should I make a modular kernel like menix instead of a microkernel hmm

near tartan
near tartan
uncut jackal
near tartan
#

if you only have dynamic modules, that works

uncut jackal
#

but I can do the linking step out of cargo

#

i use nixstrap :3

near tartan
#

:3

#

good for u

#

i definitely want to explore microkernels

#

maybe a C kernel and Rust servers could work

uncut jackal
#

same but I don't really want to deal with having to make a good IPC with no experience

near tartan
#

yknow, efficient core, and safe abstractions on top

uncut jackal
#

sounds nice

uncut jackal
#

I'll keep the gearbox project and name for a microkernel

#

but I'll first do a modular kernel for learning

#

so I need a new name ig

#

and I'll go back to gearbox when I feel like I'm ready for a microkernel

near tartan
#

the worst part about writing a rust microkernel is the toolchain

#

that's extremely annoying

#

but i like the concept of microkernels more than monoliths

#

i just feel like a dumbass with implementing it

uncut jackal
#

yea and imo microkernels provide u interesting design challenges

#

which is more important than practical pros and cons when doing hobby osdev

fair lintel
uncut jackal
#

is it portable

fair lintel
near tartan
#

but its easy to port

uncut jackal
#

checking for the value of EOF... configure: error: computing EOF failed

#

wtf

sick flax
#

No systemd? No bitches

uncut jackal
#

ill port systemd to linux

#

done

near tartan
#

so yeah

distant cypress
#

it's rewind rewrite time

near tartan
#

true

#

this rust excursion has given me some insights on what i can improve with my design

#

and what doesn't work

#

i want to focus on getting a really good scheduler

#

and efficient IPC

distant cypress
#

a good "kernel" with good synchronization primitives is probably really good to have yeah

#

I kinda regret not taking more inspiration from NT etc. in my work

near tartan
#

in rust i could barely do LRU

#

and i didn't even bother with RCU

storm bobcat
#

It's not too late!

near tartan
#

i don't know what the differences between async and sync microkernels are

#

i might have to read up on things

distant cypress
#

oh god Davix rewrite incoming?? ๐Ÿ˜ญ

near tartan
#

i'm infecting everyone

storm bobcat
#

I didn't really rewrite I just added NT concepts onto an existing codebase and refactored it to use them

eternal wharf
#

are you rewriting in c++?

storm bobcat
near tartan
#

that's what i mean

#

tldr what's the difference?

distant cypress
eternal wharf
distant cypress
distant cypress
near tartan
#

why does managarm have bragi exactly?

#

might be a stupid question

distant cypress
#

wtf is a bragi?

#

does it give you brag(g)i(ng) rights?

near tartan
#

probably a greek god

distant cypress
#

that wouldn't adhere to the theme.

near tartan
#

afaict it's a protocol generator like protobuf

marble salmon
#

There are a few popular crates that implement it

#

crossbeam_epoch and scc have implementations

near tartan
#

ah

marble salmon
#

The trick is usually that the rcu epoch is annotated with a lifetime

#

which can't leave the rcu protected region due to rust's type system

storm bobcat
#

So it makes it look like those interfaces are simple function calls

near tartan
#

ah

#

that's neat

#

i need to think about how i want to design my ipc

fast mirage
#

i will eat u

vast lotus
#

i mean if the language is making you run out of stack space when you have 128k stacks i think a rewrite in a different language is at least somewhat warranted

fast mirage
#

well like look

#

its just rust

#

its gonna be like that on any rust kernel

near tartan
fast mirage
#

ok vro

near tartan
#

my boss just gave me some really cool ideas for how to do IPC

fast mirage
#

insane

near tartan
#

i could make the kernel in C, but some servers in rust

#

like managarm

fast mirage
#

10 years before menix gcc port

near tartan
#

i dont think i'm doing async IO yet

near tartan
nocturne rampart
near tartan
#

coping hard

nocturne rampart
near tartan
#

already happened

#

scroll up bro

nocturne rampart
#

The rust version?

near tartan
#

yes

nocturne rampart
#

Damn

fair lintel
fast mirage
fair lintel
fast mirage
#

25 years before menix wayland

#

fr L

near tartan
#

maybe im using the emotional support item first

near tartan
#

if i end up rewriting i'm doing everything properly

fast mirage
near tartan
#

but i'm getting fed up with rust

#

it's just not meant for a kernel

eager compass
#

rust is not that bad for a kernel

#

what is worse is fucking cargo

near tartan
#

that too

near tartan
#

i would if that were possible with no_std

#

you need either a cross compiler

#

or somehow do build-std for alloc and core

eager compass
#

yeah

uncut jackal
near tartan
#

that's a cargo option

vast lotus
#

has to work somehow given that linux does it

near tartan
#

well yes

#

but i haven't found a way to do it without cargo or building the entirety of rust

#

I just need it to follow the llvm json spec

vast lotus
#

seems like linux just passes rust's core/src/lib.rs to rustc

near tartan
#

it probably doesn't hurt that they're upstream meme

vast lotus
#

being upstream doesn't really matter here? you can just pass a target json

uncut jackal
#

yep

#

the same way it builds a x86_64-unknown-none std with my custom target json it should build just fine

#

also is meson completely useless here?

#

i heard meson has some rust support

near tartan
#

yes, but no assistance in that regard

#

you still have to teach it how to build from source

uncut jackal
#

maybe xargo would help

near tartan
#

tf

uncut jackal
#

it's build-std before build-std was a thing

#

wrapper around cargo

#

yep u pass it XARGO_RUST_SRC

#

or it can take from rustup

#

oooo it builds a sysroot then just makes cargo use that sysroot

near tartan
#

linux?

uncut jackal
#

no xargo

#

you can build a sysroot and instead just use rustc alone with that sysroot

#

get rid of cargo

#

it should work

uncut jackal
#

@near tartan can I steal your UACPI binding

#

and flanterm binding

#

I already have a flanterm binding but it's build.rs is borked

#

and it's not reproducible

near tartan
#

but they suck

#

it's just a dumb wrapper

uncut jackal
#

is it reproducible

#

my bindings are shit and not reproducible

#

i want to get rid of em

near tartan
#

well they build

idle flower
#

and the uacpi-rs stuff isnt really done, thanks to university stuff on my sidenooo

near tartan
#

woe

near tartan
#

things are happening

mental tinsel
#

"fixes."

+500000
-0

near tartan
#

currently dealing with stupid issues

#

nvm i was passing 'example' as an array nstead of an array of an array

#

mb

mental tinsel
#

just write the OS in meson โœ…

near tartan
#

mfw

mental tinsel
#

are we back to a C rewrite

#

fire

#

how come you chose to make your C look like rust last time

#

with structs using PascalCase and being anonymous

#

and stuff like usize, u32

near tartan
#

idk

#

i will still use u32 and stuff

#

linux does too

mental tinsel
#

do you have any plans on what will be different this time

#

rewrite numero dos

near tartan
#

better vfs, better uapi separation, better arch abstraction, more efficient scheduling

mental tinsel
#

wdym more efficient scheduling

#

do you mean saving electricity

near tartan
#

no

#

less wasteful

#

last time i literally pushed all gpregs onto the stack on a switch

#

now i just change the rsp

mental tinsel
#

massive improvement ๐Ÿ˜ฒ

near tartan
#

i also want to support more risc-v boards

#

so dtb support it is

mental tinsel
#

say how come you chose to support a bunch of architectures throughout development rather than getting it all right on one architecture and then porting it to the others

near tartan
#

how can i make an abstraction over something that might only work on one implementation

mental tinsel
#

understandable

nocturne rampart
#

Ru st

near tartan
#

lol

#

i need to stop rewriting shit and just stick with one

somber solar
near tartan
#

YES

#

fun

modern hamlet
near tartan
#

yeah cooked

nocturne rampart
#

2mb kernel stack

#

Brother is never getting this working on mcu๐Ÿ’”๐Ÿ’”

near tartan
#

ill probably just turn on minimal optimizations in debug mode

grave peak
#

how do u put up with this

near tartan
#

i almost didn't

near tartan
#

i do need to rewrite the scheduler though

#

just putting tasks in a btreemap is not good โ„ข

#

also every cpu has their own runqueue with no way of moving tasks between cpus

hoary cave
#

u should have per-cpu run queues but other cores should be able to access cpu data of other cores

#

so you can assess the load of other cpus, for example

#

or put threads on the run queue of other cpus

near tartan
#

hm

#

the runqueues should probably not be part of the percpu structure (but still one queue per cpu)

#

though i'm not sure how that would work

#

my percpu code can access data structures from other cpus

modern hamlet
near tartan
#

how so

modern hamlet
#

what do you need more kernel stack for

near tartan
#

stack variables

#

rust puts a bunch of shit on the stack

#

especially in debug mode

modern hamlet
near tartan
#

yeah

modern hamlet
#

Also you could conditionally compile so debug has bigger kernel stacks

near tartan
#

that's true

hoary cave
#

100% should do that

#
  • maybe demand page them?
near tartan
#

ill also put opt level 1

hoary cave
#

idk if that's a bad idea

near tartan
hoary cave
#

but you could just gradually allocate them as you need them

near tartan
#

i should also use a memoryobject instead of just hhdming them

hoary cave
#

not every kernel thread needs 8MB of stack

#

and those that do will get it

modern hamlet
#

etc

near tartan
#

I'd just make a guard page

hoary cave
#

well you'd just fault

#

at some point

#

because you run out of stack

modern hamlet
#

Yes, and you need a new stack to generate the pages

hoary cave
#

hopefully you don't cross the guard page boundary

#

yeah but

#

that's what the page fault stack is for

modern hamlet
#

Yes

#

And you need to make sure not to overflow that one

hoary cave
#

lmao

#

recursive stack overflow because of rustโ„ข

near tartan
#

banger

grave peak
near tartan
#

have a pf stack that's enough to load the rest

grave peak
#

If its per cpu then u would hang the entire cpu while stuff is getting allocated

#

Plus u can get another page fault while handling that fault

modern hamlet
#

ideally your PFs would still be on their own stack

#

just trigger a double fault when a kernel stack is overflown

grave peak
#

ISTs aren't that flexible

modern hamlet
#

and handle it

modern hamlet
#

or at least

grave peak
#

Anyway thats not trivial at all and easy to deadlock yourself

modern hamlet
#

can be enabled per interrupt slot

grave peak
#

There are like 8 slots I think

near tartan
#

i mean the user stack is demand paged, but the kernel stack i can just leave at that

grave peak
#

You can overflow the stack while holding a memory management spinlock

#

Then u cant do anything

modern hamlet
#

true

modern hamlet
grave peak
#

Anyway demand paging kernel stacks sounds like hell

near tartan
grave peak
#

Basically yeah

#

It introduces similar problems to paged kernel code but even worse

#

Because you dont control when it happens

near tartan
#

ill just leave it

grave peak
#

So u have to live with 2 megabyte overhead per thread with rust

modern hamlet
near tartan
#

btw does linux also give threads the same amount of stack each?

grave peak
#

Kernel stack yes

#

Its harrcoded at 16k

near tartan
#

I mean user stack

grave peak
#

Nah its super dynamic

near tartan
#

damn

grave peak
#

U can set any size

near tartan
#

i guess that's determined by rlimit?

grave peak
#

Its possible that the stack pointer is allocated by the userspace even

#

Idr for sure

near tartan
#

i don't think that works

grave peak
#

U can just pass it to the thread via rdi

#

Like in theory nothing prevents that from working fine

near tartan
#

i forgot that we were talking about threads, not processes

grave peak
#

Clone takes a stack pointer argument

vast lotus
# grave peak Because you dont control when it happens

It's worse than just this: demand paged kernel stacks instantly trigger a double fault because the interrupt frame can't be written. To avoid this you have to use an IST entry, so now either your page faults are no longer preemptible or you need two kernel stacks per thread

mental tinsel
#

how on earth is rust that inefficient with stack memory usage ๐Ÿ˜ญ whaaat

near tartan
#

opt-level=0

mental tinsel
#

what does it even put on the stack

#

and why are locks an issue as well

near tartan
#

rust has no initialized heap allocs

#

like you can't zero initialize an array on the heap

#

that has to be done either with MaybeUninit

#

or must have an element type which implements Copy

mental tinsel
#

does the stack usage at least get better in release mode

vast lotus
#

with optimization the copy is usually elided and done in-place

mental tinsel
near tartan
#

a lot

#

like, the fpu area bug that i had was only caused in debug mode

vast lotus
#

but in debug mode having large things on the heap or returning large things often results in initialize-then-copy

#

sometimes even multiple copies

mental tinsel
near tartan
#

i had 0x20000

#

but i'm not sure it needs that much

vast lotus
#

that's still immense

#

hydrogen gets by on 0x2000

mental tinsel
#

I do just fine with 4kb stacks for worker threads and the reaper thread and 8kb for everything else

near tartan
#

like i said, i just put any number

vast lotus
#

and most of that's just for page alignment, i haven't ever seen it actually use more than like 0x1200

#

imo you should try setting it to 4k and double it until you dont overflow in release mode anymore

mental tinsel
#

how often does your kernel spawn threads anyways

#

with the 2mb stack situation

near tartan
#

wdym

#

it allocates one stack per thread

mental tinsel
near tartan
#

wtf am i supposed to do

#

i can just not build debug kernels

mental tinsel
#

oh true

hybrid island
#

BadgerOS uses 16K stacks, 2M seems excessive even for effectively -O0 put-everything-on-stack to me

near tartan
#

you'd think that

#

0x20000 wasn't enough

#

maybe 0x40000 is

#

stupid language

hybrid island
#

Do you actually have something that detects stack overflows with an exception, do you check the stack pointer register, or do you just think you need this much?

mental tinsel
#

who knows maybe you only need 1 page

hybrid island
#

But not by much

mental tinsel
#

your reaper thread probably doesnt

#

just make the stack size customizable

hybrid island
#

I reap in the housekeeping thread, which can also be told to do other things

#

Anything that needs to run at some point for GC but can't in current thread goes there.

mental tinsel
#

why not make deferred procedure calls and just allow there to be threads that spawn on-demand to help with that

#

that is what i do

#

it is very nice

hybrid island
#

That requires more scheduler shenanigans and I don't like doing that after how much pain it was last time.

mental tinsel
# hybrid island That requires more scheduler shenanigans and I don't like doing that after how m...

nah it's super easy i did it in 4 hours


struct event_pool {
    struct spinlock lock;
    struct condvar queue_cv;

    struct worker_task tasks[EVENT_POOL_CAPACITY];
    struct worker_thread threads[MAX_WORKERS];
    uint64_t head; // producer index
    uint64_t tail; // consumer index

    atomic_uint num_tasks;

    atomic_uint num_workers;
    atomic_uint idle_workers;
    atomic_uint total_spawned;

    time_t last_spawn_attempt;
    uint64_t core;

    atomic_bool currently_spawning;
};
``` and just make policies to spawn worker threads if there are not enough and exit them if each one has had too much time without doing anything
#
struct worker_thread {
    struct thread *thread;
    time_t last_active;
    time_t inactivity_check_period;
    bool timeout_ran;
    bool should_exit;
    bool is_permanent;
    bool present;
};``` super simple ๐Ÿ˜ƒ
hybrid island
#

Puts this on ever-growing TODO list

mental tinsel
#

now you can scale your housekeeping threads too

#

which is probably nice

#

and rather than hardcoding stuff in the housekeeping threads (i'm assuming u do this) you can use condvars and wake workers to go do work in the event pool(s)

#

very easy to use ๐Ÿ‘

hybrid island
mental tinsel
#

how does the timestamp here work, is it just using the timer interrupt

mental tinsel
uncut jackal
#

make two

near tartan
#

๐Ÿ’€ it's never getting finished

uncut jackal
#

1 rust kernel and 1 C kernel

#

is it gonna be a microkernel now?

#

you can do the rust servers thing you wanted to do

near tartan
#

everyone thinks microkernel is a bad idea

#

so i'm not doing that

#

i don't really have the time atm for it :(

#

maybe one day

uncut jackal
#

it's a good challenge tho

#

my microkernel is on hiatus

#

I'm currently making a monolithic kernel

#

a monolithic kernel that will NEVER be useful for anything

#

wait my bad

#

i wasn't thinking while typing

#

i don't plan on releasing it

#

i'll just use it as a testbed

modern hamlet
vast lotus
#

DFs are technically classified as aborts and are not guaranteed to have an accurate rip and thus should not be returned from

modern hamlet
#

oh, damn

vast lotus
#

Also, this still would require either the entire stack expansion being nonpreemptible or each thread having a separate kernel stack for double faults, otherwise you could get two of them on the same stack simultaneously

#

And even disregarding those issues, dealing with the deadlocks here would be a nightmare: the stack expansion might have been triggered while holding a memory allocation lock, for example

grave peak
vast lotus
#

Idk it's just something Intel says

marsh holly
#

a hardcoded address somewhere in the lapic with a constant ascii string "trolled"

vast lotus
#

Fwiw I don't think there's ever been a cpu where the rip is unreliable

grave peak
vast lotus
#

But you're not supposed to rely on it

grave peak
#

but the thing is if it double faults u have no way to recover the original exception values that would've been pushed

#

so where would u even return to

#

or like what would u do

modern hamlet
grave peak
#

ig

modern hamlet
#

Like, if you do push dword 5, and that value caused a page fault, and the page fault caused a double fault, then it should point to the push

grave peak
#

oh ok, then that makes it retriable ig

#

looks like intel intentionally really doesnt want u to demand kernel stacks

vast lotus
# vast lotus But you're not supposed to rely on it

Aborts โ€” An abort is an exception that does not always report the precise location of the instruction causing the exception and does not allow a restart of the program or task that caused the exception. Aborts are used to report severe errors, such as hardware errors and inconsistent or illegal values in system tables.

A double-fault exception falls in the abort class of exceptions. The program or task cannot be restarted or resumed. The double-fault handler can be used to collect diagnostic information about the state of the machine and/or, when possible, to shut the application and/or system down gracefully or restart the system.

#

From the SDM

grave peak
#

yeah that sucks

vast lotus
#

Because you'd need to make memory allocation reentrant

#

Otherwise you wouldn't be able to deal with stack expansion during memory allocation

#

Doing that is infeasible for all but the simplest of memory managers

grave peak
#

u could make a reentrant stack only allocator with some pool, like its possible

#

but it is stupid ig

vast lotus
#

Also consider what you'd do on OOM here

#

You can't just terminate the thread, because it might hold a bunch of kernel locks

grave peak
#

your best bet is just hang it until there's memory

#

iirc NT does dynamically grow kernel stacks somehow?

vast lotus
#

Yeah but then you're stuck in the handler until that memory is available, so now the peeemptibility thing is even worse: the CPU you're on won't be able to do anything until that memory is available

#

Because consider what happens if you yield away and the new task triggers a stack expansion

vast lotus
grave peak
#

perhaps

pine rock
pine rock
#

but the default windows kernel stack size is something ridiculously large like 1mb so what are you doing when you need more than that

#

i've survived just fine with 16kb kernel stacks

idle flower
near tartan
#

turns out there are clippy lints for large stack frames

#

time to disallow those

#

what kind of insane default is this???

#

okay i did some testing

#

with opt-level = 1, even in debug mode 0x8000 is enough for the kernel stack

hoary cave
#

0x8000 is still kinda insane but better than 8MB โ˜ ๏ธโ˜ ๏ธ

near tartan
#

0x4000 also works

#

but that might still be silently corrupting stuff

#

i will change it to actual mapped memory

#

not just hhdm

hoary cave
#

u apparently cant demand page it tho

near tartan
#

ill map all of it at once

#

with a guard region

hoary cave
#

i see

near tartan
#

i should probably encapsulate it as a stack object

hoary cave
#

realistic

near tartan
#

i should also implement fork already

#

and/or proper tty

#

because rn i catch all r/w calls to 0, 1 and 2 to the logger

#

instead of having an actual console

#

I'm not sure how that works yet

#

like, if stdin points to /dev/tty0, how does it get input?

hoary cave
#

stdin points to /proc/self/fd/0

#

and thats tty0 or pts or whatever opened

#

by default i guess it would be the console

#

but bash will create a pty and dup that for the child process

#

so the child process stdin is the read end of the pty

near tartan
hoary cave
#

well it depends bro

#

you mean tty0 as in the actual console?

#

that would be the input subsystem of some sort

#

like evdev

#

devices put their inputs on a queue

#

or a ring buffer

#

and if the console is allowed to take input

#

it just pops stuff off the queue

#

and it translates input events into console things

#

like ascii letters or ansi escapes

#

evdev of course assumes you are linux

#

you might want to implement another interface, idk up to you

#

and as for userspace that's where libinput comes in, if you have evdev you get it for free* and and in case of your own interface you have to implement a backned, which shouldn't be too hard

#

the terminal application would interface with the input devices using libinput or something else and get input events that way, and basically do what your kernel does to produce input on /dev/tty0 but it would write it to a pty write end

#

here's an example, with the MOD_{SHIFT,CTRL_ALT} and NO_MODS macros doing the conversion + write to the pty

#

that's essentially what you would do in your kernel to convert keyboard inputs to what you write to the console buffer so userspace can read it

storm bobcat
#

Like in fastfat

#

Where code explicitly grows its own stack

#

That's fine since you know you don't hold locks or whatever

grave peak
#

ah

storm bobcat
#

But growing kernel stacks on-demand is a no-no

near tartan
hoary cave
#

well, good question

#

i can't tell you that

#

but it would appear so..?

#

you still have to know which device it comes from so they're probably tagged in some way

#

like a device pointer/id

#

but as far as my knowledge goes that's what i would assume

near tartan
#

lets look into that

#

i want a proper input system

hoary cave
#

good luck ๐Ÿ™

near tartan
#

not a hardcoded stdin > /dev/serial

#

maybe @marble salmon knows how this works

hoary cave
#

if anything i'd try infy :^)

#

bro probably has a phd in linux internals atp