#MINTIA (not vibecoded)
1 messages · Page 21 of 1
it helps that i386 doesn't differ that much from xr17032 in the large platform-dependent areas like page table handling so i got to copy most of the code without needing to change more than a few constants
ppc port would be nightmarish in comparison lol
like most of MiPTELinear.df is just xr17032's version with 5 replaced by 12 (the offset of the PFN bitfield in PTEs)
interrupt handling was the biggest difference between the arches but that's alleviated by not being particularly complicated on either of them
nvm just ignore what i said
i fixed this in the original repo too btw
risc-v port wen
with riscv you have to manually create the linear mapping instead of being able to use a recursive entry
which is annoying and might make a port impossible if mintia relies on the atomicity of page table insertion
pretty sure mintia does rely on being able to create a recursive entry
it definitely relies on a linear page table mapping but that's not the same as relying on a recursive entry
how can you achieve a linear pt mapping without a recursive entry
theoretically you could maintain the linear mapping manually without a recursive entry, but that's only possible if mintia doesn't rely on page table insertion being atomic
whenever you add a PDE you also add a PTE within the table at the entry that would normally be recursive
and whenever you remove a PDE you also remove the associated PTE
i see
my OS doesnt really rely on that (because i use a lock on the address space)
maybe mintia doesn't either since it basically stops the entire world (by raising IPL) while modifying memory mappings (to my understanding)
but dont quote me on that
damn yeah crazy
Atomic access on page tables is cool because then I can do stuff like have mmap not stop the entire process (merely other mmap calls)
page faults should be serialized against mmap calls as well imo
otherwise you'll be seeing half-mapped data and you'll encounter undefined/unpredictable behavior galore
Solution: Walk the page table on fault to check, and if it should have worked, flush TLB
and besides the user process has no way to predict where mmap stuff will end up unless they use MAP_FIXED or spray the heap with a bunch of garbage to restrict the possible address spaces
What does this matter?
dg/ux appeared to have locking on a per-pte granularity
"how! you cant fit a blocking lock in a pte!" you can if youre clever like them
inserting a spinlock into a pte is one thing but a blocking lock!?
Yeah but POSIX mmap semantics are def easier to make if you have a single write lock
(In my model reads can occur concurrently with writes due to aforementioned atomic updates)
i don't do eager PTE modification (yet). almost all PTE modification is performed within the page fault handler
and the only eager PTE modification I'll add is for clustered readahead faulting
they cheated it slightly but yes
does mintia 1 require atomic modification of PTEs?
it doesnt rely on this because the kernel space page tables are established at boot time and arent changed
but what about userspace page tables
true but i still dont thin kit relies on that
me neither
i mean webkit-style locks fit in two bits, right? and they are blocking too
so you could do something like that/something with turnstiles to make a really tiny lock
This was 1989 so pre turnstiles
And they only used a single bit in the PTE
almost every time i look in this thread someone is talking about turnstiles 😭
why do either of them call them demons
i never understood this aspect
its like they want to attract dumb american everything-believers into conspiracy theories
its in an archaic sense of the word demon which just meant some unseen force in the background or something
in the sense of maxwell's demon rather than a christian demon
i see
just like osf/1
@icy bridge i know youve moved past this but i found a weird bug lol
is this on i386 or xr17032
probably not passing args correctly or something
its very strange because other commands are taking arguments correctly
found it: if strncpy ran out of space, it'd write the null terminator to src instead of dest. for relative paths with only one component, OSDirectoryName calls strncpy with max=0, so the output buffer wouldn't get null terminated
here's the updated image
thank you much
i noticed this just after sending it to andrew_w for his os museum
ill send the new one
how did u find the bug so fast
first I added some printfs in rm's main to dump argc and argv. when they looked correct I added some more printfs all over the command to see where the weird string came from, which revealed that the weird string was the output buffer of osdirectoryname. I repeated the same process for that function, and found strncpy was misbehaving. that's a fairly short function in handwritten ASM, so I just looked at the code for a minute and caught the error
damn
would've probably only taken like 2 minutes if I could use gdb
btw are you planning to go back to linux and fix the random segfaults?
I want to do it at some point but am currently not very interested in doing so
what is your current project?
factorio
I suspect that this is still a non-standards-compliant strncpy. IIRC:
- strncpy(dst, src, N) writes up to N bytes, incl. null bytes.
- strncpy copies up to N characters and fills the rest of the buffer with (possibly zero) null terminators.
For example, strncpy("abcde\0", 4) would give "abcd" with no null terminator and strncpy("abcde\0", 8) would give "abcde\0\0\0".
It's not meant to be C standards compliant it's a dragonfruit strncpy
Which is confusingly named the same while behaving differently (more sanely imo)
Jackal's is not called strncpy thankfully
oh I totally missed that, lmao.
yeah, the C standard library is very unsane.
I'm a simple man; I see strncpy, I assume C or C++.
Have you looked at beej's guide 🥺
i completely agree and the way i usually get around this insaneness is by adding a null terminator at the end of the buffer directly
like strncpy(buffer, source, sizeof buffer); buffer[sizeof buffer - 1] = 0;
strncpy feels slightly more sane if you have fixed length non-null terminated char arrays in structs or things tho
perhaps might've been more of what it was designed for
Yeah, maybe
I literally just made my own functions that are actually sane and just used those.
Though the way I went about that left something to be desired sometimes, it worked a lot better than official strncpy for sure.
DG/UX did the thing im planning on doing
where
page cache for file data and buffer cache for metadata
thing to remember
devices can be localized to numa nodes as well
ALSO
@icy bridge do you want to put mintia386 on r/osdev or can i do it
and can i use one of your pics of it running on real hardware
you can do it and yes
Yeah pci express root ports have numa locality and it really matter for latency
a menacing configuration i just read about is having per-node disk controllers which all control a common set of physical disks
wel its not that menacing i guess youd just represent them as all being logically 1 controller on the software end and then youd just direct each request to whatever the node-local physical controller is for the node the current thread is on
Never seen anything like that, but sounds bad
This is how the CLARiiON disk subsystem worked
Or could be configured to work
I will some time today
Do you have a reddit account that you want me to tag
i do not
Link the post once u do it
Sometimes I think I’m good at OSdev then I see what mintia can do then I realize I’m not

what can it do
isnt it just a black screen with some fireworks
If you know what goes into making those fireworks, it's pretty damn impressive.
Isn't this just impostor syndrome?
I dont think thats what impostor syndrome really is
well it is but not the comparison to others part
doubt it. the author of mintia is probably a total moron!
it's more of a "comparison is the thief of joy" thing
Yup. It doesn't make sense to compare one's own project with that of someone else, because you don't know how the time you put into it relates to that that they put into it.
whats a cool title i could use for this reddit post for mintia386
one day my kernel will do something other than show fireworks too 😔
"My OS written in a custom language for my custom architecture running on real hardware" or something
maybe ported to real hardware would make more sense
im thinking "I wrote an OS in a custom language for a custom RISC architecture, and my friend ported it to x86 on real hardware!"
"real mode os running on real hardware" to get the upvotes on r/osdev
doesn't matter it's not real mode
or "I wrote a multitasking OS in my custom language for my RISC architecture, and my friend ported it to x86 on real hardware!"
skibidi os running on 32 bit!!!
I think this is good
not sure why multitasking is specified though
trust me tho im surprisingly good at making garbage projects go viral 
makes it sound more impressive
maybe "with swap" sounds more impressive? idk
or
"with advanced features like ..."
idk
Oh god with swap is like foreign to r/osdev
i think "multitasking" is best
"paged virtual memory"
yeah for r/osdev "multitasking" is best
they wont understand "paged"
ive tried this in the title of other posts about mintia and they consistently did poorly
like <70 upvotes
"with downloadable free RAM"
the sub has grown considerably since then tho
Gondamn they're REAL stupid in r/OSDev huh?
aisix had the #2 top of all time post on r/osdev in like 2020
but i ended up deleting that post
it had like 250 upvotes
I mean they're basically just normies atp
My minecraft in astral post got less than "C running in my 16 bit operating system" where the only thing written on the screen is "in skibido we trust"
I hate the term "normies"
officer down is still in the top 10 🥀
it's so much redditspeak
If they don't even know what paging is
Its cr3 duh
i think we should be legally allowed to attack 5 r/osdev users with hammers per year
as like a purge day
these guys are normies, theyre not englightened like us redditors!!
its funny you say that because its absolutely a 4chan term
If its on the internet assume it came from 4chan
everybody who uses it knows this but its basically normalized
even normies say normie now
I don't use it basically at all but like how else do I describe it? A collection of noobs?
skibidi rizzos running on 38667
in common internet usage like lily just used it basically just means "neurotypical" and/or "mediocre"
im not blaming you in particular I just think it's a stupid term that's condescending
its just a funnier way to say that
806786
neurotypical isnt really accurate
it kinda is
idk i think we have a lot of competent neurotypical people here
do you have tism
Neurotypical doesn't do anything to describe the level of knowledge they have
competent osdevers who are neurotypical would not be in this discord theyre a postgrad at CMU and dont know what discord is
Now saying noob does describe the level of knowledge
does neurotypical encompass adhd
No
if not then most people are probably neuroatypical
ADHD is very much considered neurodivergent
I dont think people like korona have tism tho
idk i literally have no idea but from watching managarm talks and stuff it doesnt seem obvious
idk i wouldnt consider myself that competent but I dont have tism and ive been doing ok
Truth is you can hardly be 100% sure about someone's neurodivergence without just asking them
yeah that is true
Korona was probably pulled into discord by nd ppl 
Im not claiming I know anyone's mental state either
Do neurotypical people really not use Discord that much?
id consider myself fairly neurotypical and I use it
although maybe im not that neurotypical idk
I didn't think that would have much if any effect on whether someone uses it
do people with a high degree of autism have trouble socializing online as well
i wonder
100%
At least in my own experience
Having a common interest that I'm sufficiently autistic about is nearly a requirement
Karma farming let's go
averaging more than 1 upvote per minute so far
cant wait for that to immediately plateau to 1 upvote per 6 hours now that i said that
okay this guy will mog me
posted directly after me and has way more buzzwords
hes getting to 500 and im getting to 60
calling it now
Alpha karma farmer vs beta osdev
for now yours has more upvotes
Worse: it's like ifunny/4chanspeak
They do
I mean sure, but the internals are insane. You’re one of the most read up individuals in this server fs, that’s what I mean
I’ve got it too 😔
ok mine took off pretty well
the other guy got like 6
now i feel bad for wishing him poorly
wish i could share upvotes
Stop being so selfless... this is a cruel world, he wouldn't have done it for you

Man I gotta make a post
Some person said you should make a yt video
They're not wrong
idk why i expected a higher level of comprehension from reddit users, but somehow i am baffled someone asked "what's your programming language called"
hey im curious what you think of 32-bit arm's page table format, where the root page table is a 16kb "page" with 4096 PTEs which each map 1MB, and each sub-page-table is exactly 1KB with 256 entries
and there are two bits for "presence" status instead of one
i have no opinion
sounds like brain damage
i see
im too tired from following this venezuela shit way past my bedtime to even parse what you just said
i agree
when i was doing my port to 32-bit arm i had to modify my PMM to allocate 16kb regions, and also i just used 4 entries of the root page table at a time to get 4kb sized 2nd level page tables
@icy bridge hey do you know why this happens when i try to compile mintia386?
rm i386/LdrI386MapAsm.i386.fre.o.elf.o
gcc -m32 -march=i486 -mgeneral-regs-only -nostdinc -c -o PC/i386/LdrPCHeader.i386.fre.o.elf.o PC/i386/LdrPCHeader.S
PC/i386/LdrPCHeader.S: Assembler messages:
PC/i386/LdrPCHeader.S:91: Error: no such architecture: `default'
PC/i386/LdrPCHeader.S:98: Error: `movzx' is not supported on `i8086'
PC/i386/LdrPCHeader.S:99: Error: bad register name `%eax'
PC/i386/LdrPCHeader.S:100: Error: bad register name `%eax'
PC/i386/LdrPCHeader.S:104: Error: 32bit mode not supported on `i8086'.
PC/i386/LdrPCHeader.S:106: Warning: use .code16 to ensure correct addressing mode
.....
changing the line from .arch default to .arch i486 seems to fix it
then it doesnt recognize -std=gnu23
but thats probably just an outdated gcc moment
what archaic gcc version are u rocking damn
gcc 11.4.0
lol why so old
blame the package manager's maintainers lmao
ubuntu?
yeah
funnily enough the cross compiler i built for my OS is newer
i'd hope so
its literally gcc 13.1.0
but anyway i should be able to just install gcc13 and compile it now
fwiw you can probably drop the C standard to gnu11 or something
if you really want to keep using that old toolchain
github search through the repo shows it doesn't use embed, so unless monkuous used some funny new C feature it should just work
ah it uses auto
but you can just -Dauto=__auto_type 
anyway i wonder why the loader specifically checks for a 486
does mintia depend on alignment enforcement?
i would think it depends on write protecting kernel pages
but not necessarily alignment checking
gcc-13: error: unrecognized command-line option ‘-std=gnu23’; did you mean ‘-std=gnu2x’?
what the fuck
DriverAHCI.c: In function ‘InitializePort’:
DriverAHCI.c:453:22: warning: implicit declaration of function ‘__builtin_ctzg’; did you mean ‘__builtin_ctz’? [-Wimplicit-function-declaration]
453 | port->blockLog = __builtin_ctzg(blockSize);
| ^~~~~~~~~~~~~~
| __builtin_ctz
java -jar /mnt/c/Work/x/mintia386/dfrttrans/build/libs/dfrttrans-0.0-elfconvert.jar DriverAHCI.i386.fre.o.elf.o DriverAHCI.i386.fre.o
rm DriverAHCI.i386.fre.o.elf.o
/mnt/c/Work/x/mintia386/mintia/../sdk/link.sh link -nostubs /mnt/c/Work/x/mintia386/mintia/Root/mintia/BootDrivers/AHCI.sys.i386.fre ./DriverAHCI.i386.fre.o -d HAL.dll:/mnt/c/Work/x/mintia386/mintia/Root/mintia/HALPC.dll.i386.fre Dragonfruit.dll:/mnt/c/Work/x/mintia386/mintia/Root/mintia/Dragonfruit.dll.i386.fre OSKernel.exe:/mnt/c/Work/x/mintia386/mintia/Root/mintia/OSKernel.exe.i386.fre
xoftool: error: unresolved symbols:
./DriverAHCI.i386.fre.o: __builtin_ctzg
hm, might be a gcc 14 thing
i guess i could compile gcc from source?!
i'd just make it work with C11
so far the only C17 feature i see being used is auto
and that g builtin thing
but you can replace that with a typed alternative
__builtin_ctzl or whaatever
__builtin_ctzg seems to just be a type generic version of __builtin_ctz
ok
i gotta figure out how to keep the original ELF versions
(before converting to XLOFF)
nvm i believe it converts each object file to an xloff individually
Wait thats really stupid
Good thing 32 bit arm is dead
my only guess is that it was designed with armv5 in mind which supported 1kb divisions of permissions
or something dumb like that
"developing for dead platforms" is my middle name
sometimes, sadly
At least they realized it was stupid af in aarch64
true
And iirc aarch64 has the most flexible format, like with bit granularity va width
in my wip armv6 port i actually fill in 4 1st level PTEs at once just to keep the "4KB second level page tables" assumption going
I wonder how Linux handles 1k allocations there
Like a cache of allocated pages or something
i havent looked too deep into linux but it seems like it uses some kind of software page tables and then converts them to hardware page tables
which is kinda dumb
Yeah thats every arch, but thats just an abstraction
conversely, i don't blame the NT folks for avoiding inverse page tables on powerpc
because those are just.. bad
There aren't two sets of page tables in reality
maybe .arch default was introduced after whatever binutils version you use
maybe
changing it to .arch i486 fixed it
GNU assembler (GNU Binutils for Ubuntu) 2.38
Copyright (C) 2022 Free Software Foundation, Inc.
bit 18 of eflags is AC or alignment check
does mintia depend on alignment checks?
i understand cr0.wp but not alignment checks
it doesn't need alignment checks, that's just how you check for i486 compatibility
cpuid is i586 (and some later model i486s but it's not architectural yet by that point)
don't you mean the bits are "overloaded" because I think for the first level it was
00 - not present
01 - page table
10 - section (1mb)
11 - supersection (16mb)
and the second level is
00 - not present
01 - large page (64kb)
10 - small page (4kb)
11 - tiny page (1kb) <- deprecated I think
so it's less of "two present bits" and more like overloaded type bits
the bits are actually for type, yes. 00 means not present.
on armv6 the meaning changed, 11 means small page execute never
tiny page is an armv5 relic
lmfao
i agree
also when i was doing the armv6 port the implicit backwards compatibility bit me in the ass
cause i thought i was using the armv6 layout but in reality the armv5 layout was being used instead
also according to the trm it's an "extended small page table" of 1kb pages
Brain rot page tables
i've been doing this on m68k
what do the page tables look like on there?
depends on the cpu 😛
I've forgotten the specifics but the 68040 (and its successor iirc) have PTs with 128 PTEs at one level, and 64-32 at another, page sizes are 4k or 8k (globally configured).
there's an external mmu available for the earlier cpus that has an incredibly configurable page table layout too.
ah I should do another port soon, that was fun.
that's nice
he dgaf...
yeah idk I'm not particularly fussed about attention to my projects
yeah r/osdev isnt the highest quality feedback
very arbitrary and lots of cliches like "terry... welcome back..." type comments
its pretty clear none of these people know what theyre looking at
not very fulfilling
i think it is considered a good idea to engage in brand building though or something
which ive completely avoided doing for like 8 years
What brand /j
these sound ai generated
You are absolutely right — these are ai generated comments.
u da real ai generated comment
Today I will try finishing the baseline NUMA support and merging it
Is there a C version of mintia
i feel like this
@twilit smelt
Ab solutely terrifing
Perhaps if I meditate I can rediscover the motivation I used to have to work on stuff
Ohmmmmmmmm
@icy bridge Is the disk image generated (mintia-PC-fre.img) a fully allocated disk image? How much of it is actually used? I'm curious about something...
i believe it's just a fixed size that can be increased in the makefile
don't know how much of the default is used
i see
i wonder if you can fit an image of mintia386 on a floppy disk
i have recently gotten my hands on an old pentium laptop, sadly it's missing a hard drive though
so i was thinking i could experiment with floppies instead
@mortal thunder i got it small enough to fit on a 1.44M floppy
that being said, there is no fdc driver, so it's a bit useless
this is where it gets to in qemu
if you're interested in implementing the fdc driver yourself, this is the diff to get it to output a 1.44M floppy image: https://hst.sh/otamibetuv.rb
compile with make -j16 SMALLDIST=1
ah thats cool, thanks
i might start implementing drivers to get it on there
you should only need fdc
and isa dma since fdc depends on that
the challenge will be allocating isa dma buffers since afaik mintia has no mechanism for allocating memory with a physical address range restriction
werent there other quirks that prevent mintia from running on a pentium (i586)
neat
as soon as i manage to find a well priced fdc to usb unit and some floppies, and i finish my exams, i will start messing around with that
with fdc to usb unit you mean plugging a usb floppy drive into an internal floppy connector?
because otherwise you'll need to use a usb driver instead of an fdc driver
no... i mean buying a floppy drive usb device so that i can write floppies
ohhh
since this laptop doesnt have a hard drive i have no way of writing floppies
sorry brainfart
although
technically i can solder wires behind the weird proprietary connector it uses
since its literally almost just IDE
slightly rearranged
so eventually i will have a hard drive/CF card/SD card connected to it
does the machine have PCI or is it ISA only?
hmm i'm not sure whether that's an indicator of whether its internal devices use pci
The dock connector at the back has support for adding cards... but only ISA cards
for what it's worth the BIOS date is 1998
I guess it doesn't then
Here is the BIOS screen
yeah im not sure, something of that era should have internal PCI at the very least
it's important because IDE without PCI can't do DMA
It probably doesn't do DMA
from what I can see
wow only 16 megs in 1998?
oh wait is this a laptop?
yeah i'm blind
this is a laptop, yeah
it cant?
what about 16 bit dma below 1mb
the oldschool stuff
nope ide doesn't use that
ahhh nvm then
ISA DMA is so slow that even back then it was better to just use PIO
even with a large sized request?
interrupt driven PIO of course but still
apparently yes otherwise it'd have had isa dma support
pio is pain
mintia: please work on me there are so many interesting problems to solve like NUMA things and vmm and IO and whatnot :)
the unknown ailment where i sleep 16 hours a day and spend all functioning moments either in class or doing homework or making money for tuition:
waiting for the day mintia gets a new progress update
I look back on like November 2021 where i randomly wrote like 30,000 lines of code in a month the same way medieval Italians with no running water would look back at the Roman Empire
Abrupt and brutal fall off
they have bigger problems than that
one reason im having trouble with finding the motivation I used to have to work on this is that my outlook on the industry and this entire field is increasingly bleak
If uni were free I'd probably be trying to pivot away into a completely unrelated major right now
Sadly im almost done with my cs degree
I'm just not excited about it anymore i think the moral/ethical/aesthetic positions I feel are right will also lose materially and im not interested in getting my shit kicked in
bleak in what way?
im increasingly seeing that the only corners of it that i have any interest at all in being around any of the people involved in it
and dont think theyre bloodsucking soulless cretins
are places im unlikely to find myself because they recruit smarter people than me from like MIT and shit
i also think the aesthetics/morals of the field are going down a dark like fascist technocratic path and that its inevitable youll need to pretend to like the people peddling that shit at some point if you want to make good money doing anything in the field
i just cant pretend to like people that i dont like
never been able to do that
I don't think this is true
i also think the social/cultural integrity of those corners is doomed to collapse
anyways
so
i think they only still exist inertially
which corners exactly?
but "systems stuff" is very broad
i dont know enough to define it more narrowly i just know that hardware people and like firmware and OS people are some of the least likely people to be insane
like the management and the outlook of these groups
i think part of it is a lot of them are populated/managed by oldheads who still have 80s/90s/00s era philosophies
but idk for sure
if you look at like Oxide Computer i think thats an example of a company that doesnt thoroughly repel me at every level
which is good
but i dont think it can last
we're entering the age of the grifter and theyre going to infiltrate and destroy everything before it gets any better
that is, if it ever does
civilization might just collapse instead
lol
i think you're painting an overly pessimistic picture of the industry
the industry captains are all moronic child rapists who are actively working to make life worse for the rest of the species for their own self enrichment
like
there are plenty of companies that work on OS adjacent software
they are diverse
the industry does not only consist of sam altman and mark zuckerberg
either child rapists or good friends with child rapists. the second part is almost universally true
i think there are maybe 1 or 2 major tech CEOs who are not lizard people atp
tim cook is a good candidate for not being a lizard person
his eventual replacement is more likely than not to turn out to be a lizard person though
this is what i open up the thread to 💀
i do believe there are structural forces that are making the lizard people overwhelmingly outcompete the sincere throughout the industry
historians will probably look back on the current cultural moment in the tech industry the same way we look at like precursor groups to the nazi party lol
its just evil shit
runaway individualism & contrarianism from incredibly powerful and wealthy idiots combined with a right wing moment
not sure why im meant to spend decades of my life working for entities that i truly believe are pure evil and will be responsible for the worst villainy of the 21st century just because i happened to get fixated on computers as an autistic preteen instead of cars or something
i often wish i was born like 10 years earlier i have a feeling things would be much more straightforward and id have been in the industry for 8-10 yrs by now and would have a good shield of cope to make it easier to pretend im not trying to get noticed and recruited by like, nazi troglodytes
ofc things might abruptly swing back left and then id be in better shape but im never going to forget what ive seen with my eyes and heard with my ears from these people over the last few years
what left the biggest impression?
the revelation that a few of the tech billionaires are active movers in plots to bring fascist authoritarianism (in some flavors, corporatocracy) to the united states in order to i guess stop having to pay taxes? or summon a machine god? or facilitate space colonization? or some other variation, and do not give a fuck about how many people suffer or die in the process or as a result
that these same people were deeply involved in an elite childraping ring for decades
and that the rest who arent directly implicated refuse to condemn them or talk about it and continue to go to fancy parties with them and shit
not to mention the fucking insane ties to US and Israeli intelligence
which would have sounded like an insane conspiracy theory if they arent spelled out so clearly in just the unredacted epstein emails
it all feels like a bad dream i cant wake up from lol
again, the tech industry doesn't only consist of the mag7
im aware its not a monolith but it operates 100% in their orbit
well according to this logic you live in this country and revolve around them no matter what
i can only make the choices that are available to me
unfortunately there would be no complete escape from these fucking freaks other than suicide lol
or maybe china in 10 years
suicide or china take ur pick
and there is always the academy
depends what you mean by that, in my country it sucks
in cs specifically
and i think unless its a very good uni its not the best way to share your knowledge
my opinions will probably relax when im not acutely freaking out about all this
Am I right in thinking that you're not too keen to drop the priority boost from KeTurnstile if, say, the wait didn't finish as a normal lock hand-off?
I'm trying to get a feel for how common it is to leave a priority boost in place longer than strictly necessary.
I don't understand the question
I probably only understand parts of the picture, not the whole thing. Right now, I can't identify all such scenarios, but here are some that made me think:
- thread termination
- wait timeout
- your system has the concept of APC, which I am not very familiar with, but from what I understand, using this mechanism can interrupt the wait
I think this can be summarised as the waiter stops being a waiter, but not because the lock was released.
If the wait is interrupted by any of these then you haven't received a priority boost from waiters on that lock
Only the owner is boosted
You would never have been the owner
In these cases, the dependency the waiter -> resource > owner no longer applies, so the owner will be left boosted for a waiter who no longer exists.
I see what you mean
Yeah for synchronization/efficiency reasons only the boosted thread removes its own boost
At lock release time
This isn't an issue
Not quite the same thing, but from a similar category of things that complicate inheritance is this change in thread priority mid wait. I tried to take all the details into account on paper and failed.
On the one hand, my previous concern did not affect correctness, but this one might.
I don't deal with that but one solution is to just break the thread out of its wait and let it go loop through the whole lock logic again and propagate its new priority
And even if what I fear does not affect correctness, it is unpleasant to think that a thread with a significantly higher priority (perhaps gifted by some very important audio stream) may remain and thus disrupt the performance of others.
Very unlikely that that audio thread will get interrupted
windows (autoboost) represents the boosts that must be removed later as a compact mask that travels with the dependency edge and/or the head's summary (a "head" representing the contended resource identity, reachable via hashed lookup)
unboost is separable (windows priority inheritance can apply and propagate 3 types of priority boosts): the token's lower 30 bits are CPU scheduling boost contributions
a boost contribution maps to one or more floor bits, floors are ref counted, so multiple dependencies can grant the same floor, and removing one dependency only decrements the floor
when the last contributor goes away, the bit is cleared and the thread's effective priority is recomputed from remaining floors
0 -- a priority change occurs and autoboost has established (a) a thread entry representing that thread's relationship to a resource (b) a head representing the resource identity (c) a cached key/token stored in the entry/head that summarizes the waiter pressure and any priority dimensions
1 -- mark affected autoboost state dirty and enqueue processing.
2 -- enumerate the thread's active autoboost entries and process entry-by-entry.
3 -- recompute the thread's priority key(s) used for ordering and for token generation.
4 -- if the computed key differs from the cached key, repair ordering in waiter/owner sets (reinsert in an RB tree according to the new key).
5 -- recompute head summaries; once waiter ordering changes, the head's cached max pressure and any derived target mask(s) may change. determine which owners are affected and compute the new composite token(s) that should apply to those owners.
6 -- apply token deltas. conceptually: (a) Remove = OwnerEntry->AppliedToken & ~RecomputedToken and Add = RecomputedToken & ~OwnerEntry->AppliedToken (b) UnboostThread( Owner, Resource, Remove ) for the removed bits and the symmetric routines for the added bits.
7 -- if an owner thread that just gained/changed boost is itself blocked behind another autoboost participating dependency, autoboost may need to propagate the new pressure: mark upstream state dirty and queue a worker for chain propagation, or push affected heads/threads into a processing list
liminal space
i love how we have (at least from what i know) the first known instance of an explanation of autoboost's implementation in NT randomly dropped in the mintia channel
certified osdev discord activity
Found in the network of underground tunnels under the UofUtah
Which I've been exploring between classes
btw.... " summary (a "head" representing the contended resource identity, reachable via hashed lookup) "
isnt this how it works in turnstiles
I may not be a good advisor here, as it turns out that my knowledge of turnstiles is rather poor
for example, I didn't know that they use an intrusive max heap and I was mistaken about how they work
with turnstiles it goes like lock address -> hash bucket -> turnstile object for that lock
what about autoboost?
then how do you know about it?
resource identity -> bucket -> autoboost head entry containing the ordered sets and cached metadata
I don't remember if turnstiles have a global hash table; maybe there's a clue there
in autoboost, it's somehow sharded and the key to its partitioning is not entirely clear to me, but apparently each shard has its own set of trees/lock
perhaps you have something similar with turnstiles?
i think its global for kernel and thats it
but idk for sure, @twilit smelt is an expert on turnstiles
turnstiles do use a global hash table, but you could also split it up per-numa-node or whatnot if you so wished
turnstile_block():
addr = mutex_addr
turnstile = lookup_turnstile(addr) // looks in global hash table
my_turnstile = this_thread.turnstile
if turnstile:
add my_turnstile to turnstile's freelist
else
donate my_turnstile as this lock's turnstile
turnstile = my_turnstile
add to turnstile's wait queue
block on turnstile
a very simple slighly lobotomized pseudocode for turnstiles
i might take an official break for a while and focus on my other hobby which is cropping up in my attention lately
from when i was a tween
conlanging
ive gotten interested in the etruscan language which is only known in pieces and fragments and it hink it would be an interesting learning exercise to try make a like historical fiction conlang that basically takes etruscan and fleshes it out with some reasonable guesses (or for most vocabulary just made up but phonotactically coherent roots) into a usable language
something like that
I didn't want to leave this point unfinished and thanks to the possibility of creating pseudocode, it became easier to look at it and understand from this fragment that the partitioning is by processes for user mode entries (the shard is chosen from a per-process bucket table, shards lead to RB trees of autoboost heads)
I apologize for intruding on your channel with my information, which is not entirely on topic.
What you're saying is more on topic so that's fine
so how would a lookup for user mode look
tbh it's more about discipline than motivation at a certain point
waiting for motivation to come back / focusing on side projects only works until a certain point and you will slowly abandon your project if you keep waiting for motivation to strike again
identity key -> select table partition -> select shard -> lock bucket -> lookup head entry in bucket RB tree -> if not found allocate a new head from a slist (pop from cache) -> ... -> on teardown remove from RB tree and free head (return to cache)
everything related to the windows scheduler ("ke") and in general everything related to kernels
as a programmer, I like how the scheduler has been modernized, very nice architecture; as an enthusiast, I like the architecture as a whole
my compliments to both the current and original teams
and that's definitely off topic 🥲
I don't mind at all
@twilit smelt why are casts no-ops in the IR generation stage in jackal
do you expect the truncation etc. to happen in like the code gen
they have implicit effects like generating the signed versions of certain IR instructions
truncation in local variables isn't a thing in jackal you can't rely on it to do that for you which is stated in NOTESFORSPEC
It may or may not do that
the current compiler doesn't
sandwichman's probably will since it's not terrible
this isnt terrible either
It is
im looking at it cuz i want to go back into compiler dev
and finish my compiler
I never went past a frontend + transpiler
and i dont really have a full mental map for the process of AST->IR->Optimization->Assembly
and havent seen any books that actually provide a good mental model
Please explain to me something I keep forgetting about Windows: thread states
I remember a table showing several ready states at once
in simple terms:
deferred ready -- the thread is runnable, but a CPU needs to be selected.
ready -- the thread is runnable and a specific CPU has been selected.
standby -- the thread is runnable and it has been selected to be the next one on a specific CPU.
reasonable system
there's an interesting state called transition which means threads stack is swapped out which is i believe a unique feature of windows today
but what idk for sure does it mean thread in transition can't be put into ready state
or when the outswapped thread is readied it's put into transition while it's being swapped in
older versions of mach used to do the same
does XNU still? lets find out!
nope!
the code to do so is all gone
they decided at some point to get rid of it
or the people working on mach 3.0 before them did
or whatever version of mach they used i dont remember
the copyright on that file only goes back to 2003
very interesting
lets look to see if the earliest versions of OSX from before that still retained the kernel stack swapping code
it does!
OSX had kernel stack swapping and removed it c. 2003 looks like
that's cool, wonder why they removed it
the thread is being treated as logically becoming runnable, but it cannot be placed on a ready queue yet
this is for the "transition" state (6), and the "wait for process in swap" state (9) is a process-level gating wait
Common feature
Solaris, FreeBSD do it
i dont think they want to give you any warranty
is there any reason xnu removed it
lots of memory now and they might have judged its a reliability liability
hate that those rhyme
also it can make debugging really annoying
having written a kernel that does kernel stack swapping the most annoying thing in the world is when you break into the kernel debugger to go stack trace some thread and it says
"Kernel stack swapped out!"
like well fuck
now what
:(
fair
i was originally thinking it wasnt really practical on powerpc
gcc stores function arguments in r3 to like r15 i think
i feel like it uses the stack on ppc but not as often
idk how thats related, maybe the amount of stack usage couldve made it useless
they were using kernel stack swapping for at least 5 years of xnu on mac ppc (assuming xnu starts somewhere around 1998)
idk if rhapsody had xnu
might have been the next kernel still
those are different apparently
rhapsody was based on nextstep though, at worst its based on a mach version
true
or whatever the ns kernel is called
oh ok nvm its based on mach
apple forked it into darwin
that was open sourced
basically xnu is based on this 
i think 
what i have found is that XNU appears to be a sort of greenfield reconstruction of the nextstep mach 2.x kernel architecture, based on fresh and unencumbered sources in the form of 4.4bsd-lite2 and osf/mach
insanity
the nextstep kernel was derived from 4.3BSD and that was encumbered until 2002
it didn't stop apple publicly releasing its source in early versions of darwin however
oh 😭
isnt the kernel stack a few pages at most
why would you need to swap it if you have more than like a few megabytes of memory
also wouldnt it be possible to retrieve the part on disk where it was swapped out to
a nextcube could have 8 mib of ram, suppose you have an 8 kib kernel stack (i don't know, it's possible it was that size), 40 threads eligible for stack swapping, you can free up 320k or so of ram, a reasonable proportion
and when stack swapping was invented the ratios would've been even more favourable
okay thats a lot of ram
but even then, is it not possible for the debugger to just dump this info
Yes but the debugger cannot read the disk
not read the disk, just dump the disk device + lba of the pages
well sure but you can't use that since interpreting the stack manually is pain
no pain no gain
that's just not how this works
this introduces considerable complexity to the debugger
i havent done osdev in years
i dont really remember the limits of debuggers
Debuggers really don't expect you to do anything but debug userspace and it shows. And it just gets worse if you use a custom language.
ig u cant rely on any of the vmm data structures to be valid either huh
i thought debugger meant like kernel's builtin debugging utilities in this context
not gdb or whatever
oh
that's exactly the sort of thing i would expect a lot of debuggers to have at least a little resilience against
Most kernels are very limited in what self-debugging they do at all
i mean, if the kernel panics, is there anything that you can expect to be in a valid state?
Technically no, practically a lot of stuff is usually intact.
My kernel does an attempt at showing a backtrace, the registers and virt2phys if applicable
hopefully a debugger that's relatively independent of the dynamic state and doesn't trust it too much
it does truncation and extension by default but if you provide the --xrsdk switch it doesn’t
that switch tells it to mimic the original compiler in terms of syntax and code behavior
if your IR only assigns each variable once and most instructions simply create new variables to store the result
why not treat the instructions themselves as variables
hmm
do you know of any books / resources i can read about this stuff?
specifically about IR, code gen and optimizations in general
There's the dragon book but it's famously very academic
i read that one a few years ago but i recall it being more of an overview / explanations of the concepts rather than exploring it more in depth
ill skim it again
the audience for the dragon book is not "random person who wants to write a working compiler as a personal project"
its like
a reference for a person who has been doing compilers professionally for 10 years and has a master's or phd in CS with a focus on compilers and adjacent topics like graph theory
type of thing
(im being a bit hyperbolic but essentially true)
yeah im looking for something thats more textbook-ish ig
how many human languages do you know
zero
wise words
^ in my IR, inputs to instructions are just pointers to other instructions
multiple results is easy enough by using some sort of instruction that just selects output N from another instruction
often called a projection node/inst
well
this makes things much simpler
by giving instructions a reference count
that could also help with like
idk it could help with something somewhere
It could help with dead code removal and register allocation
oh yeah use counts/lists are very useful
in my IR each instruction keeps a list of instructions which use itself as an input and the corresponding input index
i bitpack the index into the top bits of the pointer
its a very permissive environment for APCs to run in
because lazy APCs only get executed before returning to usermode and also while the thread is blocked on behalf of usermode in the kernel
which are times where no locks are held (aside from possibly superficial locks like the one on a file object for atomic append)
so such an APC can do a lot of stuff including initiate IO and so on
safely
this is my alternative to the error-prone thing NT does where they increment an "APC disable count" when entering unsafe code like filesystem drivers where an APC shouldnt run
which i dislike because it requires spamming these increments and decrements all over driver entrypoints and whatever
god help you if you miss one
as i understand it windows would bsod in such case
i see, it removes the burden and works on the opposite principle with safe places when its good to do so
turns out theres its own apc disable count for both special and regular kernel mode apcs
why did they separate them originally?
normally youd raise to apc irql and that way disable them
but there must be some reason for kernel apc disable count to exist
and be used
if I understand your question correctly, it's probably to avoid touching IRQL
the KeRaiseIrql is basically "mov cr8"
the scheduler uses APCs to terminate or suspend the thread, so when holding a lock you need to either frequently touch IRQL or use KernelApcDisable
otherwise this could result in a system deadlock, think of a scenario when a suspended thread is holding something other threads depend on and remember that thread suspension is performed by a kernel APC queued to the target thread
though not all locks require a critical region with KernelApcDisable, as some implicitly prevent suspension
i wonder is it that bad?
I think it could be expensive under virtualization because of vmexits
now I think that maybe they could've done the s/w IRQLs in s/w
mintia1 also did it that way i think
btw do they queue an apc to suspend? i heard they now can convert into suspended state directly
ah wait itd work only for waiting threads
why not?
you could suspend the waiting thread immediately, but otherwise APC works well
I know that Windows has this optimization
yeah so that you dont need to wake a thread to suspend it
apparently its important
one pretty important reason I see is transition threads
NT can swap out kernel stacks of threads that wait 15 seconds or so and longer
if you try to suspend such a thread, when you try to wake it up the stack swapper will inswap the stack back to send the thread back to wait
i didnt think of that
and why th is there so much code there
it's basically
if CurrentIrql != NewIrql:
writecr8(NewIrql)
if KiIrqlFlags != 0:
if (KiIrqlFlags & 1) != 0 and CurrentIrql <= 15:
if NewIrql >= 2 and NewIrql <= 15:
if CurrentIrql == NewIrql:
Mask := (1 << NewIrql)
else:
Mask :=
(((1 << (NewIrql + 1)) - 1)
AND (ALL_ONES << (CurrentIrql + 1))
AND 0xFFFFFFFC)
CurrentPrcb.SchedulerAssist+5 := CurrentPrcb.SchedulerAssist+5 OR Mask
return CurrentIrql
so yeah, there is a SchedulerAssist update, but IRQL changes still happen via writecr8
well you can always have a debug version of your kernel which verifies you dont have cycles in your locking, no?
That's not a locking cycle
incrementing the apc counter is like taking a lock though
all you can efficiently check is whether the apc counter is 0 on exit from the kernel
youre right that in a debug version you could do something INefficient to more effectively ensure that these occur in pairs
but i still find it ugly to spam these increments and decrements all over code that frankly shouldnt need any knowledge of the detail of whether it can safely run an APC in the middle of it or not
like random driver code
what are you doing instead?
a special type of APC that is only dispatched during a wait on behalf of usermode and also upon return to usermode
this is different from a user APC with only a kernel function because it doesn't interrupt the wait, the wait is resumed by an outer loop
what exactly qualifies as wait on behalf of usermode?
a wait where the mode parameter is supplied as USERMODE
it doesn't necessarily mean that important locks aren't held or that non-reentrant regions aren't active, does it
it is overloaded with several meanings
for example in NT it means "its safe to swap out the kernel thread stack" (because there are no pointers to anything on it that might be accessed by another context)
suppose you're mid-IO/FS path and you hit a user wait (or a boundary that qualifies as return to user), if such an APC can initiate IO, can it reenter the same stack while it's already active?
that just doesnt happen along such a path
for example mutex waits are always designated kernel mode
and blocking on synchronous IO happens after the request packet has been fully enqueued and the driver stack has fully returned back to the syscall implementation level
so that can be designated usermode
"wait mode" might be a somewhat bad abstraction which ive copied from NT where it is also maybe bad
due to how many things it conflates
the original purpose on NT was just to designate whether a wait should be quit if an event arrives that would have interrupted usermode
then early in development it was overloaded with "is it safe to swap out the kernel stack?"
and other meanings that tend to align with a general theme of like
the final long lasting wait at the end of some in-kernel processing caused by a syscall
which occurs at a shallow level in the kernel where few or no locks are held and no pointers on your stack could be used from other contexts
especially if its indefinite (like blocking on user input)
ok it might be a good abstraction but the names are bad
you might call it "wait level" and have it indicate which logical level of the kernel the wait is occurring in
like you could rename usermode wait to like, superficial wait or something
and kernelmode wait to like
balls deep wait or something idk
not that
it also couples your user APC safety to a caller chosen flag?
what enforces that the waits where user APCs run are exactly those phase boundaries, not just a wait that happens to be tagged user-ish
well these are not user APCs, my usermode APCs work basically like NT's do
these are "lazy kernel APCs"
or LAPCs
theyre lazy cuz they arent executed until the next wait with the mode designated as usermode or the next return from the kernel to usermode
as opposed to normal kernel APCs which are executed as soon as the thread is scheduled in and is below APC level
what enforces that you indicate a usermode wait at a time where it is appropriate is the same thing that enforces you dont access a null pointer and crash the kernel
so balls deep wait is not called wait mode on NT and it's a user mode only thing?
i may be being confusing
"wait mode" is a parameter on the internal kernel mode wait functions
on both mintia and NT
its not something you can specify from outside the kernel
ooh i see
the wait mode on NT is supplied as either usermode or kernelmode and indicates what its safe/expected for the kernel to do with the thread's wait at that point
same on mintia
this is how its described in NT's docs targeted at driver authors
which is extremely vague and doesnt at all capture what its doing lol
the workbook probably has a better description
so instead of drivers pairing APC disable, they must correctly classify which waits are superficial boundary waits?
a driver on mintia will basically never do a usermode wait
then if someone mistags (intentionally?) a deeper wait as superficial you've reintroduced reentrancy hazards with a different annotation
theyre all fundamentally asynchronous so they just execute in a straight line path without blocking hopefully (can still occur if contending on a mutex or etc, which is always a kernel mode wait) and then after kicking the hardware to start the IO and enqueuing the in-memory structure representing it, they return back up to the top
and the wait on behalf of usermode for the IO to complete is done in the generic code in the kernel proper
at the end of the read/write/whatever syscall impl
yeah but like in the docs i can just say "if youre writing a driver you probably shouldnt ever tag a wait as usermode"
im unsure why NT's docs dont say that
i cant really stop a driver author from intentionally doing something malicious
there are easier and more useful ways to be evil as someone whose kernel driver has been loaded into the system than to exploit some misuse of a parameter to an internal kernel function
Lowest-level and intermediate drivers should specify KernelMode.
pretty sure they do
theres an implication there that theres some vague classification of a driver as "highest level" which may specify usermode
but they dont explain what this is
maybe one shouldnt directly export a function with such parameter to regular drivers ?
perhaps not
but your options then are to either have a wrapper function that just calls the internal function with waitmode=kernelmode always
or to export the symbol, but only document a macro in a driver kit header file that does that
both kinda are a little ugly and convoluted
to avoid them potentially breaking a rule that is very simple and less complicated than 99% of the other rules for kernel programming
is it allowed for a lapc to block?
yes
is there a difference between mintia1 and mintia2, and which one is this thread for?
its for whichever one something is happening with but normally mintia2 now
the difference is mintia2 is rewritten in a new language
and has smp support
its basically a new kernel
that i didnt want to come up with a new name for since i like the name mintia
they are not compatible
also, they are both written for a toy risc computer architecture in a custom lang
mintia1 has an x86 port now
as well
mintia1 runs on 32-bit x86, fox32, and xr17032
the latter two are toy ISAs made by me and a friend
mintia2 runs on fox32 and xr17032
an amd64 port is planned
we have a little informal community of uber-NIHers who like writing compilers and designing architectures and stuff like that
we're collectively hoping to put together like a full semi-usable computer ecosystem made 100% just by us
between us we have like 3 architectures 3 OSes and 2 compiler toolchains at this point lol
which we like retarget to eachothers stuff for fun
i mostly use mintia2 as a kernel design vehicle, the fact it runs on a novelty toy isa is kind of way on the backseat atp hence the eventual amd64 port plans
cuz the fact it runs on a fake smp computer probably makes it sound puny
which its not
its pretty durn fancy for a hobby os
sounds more like fun
did you draw inspiration from something real for your own computer?
do u have an os yourself
maybe I ought to, but it will require a lot of patient work and time
mostly risc workstation computers like sparcstation, decstation, aviion
i think it contains one of the most unnecessarily silly goofy decisions ive ever seen in a modern architecture
how many redundant extensions to the base architecture does it cover? 😄
im referring ofc to the fact that entries of non-leaf page tables have to have all permissions bits set to 0
which means leaf and non-leaf entries have a different format
and you cant do recursive paging
for like no good reason whatsoever
its one of those things that makes it evident its a student project made by people who had only looked at linux before
linux and mips
you can still create a virtually linear page table but you have to do it with explicit mappings
you cant do the top level self-entry trick
so it adds memory overhead to something that should be free
I'd quite like to ask how useful this actually is, and forgive the slightly naive question, but is it something everyone tends to use?
It's a common debate of whether you should use them. Either way will work but of course it's extra effort to create page tables if you're relying on the trick and now need to port to an arch that doesn't have it.
they allow some optimizations
probably hyenasky refers to mapping the page table hierarchy for the process in kernel virtual address space
this makes conversion between a virtual address and its page table entry very neat
and also vice versa
pte addr -> vaddr
which is never needed but is useful implementationally to be able to do
there's a good book about the windows memory manager that explains many tricks that are useful not only in windows, the book isn't well known, so I must recommend that you buy it
What Makes It Page? is the name
au contraire
my approach to working set aging & eviction by iterating the PTEs of page table pages with active PTEs in them needs a way to get from the PTE address to the vaddr it maps
Good book
so i have to stash the base of the range described by a page table into the page struct to do that
the guy basically broke down the entire virtual memory subsystem in windows into molecules and wrote a book in calibri font like a true boss
if i had virtually linear page tables then i could use that to calculate instead
it's written in a default font, clearly hasn't been properly proofread, and contains typos, but it is magnificent
the man wrote it and disappeared
what kind of virtual memory system do you have?
I found it interesting how you presented the aging of the working sets
Thank you for the recommendation
oh yeah ive read a bit of that book
flexing some of my osdev journey books
books I couldn't find in pdf form or I just felt like owning a physical copy of
how can you not find pdfs
sometimes there just isn't a pdf
you have a wonderful collection, a good reason to show it off
have you read them all?
ive read those all in full except for pc interrupts and modern compiler design
I havent read the linux one, how good is it
well tbf I've only read one and a half in that list 
It's a good book about linux
also I really like the VAX architecture handbook design
i see, you do nt re?
also pro tip idk if you know about annas-archive
but like if you dont find it on there then i wonder if the book even exists 
i have looked there and failed to find anything before
i only knew about hitchhiker's guide to vms because someone mentioned it in a wikipedia talk page for rsx-11/m
couldnt find it online anywhere
found someone selling a used copy on ebay
yes and no, because normally I don't, I'm just interested in operating systems in general, and as part of some research on schedulers, it seemed to me that windows one wasn't described very well in its modern form, so I'm kinda digging into it
like there's so many cool books that also have cool covers
i see
so has it changed a lot?
what even is the cover of the linux one
a man polishing a gigantic glass orb
is the glass orb meant to represent the linux kernel
o'reilly covers are all weird
but they look cool
you should buy the solaris internals book it's pretty good
hitchhiker's guide to VMS is an underrated book about its internals
the author looks like this
do you buy all of them used?
a lot of these have been out of print for 20+ yrs so
makes sense
this copy of hitchhiker's guide to vms was printed in 1990
yes!
many fundamental things still apply, but yes
My used copy of Windows NT File System Internals came with the sample code floppy
miraculous stuff
crazy
the seller didnt even mention that
succeeded in examining the contents?
i should buy a usb floppy drive and try to digitize it
i havent tried yet
if i do ill put it on archive.org
can you implement really old NTFS with that book
not just the floppy but like the entire book
its not about NTFS
oh
its about implementing a filesystem driver for NT
it's Windows NT + file system internals not Windows NT file system + internals
not about NTFS
this book (not my picture) is about NTFS
essentially, a must-read if you are a developer of file system drivers or file system filters for windows
theyre basically called the same thing but are way different
yes lol
BUT WHY 😭
a pleasant surprise with inside windows nt was the cool hologram on the cover
