#Zag

1 messages ยท Page 8 of 1

fallen bobcat
#

u do this and then sysctl can tune dir.some_knob

heavy sandal
#

ah neat

fallen bobcat
#

the way freebsd does it is kinda crazy, historically sysctl didn't have names but rather IDs (so like kern.whatever would be something like [1, 2]), now it uses string names but to handle legacy code it still uses numerical IDs, and to find names it searches into a special ID

#

so you have to do 2 syscalls for sysctl, one to get the IDs from the string name and one to set the value

#

and it's a linear search of names in that entry ๐Ÿ’€

#

what I do is have an AVL tree ordered by lexicographical ordering of the names in each directory, and the linux subsystem will simply convert file paths to the standard . syntax I guess

heavy sandal
fallen bobcat
#

idk how that would work

heavy sandal
#

oh right tree not strict map

fallen bobcat
#

no it would work

#

but idk how to write it

#

because the way I do things rn parent is a type so I can't insert to it directly, I put nodes into an executable section and traverse it and insert them:

#

ah I don't think StaticStringMap would work here because I need to add the KVs one by one basically

heavy sandal
#

you could somehow build it all at comptime? idk

fallen bobcat
#

there is probably a way to build the tree at comptime though

#

yeah, I just don't know how

heavy sandal
#

if you declared it all in one place itd be easy

#

but idk how youd do it here

fallen bobcat
#

do you think I can declare the type with const first then refer to the storage and add it to a comptime hashmap or something

#

like

heavy sandal
#

comptime global vars dont exist

#

is the issue

fallen bobcat
#
const Holder = struct { var storage = ...};
comptime_hashmap.insert(&name, &holder.storage);
#

ah

#

im sure I could build it at compile time

#

it's just very annoying

heavy sandal
#

yeah

fallen bobcat
#

I wish zig had some type of compile-time section or something, where you could iterate over all variables in that section and do stuff on them

#

Kind of a crazy concept but I think it'd be useful

fallen bobcat
#

@languid canyon what is that linux thing where you have variables that are read-only after boot

languid canyon
#

What are you asking exactly

#

Just a section thats changed to ro after init

#

__ro_after_boot I think

fallen bobcat
#

what is it called

#

ah ok thanks

languid canyon
#

Or after init

#

Just grep

fallen bobcat
#

I've added tunables, which are cmdline parameters but better:

#

for dynamic parameters you might wanna set on boot

#

i saw it in xnu code and thought it was kinda like sysctl but it wasn't, though I will continue my sysctl-like thing too

vital summit
fallen bobcat
#

it's not

#

also tf you mean "linux"'s sysctls ๐Ÿ˜ญ

vital summit
#

like the way they're defined

fallen bobcat
#

linux sysctl is cancer

#

BSD-style sysctl tho is pretty good

fallen bobcat
vital summit
#

i only meant syntax lol idk if they're related

fallen bobcat
#

this is my sysctl-like thing

#

I wont name it tunable tho I'll have to find another name

fallen bobcat
#

the larp never stops

#

i added basic hardening features to the allocator

fallen bobcat
#

@heavy sandal LOL

heavy sandal
#

lmao what did you do

fallen bobcat
#
        self.cpus = @ptrCast(@alignCast(cpu_zone.alloc(.{}) catch @panic("Failed to allocate per-CPU magazine state")));
``` I think it doesnt like this
heavy sandal
#

hm

#

idk why that wouldnt work tho

#

is the thing

fallen bobcat
#

well I do pretty weird stuff

#

this is a []rtl.CachePadded(Cpu) type so it may not like this

#

since it's like an inline type or whatever

heavy sandal
#

idk i do shit like that fairly often

#

only way to really be sure is to run a releasesafe or debug build of the compiler tho

#

and that takes like five years to build

fallen bobcat
#

what's funny is that this is 0.16 too

fallen bobcat
#

@crimson sand the NT functions for the memory thresholds are MiInitializeWorkingSetManagerParameters and MiUpdatePageThresholdsDpc

fallen bobcat
#

fkgjfkgj

#

perkenrle time

#

prekernel will do a bunch of stuff: detect cpuid, start APs, map kernel and pfndb

#

infy about to roast me

languid canyon
#

Why start aps in the prekernel? You will have to restart them for hotplug or resume from suspend anyway in the kernel

fallen bobcat
#

yeah ik, but I want the kernel to boot in a nice cozy environment

#

where all APs are spinning in their idle thread already

languid canyon
#

Ig if you decide to never support those features then its fine

fallen bobcat
#

i have to have duplicated code for pagemaps anyway so ๐Ÿคทโ€โ™‚๏ธ

fallen bobcat
#

but like

#

it's duplicated code

#

not that bad

fallen bobcat
languid canyon
#

Yeah, firmware notification on the cpu object in aml

fallen bobcat
#

i could always somehow have the same assembly file for the prekernel and kernel

#

like I don't really think it's a big issue

#

same thing for pagemaps, i have to have duplicated code kinda

languid canyon
#

I mean sure

fallen bobcat
#

but I can't here

#

idk maybe I can but too much work

#

btw @solid marsh for hot(un)plug how do you protect for_each_online_cpu?

#

do you have a lock around the cpu count or something?

#

or is it atomic and it'll get picked up next time

solid marsh
#

i haven't implemented that yet

#

i thought of avoiding the lock by allocating all the cpu structures at startup

fallen bobcat
#

ig a lock would work but it'd be shitty

#

cuz when a cpu goes offline you wanna wait till everyone is out of these loops

solid marsh
#

and then those structures have a flag indicating whether they're online

#

so for each online cpu you're interested in, you can check the bitmap and the structure

fallen bobcat
#

you could probably do it through some kind of RCU thing

solid marsh
#

you avoid having a global lock, and if you set up transitivity well you only need the lock in the structure

#

yeah, I thought about that too

#

but I'll have to see how well it plays with hotplug

heavy sandal
#

i do think acpi is guaranteed to have an object for each possible cpu/slot iirc so at least you dont have to allocate new for a hotplugged cpu

fallen bobcat
#

you wait till all cpus are in a quiescent state and decrease the CPU count only then

#

it'd be annoying because you'd have to park the cpus for a while until everyone is quiescent

#

but I don't think you really have a choice with unplug anyway

fallen bobcat
fallen bobcat
#

no that wouldn't work nvm

heavy sandal
solid marsh
#

for hotunplugging cpus I'll have a percpu task which manages exactly this

heavy sandal
# fallen bobcat <@121733282676211714> how would you do this

option a is to use externs/exports and have the kernel link to the prekernel for shared stuff. downside is you lose access to zig slices, error unions, and generally anything that isnt extern
option b is you compile the prekernel and kernel as a single executable and then split the prekernel out using objcopy somehow
option c is you just @import the same file from both and live with the code being duplicated in memory - this is what i do for my bootloader protocol file by having the root files for the kernel and loader be one directory level lower than they arguably should

solid marsh
fallen bobcat
#

What I do is do a for loop from 0 to ncpus

solid marsh
#

yeah, but ncpus stays constant

fallen bobcat
#

no

#

I have a compile time ncpus like Linux

#

And a runtime ncpus

#

Compile time is for max CPUs

solid marsh
#

what is the datastructure you traverse with the loop?

heavy sandal
#

just loop every possible cpu and skip the thing if the cpu isnt present no?

fallen bobcat
#

This is convenient because zig has no macros and it would suck to do it through an iterator everytime

fallen bobcat
solid marsh
#

the compile time constant is the maximum amount of cpus the kernel can handle

fallen bobcat
heavy sandal
solid marsh
#

then depending on the system the maximum amount of cpus is <= that

fallen bobcat
#

Unless I make it an iterator

fallen bobcat
#

But I have a runtime ncpus

solid marsh
#

and you say that it can vary during runtime?

#

uh

#

i don't understand why you would want that

heavy sandal
#

yeah i dont understand either

solid marsh
#

like, let's go back to the bitmap example

#

what if you have cpus 0..49 and remove cpu number 21

#

ncpus=49, okay

#

how does this help you

fallen bobcat
fallen bobcat
#

compile time ncpus is for cpumask

solid marsh
#

yes

heavy sandal
#

the zig std bit set has an iterator already btw

#

just gives indices of next set bit

fallen bobcat
#

Ah

#

I have my own

heavy sandal
fallen bobcat
#

because iterators suck in zig

#

and i dont have macros

heavy sandal
#

what sucks about them?

fallen bobcat
fallen bobcat
heavy sandal
fallen bobcat
#

idk why runtime ncpus doesnt work then

#

it's literally just the same thing

#

but you add if (!online(i)) continue

heavy sandal
heavy sandal
solid marsh
#

what we are trying to say is that the number is useless, unless in your datastructure you remove offline cpus from being able to be iterated over

#

then that number is obviously needed

fallen bobcat
#

dont you want to iterate over all cpus at some point

#

I do that a bunch of times

solid marsh
#

yes

fallen bobcat
#

I also use it for my counters that must go through every cpu

heavy sandal
#

unless we've been spending who knows how long using different mental definitions of what ncpus refers to and not realised

solid marsh
#

i understand his definition of ncpus as "amount of cpus online"

heavy sandal
#

yeah same

heavy sandal
#

and thats the one i dont see a use for

solid marsh
#

so if you have 4 possible cores and 2 are online, ncpus=2

fallen bobcat
#

which is why it can vary

solid marsh
#

^

heavy sandal
#

i dont see how that helps if its easier and way less sync required to just iterate possible cpus and skip offline ones

fallen bobcat
#

how do you iterate over online CPUs then? you iterate over the bitmap?

solid marsh
#

yes

#

and skip offline ones

fallen bobcat
#

well the bitmap has the same issue then

heavy sandal
#

or over a generic list of possible ones and skip offline

solid marsh
#

or also that

fallen bobcat
#

that would be slow if your CONFIG_NCPUS is high

solid marsh
#

i think that you rarely have to do such iteration

fallen bobcat
fallen bobcat
heavy sandal
solid marsh
#

one of the few cases I can think of right now is for picking on which cpu a task should be assigned on creation or when its affinity is changed

heavy sandal
#

separate from your os's supported max

fallen bobcat
#

also where is that

solid marsh
#

yes

#

just iterate over the madt

fallen bobcat
#

the madt will have entries for all possible cpus?

solid marsh
#

yes

heavy sandal
#

yeah the madt cpu entries (also the cpu device/processor objects) will have status flags for not-present cpus

solid marsh
#

the only weird thing about the madt in x86 is that, well

#

there's 2 bits: enabled, and online capable

#

the spec says that entries where enabled and online capable are 0 must be ignored

fallen bobcat
#

ah it's the first bit

solid marsh
#

so enabled means "i am running from boot", and online capable means "i am a hotplug CPU"

#

only problem is, no one fucking SETS the second bit

fallen bobcat
solid marsh
#

not even when there are real hotplug cpus

#

so you will have to find the processor objects

fallen bobcat
#

so i have to do AML in the prekernel?

heavy sandal
solid marsh
#

so in most computers, if you have both flags 0, the madt entry is just for padding

#

and in virtual machines (one of the very few places you'll find hotplug cpus), it may be hotpluggable

fallen bobcat
#

see i have a bunch

heavy sandal
#

if the madt has both bits 0 then the cpu isnt plugged in or its padding

fallen bobcat
#

very helpful

solid marsh
#

the spec says that if both are 0 it should be ignored

#

well, must I think

#

so i have no idea why no one sets the online capable bit lmao

fallen bobcat
#

that is fucked

solid marsh
#

yes

#

a little bit

#

if you see the dmesg of a machine with padding entries, it will report as present even the padding cpus

#

and then trim them off

fallen bobcat
#

ig what i could do is make the for_each_online_cpu use the cpumask with only the online cpu bits set

#

so that way I dont have to figure out the number of possible cpus

#

yeah maybe I just dont support cpu hotplug meme

#

only hotunplug ig

heavy sandal
fallen bobcat
#

what is the std bit thing you said btw

#

i have that in my bitmap

fallen bobcat
#

ah lol I literally reinvented ArrayBitSet

#

i think

solid marsh
#

so, apparently, from ACPI 6.3, the online capable bit is implemented, so if your tables are at that revision or greater, you can use that bit to know whether your cpu is usable (hotpluggable)
otherwise, if the enable bit is not set, for real hw is padding, and if in qemu, it's a hotplug cpu

#

@languid canyon insanity

fallen bobcat
#

idk how they protect against racy mask updates tho

solid marsh
#

there's a cpu write lock

fallen bobcat
#

they don't take it in the iterator tho

solid marsh
#

yeah, because you dont update in the iterator trl

fallen bobcat
#

no but

#

in parallel there's a cpu starting

#

like, one CPU is doing a for_each_online_cpu and another is starting a new cpu

#

or worse, one CPU is doing a for_each_online_cpu and another is removing a CPU

solid marsh
#

you then have a lock outside that protecting

fallen bobcat
#

so you do have a lock in the iterator then meme

#

or they let it race for most stuff

languid canyon
solid marsh
#

nice

fallen bobcat
#

can i hire one of you two to do hardware/firmware bullshit

#

so i can do actually interesting stuff

solid marsh
#

how much $$$ are we talking about god

fallen bobcat
#

you will get 10 million$ in zagcoin

solid marsh
#

welp

#

there is also a cpus read lock

fallen bobcat
#

ah yeah

#

ok that makes sense

#

thank you clanker

solid marsh
#

well, as i say

fallen bobcat
#

to me that doesnt sound really good, unless it's RW lock or something?

solid marsh
#

it is not that common to have to iterate over all online cpus

fallen bobcat
#

true

#

but still nasty

languid canyon
fallen bobcat
#

ig they could use a seqlock actually

solid marsh
#

and if you still really really want to remove the lock

fallen bobcat
#

i wonder

solid marsh
#

you could have an enable bit in the cpu structure too

#

so that enabled bit in cpu -> enabled bit in bitmap

languid canyon
#

Imo its not needed, you hotplug extremely rarely, so 99.9% of the time u grab the fast path read lock

fallen bobcat
#

yeah if it's rwlock sure

#

yeah it is

solid marsh
#

well actually, if you decide to duplicate the bit then you 100% also want a lock in the cpu structure

#

so at this point better be linux and use a rwlock KEKW

fallen bobcat
#

yeah rwlock works here

#

seqlock could work too

languid canyon
fallen bobcat
#

why not

languid canyon
#

Seqlock allows intentional races, here you would be accessing freed data or trying to talk to a cpu thats been offlined before the second checkpoint

#

You really wanna block offlining while iterating this stuff

fallen bobcat
#

youd do it on the cpu mask or something

#

yeah no ok I dont think it'd work well

languid canyon
#

Like the nice thing is the way offlining is designed is the kernel only gets a request, but it decides exactly when ejection happens so you can postpone it until the lock is free

fallen bobcat
#

or since zig is lazy it'll see those symbols are unused

fallen bobcat
#

you have to have a lock somehow to avoid the cpu state being iterated on

#

fucking hell i have so much stuff to do and I am so slow

#

if i worked full time on it im sure it'd still take like 1 year to get where i want

heavy sandal
fallen bobcat
#

I'd rather not rely on std anyway

#

ugly function names

#

(/s but mostly because it's not stable and there are no docs)

heavy sandal
fallen bobcat
#

and I don't trust the std implementations

#

SmpAllocator ruined my trust of the std

heavy sandal
#

thats your decision lol

fallen bobcat
#

Nah I use it here and there it's just that particular thing I didn't know it had

#

I guess its useful but I reimplemented it anyway

heavy sandal
#

yeah

#

all depends on context

fallen bobcat
heavy sandal
#

this one in particular i use a lot though so i know it from that

#

but also just idk this is the sort of thing im good at learning and absorbing

#

like i still know half of the nonsense obscure things from the dotnet standard libraries despite not having used most of them

#

like my beloved conditionalweaktable

#

ive still never used it but i sure do know it

fallen bobcat
#

I'm thinking I can move all large pages to the loader

#

i mean handling of them

#

that'll simplify the kernel pmap code

fallen bobcat
#

@heavy sandal is there some kind of zig allocator i can just give a page alloc function to and it'll work

#

ideally id use arena allocator but i need another allocator for that

#

ah i think i can just use arena allocator with a custom page allocator my bad

#

i think

#

idk

heavy sandal
#

which I think is getting renamed to safeallocator? idk

#

it also needs a mutex type iirc and is a bit slow tho

#

because it traces everything and does leak checks and all sorts of stuff like that

fallen bobcat
#

Hey @vital summit is the initgraph stuff fully compile time or are there steps that are added dynamically? Like if you detect some device of some sort do you add that step to the initgraph or do you run the init manually in one of the steps

#

If so how does that work? Initgraph steps can add other steps?

#

ah ig you register the tasks but u just dont do anything

vital summit
fallen bobcat
#

cuz I'm sure I can cook something up with zig comptime and do it all at compile time

#

but if steps are added dynamically then not really

#

mhm ig u can have some kind of "features" attribute to init steps

#

and like if features has acpi and no acpi: dont run it

vital summit
#

i wanted to do subtrees

#

so you'd register a stage with a tree

fallen bobcat
#

ooh yeah

#

that makes sense

#

sounds good

vital summit
#

something like "if the root is disabled, I don't run any leaves"

fallen bobcat
#

that way you can still build all trees statically but you can choose to not run a bunch of steps at once

vital summit
#

yeah

#

what's your opinion on kernel modules

#

i considered to just remove them to cut down on boot complexity

#

also might give boosts with lto

fallen bobcat
#

I guess it depends, I do want to have them but it'll be annoying because zig and C aren't natively compatible (so id have to have a bunch of extern wrappers)

#

ig the best option is to choose whether or not they're compiled in or linked

vital summit
#

in rust it's been easy so far

fallen bobcat
#

do you expose a C api? or just rust?

vital summit
#

just rust

fallen bobcat
#

yeah ideally I'd expose a C api

vital summit
#

it does mangling with a buildid

#

so kernel abi is always the same

#

but i feel like it causes more trouble than it solves

heavy sandal
#

fwiw zig doesnt have a defined extern abi as of yet so linked-in modules written in zig would have to work over the C abi despite all being written in zig

fallen bobcat
#

I think you have pretty much everything as modules?

vital summit
#

only irqchips and serial is in kernel

fallen bobcat
#

ig that makes sense

#

i was about to say you should have the core drivers in the kernel at least

vital summit
#

now that i started to write aarch64 drivers i realize that this might be too coarse for all the little devices

#

there are so many little drivers i need

fallen bobcat
#

I'd make modules for any "big" driver then

#

stuff like nvme vs ahci

#

ig it's hard to draw the line

vital summit
#

exactly

#

in linux you can make this configurable

#

but cargo is really inflexible here

fallen bobcat
#

i need a C api

heavy sandal
#

its just that any things that cross the boundary have to be extern-compatible

#

so no error unions, slices, tagged unions, or auto structs

fallen bobcat
#

makes sense

#

but then it's annoying af

heavy sandal
#

yeah

fallen bobcat
#

like realyl annoying

#

because I have to write wrappers over every kernel API

heavy sandal
#

if you compile them in as part of the same compilation you can use zig apis tho

vital summit
#

they should make c abi ffi items

#

rust has the same issue

#

well in rust it throws a warning about ffi safety

fallen bobcat
#

i should've just written in C smh nooo

vital summit
#

fr

heavy sandal
#

its because these modern langs tend to lean towards single compilation rather than linking in stuff ig

#

and static everything

#

so ABI isnt a priority

fallen bobcat
#

maybe

#

but for a language like zig, which wants to replace C

heavy sandal
#

yeah

fallen bobcat
#

that's just unacceptable lol

heavy sandal
#

if it wasnt still generally early in dev i would be more upset about it lol

fallen bobcat
#

i can't wait till i have so much aura i can just nudge the language development towards my direction ร  la microsoft engineers with intel engineers

vital summit
#

i wish c would have some macro shit to do name mangling

#

then you could do macro generics

fallen bobcat
#

wdym

heavy sandal
#

theres a nonzero chance my kernel will be among if not the first zig project to do full dynamic linking and loading where everything is written in zig actually, once ive got that to the proof of concept level ill start poking the zig people about ABI stuff

vital summit
#

as a macro

#

and that would define a struct

fallen bobcat
#

can't you do this now

vital summit
#

no

#

how

fallen bobcat
#

like anonymous structs are now equal

vital summit
#

no

fallen bobcat
#

if they're declared the same

vital summit
#

false

fallen bobcat
#

I can swear I saw something like this as either a gnu extension or as a c26 thing

vital summit
#

only named structs are allowed to be redeclared if they contain the same fields

#

in c23 at least

#

idk if gnu has an extension

fallen bobcat
#

my main reason for using zig was generics kinda but now I realize that I don't really use them meme

vital summit
#

i only use them for containers

fallen bobcat
#

I don't use any arraylist/vec

vital summit
#

i write pretty C like rust

heavy sandal
#

...yknow kinda unrelated but i wonder how badly zig/llvm would implode if i mix higher and lower half stuff in the same binary somehow

vital summit
#

how does zig cope with writing to rbx in inline asm

fallen bobcat
heavy sandal
#

i look at C macros and my eyes glaze over and my brain shuts down

fallen bobcat
#

no ABI is also annoying for thread switching

#

but u can just make the entry points use C abi

#

I think

vital summit
#

but it's annoying

fallen bobcat
#

i make the C ABI entry point call the zig function

heavy sandal
#

i shared a macro that linux uses for declaring elf notes from C with a zig dev while asking for help on something and the person is like yeah this shouldnt be too hard to do in zig and im over here and cant mentally parse the macro at all even though its simple

heavy sandal
fallen bobcat
#

yeah callign convention i meant

heavy sandal
#

yeah

vital summit
#

as much as i like rust, in a kernel it has helped me very little, but in turn caused me a ton of toolchain issues and implicit UB that's harder to spot

fallen bobcat
#

honestly I don't even understand how that works, like wont you do context switches in the middle of zig functions?

#

like i know it works but idk why

heavy sandal
#

is the secret

heavy sandal
#

and so the actual context switch is always explicit

fallen bobcat
heavy sandal
#

thats why it works

#

it took me like a week to work that out lmao

fallen bobcat
#

ah and that function is C callconv

#

so it works

#

yea ok

heavy sandal
#

it doesnt even have to be C callconv actually, you can put the swap in inline asm and have the inline asm clobber feature do the register saves for you, but thats advanced nonsense lmao

#

but yeah thats the idea

fallen bobcat
heavy sandal
#

took me a week to wrap my head around it but thats because i went straight for the advanced bullshit version with inline asm instead of a C callconv

#

but thats me lol

fallen bobcat
#

the storage trick is my favorite

#

i use it everywhere

#

it's crazy it works

heavy sandal
heavy sandal
fallen bobcat
#

you declare a type so that you can declare a variable inside it

#

like in insert() here

heavy sandal
#

oh yeah that

#

its so slick

#

it is (or can be) equivalent to a static local in C afaik

fallen bobcat
#

yeah but ig here I'd do it with a macro in C

heavy sandal
#

mhm

#

the first time i saw that storage trick was in the csprng in the zig std

fallen bobcat
#

i just bullshitted the compiler until i made something that worked

heavy sandal
#

which uses that trick to keep the csprng state as a threadlocal static local variable

polar crystal
fallen bobcat
#

it's berkeley mono

#

you're right it kinda looks like spleen a bit ig

heavy sandal
polar crystal
#

appreciate the reply

fallen bobcat
#

do you know ProFont

#

it looks great too

heavy sandal
polar crystal
#

indeed does look great

fallen bobcat
#

i saw a guy post it on twitter the other day on netbsd and thought it looked awesome

heavy sandal
#

oh thats a pretty good font yeah

fallen bobcat
#

nothing can beat the sun firmware font though

heavy sandal
#

i forget what font i use, im not on my dev machine to check and need to leave in like 5 minutes anyway

polar crystal
#

no one can beat openindianas tty font

fallen bobcat
#

isn't that just spleen

polar crystal
#

thought it was spleen at fiirst as well

heavy sandal
polar crystal
#

but it has some differences

fallen bobcat
heavy sandal
#

yeah

fallen bobcat
#

no one listened to me last time i tried improving zig ๐Ÿ˜ญ

heavy sandal
#

with what, the allocator improvements? i think that was more the team not having enough people to review shit lmao

polar crystal
polar crystal
fallen bobcat
#

at least someone agrees ๐Ÿ˜ญ

#

.

polar crystal
#

/jk

vital summit
fallen bobcat
#

Read the comment ๐Ÿ˜ญ

vital summit
#

i see

polar crystal
#

what does it do

fallen bobcat
#

cuz the comment seems self-explanatory

polar crystal
#

nah im kidding

polar crystal
#

what does the comment do

fallen bobcat
#

it's a pretty useful thing actually, I stole it from freebsd

#

i didnt know __start was a thing

polar crystal
#

finally someone who steals from the BSDs ๐Ÿ™

vital summit
fallen bobcat
vital summit
#

TIL

fallen bobcat
#

also jesus how do apple devs manage to implement freebsd stuff but somehow with 10x more lines

#

there's a freebsd file that's 600 lines, xnu implements it in 3k

fallen bobcat
#

I cooked up something very cool

heavy sandal
#

oh?

polar crystal
#

ho?

languid canyon
#

?ho

drifting blade
#

?

solid marsh
#

hohoho

fallen bobcat
#

this

crimson sand
#

linux pelt?

fallen bobcat
#

similar yea

crimson sand
#

iirc it was criticized in android world

fallen bobcat
#

yeah

#

i know

#

they have WALT

#

iirc PELT kinda fixes it by having a util_est too now

#

but anyway freebsd's target is not like android

crimson sand
#

wdym

fallen bobcat
#

freebsd runs on desktops

#

and servers

crimson sand
#

gaming?

#

idk how good pelt is for that

fallen bobcat
#

you're aware that PELT is the linux default right?

#

the android people didnt like it because power savings or something

crimson sand
#

heard different stories about linux performance in workloads of this kind

fallen bobcat
#

this isnt even full-blown PELT, it's just an additional heuristic to do load balancing

crimson sand
#

like inversions and stuff ruining perf

fallen bobcat
#

so in a case where CPU0 has 10 evil threads and CPU1 has 10 mostly idle threads it'll chose CPU1

#

lol lots of PRs are just straight up slop ๐Ÿ’€

languid canyon
fallen bobcat
#

But like might as well improve an actually useful kernel

languid canyon
#

I see

solid marsh
#

based tbh

#

i hope it doesn't drown in the sea of slop and it is noticed

fallen bobcat
#

it's weird because they have like 10 ways to send patches

#

also it's funny because you can't compile freebsd from linux, so I had to boot a VM, modify the kernel and install it, then it crashes -> boot into the old kernel and try again

#

do this like 5 times until it works, then copy your code back from ssh over to your local machine ๐Ÿ˜ญ

fallen bobcat
#

you just can't

#

it expects a freebsd host

rocky yoke
fallen bobcat
#

maybe, but atp it's easier to just reboot and check if it works meme

rocky yoke
#

But yeah very cool work

fallen bobcat
#
  • i learned how to use ddb and sysctl
#

so

rocky yoke
#

Did freebsd not have any per thread load tracking?

fallen bobcat
#

no, for load balancing they only kept track of the number of threads

rocky yoke
#

And for top etc?

fallen bobcat
#

@inner python brought this up to me and told me this was shitty so i started looking into PELT by his suggestion

fallen bobcat
rocky yoke
#

Isn't it also just an exponentially moving average, at least on linux? What's the difference

fallen bobcat
#

yeah

#

it's a set of ewmas on linux

#

this is just one ewma

rocky yoke
#

Ah

fallen bobcat
#

wait idk what you mean

#

do you mean the % load as reported?

#

I meant PELT is basically a set of ewmas

rocky yoke
#

I mean both

fallen bobcat
#

well I'm not sure what Linux does, but FreeBSD's % estimation relies on a WMA too but it decays much slower, so it can't really be used for making balancing decisions like that, I assume Linux also does something similar (slower-moving wma for % estimation)

languid canyon
#

But yeah thats pretty cool work, i dont understand any of it (probably because i know nothing about ule)

rocky yoke
#

it's not really ULE specific, right? It's a load estimation that can be used for load balancing decisions

fallen bobcat
#

yeah

#

it's basically just an ewma of the time spent runnable (running or in the runqueue) so that you can make load balancing decisions more accurately based on cpu usage vs thread count

#

it's simpler math than linux's because linux doesn't have ticks and does it based on periods of 1024us instead, so you end up with fractional periods etc which is trickier to handle

fallen bobcat
#

the next file i will autistically focus on is the scheduler

#

i have a bunch of ideas to improve it

fallen bobcat
#

holy shit i had an epiphany

#

I wasn't sure how to embed the slab metadata in the struct page (also hadn't really thought about it) because it's basically like so:

struct slab {
  struct list_entry link;
  uintptr_t base;
  size_t capacity;
  uint64_t bitmap[];
};

This sounded annoying cuz the bitmap is sized differently directly in the struct.
I figured out you can basically shorten it to:

struct slab {
    struct list_entry link;
    uint8_t kind : 1;
    union {
        pfn_t head_pfn; // points to slab with bitmap in it
        uintptr_t bitmap; // Either an inline bitmap if capacity < 64 or a pointer to a bitmap
    };
};

Capacity is redundant if we remove slab coloring (which wasnt really that useful anyway), we can store it in the zone itself.

The cool trick is that the bitmap can be allocated via a bitmap zone, which itself only embeds its own slab metadata inline (thereby removing any possible circular dependency).
I looked at XNU and they seemed to put everything in the struct page but used a crazy buddy allocator to allocate the bitmaps or something, I think this is much cleanly avoided using a zone for the bitmaps themselves and make them use inline data (although there may be another reason why they do this)

lol i might send another patch to freebsd because they don't do this

#

dunno why i thought about this, I was doing scheduler stuff

rocky yoke
#

why do you want to include the slab meta data in the struct page?

fallen bobcat
heavy sandal
#

yeah

#

i do it too, its actually quite nice to have

#

though my slabs use a freelist instead of a bitmap so i dont need to worry about if the bitmap can be inline or not

fallen bobcat
#

There are reasons for doing a bitmap

heavy sandal
#

yeah i know

#

i didnt say my freelist version was good lol

#

but storing in the struct page is still good either way

fallen bobcat
#

i wanted to do microsecond accurate PELT in my kernel instead of ticks like in freebsd

#

the math is mathing

fallen bobcat
#

i may have done something wrong, one CPU has like 300k load the other has 0 wtf

heavy sandal
#

yeah that sounds a bit off

fallen bobcat
#

i mean the numbers should be huge

#

but like idk why theres such a high imbalance

heavy sandal
#

yeah the concerning one isnt the 300k its the 0

fallen bobcat
#

ok great it seems to work

fallen bobcat
#

perhaps my patch will get reviewed soon ๐Ÿ˜”

solid marsh
#

based based based

fallen bobcat
#

anyway I added a bunch of stuff to the scheduler which is pretty nice:

  • PELT with 1024us period accuracy, which is used as:
  1. a primary metric for the long term load balancer
  2. a tiebreaker for work-stealing
  3. a tiebreaker for pick_cpu() when a thread wakes back up
    The logic behind it being only a tiebreaker in pick_cpu() is that you wanna run ASAP even if the CPU's load avg might be high, as enqueuing on a CPU with potentially many light threads would make you wait for a while
  • Each thread keeps a WMA (75% old, 25% new) of its load when it blocks so that the estimated CPU's load is also taken into account when selecting CPUs, so that a case like a few worker threads waking up periodically it doesnt show as a load=0 on that CPU
#

wow discord is stupid, you can't nest lists

fallen bobcat
#

ah also I'll need to add staleness on the affinity, if the thread hasnt ran for more than 1 second then the affinity is lost

novel sparrow
novel sparrow
#

i mean its just a greek letter no?

fallen bobcat
#

nah it's way too ugly

fallen bobcat
fallen bobcat
#

@heavy sandal do you think you could help me with something rq

heavy sandal
#

maybe, whats the thing?

fallen bobcat
#

for fuck's sake why is zig removing my symbols

#

when in release build, it strips away the storage:

comptime {
    _ = r.percpu_init_set.insert(&pcpu_init);
}
#

this is how I call it

#

like wtf this is just insanely annoying

#

and I cant use @export sanely because I need a unique name

#

this is the kinda stuff that is just straight up fucking annoying and stupid

heavy sandal
#

if possible id say use an empty asm block with an input or output set to the thing, i think i ran into something like this with limine protocols

fallen bobcat
#

I did try std.mem.doNotOptimizeAway

#

on storage

#

and it didnt work

heavy sandal
#

hm

drifting blade
#

Make an issue

fallen bobcat
#

i tried asking on zulip and no one answered yet

heavy sandal
#

yeah i dont have any other ideas other than to start digging with readelf/objdump

fallen bobcat
#

the zig discord is full of idiots

#

and issues will get closed

#

๐Ÿ‘

drifting blade
heavy sandal
#

yeah the discord is not great

#

idk that an issue would be closed tho

#

or why

fallen bobcat
#

i think a reasonable fix is that if linksection is explicitly set then dont optimize it away

drifting blade
#

PR time?

heavy sandal
#

def sounds more like issue time to me

#

personally

fallen bobcat
#

yeah

#

im on 0.16 tho

#

ugh

#

see this is the bullshit C doesn't have

drifting blade
#

Does Zag not compile with master Zigc?

fallen bobcat
#

it used to but I depend on an external slop project that only works on 0.16

#

sadly

drifting blade
#

Which one?

fallen bobcat
#

tui library

#

for my config tool

drifting blade
#

Ah

fallen bobcat
#

it's all because of khitiara that wanted me to remove ncurses

heavy sandal
#

because windows doesnt have ncurses

drifting blade
#

So just make it not run on binbows

fallen bobcat
#

might go back to ncurses honestly idk

#

the lazy stuff in general is annoying

#

wish there was a way to disable it

heavy sandal
#

on a per variable basis yeah

fallen bobcat
heavy sandal
#

yeah

#

what id do here tbh is make a minimal repro and open an issue

fallen bobcat
#

but I've never managed to actually speak to a zig guy

#

mhm i will start a thread on zulip perhaps, is it compiler or ecosystem

heavy sandal
#

prooobably compiler tbh

drifting blade
#

Why not make an issue directly, do they really not get reviewed?

heavy sandal
#

they do its just slow

fallen bobcat
drifting blade
#

Ah k

heavy sandal
#

yeah thats where the devs talk on things that move a bit faster than issues would be good for

heavy sandal
fallen bobcat
#

andrew is in oregon

drifting blade
#

Meanwhile C3: the dev is in the languages discord server available 24/7

fallen bobcat
#

ig a lot are europeans

#

true

heavy sandal
#

mhm

fallen bobcat
#

ok zulip post made

#

time to ping every maintainer

#

no @heavy sandal ping every maintainer that way i can't be held accountable trl meme

heavy sandal
#

lmao

fallen bobcat
#

if zig would add something like __COUNTER__ I could generate unique names

heavy sandal
#

btw can you not just use the export keyword on the storage variable? idk if thatd work for the same reason theres been limine protocol issues before but it might

fallen bobcat
#

if this project wasnt like 18k lines I would probably rewrite in C, it's just annoying that 1. you cant really rely on the compiler that much 2. shit breaks so dependencies are annoying 3. types are cumbersome and verbose to use the @intFromN thing

fallen bobcat
heavy sandal
#

right

fallen bobcat
#

like I wanna export functions thru that

fallen bobcat
vital summit
#

18k is not that much tbh

fallen bobcat
#

And 18k is quite a lot for what it does lol

vital summit
#

ehj

#

i would probably spend a day on it

fallen bobcat
#

Are you trolling

vital summit
#

i'm currently rewriting evyrthing in C just to see how different it is

#

i'm like halfway done

#

0 clanker

fallen bobcat
#

you can't write 18k lines in a day lol

#

even 1:1

languid canyon
#

especially from something like zig to C

vital summit
#

the point is use 0 clanker anymore

fallen bobcat
#

I'd probably do it using clanker first then clean it up

vital summit
#

i want to rid myself of that

heavy sandal
fallen bobcat
#

fwiw my OS probably has 0 lines of useful AI code

#

Only tests

#

Idk I like zig but sometimes there's just so much bullshit for no reason

vital summit
#

same with rust

fallen bobcat
#

Besides I'd have to find a new name so not doing that trl

vital summit
#

rust has many QoL things but the toolchain is sooo dogshit

heavy sandal
vital summit
#

also basically no ENOMEM handling if you use ::alloc

fallen bobcat
#

If any

#

Bullshit = unneeded verbosity, fighting with the compiler/toolchain, etc

vital summit
#

THIS

#

they make it so much more annoying than C compilers

#

i don't get it

fallen bobcat
#

C is so good it's insane

#

Like when you think about jt

#

It's like 55 years old

heavy sandal
#

its old enough that people have thrown out the bullshit is i think what c has going tbh

fallen bobcat
#

I don't think there really has been much bullshit

#

Ever

#

Probably it's been cleaned up a bit

vital summit
#

especially with C23 there's been many QoL changes

#

like typeof(x) for example

#

or constexpr + auto

fallen bobcat
#

but I probably won't rewrite anyway, there's like 1% chance I will. I have to use zig for aura and don't wanna find a new name

heavy sandal
fallen bobcat
vital summit
#

constexpr has not

#

bools, nullptr

heavy sandal
#

also C has a ton of random bullshit if you need msvc compat, msvc has so much hot trash and broken nonsense

vital summit
#

i don't support broken implementations

fallen bobcat
#

Based

heavy sandal
#

good

fallen bobcat
#

I think it's fair to assume a GNU C compiler

heavy sandal
#

all the bullshit is contained over in msvc land where we can ignore it because its bad

vital summit
#

i feel like in C it's truly unopinionated, you can do whatever the fuck you want

fallen bobcat
#

Also what I don't really like about not doing C is general compat, modules get annoying to do and you pretty much have to write it all in the same language (like zig)

vital summit
#

wow it's almost like we have the exact same issues

#

even though we're using different langs

fallen bobcat
#

My dream language would probably be C but with a bit more modern features like stronger types etc without trying to completely reinvent it like a lot of C killer languages

vital summit
#

this is what i wished C++ to be

#

but it has a bunch of cancer attached to it

fallen bobcat
#

C++ just has too much complexity imo

heavy sandal
#

yeah no

#

theres a reason i havent touched c++ in years and i want to keep it that way

fallen bobcat
#

I love using C++ and abusing it but it gets tricky to follow

solid marsh
#

c++ is ๐Ÿ’€ if you try to use everything

vital summit
#

yeah

#

you can do the wildest shit in c++

heavy sandal
#

yeah

vital summit
#

see mlibc's sysdep interface

fallen bobcat
#

There's an argument to be made for stackless coroutines tho

#

They're good

heavy sandal
fallen bobcat
#

There are probably languages like I'd like, like C3 or odin or whatever I haven't looked at but the ecosystem is non-existent

#

Everything works with C

heavy sandal
#

yeah

solid marsh
#

c is just that based

#

sorry

fallen bobcat
#

It is

heavy sandal
#

the lack of stable linkable abi is the only real thing i miss using zig tbh

vital summit
#

in like every lang

#

idk what's so hard lol

heavy sandal
#

ikr

solid marsh
#

imagine not having a standard

#

(every compiler makes whatever they want anyways)

fallen bobcat
#

It's our problem, C was made to write OSes, newer languages weren't

heavy sandal
#

i do get why a brand new lang might not commit to a stable abi yet, but it is still annoying not to have

fallen bobcat
#

Maybe we need @long pendant 's new language to save us

fallen bobcat
heavy sandal
#

mhm

long pendant
heavy sandal
#

mood

long pendant
#

i think languages for writing OSes in are critically underexplored

solid marsh
#

problem is no one writes new oses lol

long pendant
#

there are no languages designed for that anymore, only ones from the 60s/70s/80s

vital summit
solid marsh
#

unless you're larp (which we are)

fallen bobcat
heavy sandal
vital summit
#

rust is

#

and that's even worse

heavy sandal
#

yeah

vital summit
#

so GCC-RS is literally just copying rustc

fallen bobcat
#

reminder that zig is like 15 years old lol

heavy sandal
#

i really dislike rust so tbh i didnt know that it was 1.x already tbh (as i crumble into dust at how old rust is now)

long pendant
fallen bobcat
#

Have you ever tried zig?

solid marsh
#

what special does jackal have

fallen bobcat
#

Curious

fallen bobcat
#

The cool thing are the function templates thing tho

long pendant
languid canyon
long pendant
#

i followed it a little when it had an IRC channel (2017?) and andrew r kelly was in there

fallen bobcat
long pendant
#

i remember he was a big fan of Cosmic Gate

fallen bobcat
fallen bobcat
#

And like only Andrew hangs out on there

long pendant
#

latterly it was more interesting to look at again because i found xerox mesa (which is in principle a very remote conceptual ancestor of jackal via pillar via modula-3) surprisingly had its exact same treatment of comptime

heavy sandal
#

wouldnt surprise me tbh

#

comptime is so good

#

so much better than macro soup

fallen bobcat
#

Yeah but it's not that useful tbh

fallen bobcat
#

Like I had a table to generate using math and I still ended up just precomputing it

#

using python

#

because why slow down compile times even more for no reason

long pendant
#

Interval: TYPE = RECORD [page: PageNumber, count: PageCount];
this mesa code is showing exactly the same pattern as zig type declarations

#

Interval: TYPE = is just a constant declaration (TYPE is just the type of types)

fallen bobcat
#

@heavy sandal we just need to form an osdev cabal with direct contact to Andrew so we can make zig good

heavy sandal
#

lol

#

not wrong tho tbh

fallen bobcat
#

If zag turns out to be pretty good there's a good chance I'll have influence

long pendant
#

whether or not kelly copied mesa i have no idea, but it's interesting they did the exact same thing

heavy sandal
#

yeah

#

to both of you

long pendant
#

this of course makes Zag the modern-day Cedar OS

fallen bobcat
#

I'll remember to ask him eventually

#

Because it is pretty interesting

heavy sandal
#

@fallen bobcat btw for your issue, have you tried doing verbose llvm ir and checking if the thing is in the IR or not?

#

nvm, someone in zulip checked that, it seems llvm/lld is killing it

#

@fallen bobcat btw have you tried somehow doing KEEP in the linkerscript for your set sections? since latest testing from others in zulip says its llvm/lld not zig that is removing it

fallen bobcat
heavy sandal
#

yeah would def be ideal not to worry about it

heavy sandal
fallen bobcat
#

yeah ok def is

stray kelp
#

lol

drifting blade
#

What makes you think that

fallen bobcat
inner python
fallen bobcat
#

@heavy sandal LOL

#

this is what I had to do

#

what horror

heavy sandal
#

lol

fallen bobcat
#

i looked a bit at tigerbeetle's code and I want to try refactoring everything a bit so it's cleaner and higher quality (more similar to theirs)

heavy sandal
#

yeah their stuff is very good quality from what ive seen

fallen bobcat
#

one day freebsd PR will get merged...

#

meanwhile im currently doing prekernel stuff a bit every day

fallen bobcat
#

maybe it's my code, but why does zig use so much stack ๐Ÿ˜ญ 16kib is not enough to get through init

#

ok i pushed the basic prekernel stuff, only maps stuff for the kernel and loads it atm, no pfndb mapping and stuff yet

heavy sandal
fallen bobcat
#

i think it's because this is a few calls deep and also logging uses a bunch of stack apparently

heavy sandal
#

hm

fallen bobcat
#

or just formatting in general i think

heavy sandal
#

depends ig, for the most part logging should just get inlined to your logfn

#

oh yeah no formatting is kinda like that sometimes

#

i wouldnt expect it to be that bad tho

#

formatting in zig is usually more of a code size issue than a stack one ime

#

ive wanted for a while to see if theres any good way to do stack size static analysis

languid canyon
#

another C W

#

i get the exact stack usage i expect with no hidden bs chad

fallen bobcat
#

I think this is just a standard library thing idk

#

maybe not

heavy sandal
#

idk

#

zig isn't doing any hidden stack allocs, it's all about just what functions are used

#

and how much stack those use

vital summit
fallen bobcat
#

ah i figured out why it was using so much stack

heavy sandal
#

oh?

fallen bobcat
#

i did a oopsie and had const features = amd64.cpu_features; in the function

#

so allocating a new one on the stack

heavy sandal
#

oh yeah no thatll do it

fallen bobcat
#

and that struct is quite big

heavy sandal
#

yeah

vital summit
#

i don't understand

#

can you translate for a C brain

fallen bobcat
#

big struct on stack go boom

heavy sandal
fallen bobcat
#

yea

heavy sandal
#

aka forgot the &

vital summit
#

hm

#

but that struct doesn't seem too big?

fallen bobcat
#

ig there's other stuff using the stack

heavy sandal
#

19 bools, plus 48 chars, plus however big the CpuVendor type is

fallen bobcat
#

cpuvendor is an enum

vital summit
#

that's nothing tho

fallen bobcat
#

true idk

#

but it worked

#

so ig the stack space is limited

vital summit
#

rust uses multiple pages for stack doing nothing xd

heavy sandal
#

and then round up for alignment depending on whats after it on the stack

fallen bobcat
#

I've decided that maybe an initgraph thing wouldnt be that useful idk

#

considering how I do initialization is kinda well defined idk

#

id have to think about it

heavy sandal
#

yeah i had the same conclusion

#

my init is sufficiently well defined i dont need to toposort it

fallen bobcat
#

well, I also ended up flattening the whole call stack a bit

#

now the entry point is in ex and it calls ke.init

heavy sandal
#

mhm

#

nice

fallen bobcat
#

so the stack is more shallow by like 2-3 stack frames

heavy sandal
#

that might help a bit yeah

fallen bobcat
#

and no layering violation now meme

#

is it better to have the whole function exported or should I have a thin callconv C function that just calls ex.init

#

I dont think it matters

heavy sandal
#

yeah doesnt really matter

vital summit
fallen bobcat
#

wdym

vital summit
#

i have exactly the same function declaration for my main

fallen bobcat
#

marvin when are you joining the zaggers

heavy sandal
fallen bobcat
#

idk i want this to be portable

#

the loader assumes sysv

heavy sandal
#

yeah thats what i do (though its like .x86_64_sysv or something like that) - i have the arch code specify that arch's calling convention

vital summit
#

my kernel also assumes sysv everywhere

heavy sandal
#

so i use the aarch64 standard one for aarch64 and sysv for x86 everywhere

#

and that way im never worrying about if some weird target setup i try later accidentally swaps it to a different callconv and breaks things

fallen bobcat
heavy sandal
#

(note that this doesnt work for x86_32 if you mix callconvs and use llvm, as llvm for some reason refuses to allow multiple different calling conventions in a 32-bit x86 binary)

fallen bobcat
vital summit
#

yea but I'm retarded

fallen bobcat
#

idk what you're good at but I don't like drivers and architecture/hardware code in general

#

And that's not really tricky

vital summit
#

i will write drivers for you if you can unfuck my rust scheduler trl

fallen bobcat
#

What's the problem with it

vital summit
#

half of it is vibed because i didn't know how to debug it

#

and i REALLY don't like it

#

i tried to understand it, but it kept breaking under SMP so i asked claude to fix it

#

it works, but i feel like it could be improved a lot

#

also, i like your design

fallen bobcat
#

what design

vital summit
#

the one you sent me

fallen bobcat
#

ah

#

yea

vital summit
#

the ule one

fallen bobcat
#

It's basically ule with ntisms stolen from mintia and a bunch of my own stuff

fallen bobcat
vital summit
#

good point

#

i'm tired

#

i will probably lose a lot of github stars if i rewrite KEKW

fallen bobcat
#

That's why you need to join the zig hype so you get a bazillion stars

vital summit
#

idk how to feel about zig

#

it's not quite C, but also not quite rust

fallen bobcat
#

I'm not saying you rewrite in zig Im saying you join a zig project

#

(cough cough)

vital summit
#

i mean i can do some stuff for it

#

(but you made it sound like i should abandon zinnia for it)

fallen bobcat
#

You do what you want

vital summit
#

i'm a loser chud

fallen bobcat
#

i did more prekernel stuff, now it maps the pfndb and detects cpu features for the kernel

heavy sandal
#

nice

fallen bobcat
#

I kinda want to do AP startup as well but I'm scared of duplicating ACPI code...

heavy sandal
#

if you want cpu hotplug then youll need ap startup in the main kernel anyway

solid marsh
#

eh

#

what will you duplicate

#

getting acpi tables and iterating over the madt

fallen bobcat
#

yeah

#

that

solid marsh
#

doesnt sound too bad to me lol

fallen bobcat
#

I mean I'll need it eventually anyway if I want NUMA

heavy sandal
#

yeah

fallen bobcat
#

bleh ok fine

heavy sandal
#

youll need at least the acpi table getting for numa

languid canyon
#

Cant you just make an acpi.zig file and share it

fallen bobcat
#

yes but my acpi.zig file rn also has init and stuff

#

like

#

sec

heavy sandal
#

because zig is lazy

fallen bobcat
#

I can reuse the struct definitions I guess

#

but the functions no

heavy sandal
#

could split the functions maybe

#

but yeah the structs is already a big help to reuse

fallen bobcat
#

which is not a loader thing

heavy sandal
#

mm tru

#

could generic parameterize it

languid canyon
#

does zig support --gc-sections

heavy sandal
#

if you never refer to something it doesnt even get compiled to need to be gc'd