#MINTIA (not vibecoded)
1 messages · Page 33 of 1
or i got lazy or something
btw im absolutely going to do an extremely high effort compiler infrastructure again one day which will be Super Freakin Modern
for my current project im not doing that though, in fact im building the most cursed and naive assembler ever rn
an underratedly terrifying moment is when you switch from using your initial bootstrap compiler to using the compiler to compile itself
bc the bootstrap compiler only supported a subset of the language
and when you start using the compiler to compile itself then youll start using language features that the bootstrap compiler doesnt support
and now you cant compile it without itself
thats your own doing tbh
i wrote a language spec first
and then built a transpiler to C
then built the compiler in its own lang
both according to the same spec
in fact i basically ported the transpiler in some places
readme in the "tower bootstrap compiler" which is still in the sdk repo
Tower Bootstrap Compiler
Tower -> C compiler for use in writing the real self-hosted compiler.
Won't be maintained after that compiler is complete, so this one is very
rudimentary, does little error checking, will readily let bad stuff fall
through to the C compiler, etc. Don't use this expecting a good time -- it's
purely temporary for use in developing the real compiler and its entire purpose
is to vanish as quickly as possible.
i did not realize that it would be a year between writing that readme and achieving self-hosting
this sucks because if u lose ur compiler binaries along the way, you're fucked
you wont be able to compile shit since you use new features etc.
with my way you do need to backport new features if you ever add them but 1. it's easier cuz the compiler frontend architectures are very similar and 2. you shouldnt add new features after building most of the compiler anyways
i mean it doesnt rely on distributing magic binaries
didnt you wonder how bootstrap.sh built itself after you did a fresh clone of newsdk
nope
a "prebuilt" set of C files is distributed in a tar.xz lol
C files are emitted every time you build the compiler and you can pack them into the tar.xz with packprebuilt.sh
oh so you just always have a transpiler?
ah i see
ok that makes more sense
btw whats the purpose of this fireworks pool cache
to test pool caches
should i do that as well
idk
probably because the MmAllocatePool interfaces and whatever are probably going to change soon
but the pool cache interfaces wont
actually i dont really need a data cache
i only need a single bitfield really
i can store that in like .bss lol
or whatever u have
it would only be like a few words in size
@twilit smelt where's the jackal spec
i need it or else im basically pseudocoding my way while checking the os source code to figure shit out
newsdk/Jackal/Frontend/PrsProgram.jkl
its a very small simple language youre not going to be lost for too long
array of what
of uword
do u want to initialize it
to all 0s
i dont need to explicitly 0 that right
no
thx
whats the array for
for what
of regions where the set is being evaluated
actually wait do i really need a bitfield? i could probably just use an atomic counter and check when all the threads are finished
if you declare it as a ULONG then you can use KeIncrementUlong with a negative increment (ideally specified in its full 32 bit unsigned form i.e. 0xFFFFFFFF for -1)
it returns the old count prior to the increment
yes
UBYTE is 8 bit, UINT is 16 bit, ULONG is 32 bit, UWORD is whatever the machine word is
so UWORD is 32 bit on 32 bit systems and 64 bit on 64 bit systems
UWORD is also equivalent to a pointer size
so SIZEOF ^VOID == SIZEOF UWORD
theres also UQUAD for 64 bit but that is not usable on 32 bit platforms
theres RtlUquad in the jackal RTL header though which provides portable 64 bit integer math
which on 32 bit synthesizes it and on 64 bit uses a UQUAD type directly
this is atomic right
yes
what the fuck would the point of that be if it werent atomic
why would i have a whole function just to add stuff to a variable
and suggest you use it
when u mentioned an atomic counter
if it wasnt atmic
!
u can also look
// a0 - ptr
// a1 - inc
// outputs:
// a3 - old value
KeIncrementUlong:
.export KeIncrementUlong
#IF BLD_MP
mb // Ensure coherence with other processors.
#END
.retry:
ll a3, a0 // Load-locked the location.
add t1, a3, a1 // Add the increment.
sc t1, a0, t1 // Conditionally store the new value.
beq t1, .retry // If store failed, retry.
#IF BLD_MP
mb // Ensure coherence with other processors.
#END
ret
i like the idea that i just have this random KeIncrementUlong function that just increments a ulong non-atomically that you could have just +='d
and im like demanding people use it for random increments
that WOULD be a really good bit
if someone asked why i could just go like "It encourages consistency." or some other nonsense non-answer
why does jackal lowkey feel like Lua but C
it's so weird
@twilit smelt if i did a while loop like WHILE cell_counter < MAX_CELLS DO ... END with nothing in it actually accessing the counter, the compiler wouldnt optimize it away to a while true loop right
or is there a way to do volatile accesses
ill just put a BARRIER
and hope it works
why the hell is it comparing argument names
wtf
the hyena learned Lua first (it's traditional and important language in the Minecraft community) and JACKAL is quite close to a relexified C
makes sense
also i finished the mandelbrot thing
it renders now
but you can see the scanline so im trying to make it spawn the threads in a random ish order
uuuh
theres no xor operator
well, there probably is
but ^ is just pointer deref
ok i think it might be $
compiler sources confirm ```
LexInsertKeyword ( "$", TOKEN_OPER, TOKEN_BITXOR, 0 )
i think the problem with this test is that you cant tell at a glance that a thread has frozen or something since it blends in with the background
you could render the fractal at a lower resolution but in 16x16 tiles or something and that would make it slightly more obvious that something's going wrong
the palette changes colors every time
also threads arent per pixel
theyre per cell which is like 4x4 here i think
still hard to notice a pixel not changing
but it's cool
coad?
i want kernel modules to be able to allocate per-node data and not have to go through a remote node to access it, which is not currently possible
so i think i will have a special section
which is writable during initialization of the kernel/of modules
and after initialization of a module completes, it is changed to read only and the physical memory backing it is duplicated across each node
so that they can store pointers to per-node structures there and stuff
to be more specific theyll store offsets from the base of the per node space, so that it is applicable to any node
early init will use a bump allocator within pre-allocated (by the bootloader) pages of the node space in order to allocate per-node per-subsystem data (same as it currently does)
but after physical mem management is initialized then itll initialize a shrimple free list heap using the remaining space
and will be able to add more pages to the end when it runs out
ok
can i have the coad
i threw this together haphazardly
also you have to comment out the firework KtMain
but not the rest of the firework test
cuz this uses the graphics code from that
cuz i couldnt be bothered to write that shit
i tried so hard to usewhateverthiscaseiswhythefuckdoyouevennameshitlikethis
but there might still be a few inconsistincies where i used snake_case out of habit
and forgor
the code that actually does the mandelbrot set computation is MandelbrotCalc so you can throw away everything else if you rewrite it
@twilit smelt does it work
yes
nice
spawning 1 thread per pixel is way too many though
it's not 1 thread per pixel
what is it
grid size is 64
thats a 64x64 grid of
cells
each cell is 4x4 pixels
and gets its own thread
you can delete this sleep if you want
btw multiplications didnt work for me
inside of macros
so the max_cells and max_width are hardcoded
max_width is just cell_size * grid_size
max_cells is grid_size * grid_size
already fixed
what does the [ ] do
its like a quote
huh
its cool that the time used scales almost perfectly with the number of processors
you can remove the beginflag stuff but then you will see the obvious scanline
and it probably wont be a good stress test either
cuz this forces all the threads to work at the same time
i removed the sleep on the drawing threads to show more clearly how it scales with more cpus
it works on fox32 as well
but looks much more evil
bc fox32's framebuffer is 32 bit ABGR
good to see my scheduler actually distributes load
so was this of any help
well that has to be fixed tbh, the idea is that each frame has a different palette so it's easier to spot deadlocks
there are no deadlock bugs in mintia scheduler anyway
i will possibly clean it up and include it as part of ktests.sys selectable with another boot arg or something
but keep in mind it took me like 4 months to do that with the original fireworks test
so
lol
Nah I found one
wher
wont tell
p
also i changed my mind
if you passed in a continuation to a wait function, it will always be called, no matter how the wait function returns
i made this decision after realizing the needed routine to directly call the continuation function is like a handful of instructions and itll clean up continuation-based code a lot
// a0 - continuation
// a1 - waitstatus
// a2 - thread
KepExecuteContinuation:
.global KepExecuteContinuation
// Reset the current thread's kernel stack to the top and execute the
// continuation.
mov sp, long [a2 + KeuThread_KernelStackTop]
mov t0, long [a0 + KeContinuation_Function]
// Set link register to zero to terminate stack traces and jump to the
// continuation. The arguments are already in the correct registers.
mov lr, zero
jalr zero, t0, 0
its just this
who knew that switching back to your own stack in the middle of execution could be a useful operation
this albums biggest cultural impact will forever be this generational slander like drake is just the hickory dickory dock guy now as far as im concerned
Quoting Kalshi Music (@Kalshi_Music)
︀
Our traders forecast Iceman to spend 4.4 weeks #1 on Billboard 200
mintia2 continuations theme song
that and that one ai "i am iceman" song with its countless variations
this is funnier
also my top 15 spotify songs of all time are all songs that i listened to on a loop for days straight at some point while fixating on something
except for #1 thats just one of my fav songs of all time and i listen to it a lot randomly since 2018
true
one thing i love about IRQLs and NT-like software interrupts is how often theyre a cheat code to get out of lock ordering violations
"oh i cant enqueue a work item to this worker thread deep inside the scheduler because im under a thread lock and possibly the ready queue lock already. no problem ill just set a flag in the current core's prb saying 'enqueue this work item please' and then set a software interrupt pending at KEP_IPL_DPC and do it then"
this man is a genius
the beginning of the end
"it would 'only' take me a few months" -3 years ago, still not even half done
well it's not really a 1:1 rewrite
far from it actually
so I think that estimate can be disregarded safely
it took me like a year just to write the self hosted toolchain, it didnt work until april of the following year
so that estimate was insanely wrong
even if i had done a 1:1 rewrite it would have taken over a year and a half prob
sometimes i remember how bleak the self hosted toolchain felt the entire time and im glad its so far behind me now lol
it felt like a quagmire id never get out of and that my project was officially dead and ruined
so much harder than i expected
i still have like compiler ptsd that makes me not want to touch it bc it was so difficult
i just dont have compiler brain
This is what is called TP_WAIT in Windows.
the difficulty increases like quadratically as you increase feature set from smth like the dragonfruit compiler and i didnt realize that, i thought itd be more linear
is it used pervasively? and does the thread yield its kernel stack immediately
It scrolled all the way down...
lol, happens
TP_WAIT is used in user space. Generally speaking, developers hate coding to the continuation paradigm.
That's why language crutches like async/await are popular (essentially they make the stack a continuation context)
my continuation thing is kernel space and is meant to be a replacement for pageable kernel stacks
as a way to free up kernel stack memory while a thread is doing a lengthy wait
i was going to try to implement all the top-level syscall code in a continuation style
so that lengthy IO waits and stuff will all yield the kernel stack immediately
to a per-node free list of kernel stacks which is periodically trimmed by a worker thread
Yeah, I got it
So you're going to adapt your public wait routines to work with this paradigm
yeah, optionally
how im thinking it will work is that if you want to wait with a continuation, you get a pointer to a continuation structure with KeGetContinuation() which returns a pointer to an embedded continuation structure inside of the current thread, and then you fill it in with a function pointer and up to 3 parameters (may end up being more or less depending how many i end up actually wanting)
and then you pass a pointer to that structure into KeWaitForObjects
and if you have, then a continuation-style wait will be done
adn your continuation function will be called with a pointer to the continuation you passed in
right now continuations are not allowed in APCs because they trash the stack which you kind of need in order to resume whatever was happening before the APC occurred, but if i ever figure out some way to get around that (like compressing the stack instead of discarding it or something) then KeGetContinuation() will be able to return a pointer to a secondary continuation structure if it is called from APC context, so that an APC delivered during a continuation wait doesnt trash the stuff set up previously
so im trying to future-proof it for if i try to make it fancy enough that it can be done within APCs
which is pretty unlikely
bc i see the most utility for it in like top-level syscall code as i mentioned
kernel APCs are very much not that
but yeah
the Mach paper i read actually directly compares kernel stack paging with continuations and gets better results for the latter
which makes sense to me because it immediately makes the kernel stack reclaimable rather than paging it out to disk after some delay
whats the motivation for that
if you already had paged stacks implemented
because i believe this is better given that 1. see my directly previous message and 2. ill be able to use it from the ground up in the places where itll count most
it also eliminates like wait list scanning activities and stuff
its lower overhead than paging them out
assuming i can use it ground-up in every single place i would otherwise have made the kernel stack pageable (which i believe i can given experiences w/ pageable kernel stacks on mintia1) i think itll be an unambiguous improvement
especially direct hand-off is super cool
where if youre switching away from a thread that waited w/ a continuation, into another thread which waited w/ a continuation, you can directly hand over your kernel stack
if the large majority of waits are continuation style (which i believe i can achieve) then this will reduce kernel stack memory overhead to being near as good as per-processor kernel stacks, without the drawback that usually has of not supporting kernel preemption and whatnot
you also dont have to save or restore any context if you do this
i dont think NT kernel could substantially switch to this because although they could certainly add APIs for doing it, they wouldnt be used very pervasively by third party drivers and it would also probably be a substantial engineering effort to rework some of the IO codepaths and whatever to do this
so its possible this is just better than kernel stack paging and i get to benefit from doing it ground up lol
same reason NT unfortunately cant switch to an iterative IO enqueue model and so on
baggage
me reading design docs from 1989 where they hadnt thought of iterative io enqueue or this yet
if DEC SRC had done a paper on continuations in Topaz in like 1986 then the NT kernel would probably have them today lol
rick rashid probably told dave cutler about them considering his mach continuations paper came out around the time he had the NT team's ear, but it was like 4 years deep into NT development so if he was told about them he most likely was like "thats a good idea but no we need to Ship."
considering 3rd party drivers its better not to touch the entire io management system in nt at all
because they care a lot about compat
they have touched it over the years and dramatically overhauled it on a couple occasions i believe
but yeah its really difficult to keep important drivers compatible
while doing so
some internal stuff?
because you cant break driver apis
like the plug n play manager was basically a complete redesign of the IO manager that had to contain the classic IO manager as an inner layer/subcomponent for legacy drivers, sort of
drivers devs were more active back then i believe nowadays many companies kinda forget to update their drivers
yes
and you may deal with very old driver which sould run on newer versions
darryl havens designed the classic IO manager and he was coming directly from like a 70s/80s mainframe background for IO thought
which was very unfortunate to have while writing a PC kernel during a time where plugnplay on PCs was right around the corner
so he designed this whole very good extensible IO system that took lots of lessons from VMS's successes and failures and so on
and was completely unsuited for the hardware that was like 6-10 years around the corner
so that sounds like it posed a massive engineering challenge pretty quickly
this is why i didnt study NT's plugnplay architecture beyond some superficial skimming of docs and stuff
and instead studied xnu iokit
because NT's IO stuff is like 99% accident and it shows lol
xnu's is 99% engineered
so its a lot nicer
the classic io manager would have been excellent if every PC was just a miniaturized VAX forever
but unfortunately that was only true for like a few years
The latest major addition is so-called driver proxies for hot-swapping drivers
not knocking him at all btw theres no way he could have predicted what was around the corner it was just unfortunate timing
iokit is better in terms of writing drivers/how drivers are structured but NT IO makes more sense imo
i was going to fuse the best parts of both
Like can you even compare them? It seems iokit is more of a driver framework or something
iokit structuring for like driver design and classes and matching and whatnot, but with NT-style IO packet dispatch
yeah that makes sense
they are directly comparable
iokit is xnu's low level io system for drivers
afaik iokit uses event loops or something to dispatch IO I don't remember
unfortunately due to its own baggage it also has a higher level io system which is the BSD filesystem layer
iokit is fundamentally async but the BSD filesystem layer is fundamentally sync
and the filesystem drivers are not iokit entities
they merely call iokit to interface with the storage stack
my fs drivers will be the same type of entity as any other storage driver
more like NT
and be fundamentally async
does xnu have async io wait capabilities like nts iocp
it probably does in the form of like posix AIO and whatever
but its implemented internally with worker threads due to the fundamentally sync nature of the bsd layer
rather than async IO requests
to simplify stuff i was going to immediately dispatch any cached async IO to worker threads (i didnt support it at all in mintia1)
rather than do the NT thing where it first checks to see if all the required data is already cached and if so directly does the copy in the context of the requesting thread and returns, and otherwise chucks it to a worker thread
which is an optimization but causes tons of special cases EVERYWHERE
that i dont like
like there are enough weird rules for driver authors to have to remember to not deadlock random system worker threads and whatever bc they used the wrong pool for this FCB or whatever
without adding that stuff
noncached async IO will be done as a direct async io request
linux does worker threads in either case and seems to get by just fine, and dont quote me because im not sure about this at all but i think the most important high performance applications like DBMSes tend to only use async noncached IO, because they do their own caching
idk what rust async io libraries do
but if someone ends up trying to run some kind of high performance rust application on amd64 mintia2 in 2038 then
they are evil probably
so
iocp?
windows completion ports
osdev beats
this guy also composed some of ultrakill's soundtrack
easy listening muzak
also i really hate these names
like it's just random jargon
very uninspired
not that the music is bad
i have a solution
LOL
ive listened to ki by c418 while studying ki by dave cutler
organically
before
What is Ki?
the song or the kernel component?
What sort of component is Ki?
indeed
Ah, perhaps. That would mean that Ke stands for functions exported to third-party developers.
i think it's equally plausible that it's something else tho
it is kernel internal
Ke stands for either Kernel or Kernel Exported
mintia2 has THREE prefix suffixes
-u: undocumented, exported outside the component but used only by other components in the kernel proper
-p: private, not exported outside the component
none: exported to kernel modules
so i have Ke, Kep, and Keu
The former -i for "illegal" was condemned as dehumanising language and that's how -u for "undocumented" came about in Mintia
Caused a bit of controversy at the time and was condemned as "utter woke nonsense" by the Maga contingent among the XR/corporation staff
that is 100% true
except -u is a thing that has no nt counterpart
and -p is the -i replacement
-p stands of course for purple person, which im racist against
those god damn purps
(intentionally ruining the joke by riffing on it in an unfunny way because i HATED IT)
once i got called the p word because i was choking and my face turned purplish
i dont think so because there are many ke functions not exported outside ntoskrnl
they're a band
what's iterative io enqueue
Instead of each driver going down the stack themselves, you do it in a topmost loop
ah okay
that just seems like the natural thing to do, to avoid stack overflows if nothing else
Yeah that's why it's a design flaw
update on the guy vibeporting NT to SPARC
you can tell the LLM is really understanding NT's design by the fact it made something called KiPeResolveImports and KiMmMapImageFromFat
definitely not making a huge intractable mess of everything
as of the recent CHM digitization work there is now enough footage of the DECwest ppl to make a vaporwave edit about the MICA team
continuations-based firework test seems to be working
direct stack handoff is happening a LOT
and seems to work
which is quite cool
every H is a stack handoff
not yet tested is the stack allocation worker thread
it is never signaled right now because theres no stack cache trimming implemented yet
which means theres always sufficient kernel stacks on the list
and therefore it is not invoked
this is so cool lmfao
who needs kernel stacks anyway???
im going to make all thread entrypoints into continuations now so that their kernel stacks can be allocated from the per-node cache list upon first schedule, or be handed off to
the function pointer type KeStartThreadF will go away, all thread entrypoints will be KeContinuationF
something really crazy you guys is that this worked first try
im TOO GOOD
that's what I've been saying since forever 
you have inspired me
Tbh I can probably go the other direction (from 1 stack per CPU) and also start allocating per-thread stacks for blocking stuff
to have the same system as you and a preemptible kernel
but idk if it matters that much for a microkernel
Do you have a link to the continuations paper?
I'm in a mood for editing osdev wiki lately 
this is gonna be such an enormous win on small memory systems
im very excited
the dcache benefits of the direct stack handoff are also very cool
and the fact u like completely bypass context saving and restoring when u do that
u just set sp to the other guy's kernel stack top
boom ur in
really very cool and interesting
er no
u dont even do this
u set sp to YOUR OWN kernel stack top, which now belongs to the other guy
fox32 arch code is bit rotting a bit during all this
foxi386
at thread creation and reaping time, the only thing that will happen wrt to the kernel stack is that quota&commit will be charged/uncharged for it
the thread will not get a kernel stack until it is first scheduled (since the entrypoint is a continuation)
and kernel stacks will be freed only by the kernel stack cache list reaper
this might be the second most radical kernel stack management in the hobby kernel space after @coarse current who does not manage kernel stacks
honestly maybe this should be taught as the default way to do it because its so much better and its not even that hard
one scary thing is the assumption of infallibility of kernel stack allocation at the point where it needs to be done
this is fine because its a blocking allocation and a guarantee was made earlier on that pages will always eventually be available for it by charging commit for it at thread creation time
but theres no such guarantee for virtual address space
if i run out of that theres not much good to be done
so that might just end up being an eternal loop of 500 millisecond sleeps hoping some virtual space eventually frees up lol
Because your kernel had a lot of careful planning and design with specific goals cince the beginning
continuations were not planned until like a week ago
In my kernel, for example, any allocation can fail at the moment, and I don't do this
But you don't overcommit memory
I see familiar people in the revision history...
i just realized i need a commit counter for virtual memory
ive been missing that
system virtual memory
nvm that doesnt work cuz it doesnt reflect virtual fragmentation
duh
this is cool, like 100+ fireworks particle threads all share the same ~12 kernel stacks without allocating any more
it can now run in like 1MB RAM
with all the particles
on uniprocessor its now doing fireworks at 768KB
ok it deadlocks after a while but this is expected lol
deadlocks on free pages that it cannot scrounge up due to the entirety of phys mem being eaten by thread structures and kernel stacks
i think the continuations branch will be ready to merge once i get the fox32 code up to date
im gonna leave continuations fireworks running all night and see if it breaks
mintia2 continautions theme song but for real
this is my on loop forever song for working on that
what exactly is a continuation
Inferno is the upcoming fifth studio album by Scottish electronic music duo Boards of Canada, scheduled to be released on 29 May 2026 by Warp. It marks the duo's first studio album in thirteen years, following Tomorrow's Harvest.
Inferno retains the electronic sound of the band's previous releases, while also featuring increased live instrumenta...
‼️
ik
did you see it?
that is my video i just took
vibey things happen to me in real life because im not a larper. im just that vibe.y
"im not a larper"
— liam, 2026
yeah thats a bold claim coming from john larp
"im not a larper"
i believe we're experiencing a definitional disconnect on the word larp as used here.
today i must finish the fox32 support for continuations
ah my bad i thought it meant live action roleplay /j
i was referring to the ai crypto grifter type of larper
All larpers larp but some larp more than others
evil larp (self-serving, deceptive, soulless) vs good larp (whimsical, interesting)
whimsical?
you're larping about being a white software engineer who works for a far-right corporation that supports fascist ideologies
making computer systems whose resources are mined up by slaves in colonized territories
used to further war efforts and mass spying on your country's people
whimsical/interesting? more like XR/fascism
counterpoint no im not
prove it
the average XR/engineer is just furthering the american dream of bombing innocent civillians to get oil
soo what are continuations exactly
and how do they relate to kernel stack
like stackless coroutines
never heard of the concept before
doesnt stackless basically mean stateless
where do they save the data
instead of blocking the current thread, u get a continuation callback
once e.g. a page fault is satisfied
void continuation()
{
printf("wohoo!\n");
}
void main()
{
printf("yahoo!\n");
sleep_with_continuation(continuation)
printf("whoppie!\n");
}
so this would print
yahoo!
wohoo!
?
i dont really see what benefit there is to doing this
@twilit smelt is this how it works
or am i wrong
you can throw away the kernel stack
across the wait
almost all threads are spending almost all of their time in waits that are good candidates for being made into continuations
you still have the overhead of deleting and constructing a new stack
no
for one if youre doing a switch away from a thread waiting w/ a continuation into a thread that is going to execute a continuation, you can directly hand off your stack and this case is much faster than normal context switching
for two if youre not doing that you can put your kernel stack on a per-node list of cached kernel stacks
no
and it will still be there when you come back hopefully
?
well he expected that it would resume
i dont see whats wrong with his example
or i guess he didnt but that pritnf at the end is dead code no?
yes, so it would print yahoo and wohoo but not whoppie
thats just to demonstrate that it doesnt return control there
ah ok
did you completely miss the part where he put the expected output lol
yeah i misread it
isnt this basically like DPCs
yeah lol
with a DPC you register a callback and lose all of your stack
and then at the end of the interrupt
that callback gets called into
with a continuation you register a callback and lose all of your stack
and then at the end of the next interrupt
that callback might get scheduled
Like call/cc 
i dont think its like call/cc? call/cc constructs a continuation for the current frame then calls a callback with it as an arg, while here you are throwing away the current frame and calling a continuation
I know, but I couldn't let continuations be mentioned without mentioning scheme 
based
do you give a thread (waiting for a continuation) a thread stack when an event wakes it up, or when it's primed for scheduling in?
what's the cost of allocating/reserving a kernel stack if you do the latter?
then you'd enter a blocking state waiting for that thread to exit or request another wait by continuation
afaik when it's readied he gives it a stack from the list and if there isn't any you wake up a worker thread to allocate the stack
smalltalk's Continuation>>currentDo: https://www.gnu.org/software/smalltalk/manual-base/html_node/Continuation-class_002dinstance-creation.html#Continuation-class_002dinstance-creation
GNU Smalltalk Library Reference: Continuation class-instance creation
it gets a stack at the time it is selected to be scheduled into
rather than at readying time
this allows free hand-off of the stack from a thread that is waiting on a continuation, to one that will execute a continuation
continuations are merged now
fox32 port proves its utility by revealing some bugs that were not as easily revealed by xr17032 based testing
i was initially going to do the nice thing i did with mintia1 where i had a header containing all the userspace-facing syscall definitions
which was the header included by userspace programs to get the syscalls
and i had a script that would parse it and generate syscall calling code
so i only needed to change that header
but jackal is much more annoying to parse
so
im going to just have a text file with simplified syscall definitions in csv format and generate a table from that perhaps
you already have a parser
this is why compilers should also work as standalone libraries imo
just link with libjackal, parse the file and read the AST / symbol table / whatever to do your stuff
libclang my beloved ❤️
the amount of cursed things I have been able to cook because of it
like what
there was a stack overflow in the idle thread introduced by changing the semantics of the kstack parameter to KeuInitializeThread that was masked by nothing important being in the way on xr17032 but caused an immediate crash on fox32
specifically the fox32 interrupt table was in the way and it got smashed which caused the next timer interrupt to jump to a crazy address
interesting
would you guys consider the design of mintia2 to be "exotic"
no
yes
I think your design is well reasoned and based on historical systems- the only thing that's exotic is that you chose to implment the kernel in your own language. It's like taking a super challenging and difficult task, and making it 5-10x harder just to prove you could do it. I respect it, but it had to be quite the lift.
have you tried continuation-izing your mandelbrot test yet
i think that would be interesting, see fireworks test for an example of how that works now
i would argue it's exotic because your OS implements ideas from every major kernel (NT, XNU, etc), in its own way, with its own spins
not that there couldn't have been something like NT with IOKit...
but right now there isn't
oh, and the continuation feature. I don't think I've seen that anywhere
NT definitely does not have it
its in mac os x
it wont be used as prolifically as i will use it though
ill be able to use it for IO waits which mac os x could not do because it has a fundamentally synchronous IO system in a way where it blocks deep inside BSD code and this doesnt lend itself to being continuationized
it could do it but it would require redesigning all their filesystem code and stuff
IOKit is implemented on top of the fundamentally blocking BSD file system code?
iokit is beneath the bsd file system code
its used to implement the storage stack and whatnot
it is fundamentally async
I see
the filesystems are implemented in a fundamentally synchronous manner by making iokit requests (indirectly through the cache)
But the fundamental async-ness isn't used?
I see
filesystem drivers arent iokit drivers in xnu
they dont have that unity that NT has
not yet
i dont really want to improve that test rn
i want to rewrite it when you have a proper testing framework
its broken right now bc i changed the thread interfaces
i made thread start functions into continuations for example
they are KeContinuationF now instead of KeStartThreadF which has been removed
this allows direct stack hand-off to newly created threads bc their entrypoint is called in a way consistent with how continuations are invoked
Provided to YouTube by IIP-DDS
Father And Son · Boards of Canada
Inferno
℗ Warp Records
Released on: 2026-05-29
Producer: Boards of Canada
Music Publisher: Warp Publishing
Composer: Boards of Canada
Auto-generated by YouTube.
i see
the wait functions also now all have a continuation parameter
which needs to be NULLPTR if youre not waiting with a continuation
Provided to YouTube by IIP-DDS
The Word Becomes Flesh · Boards of Canada
Inferno
℗ Warp Records
Released on: 2026-05-29
Producer: Boards of Canada
Music Publisher: Warp Publishing
Composer: Boards of Canada
Auto-generated by YouTube.
depends
what sets it apart is obviously programming language and the isa
thats all? 😦
obviously
there are many less obvious things, but I haven't read the source too much
and only occasionally look into this thread, so I'd rather not make up things I think are correct
are continuations like coroutines?
basically awaiting a continuation?
no
i have an example
1 min
#1322494605819908156 message
no
why do people keep confusing them with DPCs 😭
it's basically a function the thread continues running on when its woken up
yeah
so it implies a bunch of cool stuff
like you can just throw away the stack
it's pretty easy to implement and you ahve big gains which is cool
nobody's confusing them with DPCs
they are just similar
even if you claim they are not
they arent?
they're not at all
both involve a mechanism where you offload work to a callback
this is not work offloading though
you are offloading the rest of your work to the next time you get scheduled
So can that function return then?
Or trying to do that will just crash lol
no since the stack is empty
well it can return to e.g userspace code
no, it's not offloading work
Ah
it's continuing execution in a different context
a DPC is used when you wanna do stuff without being in a place where interrupts are disabled
that's actual offloading/delaying
and a DPC is conceptually a software interrupt, this isnt
it's just a way to indicate "i dont care about my current context, when i return put me at address X"
that's basically the internal state machine of co_await
basically a "resume from"
crash crash crash sahur
the thread is getting readied twice
its so ready
are you hustlin with a positive attitude
going to ahve to resort to something like putting a small circular buffer in the thread structure and insert bytes into it every time it gets readied to indicate different events so that i can inspect that after stuff blows up to figure out whats going on
cuz i cant figure out wtaf is happen
Cant believe there's a race condition in my mintia distribution
Maybe you can add hardware watchpoints in the emulator to make it easier or something, like x86 debug registers
already did that to solve a second bug earlier
if (((address & 0x0FFFFFFF) == 0x75c) && (srcvalue == 1)) {
proc->Cr[EBADADDR] = address;
XrBasicException(proc, XR_EXC_UNA, proc->Pc);
return 0;
}
just threw that in there
a spinlock was getting set to 1 due to memory corruption and that was how i figured out who was doing that lol
i wrote an s0 instead of t0 in an assembly routine
yeah might have figured it out
the circular buffer thing did the trick as a debugging aid
seems to be fireworking much longer now
such a goofy mcguyver way to debug something
this was the issue
at the time i did the second check for NOT next^.KernelStackTop, the thread next may have been enqueued to the stack allocating thread by KepAllocateKernelStack, if none were on the per-node kernel stack cache list
which means that it is now in the custody of another asynchronous context which may be running on another processor
and its incorrect to touch it
as a result it was sometimes happening that:
- cpu0: want to switch to a new thread, select
nextfrom the ready queue - cpu0:
nexthas no kernel stack because it donated it when it blocked w/ a continuation, so callKepAllocateKernelStack - cpu0: it finds that the per-node stack cache list is empty, so it enqueues it to the stack allocation worker thread
- cpu1: the worker thread runs REAL fast and gives the thread a stack and puts it back on the ready queue (which can happen easily because the emulator timeslices vcpus atop a smaller set of host threads)
- cpu0: the second check of
next^.KernelStackTopfinds a kernel stack, so it goes ahead and switches into it, and is now running innexts context while it is simultaneously on the ready queue - cpu0:
nextwas a fireworks particle thread which does its thing and goes back to sleep - cpu0: the timer expires and readies the thread, but it was already in the ready queue, leading to a crash
multiple variations of this could happen with the order of events switched around which could lead to ready queue corruption (which caused the crash in the original screenshot i posted) or other types of crashes
anyway i fixd it
yet anothe rbug that probably would have just killed my project if it happened to 2020 me
i wonder if one reason there arent a lot of hobby kernels with crazy features is that they often lead to proportionally difficult bugs which weeds out a lot of them bc their authors dont have enough bugfixing experience to figure it out so they end up giving up on the feature or on their entire kernel project
its funny i even mention in the comment here "it is now in the custody of a worker thread" and yet i still boldly access a field of it right above there
im stupid...
i think one thing that helps me make robust kernels (mintia1 & hopefully also mintia2) is the resource constraints i put myself under
like it doesnt take much to run up against edge cases caused by limited memory or slow cpu
slow cpu especially reveals a lot of race conditions
ive noticed a lot of ppls hobby kernels like
if they run it up against some really tight constraint or whatever and it crashes in some strange unexpected way
they go like "meh, its out of memory of course itll do something weird!"
and dont look into it
running fireworks test on mintia2 under limited memory w/ no swapping available has taught me a bit about doing effective OOM-resistant code paths lol
i ran into deadlocks that mintia1 would have had as well but would have swapped its way out of
what if it has no pagefile?
that is, what if the only way to get free pages is for them to be freed up by someone releasing a resource (ie a firework particle thread exiting and freeing up its kernel stack etc)
if you deadlocked between freeing those resources and allocating them then theres no way to get out of that situation
if theres swapping then thatll free up pages from underneath it and problem solved
which is why i didnt run into a lot of these deadlocks when testing mintia1
on mintia1 i would always test stuff with a pagefile, and if it locked up without one i would tend to go "oh well it has no pagefile, of course itll do weird stuff" and not investigate
turns out all those lock ups were probably fixable
in mintia1 my rule for memory robustness w/ a pagefile was:
- hold no resources required by the pageout codepath while waiting for free pages
if followed strictly, this is sufficient for avoiding deadlocks while you have a pagefile
it is NOT sufficient if you dont have a pagefile. you can still get deadlocks between explicit freeing and allocation paths, which are normally masked because you swap your way out of them
you need this more general rule, which implies the last one:
- hold no resources required by any freeing path while waiting for free pages
mintia2 follows this more general rule, mintia1 didnt
in fact i think most modern kernels dont follow that rule
because having swapping masks the issues that result without it
you might be able to swap your way out of that deadlock assuming you have swap space available, but you now force those threads to wait for something that could take much longer than someone naturally freeing up resources: disk IO!
new bug
reminds me of a bug i had in my own os
somehow turnstiles donated on the chain/on the free list of another turnstile are getting yoinked by two different threads
a thread could somehow run on two different CPUs if it was unwaited and readied with just the right timing https://github.com/iProgramMC/Boron/commit/392ebdcfdd486dc3b53558012df699c7e886b7b7?diff=split
I wouldn't dare say this is sufficient either
What if you run out of storage space?
commit
Then you really can't allocate memory, and the situation is the exact same as if you didn't have a page file at all
commit what?
limit
the question isnt about materializing memory out of thin air its about not deadlocking when you run out
but don't you also apply a commit limit when there isn't a pagefile present
yes of course but my question was would mintia1 not also have problems if you run out of page file space
just as you say it would if there isn't a pagefile to begin with?
commit limit
it will not behave weirdly when pagefile runs out
it will start to return error statuses in response to memory allocation attempts
wouldn't it do the same without a page file?
youre somewhat confused i think
whats different between the two cases: when all your memory is used up and there isn't a page file, vs when all your memory is used up and the pagefile has grown to its maximum extent possible
you can't allocate more memory in either case
im talking about not deadlocking memory allocation of memory that has been successfully charged against the commit limit earlier
Wouldn't both of these just be mostly the same thing where you either fail allocs or have to OOM-kill
the commit limit shouldn't be higher than the amount of memory you can allocate at all. with a page file or without
i might be confused
Eh. The big modern kernels (e.g. Linux) do allow you to overcommit memory
By default
mintia1 doesn't allow you to overcommit memory afaik
That's why there is an OOM-killer
The issue you tend to get is with applications that assume overcommit is a thing. They'll make a big honking anonymous mmap and assume it's actually demand-allocated.
If you have too many, you run out of RAM early
youre probably tripped up on a mis-abstraction i used in my explanation which was to differentiate "freeing memory by pageout" versus "freeing memory explicitly" when its probably better to say "freeing memory implicitly" versus "freeing memory explicitly"
the first rule prevents deadlocks during the implicit & asynchronous memory freeing process and the second rule prevents deadlocks during all types of explicit memory freeing as well
explicit memory freeing being like calling free() on a block of heap
i see
implicit memory freeing being the underlying page frames of that heap block being swapped to disk
that type of thing
so how do you solve this deadlock situation
.
it turns out there are idiomatic things you can do to hold to this rule
the one where a thread that holds resources cant be woken up because there's no physical memory available and yet you need memory
this is an accident of unix history not an intentional kernel design thing
NT does not do this
as a result it needs no OOM killer
I see
by "resource" i meant like a mutex
right
So the NT applications just don't assume overcommit is a thing then
ideally you wouldnt hold resources while being in a position where you can't be woken up to free them
basically NT has something called a "commit limit" which is the number of page frames available in RAM plus swap space. whenever you allocate memory, it charges pages against the commit usage. when the commit usage is going to exceed the commit limit, it blocks your thread while a worker thread extends the pagefile and raises the commit limit (if possible)
if the pagefile cannot be extended because disk is full or it reached a hard limit, you get an error status return at memory allocation time (basically, from the mmap() call (really the NT analogue thereof))
rather than the kernel suddenly realizing it cant fulfill a request at page fault time
at which point theres nothing good to be done except to start killing people
which would raise a sigbus on linux
it might choose to kill someone other than you
no linux is actually just uniquely lazy here
XNU has dynamic swap space expansion for example
huh
except instead of extending a single pagefile, XNU will create more swapfiles
1GB at a time by default i think
well I'm making a unixlike so I kinda have to overcommit won't I?
which also allows it to delete them when they empty out
i think theres an inbetween where you can like do this
except, if you fail to extend the pagefile in a timely manner, just let it go ahead anyway unless overcommit is really extreme
i think XNU works this way
dont quote me
well either way... have to fix my drivers first
oh
linux could never
that's interesting
this requires very well designed integration between the kernel and window server
which linux utterly lacks
due to decentralization
yeah you would need an emergency stockpile of memory that it uses to pop this up
or it has to be preallocated in its entirety at boot
cant it do some other form of popup on a tty or some other that the kernel controlls?
it needs a deep integration with the wm I believe
tty popups would require less memory so I imagine it could
in a classic linux move, they added some metrics which of all things a systemd component monitors and uses to kill processes before there is an OOM-condition
i think windows has this too in the form of kernel to CSR server (aka CSRSS) communication
... of course
everything systemd eh
(not my picture)
this dialog is popped up from csrss
(which is why it doesnt have a theme)
i think this only pops up when the situation is VERY bad
otherwise it just transparently extends it
and doesnt bother you about it
and IIRC the kernel has a port to which it posts messages like this for csrss
inexplicably this does not even integrate with service management, systemd-oom still just deterministically SIGKILLs people
will be really fun to figure out how donated turnstiles are managing to get taken by multiple different threads
this dialogue box is deceptively simple for how fucking insane the IO subsystem and filesystem driver underpinnings are to allow the "Try Again" option to work transparently
it goes to lengths nobody else goes to, everybody else just fails the IO requests at the point where the media has disappeared
all for the purpose of Windows/DOS user experience compatibility
the message also goes through many hoops to show up like this
kernel sends the "no disk" message -> message port created by kernel -> csrss receives said message and shows it to the user
and when the user chooses something, the reverse happenss
oh yeah this would need to be able to reopen an fd transparently to the application during a read call right (using unix terms here)
that's crazy
i dont think so?
not exactly but yeah theres like 10k+ lines of code specifically for this feature
in NT 3.x
it doesnt close any FDs or anything
and it would keep the file object (equivalent of file description) and fcb (equivalent of vnode) alive
it basically has to take all the pending IO requests and put them in a bucket until the underlying medium comes back
it slides it back under the filesystem mount
and then puts the IO requests back down the top
to retry them
is that why windows can survive a page file drive being surprise hot unplugged and later replugged
i don't think it can
or can it not do that? I heard something about it being able to do that some time ago
i don't believe you can setup a page file on a removable drive
and if a non-removable drive is removed you've got bigger problems anyway
huh I might've misremembered/misinterpreted what I read then
fun fact, due to how the floppy controller worked, there was no physically possible way to implement this free of races with the hardware, and if a user managed to jam it in or yank it out at precisely the wrong few cycle window then you could get corruption or a system crash. they were aware of this and simply tolerated the possibility for the sake of UX compatibility with DOS Windows
I would be very, very surprised it would be able to do this
the Abort/Retry/Fail dialogue was a non-negotiable feature they couldnt talk their way out of doing
it was considered utterly essential for the Windows experience lol
by the higher ups at MS
i think its a cool idea
i guess yanking out floppy disks and putting them back in and expecting everything to work was something windows users had gotten very used to doing
so the NT team were mandated to make it work
(99.9999% of the time)
well sure but if you did it during a write you could corrupt it
the floppy controller is just a bitch to deal with all the time
i remember seeing a video about an NT engineer complaining about its "backwards-ass-ness" (not actual quote)
because it doesn't reliably report unplug/replug/media change despite being a removable medium
Windows does so many interesting things it's a shame their userspace sucks
yeah theres a tape from 1989 where the NT guy in charge of the IO system goes on a like 10 minute tangent about how bad the PC floppy controller is
its really funny because he was coming directly from the VAX world where everything was extremely engineered
then i saw that tape and remembered it now
I tried to implement a floppy driver for mintia386
it's the main reason why I switched to targeting ahci based machines
i'd love to see this
ill find it then
because those are from the era where floppy was basically already irrelevant
im probably being hyperbolic when i say 10 minute
it was more like a minute
maybe two
[Recorded March 21, 1991]
Recording of "Microsoft NT overview : Microsoft confidential"
Catalog Number: 102717748
Lot Number: X2675.2004
i think its this one
yeah
terminology in that video is a little confusing because he sometimes lapses into VMS terminology and calls a thread a process
when he says "process" there he means a kernel worker thread
that was indeed confusing the first time i heard it cause i was like "uhh...? didnt know NT did file system servers"
(it doesnt)
i'm not sure who first established the modern definition of process v.s. thread
it was already well established by NT days, i think here hes just like got VMS dementia a little bit
there's an inclination to say mach but they called a process a 'task'
but by whom and when?
its very likely a multiply independent invention
almost everyone called their unit of execution and address space container a process
when it became useful to have multiple units of execution within an address space
they kept the term process for the container
and called the subunit of execution what everyone else was calling it which was a thread
idk who invented the term thread though
for several unixes it was called a 'lightweight process'
so thats why gdb refers to them as "LWP"s
was this an enjoyable bug btw i went to the effort of writing this up and nobody commented on it :(
i have reasonable confidence mach invented the distinction but they called their process a 'task' for whatever reason. i know the thread was around earlier than that but i think more as a loose thing, "thread of execution" sort of thing
possibly NT is the first to firmly call them process and thread
i feel like the mach papers talk about it like its a thing that was already an academic phenomenon
and theyre more like "we did the first good job of it in a unix kernel"
i also have a very vague memory of seeing the term "multiple threads of execution in a process" being listed as a 'wishlist' feature for VMS in like 1981 in one of those DEC documents i saw on the CHM website
there might have been some precursor research to mach done by other ppl that has been completely overshadowed and we never hear about it
they present it like their own invention in the 1986 paper, but that doesn't preclude it isn't:
It has been clear for some time that the UNIX process abstraction is insufficient to meet the needs of modern applications. The definition of a UNIX process results in high overhead on the part of the operating system. Typical server applications, which use the fork operation to create a server for each client, tend to use far more system resources than are required. In UNIX this includes process slots, file descriptor slots and page tables. To overcome this problem, many application programmers make use of coroutine packages to manage multiple contexts within a single process (see, for example, [2]).
Mach addresses this problem by dividing the process abstraction into two orthogonal abstractions: the task and thread. A task is a collection of system resources. These include a virtual address space and a set of port rights. A thread is the basic unit of computation. It is the specification of an execution state within a task. A task is generally a high overhead object (much like a process), whereas a thread is a relatively low overhead object.
To overcome the previously mentioned problems with the process abstraction, Mach allows multiple threads to exist (execute) within a single task.
im almost certain that it was a concept that was going around before mach
i think it's distinctly possible it was, maybe even probable
like i swear i saw documents from 1979-1982 that mentioned a lack of thread-process distinction in VMS as a regret/criticism of the design
because it was like a new design that could have done that newfangled thing and didnt
but after discovering mach literally invented the TLB shootdown i'm hardly surprised by anything else it might have invented
i think multics didnt need a tlb shootdown because all the cpus shared a tlb which was like its own cabinet lol (actually i think it was integrated into the shared memory controller, which was its own cabinet)
so if one of them issued an invalidate command it would take effect for them all
they didnt call it a tlb i cant remember what they called it
something very 60s and overengineered sounding
the goal of mintia2 is to be the multics of hobby kernels
in terms of being a gargantuan unmaintainable mess filled with insane features
apparently the Associative Memory Unit
each processor contains a small, fast associative memory which remembers the most recently used address translation table entries.
this is possibly a later change or i just misremembered
since its per-processor perhaps there lay a tlb shootdown
which they considered such a trifling implementation detail that they didnt name it
lol
I might be wrong because I'm not very familiar with XNU, but it looks like they have a killer subsystem called CONFIG_JETSAM:
https://github.com/apple-oss-distributions/xnu/blob/f6217f891ac0bb64f3d375211650a4c1ff8ca1ea/bsd/kern/kern_memorystatus_policy.c#L322
and
https://github.com/apple-oss-distributions/xnu/blob/f6217f891ac0bb64f3d375211650a4c1ff8ca1ea/bsd/kern/kern_memorystatus.c#L4917
no idea
"On macOS, the memorystatus_thread will instead perform a "no-paging-space" action, which entails either killing the largest process if it has over half of the compressed pages on the system, or invoking a process's voluntary pcontrol action (one of: kill, suspend, or throttle)."
this suggests that it's not just ios
bigg stack trace
Hello Mr Bigg Stack Trace, How You Doing Mr Bigg Stack Trace
intentional crash while debugging turnstile weirdness
wanted to see if i could get it to crash by setting a particular field to a particular thing at a particular moment
if it does then im close
it did
nice of tonight's trio of bugs to present themselves serially so as not to confuse me
i think it's rather a more advisory/cooperative system
that's not to say it doesn't kill at times but i think it usually gives warnings and in any case there is much negotiation about how and who gets killed
they invented it for iphones where there is no swap
the lack of swap necessitated the invention of kernel modules as memory-mapped files in NT for Windows Mobile lol
so the pages of text can be discarded
rather than written out
i ran into a NT guy in virtuallyfun discord who mentioned that and he said the sheer length of stack traces from crashes that happened while they were developing that was like something out of a nightmare
it's always interesting to think about ways to page more intelligently especially in the absence of a swap file
page faults on kernel code in random high level drivers that became memory-mapped files had much, much deeper stack traces because it doesnt take any of the shortcuts that pagefile reads do
in particular the page faults could nest more levels
because being normal memory mapped files, some of the data needed to read them was itself in paged pool
#lounge-0 message some discussion i had with _64 on the topic of whether paging dynamics could become smarter
why didnt they just enable swap
they could get away with putting just 16mb if they added swap
phones had very bad drives
unless early NT mobile devices didnt pack writable storage
I'm guessing the kind of storage they had in their phones really didn't like writes
in which case swap is a bad idea
a typical device when pocket pc 2000 came out had about 32mb of ram and maybe about the same of rom
until windows mobile 5 (which was quite recent, 2005) the only built-in persistent store you had was the ram itself (so you had to be careful not to discharge your pda/smartphone lest you lose everything)
does that mean you couldnt turn off your phone
or was it like
bios nvram type of thing
there was no ordinary turn-off, it would just sleep, but the battery then would last for several weeks in that state
in case you had to replace the battery a lot of them also had a little backup battery too though
thats cool
i had a windows mobile 6 phone (second hand) in the dying days of that platform
i miss it, it was very robust
now literally no one has heard of windows mobile (nor symbian or palmos, or even blackberry)
no one, anyone who did remember them died
i remember being a kid and using one of those stupid phones with the metal pen thing
the stylus
the big idea of the time was you'd just handwrite onto your phone and it would recognise it
it might have been useful if it worked on doctors
But until Windows Phone 8, mobile "windows" devices were running the Windows CE kernel which is distinct from NT
FOUND MY TURNSTILE BUG
another like 1-2 line silly mistake causing a huge constellation of symptoms
in this function which replaces a thread's turnstile with one from the local node, i was loading the thread's old turnstile oldts before allocating the new one
if the thread blocked on a mutex while allocating the new one, it might donate its turnstile away
and now oldts is a stale pointer
so then i go ahead and free a turnstile that belongs to someone else
lmfao
the solution is to move oldts := thread^.Turnstile to after the MmAllocateFromPoolCache call
the original symptom for this btw was a page fault caused by the turnstile slab cache's free list head pointing to a listhead of one of the turnstile hash table chains for some inexplicable reason
which was circular linked list corruption caused by people thinking that the turnstile was on different lists
downstream of this bug happening
you do slabs now?
pool caches have a backing slab cache which is backed by the heap (this is going to change btw)
pool caches r magazine caches
im going to xnu-ize them
idk what xnu does but you should freebsd-ize them
see starting here for plan
back to 0 known bugs
strong believer in the "do stress tests regularly and fix all found bugs before doing any further feature development" thing for solo kernel projects
@icy bridge didnt u run into only one bug in mintia1 while porting it to 386
and it was me forgetting to return a value on some codepath of reading from the viewcache
dj sacred is good fucking taste
the find.exe command apparently almost got open-sourced
instead, it was rewritten in rust
at least there's deps/ntsort/sort.c
speaking of which, who were the authors of ulib again?
markl maybe?
does anyone remember this piece that was on the NT server website? https://web.archive.org/web/19991013044932/https://www.microsoft.com/ntserver/nts/news/msnw/LinuxMyths.asp
I wonder if any of the amd64 OSes that run the fireworks test could do it as well as mintia2 if their x86 emulator was cranked down to like 20 MIPS
bochs would let you limit the IPS but it has some issues with amd64 so it couldnt use many (even baseline) extentions
they run so fast that the fireworks test isnt that good of a stress test because even with hundreds of particles it still spends 99% of its time idling
with all the particle threads asleep
Idk but mine runs fine with TCG on an arm macbook
first we need to find an x86_64 emulator that limits the IPS
but i can try running my fireworks test on ia-32 in bochs if you want
cough cough bochs supports this
Whoops
Already mentioned

Well it may work for x86-64 atleast
But a hard maybe
i dont think bochs supports x64
It does
Just not very well
It can’t boot Linux
But my kernel somewhat survived 💀
(Before dying in ring3 stuff because SSE iirc)
Its pretty good id say