#Jeff BezOS

1 messages · Page 3 of 1

nova fiber
#

oh and i can now emulate reads and writes to cr3 in my test harness

#

i'll do actual paging emulation soon i suppose

urban schooner
#

Wait you wrote an x86 emulator for testing your kernel?

nova fiber
#

Sorta

#

Its closer to paravirtualization

#

I use signal handlers and ptrace to single step execution and capture side effects

#

So like rdmsr, wrmsr, changing page tables, doing mmio

nova fiber
#

i think qookie originally suggested using ptrace and self debugging

#

very good suggestion

#

completely insane execution on my part but i cant argue with the results

nova fiber
#

hm i think im going to have to start ref counting pages

#

sharing mappings without leaking stuff or holding onto alot of extra memory is a bit tricky

nova fiber
#

i think tomorrow i will move the elf loader into a shared project between the userspace and kernelspace

#

will be a little wonky to write but whatever

urban schooner
#

What sort of stuff do you test with it

nova fiber
#

i'd like to eventually test interrupts with it by using pthread_sigqueue

#

and at some point test paging by using memfd_create and some clever use of mmap and mprotect

#

oh fun thing about this is that it exposes bugs in linux's zram kernel module meme

#

zram doesnt page in stuff correctly if you use mprotect inside a signal handler so you always read back FF

urban schooner
#

Damn

#

Feels a tiny bit overkill lmfao

nova fiber
#

possibly meme

nova fiber
#

rtld can now launch statically linked processes in userspace so thats progress

#

although the mmap code is a real mess so i think its time to write that paging test harness and get that sorted out

#

and maybe finally get that tlsf implementation for physical memory working

#

and pthread_sigqueue to try and track down some of the deadlocks im having

#

if im feeling abitious i may be able to test actual context switches by handling the #GP from iretq

#

and msr access to gsbase and fsbase

#

oh unrelated but got xdrpp building for the package tool

#

havent integrated it yet

nova fiber
#

ok so i think for emulating paging i'll need to fork a process for each emulated cpu core, create a shared memfd file, then trap on writes to cr3 and sigsegv to map the memfd into each processes address space as needed

#

shouldn't be too hard i dont think

#

sharing test data is going to be a bit annoying, although if CLONE_VM behaves how i think it does then that also might be fine

prisma stirrup
#

Admittedly I've only skimmed, but why create an emulator instead of fiddling with qemu? Or does the emulator runs as a user program in your os?

nova fiber
#

doing unit testing inside qemu would be really hard

#

doing it on the host machine means i have access to better debug tools, can use valgrind, get coverage reports, and can write 200 tests for a single thing without having to spin up alot of vms

#

its also alot quicker to run a unit test than launch qemu, my ioapic tests run in 140ms which is orders of magnitude faster than just launching qemu

prisma stirrup
#

Cant argue with speed, though all host debugging tools would be attached to your emulator

You could use a common snapshot for all of your tests, and automatically restart from snapshot and choose a different run, it's going to be a lot slower then a dedicated emulator but you'd avoid the need to debug emulator problems and youd have a lot more capability to teat different things

#

Though writing an emulator is definitely interesting and thats a worthy goal on its own

nova fiber
#

honestly debugging the emulator after the initial debug register setup hasnt been too bad, although i have been looking at using qemu or virtualbox source code to emulate some of the devices for me

nova fiber
prisma stirrup
#

Can't vouch for virtualbox but qemu is very clean and easy to get your bearing once you get what they're doing with memory mapping and their objects registration

nova fiber
#

i have spent 8 hours attempting to get code coverage for 5 lines in my allocator

#

i cannot for the life of me reach this codeblock in a test case

sour geyser
#

Remove them meme

nova fiber
#

i hit it in regular usage pain

#

i havent a clue what obscure sequence of allocations i need to do to hit that block though

#

i swear im going to end up implementing fuzzing just for this

nova fiber
#

hrn good enough for now i guess

#

i've got 100% branch and state space coverage aside from that function

#

now to finally kill off my old pmm

#

actually not quite, forgot to add dynamically adding memory to the heap

nova fiber
#

ok got that done, also added grow and shrink

#

cant do realloc since the backing memory is inaccessible, so moving the block is impossible

nova fiber
#

Oh i think i'll also need to implement allocation splitting

#

Since i refcount pages at whatever granularity the range was allocated at i need to be able to split an allocation if two processes map overlapping areas of memory

#

retaining an entire 2gb allocation because a process has 4k of it mapped seems not so great

zealous mirage
#

it's one thing if it's small multiples like 64k. then if you're replacing pages, it's not a huge waste if someone only cares about 4k of it and doesn't touch the other 4k component pages

#

but if it's 2mib and you retain 2mib worth of data when someone is only ever touching 4k of it you have a big waste

#

(this is a page replacement rather than allocation specifically problem but a big one)

nova fiber
#

im not a fan of the idea of fixed overhead associated with just using a resource like memory

#

i was originally going to associate a 16 bit counter with each 4k page which is only 0.04% memory overhead, but then scaling that up it feels bad to waste a whole 16gb of ram just to count pages on my desktop

#

i think that the correct choice for an OS is usually to optimize for space complexity of data rather than optimize for speed within reason

nova fiber
#

my tlsf heap technically has O(N) space requirements for its freelist, but to handle 2tb of memory the freelist is only 5kb so im not too worried

nova fiber
#

god is this tempting to abuse

#

256 bit atomic loads and stores

#

some intel chips even have atomic 512 bit loads and stores

brave cape
nova fiber
#

oops thats 4% i missed a decimal place

#

my bad

#

160 megabytes my bad

brave cape
#

160 megabytes out of how much, like 64 GiB or something? that is negligible.

nova fiber
#

398gb

#

still feels wrong to just eat the memory when i could instead not

brave cape
#

even more negligible then

#

do you not have a struct page?

nova fiber
#

no

brave cape
#

so where is linkage for e.g. page cache pages?

nova fiber
#

right now i have no disk drivers so i just havent gotten around to that

brave cape
#

at some point, you will probably need linkage for the pages somewhere for LRU and additionally per-page refcounting and locking for IO. now, if you really don't like struct page, you can store it in e.g. an array per memory object, where a "memory object" is e.g. a filesystem-backed mmapable file or anon, possibly shared memory. but a struct page is just convenient for this type of thing.

nova fiber
#

i'll have something like that eventually, just with granularity thats based on the size of the allocation rather than per-page

brave cape
#

splitting allocations will probably become harder as a result of no per-page linkage and refcounting etc. IMO it is already hard enough

nova fiber
#

after alot of testing i've concluded its now dead code

#

its a private function and i changed the callsites enough thats its no longer hit

brave cape
nova fiber
#

i cant hit in real usage either now lol

brave cape
#

lol

#

so are you just going to replace it with assert(!prev->isFree());?

nova fiber
#

pretty much

nova fiber
#

more thorough testing of the tlsf heap has revealed even more bugs

#

wow i suck at writing allocators

#

thank god for gcovr

nova fiber
#

i think i hammered out all the bugs for now

#

im sure i'll find new ones tomorrow though meme

umbral grotto
#

Like

#

Why are you giving it string views

#

asm is not a function

nova fiber
#

you can give a static assert a string view for its message at compile time

#

you can now do the same with asm

umbral grotto
#

"this would be useful for people writing SIMD libraries. You could also use it to write a C++ compiler in C++."
no shit

#

you could already do that

nova fiber
#

you can also give it a plain string as long as its constexpr evaluated

umbral grotto
#

aren't plain strings uh

#

constexpr evaluated already?

nova fiber
#

sorry i meant std::string

umbral grotto
#

oh std::string

#

but why would you give asm anything but a plain string

#

i do not get it

nova fiber
#

so you can generate asm dynamically based on parameters

#

like generating different avx instructions depending on if you're working with 128bit or 256bit vectors

#

its a little insane either way, but could be fun to abuse

#
constexpr std::string GenerateIsrTable() {
  std::string isrs;
  for (size_t i = 32; i < 255; i++) {
    isrs += std::format(
      ".align 16\n"
      "AsmIsr{}:\n"
      "  pushq {}\n"
      "  pushq {}\n"
      "  jmp AsmIsrEntry\n"
      , i);
  }
  return isrs;
}

asm(GenerateIsrTable());
#

C++ as a macro assembler

prisma stirrup
#

That's cursed lmao

brave cape
#

C++ as a macro assembler, what god intended higher-level languages to be.

#

this shows that we've made full circle and are back where C started

nova fiber
#
#

aside from timing out godbolt

nova fiber
#

in os related news the process vmm is coming along

#

i now no longer leak all allocated memory meme

#

i properly split physical page ranges as needed to correctly track owner counts

#

i will need to add some more apis to my allocator and page table manager to support doing multiple operations at once to guard against out of memory situations

#

right now its possible to oom during an operation and leave stuff in a slightly busted state

#

i also once again have mapping another processes address space working, and now it also only maps the areas that the other process has mapped

nova fiber
#

and also follows the mappings if the other program has mapped a file or whatever

nova fiber
#

lowering the generated asm size makes clang explode

nova fiber
#

today has been one long bruh moment

#

implemented transactional tlsf heap updates, transactional page table updates, and made a whole heap of stuff resilient to oom by using that

sour geyser
#

That's pretty cool

nova fiber
#

im not looking forward to writing a transactional b-tree and b+ tree

nova fiber
#

small poll to anyone who cares to respond: if you mapped a processes address space into your own, and the range you requested to map either didnt start in a mapped area, or contained holes of unmapped memory. how would you expect the mapping to behave? should the mapping always fail if there's holes, only fail if the beginning of the range isnt mapped, only fail if nothing would be mapped?
diagram provided to visualize

#

horitontal bar is the requested memory to map, shaded blocks are mapped in the process, unshaded blocks are unmapped

#

second question, if a processes address space is mapped into your own and the process dies should the memory remain mapped with whatever was there when the process exited, should there be a SIGBUS signal equivalent like posix does with removed media, silently unmapped, reprotected as noaccess?

olive musk
#

As the request cannot be fulfilled (i.e. I wanted a mapping of size X, and it is not of size X)

#

And for the process dying thing, idk that is a good question

#

Both options would make sense

nova fiber
olive musk
#

Your current way works too, it's a tricky question

prisma stirrup
#

I would expect it to fail as well, otherwise every caller would have to be worried it succeed but not really.
2 can go either way I think, probably some unmapping would be required, perhaps unmap everything and treat the shared memory as if it was swapped out?

brave cape
#

this is very difficult to support.

#

it will probably mess with assumptions about non-shared memory (i.e. MAP_PRIVATE or MAP_ANON|MAP_PRIVATE)

brave cape
#

I would just not support mmap on that file

#

not worth the effort

nova fiber
#

i mean i already support it lol, its how my rtld does program loading

brave cape
#

??

#

please explain

nova fiber
#

the rtld creates an empty process, then maps everything needed into the process, then creates a thread inside the new process

brave cape
#

that's not what this is

nova fiber
#

this way i dont need to make the rtld relocate itself, or do deduplication of shared libraries in the kernel

brave cape
#

as I understand it, your rtld is effectively executing mmap in the context of another process

brave cape
nova fiber
#

yes, it also has to map the other processes memory into its own process to write the relocations

#

plus setup of the tls and a few other bits

brave cape
#

part of why this is hard is because there are no clear semantics that everyone "obviously" agree on. e.g. what if process A mmaps some pages from process B, but then process B changes those underlying pages? does the mapping in process A also update? and what if process C now comes along and mmaps a bit of process A into itself? it quickly explodes in complexity.

nova fiber
#

i havent found that tbh, its got mostly the same semantics as shared mappings on a file

brave cape
#

and what if process A mmaps a bit of process B into itself, while process B also mmaps a bit of process A into itself, creating a cycle?

nova fiber
#

it'll all map to the same physical memory either way

brave cape
#

spontaneously I would expect that it'd work in a way where if process A mmaps a bit of process B into itself, a page fault in A is handled by running the page fault handler as process B, taking the resulting physical page and plonking it into process A. then some kind of mmu notifier control mechanism so that whenever process B's page tables change, the entries in process A are cleared.

#

this becomes problematic if there are cycles.

nova fiber
#

currently mapping a process just gets you a snapshot of whats currently mapped, if the subprocess updates a mapped area those changes arent reflected in the parent process

brave cape
#

yeah that simplifies things substantially.

nova fiber
#

oh dear

nova fiber
#

pain misery suffering

#

1 gazillion edge cases

#

4k sloc of tests added in 2 days m_catdie

#

my internal design is definetly lacking in some ways but at least it works

iron mist
umbral grotto
#

When the process dies I would expect the mapping to continue working as it did while the process was alive

#

If I implement such a feature in Boron then that is how it will work

#

(Boron tracks user processes via the object manager so the process and its internal structures are only destroyed when that object loses all its handles)

#

(And the page map is destroyed in much the same way)

#

Now, mapping a process' address space into your own would add a reference to it so the process is still "kept alive" by virtue of you having mapped something from it into your own address space

nova fiber
#

thank you all for the input him, you've given me much to think about! I will mull it over for a bit and make a final decision once I get all my tests passing

nova fiber
#

i hope its implemented in clang somewhat soon, there is a fork with it implemented

#

my code is littered with a ton of asserts

prisma stirrup
#

Its nice, but seems more like synthetic change that might not be adapted quickly

#

If it was assert on debug builds and assume on release builds it would be nicer imo

zealous mirage
nova fiber
#

got the new memory stuff working

#

the code is a bit messy but it's got nearly 100% test coverage some im pretty confident it works for the most part

#

now to get testing interrupts working because my scheduler keeps deadlocking and forgetting tasks

#

I think i'd also like to run the build with clang time trace and do some cleanup of my build files because im recompiling some files 8 times due to permutations of test build flags

nova fiber
#

figured out how to emulate a different page table per cpu core

#

abusing clone3 and an allocator inside a MAP_SHARED memfd

#

only the shared mappings are changed so i can do different mprotect and mmap calls per cpu core and they wont be visible

nova fiber
#

thats new

#

seems to work though

#

anyway thats enough for today

brave cape
#

gregset_t :p

brave cape
# nova fiber funky

anyway you ought to mark ContextSwitchTestBody noinline; otherwise funky stuff can happen (especially if you do LTO)

#

I will also note that this code does not seem to do anything about the callee-saved (AKA non-scratch) registers. That is possibly a problem.

#

well, maybe PvTestContextSwitch does something that is non-obvious from the above code sample

nova fiber
#

im using it to test interrupts

nova fiber
#

it wont see that with a computed goto mind you, i tried taking a reference to a label and that was optimized away

#

only git has this problem

#

like i never lose actual data so im not sure what the deal is

#

the .git folder just ocassionally dies after a restart

prisma stirrup
#

Maybe git executable shit itself? Odd

nova fiber
#

this has happened on every computer i use and its consistently only ever git with this issue

#

its very odd

nova fiber
#

anyway context switching for interrupts now works

nova fiber
#

a bit scuffed but i can now emulate paging and smp

urban schooner
#

The Greg Type

nova fiber
#

found a lockfree priority queue

#

i think that should kill off a few more locks in the scheduler

nova fiber
#

truly bleeding edge library

stone igloo
#

also

#

skip lists can be used as a lock-free sorted associative map as well and they are much more generic

nova fiber
#

Can't deadlock in the scheduler if nothing ever takes a lock

stone igloo
#

lol

stone igloo
#

but yeah fair

nova fiber
#

OK yes wait free not lock free

#

But you know what I mean

nova fiber
#

scheduler still deadlocks h_pain

#

I'm giving funqual another shot to see if i can get some better analysis than clangs rtsan can get me

#

somewhat related clangs consumable annotations let you implement substructural linear types and destructive move

#

in that example current is consumed by the RaiseIpl call, but since theres no ReleaseIpl call for dispatch its an error

#

slightly spastic code but this will get me some of the analysis i want

#

I can make nonreentrant functions take a special tag type as a parameter, then use that to ensure i dont accidentally call a function when i shouldnt be

#

if im feeling extra i could use the swift calling convention

#

since it removes empty types from the callconv

#

zero overhead™️

#

actually nvm the default clang calling convention also elides zero sized types

#

gcc doesnt though lol

nova fiber
#

made scheduler deadlock a bit less

#

(i think)

nova fiber
#

scheduler is still forgetting tasks i think

#

its very hard to debug if its a deadlock outside the scheduler or if its the scheduler itself forgetting stuff

#

not really sure where to start debugging this honestly

nova fiber
#

im going to try and fix some of the bugs in funqual and use that to try and hunt down possible issues

#

it may actually be easier to use the existing clang function effects code and extend it to support more tags

#

although the clang one doesnt accept any kind of rules file, but that might not be impossible to add

nova fiber
#

patching clang wasnt too hard

#

oh and bruh moment script of the day

#
function unfsck() {
    git fsck --full 2>&1 >/dev/null | grep 'error: object file' | awk '{print $4}' | tr '\n' ' '
}
#

because it happens at least twice a week

#

git just cannot handle wsl turning off i guess

urban schooner
#

That's why I keep gitting on my windows drive and use wsl only for compiling

#

Very convenient with fork client

nova fiber
#

i've narrowed down my deadlocks to the scheduling and rcu queues

#

adding elements to them can allocate

#

so i think i'll move to fixed size scheduling queues and intrusive rcu object headers

nova fiber
#

modifying clang to support reentrant and nonreentrant attributes was the right move i think, its much easier to track the state with automated lints rather than manually reading comments

nova fiber
#

knowing how to modify the compiler of your preferred language has to be in the top 10 useful things when programming ngl

prisma stirrup
#

Modifying dependencies in general is a great skill, though compiler is kinda taking it too far lmao

#

Modifying qemu helped me a ton

nova fiber
#

yknow i actually havent found a need to modify qemu yet

#

i must not be using it wrong enough yet

#

i've done some horrible things to some of my other dependencies though lol

#

quite pleased with getting abseil building freestanding

#

the day of the btree creeps closer but i keep putting it off

prisma stirrup
#

Re-wrote the monitor terminal because it was written like 30 years ago and its infuriating to use, can't even search in history

brave cape
prisma stirrup
#

Sadly no, got a negetive response about publishing to upstream from management for now, unless its a critical bug.

brave cape
#

😔

#

otherwise I find it likely that new contributors would be very welcome.

prisma stirrup
#

Yeah contributing to qemu is nice after passing the mailing list problems

nova fiber
#

mmm fun bug thats happened because i made my rcu lock free

#

in some of my destructors i was queuing things to be deleted later

#

this makes destroying the rcu domain recursively create more deferred objects to reclaim in some cases

#

oops

nova fiber
#

good enough

nova fiber
#

got the reentrant ringbuffer working as well

#

time to shove them into my scheduler

nova fiber
#

seems to work

#

i think

nova fiber
#

hmm fun bug

#

rax gets mangled during a syscall

#

and i havent the foggiest idea why

#

i am going insane

#

why is clang generating totally wrong assembly

#

oh i needed to use movq

trim owl
#

is your code ```c
int arg0 asm("rax") = foo();
int arg1 asm("rbx") = bar();

nova fiber
#

why wasnt that implicit from the operand size sade

nova fiber
#

i needed to use movq rather than mov

#

rax is still changing to random values when entering my syscall handler but at least its not that i guess

trim owl
#

strange

nova fiber
#

does syscall clobber rax in some esoteric circumstance?

iron mist
#

nope

nova fiber
#

every other register is correct as well

#

only rax is wrong

trim owl
#

maybe inspect the assembly at the OsSystemCall call site

nova fiber
#
(gdb) disassemble/rs $rip
Dump of assembler code for function OsDebugMessage:
/sources/sysapi/src/bezos/syscall_debug.c:
5       OsStatus OsDebugMessage(struct OsDebugMessageInfo Message) {
   0x0000000000102c80 <+0>:     55      push   %rbp
   0x0000000000102c81 <+1>:     48 89 e5        mov    %rsp,%rbp
   0x0000000000102c84 <+4>:     48 83 ec 10     sub    $0x10,%rsp
   0x0000000000102c88 <+8>:     48 8d 75 10     lea    0x10(%rbp),%rsi

6           struct OsCallResult result = OsSystemCall(eOsCallDebugMessage, (uint64_t)&Message, 0, 0, 0);
   0x0000000000102c8c <+12>:    bf f0 00 00 00  mov    $0xf0,%edi
   0x0000000000102c91 <+17>:    31 c0   xor    %eax,%eax
   0x0000000000102c93 <+19>:    41 89 c0        mov    %eax,%r8d
   0x0000000000102c96 <+22>:    4c 89 c2        mov    %r8,%rdx
   0x0000000000102c99 <+25>:    4c 89 c1        mov    %r8,%rcx
   0x0000000000102c9c <+28>:    e8 4b 07 00 00  call   0x1033ec
=> 0x0000000000102ca1 <+33>:    48 89 45 f0     mov    %rax,-0x10(%rbp)
   0x0000000000102ca5 <+37>:    48 89 55 f8     mov    %rdx,-0x8(%rbp)

7           return result.Status;
   0x0000000000102ca9 <+41>:    48 8b 45 f0     mov    -0x10(%rbp),%rax
   0x0000000000102cad <+45>:    48 83 c4 10     add    $0x10,%rsp
   0x0000000000102cb1 <+49>:    5d      pop    %rbp
   0x0000000000102cb2 <+50>:    c3      ret    
End of assembler dump.
``` i *think* this is right
#

oh maybe im forgetting to preserve r15

nova fiber
#

b KmSystemEntry if $rax = 0x31

#

im killing myself

#

fucking ==

#

aaaa

nova fiber
#

i think im losing my mind

#

why is clang generating sldt instructions in normal code

nova fiber
#

it is impossible to pass this flag to clang

#

but it will still suggest it to you

#

for some reason it just lets you disable all [[]] attribute syntax

nova fiber
#

disabled ubsan and a test started failing SCeek

#

ubsan was initializing memory for me

#

lol, lmao even

nova fiber
#

building gdb from source is kinda painful

#

it also builds with werror by default

#

so fuck you whoever chose that

#

also running make with any -j greater than 1 breaks the build which is extra retarded

nova fiber
#

and the gdb it builds by default is broken

#

what joy

#

surely using the debian buildscripts will produce a functioning gdb Clueless

#

nope

#

someone should invent the fsf but with members that can comprehend the concept of UX and end user experience

#

it would seem you cannot have gdb installed in /usr/local if the folder /usr/share/gdb exists or it will explode

#

me when i dont respect prefix values during build or install

nova fiber
#

god dwarf is infuriating

#

it behaves in strange ways and i cant for the life of me figure out why values change

nova fiber
#

Backtraces through syscalls now sorta work

#

Only sometimes for some reason

#

I think i need to mark rsp properly in the cfi

nova fiber
#

found the source of alot of my deadlocks

#

i really should've listened to the compiler warning

#

KmDebugMessage takes the message queue lock and this makes it nonreentrant

#

signal handlers need to be reentrant

#

// Takes a lock but this is probably fine was in fact not a correct statement to make

#

time to figure out how to log inside interrupts

#

shitty solution: add log messages to a buffer inside an interrupt, when outside an interrupt the next log flushes the pending messages

prisma stirrup
#

The problem is nested interrupts? The log is per core right

Also "this is probably fine" is famous last words lmao

nova fiber
#

the lock is global because it writes to the serial port

sour geyser
#

Have you considered a two stage approach?

#

Write the logs to a buffer, someone else writes them to the outputs

prisma stirrup
#

Ah then idk how adding directly to the buffer would help when the buffer write would need to be protected

sour geyser
#

I do it with a try-lock whenever a log message is queued, if you take the lock you keep writing until the queue is empty (allows interrupts and other cpus to add messages in the mean time)

prisma stirrup
#

Yeah you're right

sour geyser
#

So you have head and tail pointers in the buffer, allocate by trying to compare exchange with the head pointer

#

Sorry I meant to elaborate earlier, got distracted

#

The problem I've run into, and it's quite possibly a skill issue, is the buffer filling up inside an interrupt or faster than the queue can be drained.

#

I imagine writing to the framebuffer and serial isn't helping, but a bigger buffer has solved that for now

nova fiber
#

i have a good reentrant ringbuffer so thats probably the easiest option

#

this is also a good opportunity to move all my logging sinks out of main.cpp

#

where they have been since i started the project

umbral grotto
#

Why do you need to log in interrupts anyway? If a good reason, then why not disable interrupts completely while printing?

iron mist
#

NMIs usually need to be logged

#

or well, it's desirable to, anyway

umbral grotto
#
  1. what if an NMI interrupts your first
#
  1. what if your logging routine is interrupted
iron mist
#
  1. nmis are masked from the time an nmi is first triggered to when an iretq is issued
  2. that's why it needs to be reentrant
umbral grotto
#

well, what I propose is that every NMI you increment a number or store some information, and right when you're about to exit to interrupt level zero, start logging

umbral grotto
#

and what if you never issue it

iron mist
#

what is 'it' in this context? if it's the cpu, because it's the one executing it. if it's something else, it doesn't need to know, because the cpu masks it

umbral grotto
iron mist
#

and if you never issue it nmis stay masked

nova fiber
nova fiber
#

new logger mostly works

#

its a bit boring

nova fiber
#

the important message can be printed so im calling it for the night

nova fiber
#

after significant soak testing i have made the unfortunate discovery that my ringbuffer is not entirely working

#

it only happens once in every like 50 test runs as well, and its only marginally broken

#

but damnit i thought i had tested it enough

#

made some slight tweaks and now its every 100 test runs rather than every 50

#

cmon man im 6 off

nova fiber
#

I think i got it

#

eat your heart out freebsd my queue is better than yours frekw

nova fiber
#

just for fun heres some benchmarks of the queue

#

copyobject is just the baseline

#

id say coming within like 20% of the baseline is pretty good for a queue, especially with like 64 threads all hammering it at once

#

wait wrong column

#

nvm this shit is ass lmao

#

made it significantly worse by padding things out to cache line size as well

#

pog

#

actually no i was reading the right column

#

the CPU time is misleading because its multithreaded

#

duh i suppose

#

it gets faster as theres more contention because the ringbuffer fills up and starts dropping messages pain

nova fiber
#

clangd having another moment

nova fiber
#

didnt know /usr/share/misc/pci.ids was a thing

#

quite useful

#

the things you can learn from running random shit under strace

#

I think i've migrated everything to the new logger now

#

now to get back to figuring out that damn dwarf backtrace info

calm shell
#

whats your plan for blocking locks

nova fiber
#

blocking locks? im not quite sure i understand. dont all locks block?

calm shell
#

they spin

#

block here means "block the thread"

nova fiber
#

so like sleeping locks in linux?

#

right now i have a priority queue per object that can be waited or locked on and add stuff to that

#

its not great though

#

i should really switch to a linked list for the scheduler tbh

#

although the priority queue for waiting is useful for doing timeouts

umbral grotto
#

NT calls them "mutexes" (or mutants)

nova fiber
#

yeah in that case i just take the thread out of the scheduler and put it onto a priority queue for the mutex

#

and then ocassionally look through the queues to find things with expired timeouts and add those back to the scheduler

#

really i should be using the apic deadline timer or something to get better latency but this is good enough for now lol

umbral grotto
nova fiber
#

that makes sense

umbral grotto
#

as such there is no additional machinery that handles wait timeouts specifically

nova fiber
#

my userspace facilities are really lacking ngl

umbral grotto
#

same but I barely just reached userspace

nova fiber
#

the process, threads, and whatnot i have are all pretty hacked together

umbral grotto
#

I need to write a file system driver

#

Like, a proper disk based one, not a tmpfs thing

nova fiber
#

i have a tarfs if that counts meme

umbral grotto
#

tar is not a file system

nova fiber
#

no actual disk drivers though lol

umbral grotto
#

except if you're the osdev wiki for some reason

umbral grotto
nova fiber
#

damn

#

im not letting myself write any drivers until my userspace is functional enough to actually need them

#

and my userspace is shit and unstable hence no drivers

umbral grotto
#

I feel like I need to get some drivers working first before I can truly start working on a userspace

nova fiber
#

i figure theres no point in disk drivers if i cant open a text editor

umbral grotto
#

I have two ideas for userspace

#

One of them would be an mlibc based distribution

#

And another would be my own GUI and things

nova fiber
#

you'll need a libc either way at least

nova fiber
#

oh boy another hard to reproduce multithreaded issue

#

this time the rcu shared ptr i have does a use after free once in a blue moon

nova fiber
#

I think my shared ptr might just be fucked

#

Damnit

nova fiber
#

nvm that was easier than i thought

nova fiber
#

scratch that

#

man this is a pain in the ass

brave cape
#

RCU shared pointer?

nova fiber
#

its an atomic shared pointer that uses rcu rather than a split reference count

#

which more importantly means that its reentrant, a split reference count isnt

nova fiber
#

ah my generational rcu is buggered thats why

nova fiber
#

userspace-rcu is more readable after being pre-processed than before

#

so much macro abuse

nova fiber
#

i had written the test ever so slightly wrong

nova fiber
#

please dont tell me i wrote the shared ptr tests wrong in the same way

#

god fucking damnit

#

there was no bug i was just a rart

#

im going to leave the soak tests running for 30 minutes

nova fiber
#

ok there is still a bug it is just damn near impossible to reproduce

nova fiber
#

ok rcu is sound, rcu shared ptr is not

#

really not sure how to make my shared pointer totally kosher

nova fiber
#

now im paranoid damnit

#

more rcu soak testing

#

i am so glad i bought the giant server cpu

#

196 cpu hours per hour is great for fuzzing and soak tests

prisma stirrup
#

Can you implement snapshots in your test framework? You could easily then create a snapshot that lets you repeatedly reach the problem quicker

calm shell
nova fiber
prisma stirrup
#

I think I misremembering, you're running the tests as a user mode program under your os which runs under qemu?

nova fiber
#

the tests are just run in usermode on a linux host

#

well these ones are

#

ah i think i might have tracked it down

#

when taking nested rcu guards the generation was still allowed to change

nova fiber
#

yeah that was it

nova fiber
nova fiber
#

im starting to think my rcu shared pointer is just cursed

#

i think for now im going to not use it

nova fiber
#

or maybe this is a good excuse to implement hazard pointers

#

although i still want to use rcu for the fs at least

nova fiber
#

some possible progress

nova fiber
#

ok i think this is getting somewhere

nova fiber
#

God i really hope

#

This is such a pain to test

nova fiber
#

cautious optimism

nova fiber
#

slowly the test cases expand

#

this is really ass but still probably faster than learning how to use SPIN and write a promela model for this

urban schooner
#

What's a soak test?

calm shell
#

Mormon shit don't worry about it

trim owl
#

lmfao

urban schooner
#

Also, which tools do you use for testing? Do you test kernel code in userspace (without emulators)?

urban schooner
calm shell
#

I'm not mormon

#

That's also not an appropriate question.

urban schooner
#

I don't even know what it entails how can I know whether it is

calm shell
#

Google says soak test is what normal people would call a stress test

trim owl
urban schooner
nova fiber
#

i havent found any reliable way of reproducing bugs in my atomic code beyond this

#

i call them soak tests because i usually go take a piss while they run

olive musk
#

I will probably take a look at it eventually and do something similar (albeit smaller in scope), though I'll do it in C

#

you could probs make repo out of your x86 simulation thingy too

nova fiber
#

now that the shared pointer fiasco is over with time for a new scheduler

nova fiber
#

i did think of making the x86 simulator a seperate project but i dont think its really ready for use yet

nova fiber
#

slightly gnarly but i can test my scheduler now

#

posix signals are so great if you want to do this one really specific thing and in all other cases they're really painful lol

nova fiber
#

ough

nova fiber
#

latest linux kernel update broke the behaviour of mprotect inside signal handlers

#

sick

#

now my x86 emulation doesnt work

nova fiber
# urban schooner How?

changing the protection of the memory to RW, then writing to it, then changing it back to RO now always reads back 0xFFFFFFFF or 0x00000000

#

rather than what was written to the memory

urban schooner
#

Huh

#

That seems unlikely

#

Or its a kernel bug

nova fiber
#

its only an issue inside signal handlers when ptrace is active afaict

urban schooner
#

Let them know on the mailing list

nova fiber
#

i'll see if i can make a minimal reproducer

urban schooner
#

Yeah

#

That seems like a serious bug

nova fiber
#

it would seem canonical just decided to be retarded actually

#

setting it to 0 fixes the failing tests

urban schooner
#

What does that do

nova fiber
#

setting it to 1 disables ptrace for everything unless it opts in

brave cape
#

and that's about it

urban schooner
#

Why do you use ptrace btw

nova fiber
#

i need it to single step the test so it can set breakpoints in itself

#

the child process manipulates the parents debug registers and listens for SIGTRAP to inspect machine state and emulate priviliged instructions

urban schooner
#

So it was failing with no errors?

nova fiber
#

it was never updating the memory protection because the debug callback wasnt invoked

#

why it wasnt then exploding because of nested segfaults im not sure

urban schooner
#

Interesting

urban schooner
urban schooner
#

In the code you wanna ptrace

nova fiber
#

oh neat

#

thanks

urban schooner
#

4.15 but whatever

nova fiber
#

btree time

nova fiber
#

i think im going to do variable arity leaf pages

nova fiber
umbral grotto
#

polyglot C++

nova fiber
#

from how much everyone hypes up btrees as a hard to implement thing i was expecting alot more complexity ngl

nova fiber
#
/home/elliothb/github/bezos/sources/kernel/include/std/container/btree.hpp:240:25: error: no matching function for call to 'swap'
  240 |                         std::swap(value(mCount - 1), entry.value);
      |                         ^~~~~~~~~
/home/elliothb/github/bezos/install/llvm/include/c++/v1/any:509:35: note: candidate function not viable: no known conversion from 'int' to 'any &' for 1st argument
``` thats a new one
#

any& it would appear clang just gave up

trim owl
#

std::any 💀

nova fiber
#

oh

#

bruh

#

the lack of std:: threw me

trim owl
#

why the henk are you using std::any

nova fiber
#

im not

#

i guess i include something which transitively includes it

nova fiber
#

spent 40% of my programs runtime executing if (i > count) panic(); award

#

actually nearly 99% of my programs runtime is just spent running validate()

#

i might be a little retarded

prisma stirrup
#

Easy x10 speedup

nova fiber
small stag
#

maybe via gdb?

nova fiber
#

Yeah i debug with gdb in qemu

#

This is just peofiling code running on the linux host

nova fiber
#

Honestly not too sure how to go about profiling the kernel

prisma stirrup
#

Careful of profiling your kernel under qemu, while kvm would make it much more reliable than tcg it might still be misleading compared to actual hw

nova fiber
#

i dont have any plans on profiling the kernel anytime soon ngl

#

performance hasnt been an issue at all

nova fiber
#

i think the hardest part of testing a btree is just how much data it takes to actually fill up a tree enough for it to do interesting things

#

10 billion keys and its only got 4 leaves of depth

brave cape
#

well you could decrease the fanout of the tree for your tests. if the tree with 10 billion keys is 4 levels deep, that means you have like 100 or 300 or something sized nodes, which is a lot. if the tree works for 10 or so, it probably also works for 100

nova fiber
#

i now realize i can just use struct alignas(128) Key { int key; }; as a key rather than a plain int lol

nova fiber
nova fiber
#

Insert, find, and iterate work now

#

Delete seems tricky

nova fiber
#

swing is peak ui design

#

i must get java working in bezos

#

that was the original goal

nova fiber
#

man deleting from btrees is way harder than insertion lol

#

rebalancing leaf nodes is a hassle

nova fiber
#

turns out putting key value pairs in internal nodes rather than just the min or max key value makes things harder

#

i will not do that now

nova fiber
#

nevermind the alternative was even harder

#

god this tree is a pain in the ass to get right

nova fiber
#

on the bright side recursive lambdas are really nice

#
size_t countElements() const noexcept {
            size_t count = 0;

            auto countNode = [&](this auto&& self, const LeafNode *node) {
                count += node->count();
                if (!node->isLeaf()) {
                    const InternalNode *internal = static_cast<const InternalNode*>(node);
                    for (size_t i = 0; i < internal->count() + 1; i++) {
                        self(internal->getLeaf(i));
                    }
                }
            };

            countNode(mRootNode);
            return count;
        }
#

very shrimple

#

good feature i approve

trim owl
#

gobless

#

although passing the lambda as an argument to itself is also simple enough

nova fiber
#

that doesnt work if you have captures though does it?

trim owl
#

why not, just pass the lambda by ref

nova fiber
#

iirc it would make at least clang and gcc give up because they couldnt figure out the type of the operator()

trim owl
#

i haven't ran into that

#

i had some lambdas that took themselves as an arg and captured [&] in a recent algo & ds class project

#

and it built just fine with c++17

nova fiber
#

huh maybe i'm just skill issued

#

i guess im smoking crack

#

anyway back to my fuckass btree that refuses to work or be simple

nova fiber
#

shcokingly this works

#

current implementation leaves a ton of empty or nearly empty nodes but oh well :^)

nova fiber
#

java build systems are all as awful as i remember

#

really nasty stuff

#

anyway merging leaf nodes seems to work

nova fiber
#

can now rebalance and merge leaf nodes

#

next is internal nodes i think

#

then finally being able to shrink the depth of the tree

nova fiber
#

swing is the perfect retained mode gui library

#

less than 30 minutes to have something simple working

#

and i didnt want to blow my head smoove off the entire time so its already better than every js library ever written

#

i cant belive im saying this but maybe java applets werent so bad

#

also wtf why are the public amazon apis not turboass to work with

#

all the internal ones are so verbose i want to die everytime i use them

#

oh yeah osdev channel my bad

#

got btree stats working

umbral grotto
sour geyser
#

Retained, as opposed to immediate mode

#

You set up state to describe what and when to render and manipulate that

#

Rather than redrawing everything all the time

#

You'd be familiar with the idea, if not the name

umbral grotto
#

i see

nova fiber
#

So close to being done the btree

#

Well the functionality bit

#

I still need to make it oom resilient

#

And then add bulk updates to it as well

#

And alot more testing and probably performance tuning is needed as well

tropic berry
#

@nova fiber you alive?

#

please try the latest commit of Limine on your cursed laptop

#

see if it works

nova fiber
#

I will give it a go this weekend

tropic berry
#

it's saturday for me

tropic berry
#

i am fairly confident it is fixed

nova fiber
#

by latest commit do you mean to trunk or to 9.x

#

since the history has diverged a bit

tropic berry
#

both

urban schooner
tropic berry
# urban schooner what have you changed
        - PMM: Mark EfiLoader{Code,Data} regions as bootloader reclaimable
         rather than reserved memory, as for certain protocols, like the
          Limine boot protocol, reserved memory is unmapped at runtime, while
          these regions may contain hot data that is still needed, like Limine
          bootloader memory stacks.```
urban schooner
tropic berry
#

i am honestly not sure

#

well

#

this was a regression introduced by the new base revisions of the Limine protocol that actually unmap reserved memory

#

it was not an issue before then, obviously

#

as to why it worked afterwards, i'd say probably most firmwares do not put the initial stacks in those regions?

urban schooner
#

Hmm

tropic berry
#

either that or some caching shenenigans

urban schooner
#

Interesting

tropic berry
urban schooner
#

BTW apparently mapping high reserved memory as WB if its not covered by MTRRs can cause MCEs

#

On amd at least

tropic berry
#

well the new revisions do not map any reserved region, so i guess that is fine

urban schooner
#

Yeah as long as you only map usable ram

tropic berry
#

though that's weird

#

why would the motherboard care what the CPU maps stuff as, if it is not accessed?

urban schooner
#

Yeah apparently the CPU does some optimizations in the background and implicitly tries to access that as writeback

#

Which crashes

tropic berry
#

that's insane

#

what the fuck

urban schooner
#

Yeah

tropic berry
#

what motherboard/CPU reproduces the behaviour?

urban schooner
#

Linux had to add some workarounds for that

urban schooner
tropic berry
#

i mean sure, ty

urban schooner
#

Basically they had to change the logic for how they build their HHDM

#

To carve out usable ram and only map that

tropic berry
#

yeah so basically what revisions 2/3 of the lbp already moved to

urban schooner
#

Ye

tropic berry
#

insane, i moved to that just because i thought it was more sensible

#

and would avoid running out of RAM potentially if there were massive reserved regions

#

but like

#

i didn't know about this, that's convenient

urban schooner
tropic berry
#

how did you even run into this

urban schooner
#

Just studying how Linux builds their direct map

#

Looking at what abstractions they have etc

tropic berry
#

i see

#

well ty for letting me know, i will store this in my brain under the "AMD bullshit" category, along with the fact that you need to use rax to access ECAM space

urban schooner
#

Ill have to fix hyper to not do that as well

#

Yeah lol

#

So much bs from amd

olive musk
#

I'll have to fix my kernel not to do that too

#

So you ensure you just map usable memory?

urban schooner
#

Well for pages that aren't usable memory u map them as uncached

olive musk
#

I wonder how the guy even found where the bug came from lol

urban schooner
#

Or don't map at all

urban schooner
olive musk
#

So instead of blindly mapping the first 4 gib (or higher if you have more memory) I should just map usable entries

urban schooner
#

First 4g are covered by mtrr so u can blindly map

#

But above that yes

tropic berry
#

@nova fiber it is the weekend now

nova fiber
#

aye, i built the limine images i just need to monkey patch my kernel build again

nova fiber
#

yup works now

#

my kernel immediately explodes on this laptop but limine is fine

#

@tropic berry

tropic berry
#

yay ty

nova fiber
#

btree finally works

#

i dont think that was worse than the tlsf allocator in terms of difficulty but that was definetly more finnicky

#

so many edge cases

#

fun exercise though, but i think i'll hold off on implementing a b+tree

nova fiber
#

i've been robbed

#

thank god i setup cost alarms

nova fiber
#

man wtf is going on at java conferences

trim owl
#

allegro-sponsored hentai rental store in warsaw

brave cape
zealous mirage
#

there was a presentation at one titled, and i quote exactly, "CouchDB: Perform like a Pr0nstar", complete with a picture of a nude woman on each slide

#

this was what fired off the entire CoC movement in software

nova fiber
#

bruh

nova fiber
#

fixed yet another bug in the btree

#

woe 5 million edge cases be upon ye

nova fiber
#

i think i've beaten all the edge cases out of this damn tree

#

I dont trust the implementation so i think more tests are in order but if it does work then i have a btree thats resistent to oom

#

which i think is the last data structure i need to replace abseil and make my entire kernel oom resistent

nova fiber
nova fiber
#

now have some fuzz testing and stress testing for the btree and it seems to still work

#

performance is meh but i know a few things i did wrong that are easy to fix

nova fiber
#

looking at test coverage its not quite 100%

#

theres a few branches that are never taken

#

slightly worrying

#

A couple are because I dont have any tests for oom cases which is fine

#

one is that i never test the branch of splitting the root node when its an internal node

#

which is more concerning

#

anyway time for employment

nova fiber
#

i do not like being oncall

#

anyway adding custom allocator support

#

oh and custom comparator support

urban schooner
nova fiber
#

Custom allocators work now, and I also have test coverage for the oom cases

#

Just comparators left

#

The end is in sight for this damn btree

#

Oh I guess I'll need to implement another one for fs related stuff

nova fiber
#

Inb4 he spent his entire career writing btrees

calm shell
#

that guy (gordon letwin) implemented a b+tree for the hpfs driver for os/2 in 16-bit x86 assembly and it was so large that it needed to be split into different segments which would be explicitly hot-loaded in and out (potentially incurring segment swapping to disk), while doing an efficient b+tree rebalance on disk

#

in like 1985

#

so u have no excuse.

nova fiber
#

Oh man

#

I haven't even bothered to look at the code size of my btree lol

calm shell
#

and it worked perfectly. no bugs ever found

olive musk
#

Ok but he's never written a Cthulhu compiler has he

nova fiber
#

I'm hoping to at least manage the bug free bit with the amount of testing I'm doing

#

It helps that I can run 3 cpu hours of testing every minute on my machine meme

calm shell
nova fiber
#

I should setup some real™ fuzzing with afl for some of my code next probably. I imagine just using rng isn't catching everything

olive musk
#

Do you have kernel mode tests

#

Like kunit

calm shell
#

you can tell by the like sassy buzzfeed writing style

#

and the overuse of analogies

#

that dont quite fit

olive musk
#

No human would describe NTFS as a digital fort knox

olive musk
calm shell
#

also the emdashes

olive musk
#

Ah look at the author's description

#

"sent from my neural network"

#

Idk what that means exactly but even he admits this is AI

nova fiber
#

I think I'll try writing some new ones soon ish

#

My only tests like that right now are a script that launches every emulator I have with a kernel image

#

I should try to automate network booting again on some of my machines would be cool having a rack of actual test hardware

calm shell
#

will it be rock solid enough to forkbomb indefinitely and keep enough sanity for the user to recover

#

linux cant do that.

nova fiber
#

How would one go about doing that

calm shell
#

just do sane things when you run out of resources

nova fiber
#

How would you handle there's a bazillion processes sanely

calm shell
#

dont crash

nova fiber
#

Well yeah that's like the baseline

calm shell
#

linux crashes

nova fiber
#

Not sure how you'd make it remain responsive though

calm shell
#

thread priorities and pre-allocating anything needed for recovery

nova fiber
#

So marking interactive processes as very high priority

calm shell
#

something like that

nova fiber
#

Hmm fair enough

calm shell
nova fiber
#

I was expecting arcane scheduling algorithms and heuristic honestly

nova fiber
#

i now have actual fuzz targets for the btree

#

will run them for a few hours to see if anything crashes

nova fiber
#

ok 32 cpu hours of fuzzing and no bugs found

#

I think thats good enough for me

olive musk
#

you need to run them for a year

#

at least

nova fiber
#

hmm the abseil btree scales better than mine at large element counts

#

reducing the internal node size gets me closer to their performance at large element counts but its worse at smaller counts

#

ah right i remember my merging of nodes is stupidly badly implemented

#

n^2 complexity node merging trl

olive musk
#

I like doctest but idk if I should use gtest instead

nova fiber
#

gtest is pretty good in my experience

olive musk
#

and for fuzzing do you use google's fuzztest?

nova fiber
#

i just write llvm fuzz targets currently

olive musk
#

doctest is catch2 but doesnt take ages to compile basically

nova fiber
#

google fuzztest is a bit hard to build with meson

olive musk
#

ah

nova fiber
#

catch2 is really scuffed

#

dont like that library

olive musk
#

why?

nova fiber
#

it does all kinds of fucky stuff for no good reason

#

redirects stdout and stderr and applies broken formatting rules to it, installs exception handlers on windows which breaks alot of stuff

#

i think it also fucks with some signal handlers

olive musk
#

i think doctest is better

nova fiber
#

which is just like bruh

olive musk
olive musk
nova fiber
#
kernel
  - src
  - include
  - test
    - container
      - btree.cpp
      - btree_stress.cpp
      - btree_fuzz.cpp
``` currently
#

maybe eventually i'll have seperate folders specifically for fuzz targets

olive musk
#

ahh that makes sense

#

I will steal this

nova fiber
#

i also put the benchmarks in the same folder

olive musk
#

im testing C code tho

#

should still work fine

nova fiber
#

i mean you can have tests written in c++ for testing c code

olive musk
#

yea

#

C tests frameworks are lacking

#

compared to C++ ones

nova fiber
#

c doesnt really have the facilities for what makes test code nice to write

#

very hard to do automatic registration of tests

olive musk
#

yeah

nova fiber
#

annoyingly i think java probably has the best testing frameworks

#

junit5 is really nice to use

olive musk
#

what the fuck

nova fiber
#

bruh

nova fiber
#

I think clang has shit the bed quite badly

#

im not tripping that this is valid c++ ```cpp

std::vector<int> GenerateKeys(size_t count) {
    std::vector<int> keys;
    keys.reserve(count);
    for (size_t i = 0; i < count; i++) {
        keys.push_back(int(i * 10));
    }
    return keys;
}

std::vector<int> GenerateRandomKeys(size_t count) {
    std::vector<int> keys = GenerateKeys(count);
    std::shuffle(keys.begin(), keys.end(), mt);
    return keys;
}
#

ok thread sanitizer is tripping on data races to llvms coverage internals

#

hm nuking the build directory fixed it partially

umbral grotto
#

and how is a container overflow possible if the byte is 0 bytes within a 2044 byte region

#

also why is the region size not aligned to 8 bytes wtf

nova fiber
#

it was a false positive

#

really not sure what caused it though

#

I find it very aggravating that the clang and llvm teams went through alot of effort to make sure sanitizers dont break abi, and then google abseil just throws that out the window and makes enabling sanitizers change abis for like half their containers

#

more reason to be rid of it i guess

stone igloo
#

enabling extra checks in debug mode is reasonable

nova fiber
#

ah well i just disabled the 2 failing tests

#

will fix them some other time when i can be bothered to deal with picking apart the build graph

#

in better news my btree is now significantly faster than abseils

#
----------------------------------------------------------------------
Benchmark                            Time             CPU   Iterations
----------------------------------------------------------------------
BM_AbseilBtreeInsert/32         166697 ns       166694 ns         4321
BM_AbseilBtreeInsert/64         309305 ns       309304 ns         2105
BM_AbseilBtreeInsert/512       3374607 ns      3374569 ns          206
BM_AbseilBtreeInsert/4096     31639941 ns     31639079 ns           22
BM_AbseilBtreeInsert/32768   282632297 ns    282615806 ns            2
BM_AbseilBtreeInsert/131072 1200292838 ns   1200249039 ns            1
BM_BezosBtreeInsert/32            4492 ns         4492 ns       156003
BM_BezosBtreeInsert/64           13876 ns        13875 ns        50178
BM_BezosBtreeInsert/512         653867 ns       653844 ns         1071
BM_BezosBtreeInsert/4096       7534689 ns      7533914 ns           93
BM_BezosBtreeInsert/32768     68250443 ns     68250797 ns           10
BM_BezosBtreeInsert/131072   356750578 ns    356751991 ns            2
``` pretty happy with this
olive musk
#

did you enable optimizations?

#

at some point I thought I was beating abseil's hashmap

#

but optimizations werent enabled meme

nova fiber
#

fair point

olive musk
#

because abseil handles optimizations very well usually and is significantly faster

nova fiber
#
----------------------------------------------------------------------
Benchmark                            Time             CPU   Iterations
----------------------------------------------------------------------
BM_AbseilBtreeInsert/32           1016 ns         1016 ns       704989
BM_AbseilBtreeInsert/64           2235 ns         2235 ns       313278
BM_AbseilBtreeInsert/512         24204 ns        24203 ns        29537
BM_AbseilBtreeInsert/4096       370072 ns       370073 ns         1962
BM_AbseilBtreeInsert/32768     3479640 ns      3479541 ns          202
BM_AbseilBtreeInsert/131072   15598496 ns     15598276 ns           43
BM_BezosBtreeInsert/32             348 ns          348 ns      2062867
BM_BezosBtreeInsert/64            1114 ns         1114 ns       618366
BM_BezosBtreeInsert/512          69912 ns        69913 ns         9617
BM_BezosBtreeInsert/4096        821538 ns       821521 ns          843
BM_BezosBtreeInsert/32768      7343610 ns      7343648 ns           93
BM_BezosBtreeInsert/131072    38884775 ns     38884592 ns           18
----------------------------------- stderr -----------------------------------
``` hm i still do better at smaller element count but my node splitting is a bit inefficient
olive musk
#

yeah they tend to optimize larger sets I guess

nova fiber
#

i think its just because my rebalancing and splitting is implemented in a really stupid way lol

olive musk
#

but still that is very good considering most times your kernel wont have that much optimizations enabled and your thing is freestanding

nova fiber
#

I havent a clue, is the rust btree any good?

nova fiber
#

anyway now that the btree works back to scheduling

#

i have some actual unit tests for this one

nova fiber
#

spent 2 hours tracking down a bug in the scheduler and it was actually a bug in my test code

nova fiber
#

so my scheduler works fine but my tests are flakey because the linux scheduler will sometimes decide to just not schedule the test thread for long enough

#

very annoying

#

ok finally got the tests not flakey i think

nova fiber
#

fun leenox thing i have discovered

#

there appears to be a quite low upper limit on how many signals you can send per second that seems to be tied to each hardware thread

#

which i imagine in 99.9% of code is not an issue

#

but my entire test infrastructure depends on being able to yeet around signals

#

halfmemeright at least it helps me discover race conditions

#

actually this limit might be global

#

does linux take some big lock somewhere when sending a signal

#

if i run the same test on 64 threads it takes about 900ms per run, but if i run the same test on 128 threads it takes up to 2000ms

calm shell
#

there are terrifying implications about the existence of some evil flag on some evil syscall somewhere if they were forced to do a big lock around signals

nova fiber
#

in my case these are signals sent with pthread_sigqueue so maybe thats a special case or something

#

surely signals that get routed back to the current process or thread dont have this behaviour

#

i hope

nova fiber
#
[----------] Global test environment tear-down
[==========] 4 tests from 1 test suite ran. (1518 ms total)
[  PASSED  ] 4 tests.
----------------------------------- stderr -----------------------------------
==494247==WARNING: ASan is ignoring requested __asan_handle_no_return: stack type: default top: 0x755801efee80; bottom 0x77f8042e3000; size: 0xfffffd5ffdc1be80 (-2886255657344)
False positive error reports may follow
For details see https://github.com/google/sanitizers/issues/189
``` never seen this before
nova fiber
#

made my btree a little more correct™ in respect to move semantics

#

so i should be able to put unique_ptrs into it

nova fiber
#
----------------------------------------------------------------------
Benchmark                            Time             CPU   Iterations
----------------------------------------------------------------------
BM_AbseilBtreeInsert/32           1004 ns         1004 ns       702164
BM_AbseilBtreeInsert/64           2237 ns         2237 ns       309835
BM_AbseilBtreeInsert/512         23656 ns        23656 ns        29687
BM_AbseilBtreeInsert/4096       366434 ns       366425 ns         1937
BM_AbseilBtreeInsert/32768     3494527 ns      3494471 ns          201
BM_AbseilBtreeInsert/131072   15795159 ns     15787811 ns           44
BM_BezosBtreeInsert/32             397 ns          397 ns      1741940
BM_BezosBtreeInsert/64            1089 ns         1089 ns       649221
BM_BezosBtreeInsert/512          44395 ns        44395 ns        16188
BM_BezosBtreeInsert/4096        535292 ns       535283 ns         1274
BM_BezosBtreeInsert/32768      5008254 ns      5008275 ns          139
BM_BezosBtreeInsert/131072    22207820 ns     22206906 ns           32
BM_AbseilBtreeFind/32              220 ns          220 ns      3224565
BM_AbseilBtreeFind/64              538 ns          538 ns      1286350
BM_AbseilBtreeFind/512            6774 ns         6774 ns       106461
BM_AbseilBtreeFind/4096         107758 ns       107347 ns         6368
BM_AbseilBtreeFind/32768       1663392 ns      1663395 ns          422
BM_AbseilBtreeFind/131072      8411123 ns      8411073 ns           83
BM_BezosBtreeFind/32               214 ns          212 ns      3288641
BM_BezosBtreeFind/64               507 ns          507 ns      1382288
BM_BezosBtreeFind/512             6622 ns         6622 ns       105640
BM_BezosBtreeFind/4096           62806 ns        62806 ns        11134
BM_BezosBtreeFind/32768        1549433 ns      1549365 ns          447
BM_BezosBtreeFind/131072      13093260 ns     13092940 ns           54
``` inching closer to abseils btree
nova fiber
#
BM_AbseilBtreeFind/32              210 ns          210 ns      3373836
BM_AbseilBtreeFind/64              522 ns          522 ns      1328218
BM_AbseilBtreeFind/512            6569 ns         6569 ns       106476
BM_AbseilBtreeFind/4096         101972 ns       101969 ns         6651
BM_AbseilBtreeFind/32768       1673233 ns      1673149 ns          419
BM_AbseilBtreeFind/131072      8359888 ns      8359453 ns           84
BM_BezosBtreeFind/32               212 ns          211 ns      3326127
BM_BezosBtreeFind/64               507 ns          507 ns      1383173
BM_BezosBtreeFind/512             6912 ns         6912 ns       100871
BM_BezosBtreeFind/4096           81907 ns        81906 ns         8568
BM_BezosBtreeFind/32768        1434938 ns      1434941 ns          487
BM_BezosBtreeFind/131072       7289521 ns      7288763 ns           96
``` google eat your heart out
#

insert is still lagging behind a bit but i know why now

#

I think i might be able to beat googles insert by alot with a bit more effort

#

google doesnt use a floating node start point which i think i should be able to implement

nova fiber
#

storing the parent index in each child node lost me about 1% performance

#

and it destroyed the debug performance

#

not doing that

nova fiber
#

seeing as it wasnt that im not sure what abseil is doing that im not

#

oh hm maybe its the data layout

#

abseil stores pair<key, value> data[] in its nodes, i store key keys[]; value values[];

#

so i suppose it would make sense their insert is faster because the insert has better locality

#

and my find is better because it has better locality when searching

#

abseil also uses significantly smaller node sizes than i do

#

they target 256 bytes per btree node and i target 4k, so my search has a much shallower path

#

but rebalancing is going to be more expensive

#

i wonder if fiddling with the target node size could improve performance

#

the bigger the node the faster the search and the slower the insert

#

i guess that makes sense

#
----------------------------------------------------------------------
Benchmark                            Time             CPU   Iterations
----------------------------------------------------------------------
BM_AbseilBtreeInsert/32            980 ns          980 ns       718313
BM_AbseilBtreeInsert/64           2189 ns         2189 ns       323443
BM_AbseilBtreeInsert/512         22612 ns        22612 ns        31039
BM_AbseilBtreeInsert/4096       351221 ns       351223 ns         2010
BM_AbseilBtreeInsert/32768     3401683 ns      3401557 ns          207
BM_AbseilBtreeInsert/131072   15356178 ns     15355598 ns           46
BM_BezosBtreeInsert/32             370 ns          370 ns      1909469
BM_BezosBtreeInsert/64            1050 ns         1050 ns       656605
BM_BezosBtreeInsert/512          18329 ns        18329 ns        37530
BM_BezosBtreeInsert/4096        192800 ns       192799 ns         3544
BM_BezosBtreeInsert/32768      2616822 ns      2615590 ns          265
BM_BezosBtreeInsert/131072    12181829 ns     12181126 ns           58
BM_AbseilBtreeFind/32              225 ns          225 ns      3109016
BM_AbseilBtreeFind/64              558 ns          557 ns      1292646
BM_AbseilBtreeFind/512            6849 ns         6848 ns       102231
BM_AbseilBtreeFind/4096          99543 ns        99543 ns         6388
BM_AbseilBtreeFind/32768       1675751 ns      1675628 ns          412
BM_AbseilBtreeFind/131072      8414508 ns      8414289 ns           83
BM_BezosBtreeFind/32               211 ns          211 ns      3318670
BM_BezosBtreeFind/64               506 ns          506 ns      1378679
BM_BezosBtreeFind/512             7200 ns         7200 ns        97214
BM_BezosBtreeFind/4096           81420 ns        81420 ns         8649
BM_BezosBtreeFind/32768        1507127 ns      1507130 ns          461
BM_BezosBtreeFind/131072       7104118 ns      7103604 ns           99

success

#

and i will note that my node size is still 4x the google one

#

i guess doing SOA rather than AOS makes quite a difference

#

although saying that in real™ usage im going to keep the node size to either the disk block size or the isa page size

#

but good to know that my btree isnt too much of a slouch

nova fiber
#
BM_AbseilBtreeErase/32             336 ns          336 ns      2082525
BM_AbseilBtreeErase/64             679 ns          679 ns      1018326
BM_AbseilBtreeErase/512           5383 ns         5383 ns       130322
BM_AbseilBtreeErase/4096         43505 ns        43505 ns        16270
BM_AbseilBtreeErase/32768       344294 ns       344295 ns         2014
BM_AbseilBtreeErase/131072     1416851 ns      1416857 ns          469
BM_BezosBtreeErase/32             26.7 ns         26.7 ns     26035775
BM_BezosBtreeErase/64             54.2 ns         54.2 ns     11838819
BM_BezosBtreeErase/512             437 ns          437 ns      1589267
BM_BezosBtreeErase/4096           3383 ns         3383 ns       205233
BM_BezosBtreeErase/32768         27143 ns        27142 ns        25560
BM_BezosBtreeErase/131072       110609 ns       110610 ns         5650
``` i also demolish abseil on erasing elements
nova fiber
#

actually i was benchmarking erase a bit incorrectly

#

im a touch slower than abseil

nova fiber
#

anyway back to actually working on the kernel

#

new scheduler is looking alot less unstable

#

will see if i can hack together some test images so i can test them a bit more thoroughly

#

signals are pretty good but emulating page tables swapping and other systems interacting with it is a bit painful still

nova fiber
#

I have forgotten what the apic ISR is for

#

why are timer interrupts not being delived on my bsp thnk

#

Oh i think the problem is the PIT is still running, and i don't have an interrupt on the PIT IVT entry so i never send the EOI signal

#

so i then never get another interrupt because of that

#

that seems plausible

nova fiber
#

bruh i spent like 2 hours debugging why task switching wasnt working

#

it was working the entire time

#

i forgot that my logging was async so the buffer was filling up faster than it could flush so it looked like only one task was ever beeing ran

calm shell
#

lol

nova fiber
#

on the bright side i was at least able to use said logger to debug this since its entirely reentrant

#

you win some you lose some

#

and just in case i now have a test to ensure that my scheduler is somewhat fair

olive musk
#

man is the unit test lord

#

is that in kernel mode still?

nova fiber
#

all my scheduler tests are still in usermode

olive musk
#

ah still very cool

nova fiber
#

i've been working on making proper test images so i can run gtest in kernel mode but thats taking a bit

olive musk
#

you could do something like kunit

nova fiber
#

kunit is loadable kernel modules that poke stuff right?

olive musk
#

I think it's basically unit tests as loadable modules yea

nova fiber
#

at the point i have loadable modules i'll definetly look at that

olive musk
#

you can do it without modules too

#

opt-in on compilation or something

nova fiber
#

i mean thats basically what my test images are right now

#

they just have a different kmain function

#

but being able to run all the tests in a single vm would probably be good

#

right now i launch a qemu domain with libvert per test suite

#

i really need some way of launching the tests in every vm i've got

#

qemu is a bit lax

nova fiber
#

im able to test my multicore scheduler but addrsan isnt able to cope

#

pain

nova fiber
#

figured it out

#

had to send an extra interrupt to each thread

nova fiber
#

all the llvm sanitizers remain very unhappy though

#

i guess completely nonlocal control flow and custom thread context switching doesnt agree with them

nova fiber
#

man these scheduler tests a bit flakey no matter what i try

#

im at the mercy of the linux scheduler to actually give the tests enough of a timeslice to run within time

#

does linux have anything in the way of "please give me the next 200ms of cpu time on this core" or equivalent

#

pthread_attr_setschedpolicy seems to be round about what i want

nova fiber
#

setting the scheduling policy seems to kinda help

#

not sure how i'd integrate sudo setcap CAP_SYS_NICE+ep into the build process sanely though lol

#

I guess as part of the build i could add some stuff to the sudoers file to allow that to be invoked specifically on the tests that need it

iron mist
#

so just set the scheduling policy to that for 200ms

nova fiber
#

integrated it into the kernel and it seems to be working

nova fiber
#

Got some basic sleeping implemented, still need to test it though

hollow gorge
#

wut is going on here

#

ohhh you save all registers

nova fiber
#

Yeah it's a touch silly, I should probably clean up some stuff

nova fiber
#

got some basic tests for sleeping

#

seems to work properly

#

testing timing sensitive stuff is kinda hard

hollow gorge
#

make a realtime thread priority

nova fiber
#

i mean unit testing it, actually verifying it works manually is fine

#

i dont particularly want to mark all my tests with a bunch of SUID bits to make them run properly

nova fiber
#

slightly random but got my c++ docker client working enough to use for testing stuff

#

used testcontainers a bit on some java project and im pretty sold with the experience

#

very good idea to be able to create a docker container with a database or something in it for unit tests

nova fiber
#

very nice

#

anyway back to OS stuff, im actually integrating the scheduler into my existing system so i hope to have a working userspace again soon

#

or at least a less unstable one

nova fiber
#

man actually integrating the scheduler is a bit painful

#

i dont want to just shove void*s into the scheduler entry struct but i dont have any good way of getting the associated system thread from the scheduler entry

nova fiber
#

my current scheduler holds scheduler entries, but a scheduler entry alone is not enough to reconstruct a tasks state so it can be run. i need stuff like the kernel syscall stack pointer and extra bits i don't store in the entry

#

and i cant think of any good way of getting that context from the scheduler entry that isnt either really fucky offsetof hacks or just cramming random pointers into the scheduler entry

hollow gorge
#

so like thread queues?

#

or what

nova fiber
#

I have a scheduler entry which contains everything the scheduler needs to know ```cpp
struct SchedulerEntry {
uint64_t mId;
std::atomic<TaskStatus> mStatus{TaskStatus::eIdle};
std::atomickm::os_instant mSleepUntil;
TaskState mState;
};

```cpp
struct Thread {
        sm::RcuWeakPtr<Process> mProcess;

        /// @brief Intrusive sheduler entry block.
        task::SchedulerEntry mSchedulerEntry;

        km::StackMapping mKernelStack;
        km::StackMapping mUserStack;
};