#Zag
1 messages · Page 6 of 1
the problem is despite having actually read the papers on this i dont really fully understand what a magazine is here lmao
(i wasnt just talking about wanting to read through your new opts, i meant the whole thing lol)
yeah yeah
What's that?
like rcu but cooler
Ah
@heavy sandal thoughts?
imo this is sad because this is clearly an improvement
But it fractures the zig community
every single commit is co-authored by claude and theyre now in hell and stuck way behind and wont be able to rebase new zig in anything resembling a sane way
ok but they have a better compiler
also like. what in gods name are they doing that theyre running into compile time issues
no they have a sidegrade - theyre behind on some huge improvements to type resolution in the main compiler
in what phase of compilation
if it says llvm emit object theres nothing zig can do about that
I'm not sure, linking in particular is the slowest I think
thats llvm being slow as balls
They can parallelize it
Like bun did
bun isnt parallelizing emit object
You can't claim llvm is slow when clang compiles stuff much quicker
they parallelized sema
that could be the same? idk
theres def room for improvement but most zig users nowadays dont even need the llvm backend
and most people arent as insane as bun to be hitting time issues in sema of all places
mhm
I might try to contribute to the compiler to make it faster
mhm
compiler perf is one of the big things people are working on rn so if you manage it then good
its just that most of the focus has been on the self-hosted stuff
there may actually be a reasoning here btw, since zig links to llvm and uses their emit api and afaik clang does its own more tightly integrated thing because its part of llvm
and the api to emit stuff directly is slow as balls iirc
that's quite worrying
yeah
and it's not as though parallelising things is a trivial matter
thats why i dont expect most of the community to want to use that fork if thats the code quality
if they didn't review claude's PRs well enough to at least separate restyling from new features, then you have to wonder what other problems might be lurking
yeah exactly
The changing of magic numbers is also an uhhhh
yeah
as i have found LLMs are fantastic at producing something that looks like a solution to a problem, but to the trained eye, it becomes immediately clear that outside of the narrow conditions the LLM considered, the solution is usually at least inelegant or restrictive, and often fundamentally broken
Yeah thats why you dont ask it to implement features
Only specific tiny scope functions etc
at least for the time being, the only guarantee of quality is a thorough understanding of the architecture of your own program, then you can check whether it's accounted for everything, or not
and i would generally be sceptical of commits coming in that are "coauthored by" an LLM
I also like to just ask it to review my code and occasionally it points out a bug or two
I'm thinking LLMs are good to show PoCs
Like this
Bun could've just implemented a PoC on the compiler that showed it could be greatly optimized
and then edit the code to make it higher quality
or use that as guides to write it by hand and better integrated yeah
imo if theres any valid case for llms in programming its r&d stuff and POCs. the thing you use to say hey this is proof that this project is worth working on and then you dive into it for real
yeah I agree
that is true but it doesn't mean that LLMs are not a significant advantage in drafting these changes
i agree, i tried copilot a few times and some of its proposals were basically decent, and it even considered some important edge cases, though the final code it proposed had its own problems
as i said: if theres any use its for proofs of concept or initial idea drafting and then you do the real thing mostly by hand to get it right
one of the interesting things is that they seem to try to guard against conditions which are virtually impossible to trigger (i.e. they might happen if you plugged a serial console in and opened a hex editor on the live kernel memory, and gave the keyboard to a monkey) which produces an effect of "wow, it's really considering the edge cases" but while ignoring logical faults
yeah, you definitely can't trust it to cover all cases without review
it will consider obscure ones without exhausting obvious ones
it's at least a more sublime way of satisfying the reward function than what they used to do, which was to delete tests that it couldn't get to pass
I think the next thing I'll add will be turnstiles
turnstiles?
the allocator would need more kernel infrastructure to get better
it's a bit like webkit parking_lot if you know that
i dont lmao
is it just a thing that lets you release one waiter at a time?
so what functions does it have?
where the address of the lock is hashed and indexed into a global array of turnstiles
ok so thats where it is but what does it do
turnstile_lookup, turnstile_block, turnstile_wake
or something
Turnstiles and priority inheritance -- SunWorld, August 1999
this is a good overview
the locking in particular is a bit tricky to get right
oh its wait handles ok
I had started to implement them in my C code but was skill issued and didnt have the patience to go through it
ive got something similar called a WaitHandle except i made them fields of the sync object
I'm not sure thats the same thing
also this allows for pointer-sized mutexes which is cool
so is this basically just an encapsulation of the wait queue for a sync object?
im pretty sure its just me being stupid but im having trouble understanding still from that article
there's a description in solaris internals
if u want
so its an encapsulation of wait queues then, which is what my WaitHandle is (my name is kinda shit i should maybe change it sometime)
I'm not sure what you mean so I can't really say but I think, yes, broadly
my WaitHandle is a wrapper around a wait queue, and provides functions to enqueue a thread and to signal one or signal all waiters
so yeah same idea
also this
this is from the freebsd book
I only have that book on my mac
i have the solaris one on my desktop
mhm
the temptation to template the allocator
specifically I am wondering if having separate alloc/free magazines is a perf hit if separation is not needed, so I am thinking of templating Zone so it takes a separate_magazines bool
eh kinda dont wanna mess with that rn, I'll refactor it when I do the memory stuff
interesting how much derives from solaris
like this is roughly pretty similar to freebsd
mhm
aaaaa emacs is broken
no syntax highlighting wtf
nvm I updated and they fixed it
weird
lol @languid canyon the 1 character typo fixer will strike again
no two characters even
a new record
wait ctx?
wha
whats the context
it's in a freebsd file
but like I kinda wanna PR to fix that typo
professional typo fixer
i dont even see the typo lmao
assicated
ah ok yeah i see it now
freebsd is cool because they accept github PRs now
CV:
- Respected contributor for Linux and FreeBSD, having fixed many typos across all code bases
bruh i am having a weird bug I didnt notice until now
I am testing blocking on events and there is some weird corruption happening
oh hey welcome to my hell of 2-3 weeks ago
it's weird it never happened before in the fireworks test
I'm thinking maybe it has to do with synchronization objects vs notification (like timers)
wow that was tricky
you figure it out?
well I should have thought about it when writing th ecode
the worst kind of bug
basically wait should look like this
before I fixed it, I called block() inside the cmpxchg success branch and block() is the one holding the thread lock
oh yeah
now the problem is that this can race since it can be committed without having actually blocked first
lol fr?
that you sent me that talk about the nt scheduler wait stuff to help me try and fix
in reimplementing to have wait aborts i found that bug
which was the real issue
thats good
Ithink
I may not have fixed it idk
that was def a bug
well I havent fixed the weird corruption
:(
F
idk why it just straight up crashes into unitinialized memory or something
omg I can't write
i still have an issue like that but it only appeared when i did callback handling for io instead of just always using events and i gave up and killed the callback part and always use events now so it doenst happen
bruh
ugh this is so tricky
what's annoying is that I thought I had tested the scheduler extensively with the fireworks
turns out it didnt handle that edge case
No idea yet
I thought it was a turnstile bug but it turns out it's a bug somewhere in my waiting code or something which causes corruption (probably stack corruption?) which leads to a random jump
oh?
ah
I'm sure the bug is some locking bug on the thread i just dont know where yet
what was this one?
forgot to pin the idle threads 
actually that may have been it
CPU 0's idle thread gets stolen by CPU 1, runs on CPU 1, CPU 0 goes idle, it runs its idle thread -> both CPUs are running the same thread
oh lol yeah thats a problem
ok again I think that was a bug but maybe not THE bug, but now I have another crash I think I can manage
some thread gets popped tiwce
aaaa I think I fixed it
this is wrong
the check should be before assigning td
no nvm that was a bug I think but still not the one 😭
F
good luck
well now it doesn't crash anymore but idk why 
ok well remember that
I forgot to do it on amd64 too 🤦♂️
now I think it all works
turnstiles seem to work too 
🎉
well with no PI though 
because I am skill issued I wanna clean up how priorities work first
not doing much work on this because I have had the coolest idea ever
and trying to do that instead
what is it
it's stupid but i managed to fit llama2 inference in like 1500 bytes
I wanted to do that but It's impossible
Just the attention loop and stuff is too big
work should resume soon™
first step will be to rework priorities so they're easier to manage
kinda wanna engagementbait r/osdev with this first though 
It wouldn’t even be bait there
They would just eat it the fuck up
yeah i posted it for the meme
I wanted to try HN too but apparently its already been posted by someone else and didnt really gain attention (probably wrong time of post or something)
and you cant repost links on HN
also im posting it literally to boost my github even though I hate doing so for that reason, I am completely honest about that, I do think it's a cool meme though
also some dude made a PR adding tests and stuff, but it's like bigger than the code itself so idk if I should merge it 😭
how so?
right now I keep a separate interactive flag in threads to mark their interactivity
I'm thinking I will put them in their own priority range or something instead
which means I'll just need to copy a number instead of copying a bool + a number
I suspect most of it is AI generated
kinda wanna setup a website for this even though it's very early stage...
procrastination 101
mostly cuz I found a cool logo
@vital summit
wats this
what is it
lol
they look neat
something like this looks cool
they also have this one but I dont think it looks very good
i think the conventional commit thing is a bit stupid
tempted to switch to just subsystem: <changes> but sunk cost fallacy 
whats your current style?
A specification for adding human and machine readable meaning to commit messages
this
but I have decided it's stupid
so now it'll be the linux/go style
I think it does help with making commits atomic though like no fixes mixed with features
but I can do that on my own
hm thats interesting i suppose
to me it feels like you cant really put commits in a bunch of baskets like that
who knows if it's a "chore" or a "refactor" or something
idk
feels weird
why do commits when you can GOOGLE_APPLICATION_CREDENTIALS=/home/pitust/.config/restic-keys.json restic backup ~/src ~/misc/prototype ~/misc/design --exclude-if-present .nobackup --exclude-caches --exclude-file ~/src/.resticignore -H nixos -r gs:[bucket name]:/ 
lmao
@heavy sandal I have a local version of zonfig working with zigzag 👀
that means it'll work with only zig as the dependency
niice
thoughts?
it's less colorful than the old UI but I cbf to port over all the colors
lgtm
llvm is still the default for some optimize modes iirc
i dont remember the details tho
well, I pushed it
the code quality sucks imo
but it works
so
well it could certainly be worse
but it could probably be better
can you try it on windows real quick @heavy sandal
i dont have the computer on atm but can test it tomorrow
lol
looks good
are you trying to get rid of all deps?
tbh its kinda not that hard at all if you just rely on KVM
the dep for the tui here probably matters more here because ncurses doesnt exist for windows
all u need is some device mmio emulation on top of the framework
(or whpx which has very similar api)
i will say zig+qemu is the same level of manual external deps as i have
imo not really worth going much further unless you find the idea of making your own emulator interesting enough to make a project of it
yeah
im not even sure what to call it if you just rely on kvm
its not an emulator, not a hypervisor either
hypervisor frontend or manager is what id call it
the main reasons to eliminate the other systool deps and stuff apart from qemu is xplat building. like without dimmer i couldnt build my disk image on windows at all because the usual mechanisms just dont exist there in the same way
but youll obviously have the programming language you use as an external manual dep and qemu is rather complex and has downloads available for all major platforms already that you can just easily grab - and qemu isnt mandatory for osdev anyway theres other vm options etc depending on context and taste
no im trolling
though a toy x86 emulator would be fun
isnt it a type 1 hypervisor or smth
no nvm
that would be line Xen or something
type 2 would be KVM
qemu is just an app invoking the framework apis
extend it to x86_64 
wait what are type 1/2 etc? never heard of that terminology before
well the CPU part isnt even that hard
type 1 is bootable hypervisor
type 1 means baremetal hypervisor
Xen for example
vmware has bootable stuff too
Xen (pronounced ) is a free and open-source type-1 hypervisor, providing services that allow multiple computer operating systems to execute on the same computer hardware concurrently. It was
originally developed by the University of Cambridge Computer Laboratory and is now being developed by the Linux Foundation with support from Intel, Citrix, ...
i forget all the names
ah so like whpx (no im not kidding, windows runs under whpx now)
yeah
the secure/nonsecure kernel memes is fun, i kinda want to try that someday
technically i think itd be the other way around actually but i usually lump the two together
omg the bun rewrite thing
everyone has been talking about it for like 2 weeks straight it feels like
oh god what now
idk
posts still being made
im just ignoring all this shit now lol
yeah me too
my personal opinion of bun did lower quite a bit
I thought it was good
its not even about rust or zig
but it's just like straight up 100% vibecoded slop now
ive had the amount of irl shit ive had to do like double 10 days ago and thats after it was already higher than normal a few weeks before that i dont have time to care about js frameworks
idk how you can feel good about that
it's a JS runtime 👆 🤓
I should write bun but not slop
call it nub
jk I dont have enough interest in the JS ecosystem to do that
last time i cared about javascript, jquery was new and im happy to keep it that way
JS runtime is taking a JS engine like V8 or JSC (in the case of bun) and adding a bunch of stuff to interact with the OS
essentially
yeah i know i just dont actually care about javascript so i cant be assed to use the right terms
bun also does package management and stuff
ive had to write javascript recently, i just cant be assed to care about it anymore lmao
but anyway idrc about people saying "no one will use zig now... its dead forever"
so a popular project that was already kinda slop, completely slop rewrote in rust because it's easier to vibecode... sounds like a compelling argument for zig not against it lol
yeah really
https://asciinema.org/a/0oejNmMFClqS2XRN Alright, here is an asciinema link that showcases a bit more TUI functionality
i made a ziggit post
because that might actually be something kinda useful
compared to most of my projects lol
nice
recommendation, start with an assembler so you can get a hang of instruction encoding
it's the end of the term and I have a motivation burst
while getting fucked by exams
I have already written an 8086 emulator
ok so then youre ahead of the curve there
I wanted to write an IBM PC emulator at some point
but I couldnt get the devices to work like I wanted (wanted to get the ibm bios running)
so I gave up
but the 8086 worked fine
i was briefly working on an emulator for a logic-gate-level breadboard cpu, with ui to be int he style of the edsac emulator, but got stuck on the ui of it and then found out that you can just write an os for the actual computers i have already and dropped that project
emulators are kinda fun to write tbh
I will get the vibecoding job offers thing and zag commits +1000% trust
Fun when it works
Timing is a bitch
yeah true
I've written a fairly accurate gameboy emulator
And that's pretty much it
I did do a bunch of cpu emulators but the devices around them are usually annoying
Because of timing and stuff
honestly tho ive been thinking about it and I'm reluctant to start a new zig project
cuz the language is so unstable, I'll have to maintain more code
one project like zag is fine
but if you add like another 10kloc repo
ehhh
isnt your kernel zig lol
yeah
but like
I mean if i start making an emulator
then I have the config tool too
then i make another repo for something
i have to maintain like 5 different repos to new zig versions
vs just one or two
ah
especially userspace programs
because the stdlib is much more prone to change
also I think I have a cool name for the system as a whole
maze
and the kernel would be zag
since a maze is full of zig zags
nice
lol
It can be unsettling when you notice that a technical assumption you've been making for 40 years has quietly expired. This happened to me a few minutes ago.
I maintain a game called "greed". It's an old-style game from the days of character-cell terminals. Not quite a classic
ESR too
wtf
i dislike the type 1/2 hypervisor nomenclature for two reasons
first, because the terms are just numbers with no description, which for some reason was irresistable to academics in the 20th century (i dislike the statistical term type I and II error for the sam reason)
second, because i don't think it's especially meaningful, if kvm is a type II hypervisor then probably vmware esx should be too, since esx is also a kernel of its own providing non-hypervisor services. the difference, as far as i know, is just that esx is more explicitly designed for hypervisor use. but this is such a continuous spectrum that i think trying to collapse it into a binary of I or II is silly
I should really finish the priority inheritance stuff
I havent had much motivation but hopefully once I get through that I can work on funnier stuff
claude add priority inheritance make no mistake
unironically if I were paying for claude or another model, i'd probably use it to analyze the codebase
I think that is a good use of AI without polluting the code
proceeds to nuke scheduler priorities all together 
The scheme I learnt about on this server is called ‘turnstiles’ (whereas I could only have come up with single-level inheritance myself); it is, I suppose, the most elegant and effective scheme one could possibly devise for multi-level priority inheritance. It will probably make your life easier.
The book on the Solaris kernel describes this scheme in detail.
Gee thanks I had no idea they existed 🫠
(I have implemented turnstiles, albeit without priority inheritance)
do you have a distinct thread lock?
do you mean instead of doing the solaris thing of having a pointer to a lock?
yeah
@heavy sandal do you think andrewrk will kill me if i rewrite SmpAllocator and make it like 2k lines
ok yes I will work on this
the current SmpAllocator could be greatly improved
i have written a shitty mimalloc style thing and it's already faster
super basic but the fast path is really fast
I think the current allocator's philosophy was "good bang for the buck"
since it's so simple it's fast
yeah
thats very much what it was
a simple and maintainable but still fast enough option
but like this is for a very bad benchmark and im improving it atm
also did you try zonfig on windows
not yet i forgor 😭
riiiip
especially the // emdash emdash emdash comments
I did make a PR tho
I truly am a saint
Wait how does it know
They have an LLM that checks for llm usage in dependencies
(a moderator added it)
@rocky yoke can you tldr sharded_slab? I know it's basically mimalloc but I'm not sure what the chunk state stuff is
do you have a specific question?
a few
i haven't checked the mimalloc internals in detail. i mostly took the main idea and implemented the rest around it
so it's likely that the state tracking is a bit different
why didnt you use the segment stuff from mimalloc, that is you have one large 4 mib allocation and split it up in 64 kib pages, it seems you picked 256 kib?
actually I think I will steal mimalloc and combine it with a few simplifications from sharded slab
should be good enough
the mimalloc paper is pretty good but it doesnt go that much in detail
ah, i just don't have that because i didn't implement it yet
that's on my TODO list for the slab
afaik it's to minimize syscalls?
yeah, it helps to prevent churn in some cases, for example when repeatedly allocating large objects
also how is the atomic stack not prone to ABA? isnt it basically a treiber stack
ahhh yeah
what other than the segment impl do you want to steal from mimalloc?
compared to sharded_slab?
I'm not sure, just in general it'll be closer to mimalloc I think
I'm just tryna figure out the layout atm
like I'm not sure what's the difference between pages_direct and pages
why the fuck did they name slabs pages 😭
i guess a page is not necessarily a slab, it can also be a large object
actually no
the slab equivalent would be the segment I think
I guess the pages would still be pages in bonwick parlance
idk
no, i think a segment can have slabs of multiple size classes
at least, that's what i'd assume
I don't think so?
look at the diagram
you have one segment per class size
from which you allocate pages
ah, pages[] is a queue, pages_direct[] is an array
no, i think you have one page per size class
"it took me a moment to remember" tf are you talking about claude 😭
the point of the segments is that you don't have to call mmap once per size class
ah yeah actually I think I was mistaken
the pages are the same size no matter what
yes, the pages are the same size but they can be subdivided into objects differently
so it doesnt make sense to have one segment per size class
apart from large object sizes, which have less pages
it's a slab in the sense that you allocate fixed-size objects from it
but then you allocate fixed-size objects from those objects
Is tlb thread local block or something?
yeah
Oh
I'm not 100% sure how mimalloc does it, but I'll do like sharded_slab and have one threadlocal heap
and use pointers
instead of indexing with id
I think the naming will go Chunk -> Slab -> Block
chunk = segment, slab = page
omg
genius idea
mimalloc does this
I can just use a bitmap instead
actually an extremely good idea
idk why they didnt think of this
Is it impossible to not have a free segment?
wdym
Why does it assert false
this is called when a segment is in the "segment_has_free_pages" queue essentially
huh
you're right
wtf
Indeed
no nvm this is normal i cant read
^
Cant u just have a freelist of unused segments instead of iterating them
Maybe thats not hot code
the bitmap idea is really good because it has other nice properties
Otherwise this is quite bad
like you can just do if (bitmap == 0) instead of used == capacity
there is probably a phd reason why they didn't use a freelist
idk what
yeah, it's on an already slow path
it being a slow path != "we must make it as slow as possible"
well, at most this iterates over 64 bit entries
maybe they have code to allocate multi-page sections for large allocs? idk if they do but it'd make sense
it's true that a bitmap would still be better even in that case though
idk for large allocs they have one page spanning the whole segment
also I think what I'll do is <= 8 kib is small, <= 512kb is large then I'll just hand it off to the OS
even if it's just, say, 128 KiB?
well, the page wont be 128 KiB
it'll be the whole size of the segment
yeah but that wastes a lot of memory (?)
or how do they do it
surely they don't round up everything over 64K to 4M?
no, it would be 512 kib
is this from mimalloc?
i'd use a bitmap to allocate multiple 64K pages at a time
https://github.com/search?q=repo%3Amicrosoft%2Fmimalloc mi_segment_find_free&type=code doesnt exist anymore?
it's from v1
(assuming that 4M is the segment size)
actually wouldnt it make more sense to make the segment 2mb
since large (OS) pages exist
well, 4M will just be 2 large pages
also wdym? Then you can't allocate one object from a page
Hm?
well, if the object size is like 128kb
and pages/slabs are still 64kb
then you need to allocate 2 to fulfill the request right?
yeah
that gets tricky
I think maybe it makes more sense to make the page size be the size of the object
idk
I agree it's weird that they waste a bunch of memory for objects that are like 512kb
maybe I misunderstood
ahhh no ok so I misread the code, they still carve up the big page in objects
with a simple freelist?
so instead of having multiple 64kib pages you have one large page of 4 mib from which you allocate objects
yeah it's the same as a regular page
except there is just one
but this one page is still split into equally sized objects?
yes
I think this is to ensure at least 8 objects fit in a page or something like that
i.e., you'll have a 512K page consisting of 4 objects of size 128K or similar
yes, well a 4 mib page
ah
since a segment is 4mib
to me it seems kinda arbitrary to do it that way and you could just do the traditional slab thing of iterating over sizes to find the one with least waste, no?
yeah i see
ah i guess for multi page allocation with a bitmap you wouldn't know which segment to look at
but this means that you're potentially wasting a lot of memory still
how?
the most you're wasting is through internal fragmentation
huh actually you do also waste a whole object since you have to embed the metadata
because there are 7 such size classes and for each one you're potentially wasting 4M (- epsilon) per cpu
so you could easily be wasting a gigabyte on a machine with 20 cores
actually, half a gigabyte but still
idk how you're wasting 4M any more than if you were allocating small objects
because you can fit pages of different size classes into the same segment
if obj_size < 8kib, carve up 4mib segment into a bunch of pages, carve pages into objects
if obj_size < 512kib and > 8kib, carve up 4mib segment into a single page, carve page into objects
Why are you looking at an old version
because the paper describes v1
and it's considerably simpler
And hasn't changed that much
Maybe they improved critical stuff you won't see
Is this for the kernel allocator?
No I checked
And they fix bugs on older versions anyway
No it's for zig
because what should one do upon seeing suboptimal std allocator code but redo all the things to maybe PR in
It's not suboptimal
It's pretty good for what it is
But on cross thread frees specifically it has like O(infinite) memory usage lol
lol
But like imo shouldn't be used as a default allocator like it is atm
What does it do for cross thread frees?
https://ziglang.org/documentation/master/std/#src/std/heap/SmpAllocator.zig this is the source btw, for others who may want to look at it
yeah I was about to send
Andrew claims it is faster than glibc but I kinda doubt that
It's faster on his benchmarks sure
Faster than glibc doesn't mean much unless it's a broad benchmark
it puts the freed object on the current thread's freelist regardless of which thread it came from
You can always make benchmarks where you're good at see the sharded_slab ones
So you end up with O(n) memory where you need O(1)
if its a large object yeah
That's what I mean
Specifically
where one thread allocs and another one frees
it actually tries to steal from other threads fwiw
but yeah
(each thread gets a lock, the stealing uses trylock instead of unconditional)
yeah
at least zig makes it super easy to swap out your own allocator if you want, this one is just meant to be a good-enough default for releasefast builds
so even if your improvements dont get merged you could make a package of it
Also do you think I can make a draft PR or RFC or something
Like Linux
probably
mhm what about having a larger page size for objects <= 512 KiB
something like 1 mib
so worst case drops from 7 * 4 mib to like 7 * 1 mib per cpu
I'll do the mimalloc thing for now, I'm not sure how this should be handled
I could also have some kind of "run" metadata which encodes a number of 64kib pages
one possibility is having an augmented rbtree for page allocation
that's ofc a bit slower than a freelist but it could still be thread local
So it wouldn't be that bad
@heavy sandal
running andrew's own benchmarks
lol
the only worse thing is RSS but that's because i havent implemented returning pages to the OS yet
also gotta love the asymmetric benchmark using infinite memory on SMP
nice
i have no idea why they ship it as the release default considering that is a known issue
imagine a production database like tigerbeetle or something that's running for a while
it will OOM
@heavy sandal im spamming you but do you know where zig devs are
IRC or ziggit
ah they have a compiler development channel on zulip, but I dont think this is what I'm looking for
nvm it is, sorry for ping
they have a ZSF zulip
oh yeah this is great
I think I can ask andrew and people directly
yeah it's zulip
there's a zig dev zulip and a zig community zulip, the former is probably what you want and has an std channel
do you think i should put up my current code on github or I can just share a file on the zulip
either probably works but if it's more complex use source control
probably better if I just share the file for now
also
remember the asymmetric workload
for some reason it's much faster on my ARM macbook
on my amd64 machine smpallocator and my own were pretty much neck-and-neck, but on my macbook mine is much faster
btw why are interested in improving the zig allocator?
idk i was curious what the implementation was and i got nerd sniped
Ah
also i could maybe potentially reuse the code for my OS
we'll see
after all, why not have a 4th allocator in the kernel 
a kernel is basically a collection of allocators soo
wait why
pmm, vmem, zone
whats zone
ah
technically even then, the slab allocator is a bunch of small allocators
a bitmap and a freelist
if you rotate the b 180 degrees then its a slaq allocator
This fixes compile errors on newer Zig, where ** was removed
lol is this AI
Yes
yeah
I see that Zig takes it's AI policy very seriously
*its
it's not zig where that review was made
and it's not a zig contributor either or anything
(afaik)
yeah
the zig no-ai policy is for zig itself. other projects are welcome to do what they want
I think im ready to post my thing on zulip for RFC at least
I've implemented alignment
wait do u think I will get slimed since I said I used an LLM to generate preliminary tests/benchmarks
no
i wasnt aware you were experienced with zig's contribution policy :p
ah bc of zig
tho whatever you do on your project should not really matter i think
I've had a stroke of genius while in the shower wrt returning pages to the OS
i'll call them superslabs or chunks here but they're mimalloc segments
basically everytime a superslab's refcnt drops to 0 (i.e all of its slabs are freed), you put it in a thread-local list of "free candidates", if refcnt ever goes back to > 1, you remove it from that list (to prevent always putting and removing it from the list in the case where 1 object is constantly freed and allocated). Then, on every heartbeat/slow path of the allocator, you go through every superslab in the list and increment its age. When its age reaches a certain threshold, you move the superslab to a global superslab freelist and reset its age. Then, on a slow path, you also go through the global superslab freelist once in a while, increase the age of every superslab and then when it reaches a threshold you free it (or madvise it)
this ensures that superslabs get the chance to be reused before getting returned to the OS by 1. you 2. other threads
i think this is pretty good and wouldnt surprise me if the guys at MS figured out something similar
cba to read mimalloc code though
man i just saw a hello world zig OS essentially with 100 stars 😭
really need to lock in so I can claim zig OS supremacy 
post on hn without any code
I cannot help you answer your question, as I don’t use any LLMs to write code. But I have a possible (but not very plausable) explanation for this. In case you haven’t read Thompson’s “Turing Award Acceptance Lecture” (and assuming you haven’t attended in 1984), the moral of his talk is: You can’t trust code that you did not total...
lmfao what
what the fuck lol
huh
Weren't their models also refusing to work on C++ code because it was "dangerous" because it was unsafe?
I think that was gemini that wouldn't allow you to write C++ if you were under 18 or something lol
Ok, no, that was Gemini
but like this is conspiracy theory shit lol
Yeah
"the zig developers have been putting secret code in the compiler ever since the first release to detect AI usage"
Introduction Welcome to my collection module! I bet you will feel shocked at my design. This is the recommended collection which the one of collections in my library. It’s negative stack. Do you believe the indexes of my stack is decreasing from -1? (Like -1,-2,-3,-4,-5,…) Do you believe the top pointer of my stack is less than the bottom...
i swear ziggit will have the lowest quality posts 😭
i have committed unspeakable crimes against the standard committee
whats a pin
mhm I guess the name should be publish_epoch
new side project dropped https://github.com/rdmsr/zync 😭
I will get back to work on zag tho since I consider this mostly ""finished"" (as a first v1) for now
i may use some stuff from this tbh
I think it's pretty cool but it will be extremely cool if I add channels
But that's a whole can of worms that I kinda don't want to open now
I'll wait to see community feedback and see if it's worth pursuing
Also I should really try getting my allocator in
are the queues in it lockless?
because a lockless mpmc is something ive been wanting
Yeah it's all lockless
What kind of channels?
Kinda like go but not asynchronous
Idk if you've ever used crossbeam, but like that
But in kernel?
No? Read the convo
Oh, I'm dumb
@past dome turnstile man how do u test turnstiles/priority inheritance
when i get to a somewhat workable state I kinda wanna port to a weird architecture
LA64 would be a good first port tho before that i think
la64 seems kinda neat tbh
apparently it has dedicated registers for setting up an hhdm in the normally-non-canonical zone of virtmem
Its lapic equivalent is a bit weird though 
what's the weirdness of it?
i don't know anything about it yet so i'll take your word for it
It's per processor
So it's like a mixture between plic and lapic
Idk, it seemed a bit odd to me
there is an lapic per processor on x86 too
whence 'local'
But the interrupt vectors are shared
I.e. in a system with 2 processors with 4 cores each, you would have 2 controllers
Where each of 4 cores share the interrupt vectors
On x86 it's per hardware thread
I don't think having a heap for the turnstiles is worth it
it seems pretty tricky to have to deal with the keys updating under the hood, i.e raises need to remove the waiter from the heap and re-insert it, and when a priority gets lowered then there's a whole can of worms here which would require scheduler integration
I suppose the priority getting lowered isnt that bad and would be essentially benign (it would only over boost) but I dont like it
maybe a rbtree would be better here if removes are frequent but I'm just gonna keep a list
work will continue tomorrow 🚀
since will has a j*b that means this is an opportunity to steal mintia's ideas and implementing them first so I can claim I came up with them 

Will is not a real osdev anymore :( we lost a good one
No real osdev has a j*b
i have actually locked in and turnstiles are pretty much done i think
i havent been able to focus for more than like 5 mins these last few days
i need the autistic motivation to come back
mood
now you get to enjoy autistic demotivation
finally pushed 🚀 🚀
ok great now worker thread time
should I go full fancy mode and do the chase-lev lock-free workstealing queue
actually dunno if that's a good idea since work items can block
actually i think I will work on an object manager of some sort, I like that idea
interesting language
it looks like propagate can live lock when two pi walks hold different root turnstiel chain locks and each needs the other's bucket?
because restart doesn't drop root
ooh I think you're right
good catch
I think I can enforce an ordering on the chain locks using the address
actually no that gets iffy
i should just drop the root and restart entirely
I think I fixed it, thanks @earnest heart
it wont be like NT; mostly just a way to centralize reference counting and zones
ill say straight up the only reason to go full NT with object manager is if you dont have a singly-rooted vfs
ime
i want a proper unix vfs tho
object manager will just be a way to manage reference counts
probably wont even be its own subsystem
thats what im saying, you have that so you shouldnt go full NT with the object manager and i agree with you there
I will just implement those things for now and do stuff like handle table management later
cuz i wanna get worker threads ASAP, and threads will be objects
or maybe I can just skip that for now 
yeah ok
I really need to start writing stuff down, I had a bunch of cool ideas I forgot
mood
one thing I recently realized tbh is that the full nt object manager stuff is actually basically just devfs + a tmpfs but only for pipes + the /mnt directory
it's basically the equivalent of VFS
I will expose objects through the VFS
but since the main goal is POSIX/linux compat they wont be used that much outside of the kernel
userspace probably cant get a handle to anything but files (or well, also stuff like timers through timerfd etc)
yup
linux workqueue is pretty complex
among the least surprising sentences ive ever read
I think I have an idea of a fairly good/simple design
There are 3 global work item queues: high, normal and low.
The high and normal both have a thread each on every CPU and for the low-priority workqueue there is one global thread.
When a thread is spawned, it registers a "on block" hook so that the workqueue can detect when it blocks and spawn another thread accordingly, this new thread is then killed off if it cant find work for something like 200ms.
mhm
is it really sensible to have one thread per priority per cpu
feel like that may use a lot of stack for threads that'll be idling most of the time
for now it's fine I guess 
whats a good name for a queue that blocks when it's empty
I realized i use that in workqueues and I'll probably need it for the reaper thread, so might as well make it generic
c# calls it BlockingCollection
and tbh i cant think of a better name than blocking_queue lol
(the c# one is called blocking collection instead of blocking queue because its technically a wrapper to add blocking to an arbitrary concurrent collection)
huh, it looks like NT has a queue object structure
that is a blocking queue but it also wakes threads when one of them blocks
yeah. i dont fully understand it yet but its there
I have thought of a way to have that and have a worker pool on top
the principle of it is something like it tries to keep a constant number of worker threads running and servicing requests
so you provide it with say 20 threads and want 10 around, and it lets 10 through, and if one blocks while servicing a request (i.e. blocks on anything but the event queue), it releases another, or something like that
Mintanium implements this
I mean itantia
I mean mintia
I called it KeBalancedQueue
for worker threads?
Yes
With the caveat that work queues use priority queues, which are a new type of dispatcher object relative to the 90s
workqueue will use a kernel queue but will hook into it to manage spawning threads dynamically
the name of the mintia itanium port
ok it will be a fake queue
it seems NT does direct handoff of items when they're added to a waiter thread
I wont do that
I'll just add the item to the queue and wake one waiter and hope it picks it up
if it doesnt then it'll just go back to eep
they use WaitStatus for this
which is kinda crazy
It's all just bytes in memory
yeah I know
but it's fun
do you do that?
I think the worst case here is that thread gets woken up for no reason
which I dont think is that bad but could definitely be improved
I don't think I do because I need the wait status
yeah but handoff of new items to woken threads in general
No
It just wakes one up and lets it go through again in a loop and find it
It's bad to give it to a thread that might not get scheduled in for a while
wonder why NT does this then
well, if you merely enqueue and wake, you now have a race where the item is visible to everybody before the selected waiter actually runs
yeah but that is not a problem, since the waiter will just loop and find that the list is empty and go back to sleep
idk im basing this off older NT
It's a bad idea for the same reason that atomic lock handoff (done 100% of the time) is a bad idea
By enqueuing it instead of handing it off, someone who is already running on another cpu can come through and find the work item and start working on it immediately by the time the woken thread gets scheduled in
yeah that is my reasoning too
maybe it just has to do with the properties of the queue object they have to maintain
or maybe they figured out that was bad and removed it in modern nt
I wanted to make my worker threads wait with a continuation so their stacks get released but it's a bad idea
It could increase latency intolerably at random moments
It's maybe a good idea for the low priority ones
I'm not convinced one thread per priority per cpu is right yet but on 64-bit systems the memory usage is minimal
my plan is to do one but if it blocks it starts another
per priority per cpu
this is what linux does
do you mean allocating and initializing a whole other thread right then and there?
basically there'd be some kind of pool manager thread that would get woken up when one of the workers block on something else than the queue, then it would spawn another thread to handle the work. Then that thread waits for new work or for 300ms and if it times out then it exits
if it can't spawn a thread directly (because no memory or something) there's a rescue thread that drains the workqueue to hopefully release memory
that is basically what linux does afaiu
I would keep a constant pool of some minimum number of worker threads and have a periodic thread check whether satisfactory progress is being made and if not it spawns more worker threads
Also I have per node queues rather than per cpu and there's N worker threads per cpu in the node
any particular reason why the queues are global like that? to avoid weird imbalances?
with global queues im worried about contention
I'm not anticipating that much intra-node contention at some given priority level of the worker queues
A lot of the work items are batched for the future
For example the thread reaper work item is enqueued for like 500ms in the future and any threads that die in that timespan won't enqueue it again
Same with object reaper (used to avoid boundless stack usage in object deletion and also some deadlocks)
huh you do reaping at a periodic interval?
No
When a thread dies and the local node's reaper queue is empty, it will enqueue the reaper work item
For 500ms in the future
It's a timed item
That's not periodic that's just delayed and batched
didnt vms do that or something
Idk
Oh yeah
One thing I was missing is that the swapper process did wake periodically to do some odd jobs
Regardless of whether memory was low
So it'd be like once every 5 sec
I'm not sure what NT's current count means, but mine will mean "number of threads that are ready to process work"
for work queues that maximum count will be one, but in practice there might be more than one thread running
i think
actually I decided against having a MaximumCount/CurrentCount thing
it's a bunch of extra logic for something i wont really use
in NT i believe it is in fact the opposite of that - its the number of unblocked threads currently working
yeah well I wnated to do both
basically any thread waiting on remove() and any thread currently doing work
but i think it adds to much complexity for too little gain
shrug
casual 8k lines file
i somehow have found an unlimited chatgpt plus hack
i used the free trial, then in paypal app I removed openAI from it
and now I still have plus even though the month has ended
codex is pretty useful going thru linux code
what the hell is it doing that takes so much
tbf there are a lot of comments
ok i figured out how it works basically
and it's better than what I wanted to do
How
the pool always tries to keep at least one running worker.
When a worker runs, it checks to see if there are enough idle workers, if there isnt then it creates one.
When a worker goes to sleep, the pool tries to wake up an idle worker.
then when a worker wakes back up, it checks if there are too many workers and if so it goes to sleep
that is basically it
interesting
mhm designing this properly is hard
the way my queue works doesnt really work with that model
bruh the queue code makes the wait code so messy lol
ok so I have an actual proper NT style queue now
i think for worker pools it'll be roughly "keep always one idle spare thread" per-priority per-cpu
so that's like two worker threads per priority per cpu minimum
but it can grow as there is more pressure on the queue, there'll be some kind of periodic pruning of threads that havent done anything but waiting in the last e.g 1 second
per-cpu queues have maximum concurrency of 1, and the global low-priority queue will have one of ncpus
to detect thread creation blocking because of no memory, you set a timer that fires in like 20ms, and if the worker is still not created you enqueue the rescuer thread which drains the work items required to reclaim memory
dunno if that should be a thing or if thread creation should return an error instead if OOM
Oh @past dome just thought about something, if you delay thread reaping then what happens if you OOM before the reaping happens? Do you expedite reaping in that case?
gibbee
I guess you could just cancel the timeout or something dunno
Or just enqueue it directly
if memory is very very low then the balance manager thread (which is awoken by low memory event) will cause the reaper to be called immediately
while emptying other caches
Ah yea
What do you think about this? Linux seems to do that but imo it seems hacky to detect OOM by setting a timeout lol
is this not SUFFICIENT
does this not suffice.
You don't have to deal with that problem cuz you don't spawn worker threads dynamically
but i will
