#uACPI - a portable and easy-to-integrate ACPI implementation
1 messages · Page 37 of 1
i love this trick
also, you don't have to deal with concurrency as much if you don't want to with microkernels
that's interesting
now that I think of it
I wonder how the performance of the two approaches compare on modern hardware
nowadays with ASIDs and assuming that most interdomain calls will be to do a small amount of work, i think more preferable is to try to call into a cpu local thread
i expect the overhead of migrating between processors will dominate the gain from not losing the l1 cache, which you may lose anyway if the system is loaded enough that the calling thread doesn't simply leave the core unburdened but is rather scheduled out
would it be stupid to just use a stripped down linux as a base for a "microkernel" based operating system lol
i had this idea just now, just disable everything that can be disabled and implement everything in userspace 
you can't disable all that much on linux i think
it would probably be a decent amount of work to expose the stuff you need to userspace and even if you strip away a lot of the config options its going to be monolithic having almost all of the syscalls
a lot of the abstractions that linux uses to expose info that drivers need to userspace rely on having fully functional drivers for those devices in the first place
i dont care
plus it has no way to process IRQs fully in userspace, you need a hardirq handler for every device in kernel
i just want pci in userspace
well Linux is open source. so you can fork it if you want to rewrite it into a microkernel
but you would have to rewrite a lot
it'd probably be more effort than just writing a microkernel
yeah its likely easier to design a kernel with it in mind from the start than to try converting linux
:(
small functional microkernel is like 10k LoC
yeah i mean, you can do port io in userspace + you can map mmio so it's not that crazy
i like the idea of just using userspace apis for everything in uacpi tho lol
I think that's slightly lower than what nyaux gets without ubsan actually
Idk how much has changed since then but when I fixed its allocator bug it got 1M
Might be due to cpu model though
ubsan had a decent hit in my kernel actually
I just changed to using hpet
Probably host system scheduling
qemu on native linux
tends to happen
my kernel swings around 200k points from time to time
old proxima on my cpu has multiple performance ranges: 4.0-4.4M, 5.0-5.3M, 6.5-6.7M, 7.5-7.7M
I believe each range corresponds to a different host cpu speed setting
so now it swung by 700k+
you probably have a range at ~500k and at ~1.1M
just take whatever is the highest 
lol
I dont want to submit this as an actual score
im using a shitty heap I cooked up to see how much my heap is impacting perf
before using this heap I got 34k
Proxima's scores are the ~median of the highest performance range
pmos has gotten 3.3M with dlmalloc, which is best-fit 
on top of first fit vmm and segregated fit pmm in kernel
sadly i still dont have a new number with my new mm/alloc, thanks to my page allocator is panicking like halfway through init
Lol
Letsgo
i don't remember which microkernel came up with it but there's microkernels where tasks can choose which vmm they want to use (which are also userspace
iirc fuchsia has that
@vagrant hull btw did u figure out the ironclad bug on your laptop?
Can uACPI Generate aml
What do you mean by generate aml?
Something like iASL
Its not a compiler
ok
L4 probably as well
Do you mean pagers?
yep
some designs have pagers per process, some have pagers shared across processes with a default pager
But that's more of a pmm though
i thought it handled paging in and out too?
I have pagers per memory objects
But it's up to the kernel to decide (I think)
That's what I'll do
When a thread accesses a page that is not present, it is stopped and kernel asks the pager to provide it
i don't really want to overengineer my pmm/vmm in my first attempt at a microkernel so I'll keep them in kernel and might move them out at some point
Even Linux has it
How do you do mmap though
hmmmmmmmmmmmmmmmmmmmmm
sus
both values
I don't return higher half address from any of my api functions
that's not higher half, that's kernel image
which is even more fucked
actually addr is supposed to be a physical address there so it's worse than i thought
whats the advantage of a per process vmm?
?
was a question to a discussion further up the chat
its the next generation os, a os for 128bit cpu's
as far as I can tell, it happens after this line: https://github.com/uACPI/uACPI/blob/80b4e1ec7f1774b445a4f3011c49251c2396e3e4/source/registers.c#L552
before unlock
so in do_write_register
hmm but I don't think that calls uacpi_kernel_map
definitely after line 533
@fiery turtle any tips? 🥺
Uncurse your kernel
No idea sorry lol
Printf debugging
Do write most likely dispatches into your api
It's not per process, but more of per mmap region, with several regions being able to have the same pager
So that filesystems in userspace can read data on demand from disk and whatnot
smh
invalid opcode
-fno-omit-framd-pointer and %rbp?
just the last value of rip and then nothing
Is this the qemu blob?
?
the one that breaks in your kernel
idk maybe your kernel is cursed or smth

or you have elves playing around with your computer
this kernel can go and shit itself
I'm done smh
osdev gang just shilled uacpi to FreeBSD at fossdem
Upstream uacpi coming soon to the BSDs
Lol for real?
lmao
to obiwan himself
based
Based af
based af
imagine uacpi in bsds before uacpi in linux
i wonder what the BSDs would get in the leaderboards
ig what's left is uacpi in NT
imagine all major operating systems using uacpi
major operating systems include reactos and bsds and haiku
may i introduce you to https://www.youtube.com/watch?v=gUEzkglsXn4
true
pure ecstasy
yea that's 😎
i should play around with reactos one day
or potentially make my own NT clone
or hear me out: darwin clone?
Based
cloning a proprietary os bug-for-bug (including driver interfaces and stuff) sounds fun
NT is the top candidate there sadly
i am working on my own, sort of, nt clone
wish there was an alternative
because NT is already done kinda
with reactos
i want an nt like architecture but native posix support
take NT 4 and fix its posix subsystem
idk how that last part is gonna work yet, but we'll see
i wonder how unhappy windows drivers would get if they were ran in userspace
at least amd gpu driver would not be happy lol
surely microsoft abstracts away quite a lot of stuff in the driver interface
then why don't drivers just work in WoA?
most stuff is abstracted away by the kernel itself already
probably because x86->aarch64 jit in kernel isn't that great of an idea
it uses cr registers for something (I think virtualization detection), though ofc you could emulate that with sigsegv handler (and same for the fixed-address shared data page that contains stuff like the system time)
hmm
don't give me ideas
i had a x86 emulator and was thinking about adding dynarec to it
you mean bad ideas?
ye
no problem
this stuff
how do you know this
it's in the public kernel headers
ah
drivers use this
yeah the driver kit headers contain this stuff
I thought qwinci just broke an NDA
the same shit is mapped in user mode at 0x7ffe0000
though as read only memory
in kernel it's mapped read write
for obvious reasons
no for running it in userspace
luckily you can catch exceptions when accessing addresses > user space end iirc
i mean i guess that is kinda obvious
I know how hard would it be from reactos lol
kinda based
and under BSD tutelage uacpi remains an independent project
Damn, which language and do u have a src
rather than getting sucked up into the linux code and the beloved kernel api getting replaced with direct calls

i will probably put it on github the moment i have a working loader
oh hey same, though mine has already diverged a lot and is zig
more like nt-inspired than an nt clone
Loader?
yeah im just inspired by the nt architecture, i dont really aspire to be an actual nt clone
prepares some structures for the kernel, loads it and the drivers
not sure what it'll do just yet
And thats loaded by limine?
but i know i'll do the initial loading and mapping of kernel and some drivers
yeah, for now
Like eir
basically
I see
i want to have a pure efi loader at some point too
Is your kernel a pe
Ah
while pe would be much easier to work with, and im more famiilar with it, i think i want to use elf
one nice thing I discovered is that with clang you can use x86_64-unknown-windows-elf target to get the ms calling conv (as it doesn't support gcc's -mabi=ms) in an elf file
ive considered pe now that limine can boot it but zig cant get stack traces on pe without windows being there but it can iterate on the base pointer easily on elf
gcc and clang are generating PEs with DWARF sections for debug info iirc
not the true and authentic format normally used for them
stack unwinding is broken tho as gdb doesn't support seh and afaik they still generate seh unwind info
even with frame pointers enabled I couldn't get it to work nicely, stuff like finish or stepping out of a function just continued the execution and backtrace only showed the current frame (or the one directly before the current one if lucky)
yeah its a bit of a mess, thats why i dont try to use pe for my zig stuff too
Why is that?
Also why not zig btw
PE is just
here's a list of sections, load them into memory
here's a list of relocations, u have to implement like 3 types of relocations - done
here's a list of external functions i want and where to find them, pls put the addresses there
ELF is similar in some regards, it's not hard by any means, but i am not familiar with ELF relocations at all, and external symbols in ELF executables work different and i find it weird how they work, also there is two different types of relocations? rel and rela, from what i gathered it's just implicit addend vs explicit addend, but i prefer the way PE does thing
also i thought about zig for a moment but i don't want to fight the compiler, i just want to write working code 
side note on the stack trace stuff, im really looking forward to https://github.com/ziglang/zig/pull/22077 so i can use the std stack trace printing and also get more info than i already have from the trace print
rel vs rela is easy, but each architecture has like 10 ways to calculate the relocated address
ive not had to fight the zig compiler much at all for my zig kernel so its def not bad compared to what it used to be
based
on one hand it allows for some very nice features (like ifunc) but on the other it is much more annoying to implement than pe relocation
yeah no, i'm not saying that, i just don't feel like trying to do dynamic linking in zig
i haven't done that and i don't want to find out what it takes lol
actually looks like it does support it
idk why it didn't really work even with dwarf info then
oh god yeah if youre doing dynamic linking then i understand. zig is very much not built to do that at the osdev level in my experience
we're @ FOSDEM now we did not have time
we shilled uACPI to obiwan after their FreeBSD modern standby talk
i like making fun of the ACPICA maintainer smashing the corvette
we already know 
lmfao
lol
I just imagine like Obi-Wan sitting in front of a computer and being like... I feel a disturbance in the VMM...
I have uncursed my kernel and I hate myself even more now
when I added v1.0 api sized io functions, I kept my old one that had a switch with sizeof(type) cases. I passed 8, 16 and 32 as width instead of 1, 2 and 4 from the respective uacpi functions. I was calling fucking std::unreachable in default: case
with v1 I get more points on my shitty cpu than on i7-13700k previously
but could a kind good cpu haver test it?
qemu-system-x86_64 -serial stdio -cpu host,migratable=off -M q35 -accel kvm -cdrom image-x86_64.iso
run a few times as difference can be a hundred thousand points
~4.1M/s on ryzen 5800x
thank you
I should also update to uacpi 1.0 and see what score I get
(on the nt thing, I implemented some of the stubbed uacpi apis like events/mutexes yesterday as I got around to implementing KeReleaseSemaphore/KeWaitForSingleObject)
could you try this as well? I get 900k more points
~4.9M
I wonder how IA32 pmOS will perform (since AMD64 is just an insane mess) 
apparently its around the same
@fiery turtle 
i can get an exact number to put on the leaderboard if you want
[00:00:00.002049] [info] uacpi: successfully loaded 1 AML blob, 1705 ops in 0ms (avg 4906870/s)
wait how tf do u get more than proxima
queued 
ah
still pretty insane
didnt know your os was that fast
thanks!
anything else queued? because that would put me in the second place on the current leaderboard, or third with qwinci kernel included
monkuous is an osdev magician
i think davix improvements also but they havent submitted them for the leaderboard yet
maybe I should also get this thing on the leaderboard after I implement the rest of the functions (well its mostly just the pci stuff that's missing), though Ill have to also come up with a name for it and put it to git 
I think a big factor to the score when compared to crescent is that I didn't spam cli;pushf;sti everywhere lol
wrong... I have plans on improving my allocator but haven't actually done anything yet
also, it fluctuates between like 600K and 2M
might be host power management stuff
what about qacpi?
i should submit a score to the leaderboard some day
that would be a welcome addition
unfortunately i haven't one yet as keyronex itself is missing high resolution time of day (that was only in the testbed kernel) and that's a task to be dealt with after i've done the driver framework work and some usb stuff
makes sense
[00:00:00.004587] [info] uacpi: successfully loaded 1 AML blob, 1705 ops in 0ms (avg 5531368/s)
intel W once again
i wonder if i could get a better score more reliably by running linux on bare metal
a tiny upgrade
[00:00:00.003999] [info] uacpi: successfully loaded 1 AML blob, 1705 ops in 0ms (avg 5662213/s)
Ill have to test after I integrate it + come up with some kind of abstraction
@fiery turtle i think i found a uacpi bug, if in create_gpe_block any of the uacpi_map_gas_noalloc calls fail after gas_validate, the cleanup uninstall_gpe_block calls uacpi_unmap_gas_nofree on the register whose map call failed, which tries to call gas->unmap, which is null because the map call didn't fully complete
to reproduce this just make uacpi_kernel_io_map unconditionally return an error, calling uacpi_namespace_load will trigger the bug (with qemu's blob at least)
doesnt it check for reg width before unmapping which would be zero there?
it's not zero because gas_validate succeeded
can reprod on obos
it happens when gas_validate succeeds and either of the map calls fail
?
stack trace i assume
just a stack trace
ah
ah, yeah I think it would be nice if I can just come up with good enough abstraction so that I don't have to duplicate code or make it full of ifdefs lol
are you using c++ btw?
thank you very much
infy I hope you'll use this one :p
which cpu
i7-13700k
sure
holy crap
i am slowly starting to dominate the uacpi benchmarking scene
with 4 scores being tested by me 
step it up smh
I was compiling uacpi before with optimisations disabled for some reason
me too
i am planning on having a decent IO + PnP subsystem so hopefully i can just have a pluggable acpi.sys
for some reason i am faulting in uacpi now
I'm not at home to submit the new build 
pmOS is -O3 + lto + AVX512 
fym avx
it's userspace
that makes me wonder, would it be cheating to run uacpi as a single-threaded userspace server and take advantage of that by stubbing out mutexes
like you're not sacrificing capability
sounds fair
I can't avoid mutexes in malloc because I have a libc thread for every process 
just make a uacpi-specific malloc implementation
malloc server 💀
bruh why is lto compiling out all uacpi's symbols
why wouldn't it
nothing in my static library persists after enabling lto in uacpi
they aren't needed
like most of them
oh 
you dont enable lto in uacpi
you enable lto in your kernel
sounds fair
?
from what i understand he compiles uacpi and makes a static library out of it
which then he links into his kernel
yes
you do still need to enable lto for the static library
but you need to make sure to use gcc-ar instead of normal ar
ah there u go
i thought lto is a linker arg
wasnt sure how it affects the compilation itself
it's both compiler and linker
lto is linker+compiler iirc
lto isn't possible unless the compiler generates IR instead of machine code
ohh right
anyway I'll deal with that later
(never, I don't give a damn about lto atm)
I want to debug /bin/sleep
(it just hangs)
uacpi shilling to haiku done
lmfao basesd
holy based
haiku is nice although i know 0 about beos or whatever its basd on
acpica
haiku pr when

when haiku maintainers get around to it 
can u let me know if this fixes it:
--- a/source/io.c
+++ b/source/io.c
@@ -838,10 +838,6 @@ uacpi_status uacpi_map_gas_noalloc(
if (ret != UACPI_STATUS_OK)
return ret;
- out_mapped->access_bit_width = access_bit_width;
- out_mapped->total_bit_width = total_width;
- out_mapped->bit_offset = gas->register_bit_offset;
-
if (gas->address_space_id == UACPI_ADDRESS_SPACE_SYSTEM_MEMORY) {
out_mapped->mapping = uacpi_kernel_map(gas->address, total_width / 8);
if (uacpi_unlikely(out_mapped->mapping == UACPI_NULL))
@@ -860,6 +856,10 @@ uacpi_status uacpi_map_gas_noalloc(
out_mapped->unmap = unmap_gas_io;
}
+ out_mapped->access_bit_width = access_bit_width;
+ out_mapped->total_bit_width = total_width;
+ out_mapped->bit_offset = gas->register_bit_offset;
+
return UACPI_STATUS_OK;
}
yeah, works now
cool thanks for being vigilant lol
wasn't really a matter of being vigilant, i made a very small uacpi impl to test the performance of my rewritten kernel and ran into it
ah
how did that go btw
pretty much the same performance, which is what i expected and wanted, just wanted to make sure i didn't accidentally regress anything
is that in kernel land still?
yes
no - this is temporary and small, just to test performance of basic kernel stuff. the only reason i did it was to check i didn't introduce any regressions compared to the prev rewrite
makes sense
@fiery turtle is there a way to replace e.g. uacpi_kernel_alloc with my own definition, so that I can e.g. inline some stuff if __builtin_constant_p (size)?
lto
lto is kinda "meh" in this situation
that doesnt really work because kernel_api.h still defines the prototype
yep.
how does it not work? the compiler will then see the definition
because multiple definitions of a global symbol
you make it inline?
cannot change the definition in uacpi/kernel_api.h though
I'd assume its enough if the definition is marked inline
basically this is my kmalloc:
I think it would work if you'd just make it normal inline inside uacpi_libc.h (though then you need to also instantiate it once in some source file because the way inline works in c is stupid)
if you make it normal inline you'll get multiple definitions
in c++ you'd get sane inline behavior :^)
nope... does not work
if you can get this definition to be included before kernel_api.h it'll work
you do have to use static in that case
if it's included afterwards, you get a compiler error
ah yeah
but like
it's the world biggest hack but it works
why isn't lto sufficient for this
but I won't use it, because it's too hacky
how is it hacky
my build system is... weird
ah
I guess I can just
void *
uacpi_kernel_alloc (uacpi_size size)
{
if (size == 32)
return kmalloc (32);
else
return kmalloc (size);
}
so it will slightly optimise the common-case of allocating 32-byte objects
but there are bigger, more important performance improvements to do
maybe also add likely there?
nahh
the branch predictor is sufficient
also I don't want to move that other kmalloc to a cold section
__builtin_expect actually makes a pretty huge difference in performance
i forgot the exact numbers but it's very much not insignificant
but anyways, I won't do this. Instead I will work on CPU-local object bins for slab
which requires runtime allocation of CPU-local storage, the way I plan on doing it.
the thing is, since slab uses this dynamic runtime allocation of CPU-local storage, the implementation of dynamic runtime CPU-local storage allocation cannot use slab
though that's not a problem (just don't support free and it's fine)
solaris fixes this by allocating cpu-local storage using vmem
I'll probably do something similar
rustc (vmem shill)
the solaris allocation stack is very well made
there's a reason why everyone stole it 
theres different branch preditiction stuff for cold vs just unlikely
for now I'm just going to bump-allocate from a 16KiB or so statically allocated region. later I might reserve like 1MiB virtual address space and only actually populate it with physical pages when needed
(16KiB/CPU)
this is what the fastpath of my new slab allocator implementation will look like
sadly, it loses the ability to allocate memory in IRQ context
I can have a separate IRQ-safe allocator
Don't you want to preempt_on even if num is zero
but yeah... good point
I moved the initial preempt_off () to outside of the first branch
won't affect perf
will make code simpler
👍
ok... the fastpath for allocation should be like 20 instructions or so
but I gotta write the slowpath too
Might try porting uacpi
They have their own fork of ACPICA basically
No clue how much they changed
thats every os
because u cant integrate it without forking
u have to change headers and stuff i think
Didn't know ACPICA was that bad
Which Linux forked for themselves?
sorta
acpica has native linux support scripts inside the repo
and headers as well
you can kind of upstream support with your headers if your os is popular
lol
1.35M on my 5800x
using qemu-system-x86_64 -accel kvm -cpu host,migratable=off -M q35,smm=off -drive format=raw,file=pmos-hyper.img (yes i know it's i386)
do you have an x86_64 image for comparison?
what the fuck that's faster than proxima and it's running in userspace
hold on
pmos i386 is now the top of the leaderboard lmfao
actually it probably wouldn't be faster than proxima if proxima didn't suffer from the intel lock cmpxchg shit
i need to add fast (or rather not insanely slow) ipc stuff to x86_64 and check if it gets the same performance...
it varies wildly but i think it's due to wsl, mostly consistent around 5.5-6M
like to see if this performance is credible
i need to resume work on sirius (my i386 os) damn
probably not
possibly due to this
proxima doesnt use ipc at all and it gets less
and also temp mapping are 2 tlb misses instead of 4
hold on let me fix x86_64 build
(I don't even know if it compiles)
Also I have some "temporary" chatgpt generated code in timers, so they could be broken
☠️
inb4 this is actually 800K
It was giving about the same score as 64 bit build on my PC though
(about 1.3M on 5900X)
i'm looking at your malloc source code and it looks like you're using spinlocks for malloc
which could be where the speedup comes from, since spinlocks generally don't suffer from the intel cmpxchg shit
i'm using spinlocks everywhere
wdym?
But this is Intel
dont spinlocks need cmpxchg as well
It's slow on AMD
spinlocks can use xchg instead of cmpxchg
oh
hm how
while (!xchg(&lock->state, true)) pause();
oh
also i have no idea why the difference between intel and amd is so huge there
like sure iretq's cpu is quite a bit better than ryzen 5xxx but it's not 7 times better
some memory memes?
what if I use hhdm? 
(anyway, I'm trying to build the 64 bit image)
.
you still need to know if it was previously locked or not
cache invalidation?
whatever intel's doing with cache coherence for lock cmpxchg absolutely destroys performance
cmpxchg does the compare for you
xchg returns the old value
and it doesn't do the same for xchg
cmpxchg compares and then exchanges them, so you dont get the old value but you get the flags
also i dont see why you couldn't use xchg for whatever else you want to implement
and i think that the slow down might come from the lock prefix, but i am unsure lol
xchg has implied lock
you're right that it comes from the prefix (normal cmpxchg doesn't have the problem) but xchg with a memory operand implies lock so
This is my memory allocator fastpath now. I haven't looked at the assembly for the old thing, but I'd assume it is a fair bit worse than this.
Anyway, this makes basically no difference in the benchmark 😭
and yeah xchg true works for a spinlock because if its already true then the swap has no semantic effect
ah interesting
i use bit test things for mine because i want my spinlocks to be true 1-bit so i can have them ORd with an align > 1 pointer
64 bit image
:p
I can also make one with 32 bit uacpi server and 64 bit kernel
that'd be interesting to compare
that one gives me the same score as the 32 bit image so i doubt it has much to do with bitness
do you have tsc on?
oh. forgot -cpu host,migratable=off
now it is more reasonable
sometimes getting speeds around 3.6M, sometimes 1.4M
host CPU scheduling skill issue
Which CPU is it?
(I need to figure out how to extract the server out of the prevous image
)
mount the iso and copy the files
which one is it?
devicesd.elf
thx
also idk if you're already aware but the 2nd partition on that image (the ext2 one) is malformed
[277050.930059] EXT4-fs (loop0p2): mounting ext2 file system using the ext4 subsystem
[277050.930062] EXT4-fs (loop0p2): bad geometry: block count 16384 exceeds size of device (16256 blocks)```
i was not, but I didn't get to write the filesystems stuff yet
ryzen 9 7950x3d
apparently half the cores (the ones with extra L3) run at a lower clock speed
but also my host runs some CPU cores at lower clock speeds when they are not under load, I think
This is a major source of Davix uACPI benchmark skill issues
you can use taskset to pin a task to a certain cpu
BUT idk if that works with qemu kvm
yeah
Somehow the kernel is having a skill issue loading it
it does
I should probably setup libvirt
yeah
(let me fix it)
yeah that's what i thought but i wasn't sure
a vcpu is just a host thread that calls ioctl (kvmfd, KVM_RUN) or something
your 64-bit kernel has compatibility mode support?
thats pretty cool
IOCTL_KVM_VCPU_RUN or something
close enough
I mean I've ported userspace to 32 bits a month or so ago
@left orbit can you try it?
yes
do u have like a compat syscall layer as well
No
i get this pretty consistently
how do u make sure u dont truncate anything when returning stuff to a 32-bit program
The kernel knows that the process is 32 bits and expects arguments to be in different registers
My syscalls return 2 64 bits integers, one for result and one for whatever was requested
through registers
that fits into 32 bits registers as well
yes but lets say it does an mmap
do you also do stuff like making sure pointers stay within 4G?
u have to make sure to have an upper bound at 4g
damn nice
yeah
I have a function which checks the limit
(Which also changes for 3/4/5 paging levels with 64 bit stuff)
(on risc-v, since the x86_64 paging code is a mess and doesn't support that)
Like I do 3/1 split on 32 bit kernel, and full 4GB is available with 64 bit one
anyway I wrote some code to collect slab_alloc statistics, and here are the results. notably nr_expensive_free is very high.
I should totally write some code to only actually free objects in a background worker thread or something
I seem to be getting relatively consistent results in the 2.2M-2.3M range (so long as the guest is scheduled on the correct host CPU cores)
(also this is the full build, which doesn't exit(1) after loading acpi namespace if someone's interested)
this one
the PS2 driver seems nonoptimal
idk interrupts are half-broken
i get 1.8M on that build
maybe if u use spinlocks in your allocator youd speed proxima up on iretq's cpu as well
you must optimize for intel
oh definitely
here's a main branch build with spinlock heap, and its results on my cpu:
uacpi: info: successfully loaded 1 AML blob, 1705 ops in 0ms (avg 7933442/s)
oh that's with cmpxchg spinlocks so not even the best it can get
7.9M is crazy
interestingly using just plain old xchg for spinlocks destroys perf on AMD
i wonder how it'd do on intel
drat
jesus fkn christ I'm trying to upload an image of my kernel for you guys to test but am having severe network skill issue or something
it takes ages to upload a 10.27MB file
can someone with less host cpu skill issues than me run this? qemu-system-x86_64 -cdrom bootable.iso -enable-kvm -cpu host,migratable=off -M q35 -debugcon stdio
finally it fkin uploaded

so this would be bad then?
/**
* Optimistically try to acquire the lock with an atomic exchange. Returns true
* for success.
*/
static inline bool
spin_lock_fastpath (spinlock_t *lock)
{
return atomic_exchange (&lock->value, 1, memory_order_acquire) == 0;
}
7.1M
apparently yeah
wtf how do you have more host cpu skill issues than me?
ok what the fuck was i wrong about the fucking cmpxchg shit
so what's preferable over this then?
normal cmpxchg, apparently?
slowpath for completeness:
/**
* Slowpath for spinlock acquisition. Implements TTAS semantics.
*/
static inline void
spin_lock_slowpath (spinlock_t *lock)
{
for (;;) {
do
arch_relax ();
while (atomic_load_relaxed (&lock->value));
if (spin_lock_fastpath (lock))
break;
}
}
around 6.3M
oh btw my allocator is lock-free in the fast-case (nr_quickbin_hit and nr_quickbin_free)
what CPU?
[ 0.128253] uACPI: successfully loaded 1 AML blob, 1705 ops in 0ms (avg 6364623/s)
[ 0.127614] uACPI: successfully loaded 1 AML blob, 1705 ops in 0ms (avg 6361916/s)```
13700k
so the pci errors are intended?
yes. the PCI funcs aren't implemented yet lol
i thought that was an indicator that something was wrong which is why i included them
ah
but it doesn't matter since it doesn't execute any PCI stuff for the benchmark
cc @fiery turtle
[ 0.128499] uACPI: successfully loaded 1 AML blob, 1705 ops in 0ms (avg 6210795/s)
[ 0.129090] uACPI: successfully loaded 1 AML blob, 1705 ops in 0ms (avg 6347728/s)
[ 0.128887] uACPI: successfully loaded 1 AML blob, 1705 ops in 0ms (avg 6377479/s)
[ 0.127661] uACPI: successfully loaded 1 AML blob, 1705 ops in 0ms (avg 6365027/s)```

bruh everyone is getting 7mil these days
yeah lol
i remember when 400k was a lot
except on my CPU
So this is like normal now?
oh i don't think so ☠️
i haven't managed to replicate that
tbh i haven't seen wsl issues affect the score positively
so that must have been a fluke on your side
idk how that could have happened though
@left orbit as a sanity check, could you test these two? the first is the latest non-rewrite CI build, and the second is the exact same except built on my machine
they both get ~7.5M/s on my machine
jokes on you they are actually payloads that escape the hypervisor and run a crypto miner in the nt kernel
anyway yeah i wish windows's "this might be a virus" notifications were based on more than just "oh this hash hasn't been downloaded a lot"
they are though
this doesn't make much of a difference for me
(Ryzen 9 7950X3D)
(I also added builtin_expect to __spin_lock)
anyway, both isos get me around 5.3-5.5M
what the fuck
does intel have some sort of special optimization for cmpxchg-store
none of these mutexes are contested, the only difference should be 1 cmpxchg 1 store vs 2 cmpxchg
last one before i give up looking for this issue: this one uses acquire for lock and release for unlock instead of acq-rel for both
i seriously doubt that'll do anything but it's the only thing i can think of
as i thought
i have one more thing to try but it's gonna take a bit to implement
let's see how this worked again
holy
I haven't looked that much at the paper
but what I implemented with quickbins today is similar to how I imagine magazines to be
i think i'm gonna do per-thread magazines because my {enable,disable}_preempt is slow and it's not like i'm gonna keep this around when i'm already in the middle of a rewrite
is this for the new kernel?
how would you allocate like the lists for storing objects?
i'll probably implement it in the new kernel as well but rn i'm working on the old one just trying to see how high i could get
just statically in struct task?
extra field of fixed size in struct task
reminds me that zig has separate weak and strong cmpxchg builtins, wonder if thats the same difference
yep. ok
no, weak is allowed to spuriously fail, on x86 they're the exact same
ah ok
unlocked cmpxchg is completely broken on any multiprocessor system
because it's not atomic
ah
what do you do for {enable,disable}_preempt?
i could hit 20M with computed gotos in uacpi interpreter potentially, but thing is those are GCC specific i think and they require everything to be in a switch, which would destroy stack usage in debug mode
maybe some smart object caching could help, but i doubt it would win over a ~100ns allocator
wtf are computed gotos? I've probably heard of them but with a different name
the new kernel just increments and decrements, and when it reaches zero does a quick lockless check if it needs to reschedule
the old kernel also just increments or decrements, but when it reaches zero it takes a spinlock
goto a switch with new value to switch on
I expect the fast-case of my allocator to be like 10-20ns tbh. But I should measure
damn
cmpxchg itself is atomic as in a single instruction, but not atomic as in other processors and/or devices only see either the full outcome or none of it
but like
cmpxchg on multi-processor systems can spuriously succeed
zig's compiler got faster when they added support for them and switched over to them in the compiler
iirc
I just wanted to know how often the fastpath is hit

the slowpath steals a page from the slab->pg_full_list and slab->pg_partial_list if there any one. otherwise it allocates one. then it populates the entire magazine and returns one object
that is just unreasonably large
well
it depends on how many slabs you have
yeah
I have something similar
but I set it to min(31, objs_per_page - 1)
for reasons
so in total it's 3072 rounds
thats a minigun magazine
https://github.com/dbstream/davix/blob/master/mm/pfn_slab.c here is my slab allocator if you want to take a look at it
hopefully it isn't too unreadable
the slow case (nr_quickbin_miss and nr_expensive_free) is probably a lot slower than 20ns though
nooo yet another tabs user
sorry :p
and also yet another tabs=8spaces user
but like wtf. why is my kernel getting like 6M on intel and 2M on AMD?
gotta do -mtune
I've found the skill issue
oh this is just my luck
with magazines it's slower because none of the init that runs before uacpi allocates objects from the same slab as uacpi mainly does
i can probably minimize the impact but it's certainly not going to be faster
then your implementation is broken lol
for me magazines noticeably improved single-threaded performance
it probably does once your allocator has been used a bit
but uacpi inits too early for that to be the case
well then it's the same as allocating from a slab
then subsequent allocs will be from the cpu cache
do you allocate an entire magazine if the magazine is empty? i'm going off of the vmem paper which just lets it fill up as objects get allocated
I do whatever solaris does
wtf it took you like 25min to implement magazines
well tbh they aren't that hard
my allocator is tiny it'd only take me like 10m to fully rewrite it
depends on how fancy you want them
not that hard to add stuff onto
are there any measurements for if this improves performance?
(will not do it regardless, because it seems hard)
the point of doing that is to ensure not too much memory is wasted for rarely used magazines and so that the almost-perfect size is used for regularly used magazines
so yea it likely improves performance
and memory usage
but this is for high scalability stuff, idk how useful it is here
ok -mtune=native barely makes a difference
I get like 2.4M vs 2.3M when the guest is scheduled properly by the host
ok i fully copied the strategy documented in the vmem paper and it did indeed improve performance
but not by much
it went from like 7.5M to 7.7M
if i init uacpi 10 times i get 9M on the final one
💀
vmem is cool though
@left orbit if you want to test proxima+magazines, here it is
if you want to see perf for the first of the eleven runs, -debugcon stdio
uacpi: info: successfully loaded 1 AML blob, 1705 ops in 0ms (avg 9112238/s)
this is on my cpu
Insane
the way i've implemented it (thread-local caches) is incredibly stupid if you want actual overall benefits, so i won't be pushing it to git and i won't be submitting it to the leaderboard
but it is technically leaderboard-valid so it's fun to see the performance
uacpi: info: successfully loaded 1 AML blob, 1705 ops in 0ms (avg 6390171/s)
uacpi: info: successfully loaded 1 AML blob, 1705 ops in 0ms (avg 6718073/s)
uacpi: info: successfully loaded 1 AML blob, 1705 ops in 0ms (avg 6768290/s)
uacpi: info: successfully loaded 1 AML blob, 1705 ops in 0ms (avg 6726713/s)
uacpi: info: successfully loaded 1 AML blob, 1705 ops in 0ms (avg 6456621/s)
uacpi: info: successfully loaded 1 AML blob, 1705 ops in 0ms (avg 6670396/s)
uacpi: info: successfully loaded 1 AML blob, 1705 ops in 0ms (avg 6754508/s)
uacpi: info: successfully loaded 1 AML blob, 1705 ops in 0ms (avg 6782695/s)```
do you guys have nothing better to do for your OSes?
How did you do it?
damn, that's worse than i expected
what else is there to osdev?
exactly the same as a normal magazines impl except the caches are thread-local instead of cpu-local
Than magazines?
hey it's an improvement over what it scored on my pc previously lmao
yeah but like
Lol
the later runs should take almost 0 locks in the allocator
oh i just took the ones from debugcon
ah
okay uh
well i mean i only get one run per boot so
only reason i said to use debugcon is because the older runs would get wrapped off of the screen
@gentle peak you might want to see this
oh that shouldn't happen
guess how fast it is on my machine
11M?
13
DAMN
hooooly
no than maximizing uacpi score
What the hell
i thought i couldn't read correctly
fuuuck i should've built this with more debug info than just symbols
it doesn't even have line numbers
yea okay there is literally no beating that lmfao
Monkuous u should upstream this
now i wonder, what if i combine this with illegal techniques?

So no one can ever beat proxima
if i do userspace uacpi do i get to use sse
yes
Yeah
💀
is that bad
actually this wouldn't do much because the most impactful illegal technique is stubbing mutexes and if you stub mutexes the base allocator is probably faster than the magazine'd one (because the benchmark is single-cpu)
i'm gonna try regardless
Shouldn't have pinned it since monkuous ain't submitting it
i might be completely wrong on this but just looking at the disassembly this might be a uacpi bug actually, because it's lock cmpxchg with dest=0, which shouldn't be possible unless uacpi locks a mutex or spinlock whose kernel api create call returned null
i guess i should do a buddy allocator?
Why would it randomly repro on qemu
magazine memory usage idk
it's in ensure_register_mapped.part.0.lto_priv.0 but i have no idea what that exactly means for the location
and as i said this build doesn't have line info
is that slower or faster than buddy?
it might also be memory corruption, i only realized this just now for some reason
a buddy usually involves multiple linked lists
though it is possible to implement bitmap buddies, although those are weird
Maybe
qemu-system-x86_64 -debugcon stdio -cpu host,migratable=off -M q35 -enable-kvm -cdrom "proxima3.iso" | grep '1705 ops'
I mean u did speedrun them basically lmao
Nice
i wonder what triggers it since that's basically the same as my command line
ok with -M q35,smm=off it works
that's very strange
💀
good to know we found the cause
if you want to test perf that's the flag to use
alr
"everything seems to be working. what is wrong?"
or (and this is very heavy cope) the slightly inflated kernel binary size triggered the oom
Lol
oh wait no i lied it is reproducible in debug mode
i just accidentally passed smm=off

what if you give the VM absurd amounts of memory? like qemu -m 48G?
still happens so not an oom
Just a guess but
Smm off might force qemu into acpi mode by default
So uacpi won't try to switch back on reset
Which would skip that path
hm
don't think that's the case
also i found a typo: uacpi_deininitialize_registers
deininit
Guess not
Lol
oh wait
i put a hlt loop in uacpi_initialize_registers and it doesn't get called in the second iter
ininit*
oh wait it just doesn't get to the second iter
nvm
yeah ok i just confirmed it is indeed a uacpi bug
you were right btw i just misunderstood at the time
uacpi_deininitialize_registers gets called before uacpi_leave_acpi_mode, which uses g_reg_lock but that's already freed by said deinit
damn UAF
not really since deinit also sets it to null
How does that not crash like always
but if it weren't for that it'd be uaf yeah
because it only gets called in uacpi_state_reset and nobody does that ig
i'm pretty sure the only times uacpi_state_reset has ever been used directly by any kernel are by me trying to squeeze as much perf as possible out of it

