#MINTIA (not vibecoded)

1 messages · Page 33 of 1

shadow ridge
#

my similar idea was that the assembler should just be a dynamically linked library

twilit smelt
#

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

shadow ridge
twilit smelt
#

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

shadow ridge
#

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

twilit smelt
#

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

shadow ridge
#

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

twilit smelt
#

didnt you wonder how bootstrap.sh built itself after you did a fresh clone of newsdk

shadow ridge
#

i assumed u had a binary blob

#

tho it did cc some shit

twilit smelt
#

nope

shadow ridge
#

did u have C sources

#

that were transpiled

#

with tower

twilit smelt
#

a "prebuilt" set of C files is distributed in a tar.xz lol

shadow ridge
#

I knew it

#

I'm a genius

twilit smelt
#

C files are emitted every time you build the compiler and you can pack them into the tar.xz with packprebuilt.sh

shadow ridge
#

oh so you just always have a transpiler?

twilit smelt
#

to make them part of the bootstrap

#

jackal compiler has a C backend

shadow ridge
#

ah i see

#

ok that makes more sense

#

btw whats the purpose of this fireworks pool cache

twilit smelt
#

to test pool caches

shadow ridge
#

should i do that as well

twilit smelt
#

idk

#

probably because the MmAllocatePool interfaces and whatever are probably going to change soon

#

but the pool cache interfaces wont

shadow ridge
#

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

twilit smelt
twilit smelt
#

its a very small simple language youre not going to be lost for too long

shadow ridge
#

how do i make arrays

#

you have arrays right

twilit smelt
#

array of what

shadow ridge
#

of uword

twilit smelt
#

do u want to initialize it

shadow ridge
#

to all 0s

twilit smelt
#

then just do this

#
MyArray : UWORD[size]
shadow ridge
#

i dont need to explicitly 0 that right

twilit smelt
#

no

shadow ridge
#

thx

twilit smelt
#

whats the array for

shadow ridge
#

bitfield

#

of a grid

twilit smelt
#

for what

shadow ridge
#

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

twilit smelt
#

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

shadow ridge
#

wait

#

ULONG is 32 bit?

twilit smelt
#

yes

shadow ridge
#

oh

#

i thought uword was word sized

#

my bad

twilit smelt
#

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

shadow ridge
#

i see, that makes a lot of sense

#

ill use ulong then

twilit smelt
#

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

twilit smelt
#

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

#

!

shadow ridge
#

just making sure

#

cuz it doesnt have atomic in the name

twilit smelt
#

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

twilit smelt
#

excollonco is mandatory

shadow ridge
#

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

warm pine
shadow ridge
#

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

shadow ridge
#

uuuh

#

theres no xor operator

#

well, there probably is

#

but ^ is just pointer deref

#

ok i think it might be $

teal trench
shadow ridge
#

ok video compression really fucks this one up

#

@twilit smelt

mortal thunder
# shadow ridge

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

shadow ridge
#

also threads arent per pixel

#

theyre per cell which is like 4x4 here i think

mortal thunder
shadow ridge
#

but it's cool

twilit smelt
twilit smelt
#

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

shadow ridge
twilit smelt
shadow ridge
#

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

twilit smelt
#

yes

shadow ridge
#

nice

twilit smelt
#

spawning 1 thread per pixel is way too many though

shadow ridge
#

it's not 1 thread per pixel

twilit smelt
#

what is it

shadow ridge
#

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

twilit smelt
#

already fixed

shadow ridge
#

what does the [ ] do

twilit smelt
#

its like a quote

shadow ridge
#

huh

twilit smelt
#

its cool that the time used scales almost perfectly with the number of processors

shadow ridge
#

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

twilit smelt
#

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

twilit smelt
shadow ridge
#

so was this of any help

shadow ridge
twilit smelt
#

there are no deadlock bugs in mintia scheduler anyway

twilit smelt
#

but keep in mind it took me like 4 months to do that with the original fireworks test

#

so

shadow ridge
#

lol

warm mural
twilit smelt
warm mural
#

wont tell

twilit smelt
#

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

twilit smelt
#

mintia2 continuations theme song

carmine grove
twilit smelt
#

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

carmine grove
twilit smelt
#

stanced up

twilit smelt
#

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"

twilit smelt
#

the beginning of the end

#

"it would 'only' take me a few months" -3 years ago, still not even half done

icy bridge
#

well it's not really a 1:1 rewrite

#

far from it actually

#

so I think that estimate can be disregarded safely

twilit smelt
#

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

nocturne nymph
#

This is what is called TP_WAIT in Windows.

twilit smelt
#

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

twilit smelt
nocturne nymph
#

It scrolled all the way down...

twilit ingot
#

lol, happens

nocturne nymph
#

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)

twilit smelt
#

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

nocturne nymph
#

So you're going to adapt your public wait routines to work with this paradigm

twilit smelt
#

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

digital pivot
#

if you already had paged stacks implemented

twilit smelt
#

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."

digital pivot
#

because they care a lot about compat

twilit smelt
#

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

digital pivot
#

because you cant break driver apis

twilit smelt
#

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

digital pivot
#

drivers devs were more active back then i believe nowadays many companies kinda forget to update their drivers

twilit smelt
digital pivot
#

and you may deal with very old driver which sould run on newer versions

twilit smelt
#

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

nocturne nymph
twilit smelt
warm mural
#

iokit is better in terms of writing drivers/how drivers are structured but NT IO makes more sense imo

twilit smelt
#

i was going to fuse the best parts of both

warm mural
#

Like can you even compare them? It seems iokit is more of a driver framework or something

twilit smelt
#

iokit structuring for like driver design and classes and matching and whatnot, but with NT-style IO packet dispatch

warm mural
#

yeah that makes sense

twilit smelt
#

iokit is xnu's low level io system for drivers

warm mural
#

afaik iokit uses event loops or something to dispatch IO I don't remember

twilit smelt
#

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

digital pivot
#

does xnu have async io wait capabilities like nts iocp

twilit smelt
#

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

digital pivot
#

windows completion ports

shadow ridge
blissful smelt
#

easy listening muzak

shadow ridge
#

also i really hate these names

#

like it's just random jargon

#

very uninspired

#

not that the music is bad

blissful smelt
shadow ridge
#

LOL

twilit smelt
#

organically

#

before

blissful smelt
balmy zealot
#

What is Ki?

blissful smelt
#

the song or the kernel component?

balmy zealot
#

What sort of component is Ki?

shadow ridge
#

maybe kernel internal stuff

#

idk

blissful smelt
#

indeed

balmy zealot
shadow ridge
#

i think it's equally plausible that it's something else tho

twilit smelt
#

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

warm pine
#

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

twilit smelt
#

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)

shadow ridge
#

once i got called the p word because i was choking and my face turned purplish

blissful smelt
digital pivot
warm mural
warm mural
#

Instead of each driver going down the stack themselves, you do it in a topmost loop

icy bridge
#

ah okay

#

that just seems like the natural thing to do, to avoid stack overflows if nothing else

warm mural
#

Yeah that's why it's a design flaw

twilit smelt
#

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

twilit smelt
#

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

twilit smelt
#

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

coarse current
twilit smelt
#

you have inspired me

coarse current
#

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?

twilit smelt
#

i didnt do exactly what they did

#

but ill link it

coarse current
#

I'm in a mood for editing osdev wiki lately trl

twilit smelt
#

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

twilit smelt
#

u dont even do this

#

u set sp to YOUR OWN kernel stack top, which now belongs to the other guy

twilit smelt
#

fox32 arch code is bit rotting a bit during all this

shadow ridge
#

foxi386

twilit smelt
#

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

twilit smelt
#

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

coarse current
twilit smelt
#

continuations were not planned until like a week ago

coarse current
#

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...

twilit smelt
#

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

twilit smelt
#

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

twilit smelt
#

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

twilit smelt
#

it did not

#

mintia2 continuations appears to be a fairly stable impl of them

twilit smelt
#

mintia2 continautions theme song but for real

#

this is my on loop forever song for working on that

shadow ridge
golden meteor
# twilit smelt this is my on loop forever song for working on that
#

‼️

twilit smelt
#

ik

twilit smelt
shadow ridge
twilit smelt
#

that is my video i just took

twilit smelt
#

vibey things happen to me in real life because im not a larper. im just that vibe.y

short owl
shadow ridge
#

yeah thats a bold claim coming from john larp

twilit smelt
#

i believe we're experiencing a definitional disconnect on the word larp as used here.

#

today i must finish the fox32 support for continuations

carmine grove
twilit smelt
#

i was referring to the ai crypto grifter type of larper

queen torrent
#

All larpers larp but some larp more than others

twilit smelt
#

evil larp (self-serving, deceptive, soulless) vs good larp (whimsical, interesting)

shadow ridge
#

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

twilit smelt
#

counterpoint no im not

shadow ridge
#

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

dense vigil
shadow ridge
#

never heard of the concept before

#

doesnt stackless basically mean stateless

#

where do they save the data

dense vigil
#

instead of blocking the current thread, u get a continuation callback

#

once e.g. a page fault is satisfied

shadow ridge
#
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

twilit smelt
#

across the wait

shadow ridge
#

and save what

#

like 8 kib?

twilit smelt
#

almost all threads are spending almost all of their time in waits that are good candidates for being made into continuations

shadow ridge
#

you still have the overhead of deleting and constructing a new stack

twilit smelt
#

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

twilit smelt
#

and it will still be there when you come back hopefully

twilit smelt
dense vigil
twilit smelt
#

i dont see whats wrong with his example

dense vigil
#

or i guess he didnt but that pritnf at the end is dead code no?

shadow ridge
#

yes, so it would print yahoo and wohoo but not whoppie

twilit smelt
#

thats just to demonstrate that it doesnt return control there

dense vigil
#

ah ok

twilit smelt
#

did you completely miss the part where he put the expected output lol

dense vigil
#

yeah i misread it

shadow ridge
#

isnt this basically like DPCs

twilit smelt
#

its nothing like dpcs

#

aside from "thing runs later"

dense vigil
#

yeah lol

shadow ridge
#

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

dense vigil
#

DPCs also run at DPC irql

#

so they cant be preempted etc

warm mural
teal trench
warm mural
teal trench
#

meme based

mortal thunder
#

what's the cost of allocating/reserving a kernel stack if you do the latter?

shadow ridge
#

you dont give it a stack

#

you just handoff your current stack

#

to it

mortal thunder
warm mural
twilit smelt
#

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

twilit smelt
#

continuations are merged now

#

fox32 port proves its utility by revealing some bugs that were not as easily revealed by xr17032 based testing

twilit smelt
#

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

shadow ridge
#

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

brittle locust
#

libclang my beloved ❤️

#

the amount of cursed things I have been able to cook because of it

twilit smelt
# dense vigil 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

dense vigil
#

interesting

twilit smelt
#

would you guys consider the design of mintia2 to be "exotic"

shadow ridge
#

no

mortal thunder
#

yes

quiet mauve
#

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.

twilit smelt
#

i think that would be interesting, see fireworks test for an example of how that works now

mortal thunder
#

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

twilit smelt
#

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

mortal thunder
#

IOKit is implemented on top of the fundamentally blocking BSD file system code?

twilit smelt
#

iokit is beneath the bsd file system code

#

its used to implement the storage stack and whatnot

#

it is fundamentally async

mortal thunder
#

I see

twilit smelt
#

the filesystems are implemented in a fundamentally synchronous manner by making iokit requests (indirectly through the cache)

mortal thunder
#

But the fundamental async-ness isn't used?

twilit smelt
#

it is used

#

just not by file IO

mortal thunder
#

I see

twilit smelt
#

filesystem drivers arent iokit drivers in xnu

#

they dont have that unity that NT has

shadow ridge
#

i dont really want to improve that test rn

#

i want to rewrite it when you have a proper testing framework

twilit smelt
#

its broken right now bc i changed the thread interfaces

shadow ridge
#

cuz i basically frankeinsteined it

#

aw

twilit smelt
#

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

shadow ridge
#

i see

twilit smelt
#

the wait functions also now all have a continuation parameter

#

which needs to be NULLPTR if youre not waiting with a continuation

night needle
#

what sets it apart is obviously programming language and the isa

night needle
#

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

tame phoenix
#

basically awaiting a continuation?

warm mural
#

no

shadow ridge
#

1 min

#

#1322494605819908156 message

tame phoenix
#

oh so just callbacks

#

like dpcs

warm mural
#

no

#

why do people keep confusing them with DPCs 😭

#

it's basically a function the thread continues running on when its woken up

delicate dome
#

So it's a jump to a funcptr

#

Except you have blank stack instead of current one

warm mural
#

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

shadow ridge
#

they are just similar

#

even if you claim they are not

warm mural
#

they arent?

coarse current
#

they're not at all

warm mural
#

how are they similar

#

the only similarity is that it's a function lol

shadow ridge
#

both involve a mechanism where you offload work to a callback

warm mural
#

this is not work offloading though

shadow ridge
#

you are offloading the rest of your work to the next time you get scheduled

short owl
#

Or trying to do that will just crash lol

warm mural
#

well it can return to e.g userspace code

warm mural
short owl
#

Ah

warm mural
#

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"

tame phoenix
#

basically a "resume from"

twilit smelt
#

great......

#

found while running fireworks with low cpu speed to expose races

blissful smelt
#

crash crash crash sahur

twilit smelt
#

the thread is getting readied twice

queen torrent
#

its so ready

twilit smelt
twilit smelt
# twilit smelt the thread is getting readied twice

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

dense vigil
# twilit smelt

Cant believe there's a race condition in my mintia distribution

dense vigil
twilit smelt
#

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

twilit smelt
#

aha

#

theres the problem

twilit smelt
#

yeah might have figured it out

#

the circular buffer thing did the trick as a debugging aid

twilit smelt
#

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 next from the ready queue
  • cpu0: next has no kernel stack because it donated it when it blocked w/ a continuation, so call KepAllocateKernelStack
  • 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^.KernelStackTop finds a kernel stack, so it goes ahead and switches into it, and is now running in nexts context while it is simultaneously on the ready queue
  • cpu0: next was 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

twilit smelt
# twilit smelt

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

shadow ridge
#

real kernels panic when malloc fails

#

you're just eccentric

twilit smelt
#

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!

twilit smelt
#

new bug

mortal thunder
twilit smelt
#

somehow turnstiles donated on the chain/on the free list of another turnstile are getting yoinked by two different threads

mortal thunder
mortal thunder
#

What if you run out of storage space?

twilit smelt
mortal thunder
#

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

mortal thunder
twilit smelt
#

the question isnt about materializing memory out of thin air its about not deadlocking when you run out

mortal thunder
#

but don't you also apply a commit limit when there isn't a pagefile present

mortal thunder
#

just as you say it would if there isn't a pagefile to begin with?

twilit smelt
#

commit limit

mortal thunder
#

.

#

again. isn't there a commit limit when you don't have a page file too?

twilit smelt
#

it will not behave weirdly when pagefile runs out

#

it will start to return error statuses in response to memory allocation attempts

mortal thunder
#

wouldn't it do the same without a page file?

twilit smelt
#

youre somewhat confused i think

mortal thunder
#

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

twilit smelt
#

im talking about not deadlocking memory allocation of memory that has been successfully charged against the commit limit earlier

delicate dome
mortal thunder
#

i might be confused

delicate dome
#

By default

mortal thunder
#

mintia1 doesn't allow you to overcommit memory afaik

delicate dome
#

That's why there is an OOM-killer

delicate dome
#

If you have too many, you run out of RAM early

twilit smelt
#

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

mortal thunder
#

i see

twilit smelt
#

implicit memory freeing being the underlying page frames of that heap block being swapped to disk

#

that type of thing

mortal thunder
twilit smelt
#

it turns out there are idiomatic things you can do to hold to this rule

mortal thunder
#

the one where a thread that holds resources cant be woken up because there's no physical memory available and yet you need memory

twilit smelt
#

NT does not do this

#

as a result it needs no OOM killer

delicate dome
#

I see

twilit smelt
mortal thunder
#

right

delicate dome
#

So the NT applications just don't assume overcommit is a thing then

mortal thunder
#

ideally you wouldnt hold resources while being in a position where you can't be woken up to free them

twilit smelt
# delicate dome I see

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)

delicate dome
#

oh interestibg

#

unixes don't tend to do dynamic pagefile size

twilit smelt
#

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

delicate dome
twilit smelt
#

it might choose to kill someone other than you

twilit smelt
#

XNU has dynamic swap space expansion for example

delicate dome
#

huh

twilit smelt
#

except instead of extending a single pagefile, XNU will create more swapfiles

#

1GB at a time by default i think

delicate dome
#

well I'm making a unixlike so I kinda have to overcommit won't I?

twilit smelt
#

which also allows it to delete them when they empty out

twilit smelt
#

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

delicate dome
#

well either way... have to fix my drivers first

twilit smelt
#

XNU also does not have an OOM killer

#

do you know what it does instead

delicate dome
#

the alloc

twilit smelt
#

pops this up

#

the user is the oom killer

delicate dome
#

oh

twilit smelt
#

linux could never

delicate dome
#

that's interesting

twilit smelt
#

this requires very well designed integration between the kernel and window server

#

which linux utterly lacks

#

due to decentralization

delicate dome
#

or it has to be preallocated in its entirety at boot

vast valve
mortal thunder
#

it needs a deep integration with the wm I believe

delicate dome
#

tty popups would require less memory so I imagine it could

warm pine
#

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

mortal thunder
#

i think windows has this too in the form of kernel to CSR server (aka CSRSS) communication

delicate dome
#

everything systemd eh

mortal thunder
#

(not my picture)

#

this dialog is popped up from csrss

#

(which is why it doesnt have a theme)

twilit smelt
#

i think this only pops up when the situation is VERY bad

#

otherwise it just transparently extends it

#

and doesnt bother you about it

mortal thunder
#

and IIRC the kernel has a port to which it posts messages like this for csrss

warm pine
#

inexplicably this does not even integrate with service management, systemd-oom still just deterministically SIGKILLs people

twilit smelt
#

will be really fun to figure out how donated turnstiles are managing to get taken by multiple different threads

mortal thunder
#

or like this

#

same culprit

#

(the kernel asking csrss to show a dialog)

twilit smelt
# mortal thunder or like this

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

mortal thunder
#

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

icy bridge
#

that's crazy

twilit smelt
#

not exactly but yeah theres like 10k+ lines of code specifically for this feature

#

in NT 3.x

mortal thunder
#

it doesnt close any FDs or anything

#

and it would keep the file object (equivalent of file description) and fcb (equivalent of vnode) alive

twilit smelt
#

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

icy bridge
#

is that why windows can survive a page file drive being surprise hot unplugged and later replugged

icy bridge
#

or can it not do that? I heard something about it being able to do that some time ago

mortal thunder
#

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

icy bridge
#

huh I might've misremembered/misinterpreted what I read then

twilit smelt
# twilit smelt it slides it back under the filesystem mount

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

delicate dome
twilit smelt
#

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

mortal thunder
#

i think its a cool idea

twilit smelt
#

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)

delicate dome
#

well sure but if you did it during a write you could corrupt it

icy bridge
mortal thunder
#

i remember seeing a video about an NT engineer complaining about its "backwards-ass-ness" (not actual quote)

icy bridge
#

because it doesn't reliably report unplug/replug/media change despite being a removable medium

delicate dome
#

Windows does so many interesting things it's a shame their userspace sucks

twilit smelt
#

its really funny because he was coming directly from the VAX world where everything was extremely engineered

mortal thunder
#

then i saw that tape and remembered it now

icy bridge
#

I tried to implement a floppy driver for mintia386

#

it's the main reason why I switched to targeting ahci based machines

twilit smelt
#

ill find it then

icy bridge
#

because those are from the era where floppy was basically already irrelevant

twilit smelt
#

im probably being hyperbolic when i say 10 minute

#

it was more like a minute

#

maybe two

mortal thunder
#

i think its this one

twilit smelt
#

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

mortal thunder
#

that was indeed confusing the first time i heard it cause i was like "uhh...? didnt know NT did file system servers"

#

(it doesnt)

warm pine
#

i'm not sure who first established the modern definition of process v.s. thread

twilit smelt
#

it was already well established by NT days, i think here hes just like got VMS dementia a little bit

warm pine
#

there's an inclination to say mach but they called a process a 'task'

twilit smelt
#

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

warm pine
twilit smelt
#

NT probably got the thread terminology through mach

#

and process through VMS

mortal thunder
twilit smelt
warm pine
#

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

twilit smelt
#

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

twilit smelt
warm pine
#

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.

twilit smelt
#

im almost certain that it was a concept that was going around before mach

warm pine
#

i think it's distinctly possible it was, maybe even probable

twilit smelt
#

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

warm pine
#

but after discovering mach literally invented the TLB shootdown i'm hardly surprised by anything else it might have invented

twilit smelt
#

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

warm pine
twilit smelt
#

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

twilit smelt
#

isnt that only used on ios

#

and/or for killing daemons

hollow musk
#

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

twilit smelt
#

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

warm pine
#

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

twilit smelt
#

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

warm pine
#

it's always interesting to think about ways to page more intelligently especially in the absence of a swap file

twilit smelt
#

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

warm pine
#

#lounge-0 message some discussion i had with _64 on the topic of whether paging dynamics could become smarter

mortal thunder
#

they could get away with putting just 16mb if they added swap

digital pivot
#

phones had very bad drives

mortal thunder
#

unless early NT mobile devices didnt pack writable storage

icy bridge
#

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

warm pine
#

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)

shadow ridge
#

does that mean you couldnt turn off your phone

#

or was it like

#

bios nvram type of thing

warm pine
#

in case you had to replace the battery a lot of them also had a little backup battery too though

shadow ridge
#

thats cool

warm pine
#

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

shadow ridge
#

i remember being a kid and using one of those stupid phones with the metal pen thing

warm pine
#

the big idea of the time was you'd just handwrite onto your phone and it would recognise it

shadow ridge
mortal thunder
twilit smelt
#

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

twilit smelt
#

pool caches r magazine caches

warm mural
#

huh cool

#

didnt know you went all in on solaris slabs

twilit smelt
#

im going to xnu-ize them

warm mural
#

idk what xnu does but you should freebsd-ize them

twilit smelt
#

see starting here for plan

twilit smelt
#

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

sharp igloo
cursive charm
#

the find.exe command apparently almost got open-sourced

#

instead, it was rewritten in rust

#

speaking of which, who were the authors of ulib again?

#

markl maybe?

cursive charm
twilit smelt
#

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

vast valve
twilit smelt
#

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

warm mural
mortal thunder
#

but i can try running my fireworks test on ia-32 in bochs if you want

vast valve
#

Whoops

#

Already mentioned

#

Well it may work for x86-64 atleast

#

But a hard maybe

mortal thunder
#

i dont think bochs supports x64

vast valve
#

It does

#

Just not very well

#

It can’t boot Linux

#

But my kernel somewhat survived 💀

#

(Before dying in ring3 stuff because SSE iirc)

dense vigil