#Ultra

1 messages · Page 13 of 1

eternal sparrow
#

You’re pretty smart. I think you can get there

proper tulip
#

well i should have clarified it earlier that i don't really mean multiprocessing when i say scheduling

#

what i mean by that is having the scheduling primitives

vestal zealot
#

That is a VERY different thing

proper tulip
#

like threads + a way to switch between contexts

vestal zealot
#

No what

prime wraith
#

for multiple threads u can just allocate a few global variables to test that

proper tulip
#

sure, obviously i dont want a full blown scheduler right on boot

#

oh shit im dumb

vestal zealot
#

What are you talking about, how can you possibly run anything but asm without a stack

proper tulip
#

see thats what i mean

vestal zealot
#

Even on one core

proper tulip
#

i forget a simple thing like this and everything falls apart

prime wraith
#

did u forget that threads need stacks?

proper tulip
#

perchance

prime wraith
#

lol

eternal sparrow
#

It happens to me. Somtimes I have a hard time getting a concept through my skull

inland wave
#

same lol

proper tulip
#

i do and don't at the same time

eternal sparrow
#

Everyone has little brain farts. Dosnt make you less of a dev

inland wave
proper tulip
#

but it does feel terrible when you work on something, you think you have a good understanding of it and suddenly "threads don't need stacks"

#

i feel like an llm fr

eternal sparrow
#

I’ve had similar happen to me

#

Right in this server at times lol

prime wraith
#

i mean if u havent designed a scheduler in a while or context switch code its kinda easy to forget details

eternal sparrow
#

then JW screams at me

#

If you wanted to start a new kernel project or whatever I would love to see it

proper tulip
#

but yeah, you can just have a statically allocated stack per thread

#

ideally you need one stack, for the initial thread

eternal sparrow
#

My ISTs are statically allocated so I can trap faults ASAP and crash safely

proper tulip
#

that's very fair

prime wraith
#

@proper tulip do u have your kernel code somewhere btw

proper tulip
#

-# which tf

prime wraith
#

the latest lol

proper tulip
#

that basically means no, i guess

prime wraith
#

is it in zig?

proper tulip
#

and even if i did it wouldn't be worth looking at

#

honestly i dont remember what i worked on last

#

probably the c++ thing where i actually tried implementing my own data structures

prime wraith
#

ah

#

i remember almost converting you to make it in zig or smth

proper tulip
#

i still kinda want to make a zig kernel

eternal sparrow
eternal sparrow
proper tulip
#

abbix is already zig-pilled

#

(based)

prime wraith
#

yeah

eternal sparrow
#

But zig and other languages than C look a bit more annoying for kernel code

prime wraith
#

why?

proper tulip
#

zig is probably the closest to C

eternal sparrow
#

Mostly context switching stuff and some of the crazy build scripts I’ve seen under zig

#

And the fact I’ve been programming only in C for the past few months and it’s been a while since I’ve touched anything else

prime wraith
#

oh yeah iirc zig doesnt have any fixed abi?

proper tulip
#

ok well, context switching in zig is kinda annoying

#

you basically gotta save all the gprs on every context switch

#

not just the callee saved regs

prime wraith
#

tbh thats a nanosecond diff

proper tulip
#

because those don't exist lmao

#

yeah true, but still kinda annoying

prime wraith
#

i guess

proper tulip
#

especially if you're coming from C

sinful river
ornate jasper
#

or imaginarium with me

#

or do your own

ornate jasper
#

in any case come join the zig kernel gang

#

we have good uacpi bindings too

proper tulip
#
fn doContextSwitch() callconv(.naked) noreturn {
  // ...
}
fn contextSwitch(from: *ThreadContext, to: *const ThreadContext) callconv(.sysv) noreturn {
  asm volatile(
    \\mov %[from], %%rdi
    \\mov %[to], %%rsi
    \\call %[doContextSwitch]
    : // ...
  );
  @unreachable();
}```
#

i guess that would work?

sinful river
#

yes

proper tulip
#

nice

sinful river
#

idk I played around with it and figured it out and managed to do it

proper tulip
#

tbh i could try contributing to zag but i also might try doing my own thing

ornate jasper
#

yep thatd work

ornate jasper
#

im just lazy and do the all registers thing cause i cant be assed

sinful river
#

so I dont have to do it meme

ornate jasper
#

lol

proper tulip
#

you don't have an x86 port???

#

wtf

sinful river
#

no, do it

#

I was leaving it for you

#

cuz im kind enough

proper tulip
#

do you have anything other than um?

sinful river
#

no

prime wraith
#

lol wtf

proper tulip
#

that'll be fun

sinful river
#

bro i literally wrote all of it in like two days I cbf to port it😭

proper tulip
#

that means i'll probably have to come up with all the stuff around so it builds and iso and runs qemu too

sinful river
#

no I do that already

proper tulip
#

but that's not a big deal ig

#

oh?

#

wtf

sinful river
#

I have it all set up

#

its just a hello world

#

on amd64

proper tulip
#

i see, based

ornate jasper
#

zig build system is goated for shit like this

proper tulip
#

i decided to not install copilot or any of the ai shit after the reinstall

prime wraith
proper tulip
#

i think i will become less dependent on it

ornate jasper
#

the literal only external deps that need to be installed to build and run imaginarium from source are zig and qemu

sinful river
proper tulip
#

i can still use the web browser based interfaces for stuff but you know

#

it adds friction

prime wraith
#

yeah

proper tulip
#

so hopefully i become less inclined to do that over figuring it out myself

carmine token
#

just use AI only for the boring parts

prime wraith
#

^

proper tulip
#

yeah but when i have all this tooling at my fingertips it's just sometimes too hard not to give in when i'm having a hard time doing something

#

so instead of slowly and painfully working through it i just ai it away and it's often worse than if i did it myself

#

i don't have anything against using it as a tool but i just used it for coding and that's bad

prime wraith
#

phenomenal script quality

prime wraith
red parcel
#

nice

#

I guess if you have anything with strings it would also happen

red parcel
#

actually nvm, strings would be normal rodata so if something from init accesses them its fine

prime wraith
#

Yep

prime wraith
#

In which the NT kernel is light-years ahead of Linux.

Linux's internal allocator for big graphics buffers (TTM) stalls constantly (synchronously, in kwin_wayland) trying to allocate physically contiguous memory on a fragmented system. Now, graphics doesn't actually need the big

#

Another thing about Linux that sucks

#

The reliance on the stupid kvmalloc api that is spammed everywhere for no good reason

#

Or the api could be good, but they dont hint internally to alloc pages that it doesn't need to try that hard

latent geode
prime wraith
#

i did try to fix a specific part in iptables that caused a giant kvmalloc allocation, but maintainers didnt want it

prime wraith
#

which would make alloc_pages reclaim all memory and activate compaction threads

#

which basically brings the system to its knees

#

all for a useless optimization that was never proven to speed anything up

carmine token
#

even if an optimization is proven to speed something up, it's questionable whether it does that for common workloads or only the one that the maintainer cared about

prime wraith
#

the general idea was fine: let's grab a physically contiguous chuck if it's available, it's all in HHDM which is mapped as 1G pages usually so it should be way faster than vmalloc. But the consequences is every kvmalloc call now struggles potentially for literal minutes before falling back to vmalloc

#

which not only obliterates page cache but also literally freezes all other running threads to take their pages and migrate them to contiguous memory

#

well freeze is worst case if it happens to page fault on a in progress page, but it gets hundreds of thousands of IPIs for TLB invalidation per second which essentially means it's barely running at that point

carmine token
#

imo relying on compaction for anything other than a background cleanup is stupid

prime wraith
#

this whole system needs a rewrite imo

#

contiguous allocation should be in niche places that really benefit from it

#

btw @sinful river @ornate jasper
i found a bug in my log ring, maybe u also have it

#

i wasnt able to trigger it via tests but its still possible in theory

#

it basically needs so many records being allocated at the same time that the tail is pushed all the way from start to finish

latent geode
#

I might get inspired by your log ring :P

#

but probably not yet

prime wraith
#

feel free

prime wraith
#

cant believe i finally managed to clean up the history of my giant pr

#

all thats left now

  1. verify clanker tests are decent
  2. add INIT_CODE/DATA everywhere
  3. verify all commits contain what they should
  4. verify all commits compile on their own
#

then i can finally merge it and move on to timer stuff

#

also find out how to fix that

check_free_after_init_references.py:6: error: Cannot find implementation or library stub for module named "elftools.elf.elffile"  [import-not-found]
check_free_after_init_references.py:6: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports
check_free_after_init_references.py:7: error: Cannot find implementation or library stub for module named "elftools.elf.relocation"  [import-not-found]
prime wraith
#

it says at the top

sinful river
#

I doubt I have copied the error as I barely referenced your code

prime wraith
#

ah ok good

sinful river
#

It doesn't support 32 bit

prime wraith
sinful river
prime wraith
#

it's not a bug if there's an explicit BUILD_BUG_ON trl

#

also like it technically does if your cpu can do 64-bit atomics

sinful river
#

This is what I do

prime wraith
#

yeah i dont understand how this overflow logic works so i made it more explicit

sinful river
#

I use a seqlock

prime wraith
#

i dont think i need it since i dont support 32-bit, i can just use atomics there(?)

sinful river
#

I need it because I'm modifying two 64 bit variables

prime wraith
#

why two?

sinful river
#

I have one for offset one for initial count

prime wraith
#

shouldnt the initial count only be written once?

sinful river
#

No I set it when it overflows too

prime wraith
#

oh

dusky kraken
#

ahead of linux on that one

eternal sparrow
obtuse sparrow
dusky kraken
prime wraith
#

Lockless log ring for DOS applications

carmine token
#

everything is lockless if there is only one cpu KEKW

eternal sparrow
latent geode
#

not on dos :P

obtuse sparrow
dusky kraken
#

to get atomicity

obtuse sparrow
#

In an 8086?

#

Did that even exist back then 🥀

dusky kraken
#

yes, it causes the LOCK# signal to be asserted for the duration of the instruction iirc

ornate jasper
#

(probably because i copied from yours KEKW)

proper tulip
#

uLogRing when

eternal sparrow
#

uKernel when

dusky kraken
#

microkernel 🥀

eternal sparrow
#

Not micro kernel

#

Just a kernel you can copy and paste

#

And post on Reddit

#

We already have uHDA and uACPI

#

Just complete it with uPaging

#

uPMM

#

Etc etc

obtuse sparrow
#

I tought it was a 386 addition tbh

dusky kraken
#

i think you can even do a 32-bit atomic load with sth like les/lds

#

not sure about store though

obtuse sparrow
eternal sparrow
wicked juniper
#

where is it

eternal sparrow
#

I forget

dusky kraken
eternal sparrow
#

And zeroing the register first?

#

Ahh wait 16bit

obtuse sparrow
sterile kayak
#

no lock necessary as long as it's aligned

obtuse sparrow
#

But yeah

#

atomic store too

eternal sparrow
#

I always forget that’s atomic tbh

dusky kraken
sinful river
#

Unless you consider cli a lock

eternal sparrow
eternal sparrow
sinful river
#

Skill issue

dusky kraken
eternal sparrow
#

That’s what I meant

dusky kraken
#

well apparently 0x60-0x6f behaved like 0x70-0x7f? not sure how accurate that is and what about other opcodes

#

there is one opcode that is maybe useful, salc (al = carry ? ff : 00)

ornate jasper
carmine token
#

you can in principle implement a lock just based on load/store and a full memory fence

#

not sure if the 8086 did have a full memory fence though

eternal sparrow
#

If there is no lock pin why not do an A20 style thing with an external device

sinful river
# prime wraith yeah i dont understand how this overflow logic works so i made it more explicit
        // Return true if `lpos_current` has not yet reached `lpos_next`.
        // Uses wrapping subtraction so that:
        //   - if lpos_current > lpos_next (another CPU already advanced past the target), returns false.
        //   - if lpos_current == lpos_next (already at target), the -% 1 wraps to usize max, returns false.
        //   - if the distance exceeds data_size (should never happen), returns false.

I just wrote this if it can be helpful

prime wraith
#

Probably 90% of my kernel is marked as INIT_{CODE,DATA} now KEKW

#
  [Nr] Name              Type            Address          Off    Size   ES Flg Lk Inf Al
  [ 1] .text             PROGBITS        ffffffff80000000 001000 021fdd 00  AX  0   0 16
  [ 2] .rodata           PROGBITS        ffffffff80022000 023000 0081b8 00 AMS  0   0 16
  [ 5] .data             PROGBITS        ffffffff80032000 033000 006380 00  WA  0   0 16
  [ 6] .free_after_init  PROGBITS        ffffffff80038380 039380 007c80 00 WAX  0   0 16
#

0x7C80 bytes i guess

sinful river
#

damn that's more than I'd think

prime wraith
#

well keep in mind the entire initial per-cpu section is in there

proper tulip
#

why is it marked init?

#

are you planning on discarding it in favor of something properly allocated later on?

prime wraith
#

it's relocated to a dynamic buffer at runtime

#

yeah

proper tulip
#

i see

sinful river
proper tulip
#

probably so he can reclaim all of init data more easily

sinful river
#

I'm thinking its so that you can avoid keeping an offsets array

prime wraith
#

that plus hhdm is mapped with gigabyte pages, and I have to allocate dynamic buffer for non-bsp CPUs anyway

#

it's just easier for uniformity

sinful river
#

that could be useful

#

so you dont need a cpu_offsets array

prime wraith
#

mul is still slower than indexing an array

#

so i wouldnt do that

proper tulip
#

percpu_base + (percpu_end - percpu_start) * index is so based

#

that would get optimized into a shl

#

if your section is page aligned :^)

sinful river
proper tulip
#

or shl, yes

#

oh wait i see what you asked

sinful river
prime wraith
#

hmm maybe

#

id have to look at the codegen

proper tulip
#

depending on how big your percpu section is

sinful river
#

the problem is the compiler cant know the size

prime wraith
#

but thats not know at compile time, can it really do an optimization like that?

proper tulip
#

yes it can

prime wraith
#

yeah

proper tulip
#

the symbols are link time

prime wraith
#

symbols are, code isnt

proper tulip
#

you know how big the percpu data section is at link time

prime wraith
#

but at instruction generation time it doesnt lol

proper tulip
#

ah

#

ahhhhhhhhhh right

sinful river
#

mhm hear me out

proper tulip
#

lto :^)

sinful river
#

so you build two kernels already right

#

for ksyms

prime wraith
#

lto works yes

proper tulip
#

not ideal i guess

sinful river
#

just add a percpu size 😎

#

unironically not a bad idea

#

ah no nvm

prime wraith
#

maybe yeah

sinful river
#

youd need to rebuild entirely

#

twice

prime wraith
#

u would have to rebuild 3 times

#

or 4 times if LTO

sinful river
#

why

#

no just add it in the ksym pass

prime wraith
#

ksym pass -> percpu pass -> ksym pass 2

proper tulip
#

build with an undefined percpu size, build with known percpu size, build with kallsyms twice

prime wraith
#

if u do lto theres one more ksym pass

sinful river
#

also can LTO even do that?

proper tulip
#

oh like that

sinful river
#

well I suppose you could make per-cpu size a constant meme

prime wraith
#

tbh accessing per-cpu values of other cpus its not a super common operation

proper tulip
#

how so?

prime wraith
#

what common cases are u thinking

proper tulip
#

your scheduler will do that pretty frequently

#

stealing tasks

sinful river
proper tulip
#

putting threads on other cpu's run queues

prime wraith
#

on a scale of optimization we're talking about

#

tahts literally nothing

sinful river
#

I do remote CPU accesses on the local CPU once in a while

#

in the scheduler

prime wraith
#

it would have to be like a hot path on context switch for it to matter

proper tulip
#

you can still just as easily align the percpu data to a page

#

and either make sure it doesn't get bigger than that

prime wraith
#

thats what i do atm anyway yeah

proper tulip
#

perfect

sinful river
proper tulip
#

just slap an assert in the linker script :^)

prime wraith
sinful river
prime wraith
sinful river
prime wraith
#

you'd just have to bump it up every now and again

sinful river
proper tulip
#

i mean, realistically it shouldn't get bigger than a page lol

prime wraith
prime wraith
#

mine: percpu: Embedded 63 pages/cpu

proper tulip
#

damn wtf i see that too

#

why so much

sinful river
prime wraith
#

can u explain what that code does

sinful river
prime wraith
#

yea its kind of a lot ig

#

also keep in mind linux supports per-module cpu locals + dynamic cpu locals

proper tulip
#

is ultra gonna have loadable kernel modules?

sinful river
prime wraith
proper tulip
#

baller

sinful river
prime wraith
#

so like if your runqueue is empty?

sinful river
#

no like for stealing threads

prime wraith
#

yeah but why doesnt it check its own queue first?

sinful river
#

stealing a thread from cpu is just select_thread(null, cpu, whatever)

prime wraith
#

oh ok

#

how do u synchronize in that case?

sinful river
#

synchronize what?

#

there are queue locks

prime wraith
#

oh ok

#

so it always locks but 99% of the time it should be uncontended?

carmine token
sinful river
#

because you dont care about preempting the current thread you just care about running something else

#

I suppose a cpu-local case could be useful but i doubt the performance really matters lol

prime wraith
#

what does yield pass for cpu?

sinful river
#

the current cpu

prime wraith
#

so it reads the current cpu queue as if it was remote?

sinful river
#

yes

prime wraith
#

oh ok

sinful river
#

that is what I meant when I said I do remote local accesses

#

its to keep the code generic

#

in that case

prime wraith
#

thats fair i suppose

#

on arches other than x86 the remote vs local case costs the same

sinful river
#

it's not like it's a huge cost either

prime wraith
#

for such a hot function maybe id still add a separate impl that checks cpu local but idk

sinful river
#

it's not really hot

#

its literally like two indirections, there are more expensive things in there lol

prime wraith
#

fair

proper tulip
#

cant wait to daily drive ultra

prime wraith
#

see you in 50 years

proper tulip
eternal sparrow
proper tulip
#

i'll contribute a shitty xhci driver that only works in qemu

#

that'll add 5 years meme

prime wraith
#

or well

#

technically this is one

latent geode
#

how do you plan to do cpulocal variables for modules?

eternal sparrow
proper tulip
#

otherwise known as FUSL (Freestanding USB Support Library)

eternal sparrow
#

It has quite the ring to it

proper tulip
#

i should maybe try and get back to that at some point

latent geode
eternal sparrow
proper tulip
#

yeah iirc

#

but it was nooby's code that's private

#

mine was never public lol

prime wraith
#

but yeah its gonna take a ton of time also because im not really looking for contributors for this project, wanna focus on doing everything myself

#

since its mostly a learning project

latent geode
eternal sparrow
#

My project is accepting patches PSP1G_pspTrollar just write it all down on a mysical scroll and have an owl deliver it to me

prime wraith
#

also i wanna be the first project to have hw accel on bare metal with own driver

#

at least on igpus

sinful river
#

(@proper tulip)

prime wraith
sinful river
#

oops didnt want to actually ping trl

prime wraith
#

@latent geode a simpler approach could be to reserve some space in the initial per-cpu area probably

#

i think linux does that also

sinful river
#

dynamic per-cpu alloc sounds bad to me

prime wraith
#

its an optimization

#

very expensive code wise

sinful river
#

wdym

prime wraith
#

linux has some insanely complex code to support it

latent geode
#

I mean you could just allocate sizeof(type)*cpus and access with ptr[cpu] trl

sinful river
#

yes for most cases you can do that ^

#

I was about to suggest it

#

this is how magazines work

prime wraith
#

yeah thats how u would do it without pcpu_alloc

sinful river
#

tho if you wanted to be more efficient youd need to align it to a cache line I think?

carmine token
#

or you can allocate a per-cpu map from dynamic per CPU variable IDs to pointers

#

which means that everything is still local

carmine token
#

I don't think that the dynamic per CPU allocation adds any measurable benefit

#

Does Linux have it from pre-module days?

prime wraith
#

when u have expensive engineers sitting there doing nothing

#

u gotta make them do something

carmine token
prime wraith
#

no idea

#

but its used in a shit ton of places

latent geode
prime wraith
#

including in modules

latent geode
#

maybe a nice little abstraction

sinful river
#

what does that mean

prime wraith
#

(data*)map[var]

sinful river
#

ah so you do it per variable

prime wraith
#

u just store some handle in the variable yeah

latent geode
#

ah

prime wraith
#

or rather (data*)this_cpu_read(map[var])

carmine token
#

there is no good reason other than early linux skill issues ^

prime wraith
#

whats the TLDR?

carmine token
#

i think there is none but it was there very early

prime wraith
#

whats the skill issue part

#

wait lol

#
/* 
 * Use this to get to a cpu's version of the per-cpu object allocated using
 * alloc_percpu.  If you want to get "this cpu's version", maybe you want
 * to use get_cpu_ptr... 
 */ 
#define per_cpu_ptr(ptr, cpu)                   \
({                                              \
        struct percpu_data *__p = (struct percpu_data *)~(unsigned long)(ptr); \
        (__typeof__(ptr))__p->ptrs[(cpu)];    \
})
#

so their early per-cpu alloc just did an array of pointers

latent geode
#

:P

prime wraith
#

and the per_cpu_ptr was only applicable to dynamic allocations

sinful river
prime wraith
#

it's worse

#

since instead of a handle u keep literal void *alloc[num_cpus]

#

its like an array of arrays

#

korona's idea is u keep one single handle int alloc;

#

which is a key into a per-cpu map

sinful river
prime wraith
#
/* Enough to cover all DEFINE_PER_CPUs in kernel, including modules. */
#ifndef PERCPU_ENOUGH_ROOM
#define PERCPU_ENOUGH_ROOM 32768
#endif
#

iretq idea KEKW

#

@proper tulip see u could technically have written linux 2.6

proper tulip
#

hell yeah

sinful river
#

or what

prime wraith
#

well

sinful river
#

you could limit the number of variables

prime wraith
#

since its just a map of pointers

#

u could preallocate a pretty large one

#

yeah

#

its very very unlikely you'll have a lot of such dynamic allocations

obtuse sparrow
#

Unlikely anyone is allocating sum 16384 objects

prime wraith
#

or u could add an extra indirection and dynamically resize it

#

thats also a way to do it

sinful river
#

send an IPI when you need resizing

#

and all cpus reallocate their array

#

💀

prime wraith
#

yeah but to reallocate it

latent geode
sinful river
#

you need the extra indirection nvm

prime wraith
#

you have to have something to allocate out of

#

yeah

#

u just described how to synchronize the indirection KEKW

#

i guess for resize u could just rcu no?

#

with indirection that is

#

but imo just hardcode to a fixed capacity

#

say a page per cpu

sinful river
prime wraith
#

u can replace the pointers on remote CPUs

#

under RCU

sinful river
#

how

#

ah

prime wraith
#

and then free the old table after synchrnoize

sinful river
#

well

#

RCU is kinda overkill for that

prime wraith
#

is it?

sinful river
#

since it's CPU local data

#

it's not like every other CPU has a view on that object

#

rcu is useful when you have a chunk of memory thats viewed concurrently by multiple people

prime wraith
#

i was thinking u could allocate one table but just give every cpu a different offset

#

so its faster to write out an allocation

sinful river
#

ahh

#

mhm

prime wraith
#

Holy shit

#

Always enable -Wmissing-prototypes early

#

I just spent half an hour fixing all of them

prime wraith
#

i had -Wstrict-prototypes this entire time instead of this one

#

im fucking dumb

#

thats why it accumulated

#

uACPI also had this problem

#

thank god it compiles with that on at least

sinful river
#

what does it do?

prime wraith
#

it basically catches accidental global symbols

#

or if u forget to include a header

#

and use something anyway

sinful river
#

ah

#

is that not enabled with -Wall -Wextra?

prime wraith
#

nope

#

This is my current warning collection:

    -Wall
    -Wextra
    -Werror
    -Wstrict-prototypes
    -Wmissing-prototypes
    -Wimplicit-fallthrough
sinful river
#

imo warnings shouldnt even exist

prime wraith
#

there are some people that are against Werror like mint

sinful river
#

lol what

#

well I think a reason is new warnings

prime wraith
#

the argument is that what if the users uses a new toolchain that has more warnings

sinful river
#

yeah

prime wraith
#

yes

sinful river
#

but imo that's a C issue overall or something

prime wraith
#

nah ive had that exact problem with rust

sinful river
#

warnings/errors should be the same across standards

prime wraith
#

warnings get randomly added between compiler releases

sinful river
#

yeah that is a good point

#

I do think for development it's better to have it turned on tho

prime wraith
#

yeah

#

having a config option to turn it off is enough

sinful river
#

or do like me and download a new compiler every week

prime wraith
#

i try to somehow fight that with os-latest runners in github

#

and it catches new warnings that i dont have every now and again

#

also it doesnt help that GCC can generate different warnings at different optimization levels

ornate jasper
sinful river
#

yes but infy brought up a good point

sinful river
#

but might not be an issue with zig because zig is so unstable you kinda have to pin to a version

ornate jasper
#

yeah

carmine token
#

Warnings are not even consistent across optimization levels

queen moss
carmine token
#

The proper setup is to have -Werror in CI but not in your build system

#

Because if you have it in your build system, it just randomly breaks compilation for your users if they do something that you didn't expect

prime wraith
#

So its a very useful warning

queen moss
prime wraith
#

that's kind of outside the scope of that

#

this is strictly for compilation units

wide ether
prime wraith
#

Lol

haughty notch
#

Sorry if it's a flat brain question, but can I build Hyper for multiple arches and bios and uefi at the same time?

vestal zealot
#

seems unlikely

#

at the very least if you mean in the sense of one ISO containing all of them

prime wraith
#

Im not sure what you're asking tbh

haughty notch
#

yeah, I've ended up just running build.py twice

prime wraith
#

Oh ok

ornate jasper
#

efi uses different filenames for different arches so you can def put them all on one disk too

#

you can't do bios for multiple arches on the same disk at once easily but idk why you'd want that when you're almost certainly going to have efi for all of them

prime wraith
#

what does bios for multiple arches even mean

vestal zealot
#

Cuz BIOS just loads some garbage from disk

ornate jasper
#

yeah lol

vestal zealot
#

Without checking much of anything

prime wraith
#

its not even that

vestal zealot
#

Whereas RISC-V, ARM and probably more use EFI

prime wraith
#

this style of barely documented intXX interface is a unique thing on x86

sinful river
#

BIOS is inherently a x86 thing

ornate jasper
#

yep

prime wraith
#

on other arches non efi mode would just mean you are the firmware

ornate jasper
sinful river
#

not with things like opensbi no?

prime wraith
#

opensbi doesnt really offer a disk reading helper no?

vestal zealot
sinful river
#

Lol remember river

vestal zealot
#

In which case the thing on disk is not firmware

vestal zealot
prime wraith
vestal zealot
#

Certainly no disk I/O

prime wraith
#

using hybrid iso setups

vestal zealot
#

Usually the most you get is earlycon and a timer

prime wraith
#

so u can have both uefi and bios boot with el torito

#
  • u can treat the iso as a hard disk and as a cdrom and both will work
#

hybrid iso is a genius thing honestly

ornate jasper
prime wraith
#

lol

ornate jasper
#

because I know bios and uefi at the same time is easy, that message was about how i (probably mis-)interpreted the original question

haughty notch
#

Bios + amd64 UEFI + aarch64 UEFI

ornate jasper
#

so the latter interpretation then

prime wraith
#

yeah that works fine

ornate jasper
#

and yeah thats doable on a single disk, the x86_64 efi thing will be named BOOTX64.EFI and the aarch64 one will be BOOTAA64.EFI and the x86 bios stuff will be bios stuff

prime wraith
#

i do this for my bootloader tests and yeah works fine

haughty notch
#

Because with limine you can just ask to build everything

prime wraith
#

i can add an --everything flag if u want lol

haughty notch
#

The Hyper's build script has {i686,amd64,aarch64}, which kinda confused me

prime wraith
#

yeah

  --arch {i686,amd64,aarch64}
                        architecture to build the tooolchain for
  --platform {bios,uefi}
                        platform to build the toolchain for

There's also platform

#

technically u can build uefi in 32bit mode even though thats not something i support atm

haughty notch
#

Yeah

livid talon
prime wraith
#

yeah i know

haughty notch
#

Because of some cursed windows tablet

prime wraith
#

yeah its for some tablets

haughty notch
#

Though I have no such hardware

ornate jasper
prime wraith
livid talon
ornate jasper
haughty notch
#

it's i686

livid talon
# ornate jasper yeah, it depends on your use case. i use the standard names because i as a rule ...

It might give you funny consequence. Imagine you want to install your OS as the second to a machine. If you keep rely on the "standard names", your OS loader (be it a universal loader or your own) will have hard times with getting started. You just will have no means to start it, since without its own boot option and with the first OS having one, your loader will never be even considered by the fw.

ornate jasper
haughty notch
livid talon
ornate jasper
livid talon
prime wraith
#

it just doesnt rename them to the "official name"

prime wraith
#

why the hell does vmware prefix this with a tab ☠️

#

i thought i had a printf bug

#

\t APIC

errant temple
#

lmfao

#

is that allowed?

prime wraith
#

i mean technically yes but why the fuck would u do that

#

i swear vmware is quirkier than most real hardware out there

ornate jasper
#

ew

#

does the spec even actually require the string to be printable technically?

prime wraith
#

as always the spec barely says anything

eternal sparrow
prime wraith
#

limine and hyper already have multiple workarounds for the vmware bios lmfao

#

now this shit as well

prime wraith
eternal sparrow
#

With a fucking \t AND an extra space

#

They are just trolling

#

They got bored at the office and did this to laugh

prime wraith
#

maybe it was JW trying to troll us

eternal sparrow
#

“How cursed can we make the BIOS without breaking the operating systems and failing review”

eternal sparrow
stuck agate
sinful river
vestal zealot
prime wraith
vestal zealot
#

I always wondered why that was

#

But apparently VMWare is just ass?

prime wraith
#

Probably lol

sinful river
eternal sparrow
sinful river
#

My OS should boot on VMware but it doesn't do anything yet so

eternal sparrow
#

And if anyone complains talk is cheap

prime wraith
vestal zealot
#

QEMU is the least-bad VM software anyway

prime wraith
#

Although you will need latest limine

eternal sparrow
#

Oh and il give intel SIMICS a pass because its needed for FRED rn trl

vestal zealot
sinful river
eternal sparrow
#

It has it for QEMU KVM only if your host supports it

#

No TCG yet

#

Bochs “supports it” but its bochs so it fucking sucks

prime wraith
eternal sparrow
#

They bochd it up

#

More like the entirety of x86-64 but ya get it

sinful river
#

Eventually I might but it's so useless right now it probably boots

eternal sparrow
sinful river
#

Zen6 has FRED?

eternal sparrow
#

It will yes

#

Intel and AMD actually worked together for once and didn’t fragment x86

sinful river
#

that's great

latent geode
#

no longer have to sail the high seas

sinful river
#

What even is the difference between workstation and player

thorny kelp
haughty notch
#

pmOS almost fully works halfmemeright

#

So it can't be that bad

earnest badger
#

pmoS=piss me off system?

wide ether
#

yeah i cant unsee that

prime wraith
#

I added nested printf support to make uacpi logging integration nicer trl

void uacpi_kernel_log(uacpi_log_level lvl, const uacpi_char *fmt, ...)
{
    va_list vlist;
    struct nested_printf npf;

    va_start(vlist, fmt);
    npf.fmt = fmt;
    npf.vlist = &vlist;

    print(
        "%c%cacpi: %pV", LOG_LEVEL_PREFIX_CHAR, uacpi_log_level_to_syslog(lvl),
        &npf
    );

    va_end(vlist);
}
ornate jasper
prime wraith
#

What do u use it for?

ornate jasper
prime wraith
#

Why does that require nesting?

ornate jasper
prime wraith
#

Oh

ornate jasper
#

or for stuff in parens id get (1234 ) instead of (1234)

#

sadly i cant use my thing to do uacpi formatted logs because zig doesnt use printf syntax

#

(and also zig does log format parsing at comptime anyway theres no infrastructure to do formatting with a runtime format specifier)

eternal sparrow
ornate jasper
#

why

#

would i need to?

eternal sparrow
#

Fair? It’s just if you want printf syntax for things that may want it and because I love printf and you can take it away from my cold dead hands

sinful river
ornate jasper
#

zig format syntax is strictly better yeah

eternal sparrow
#

Damn

#

How’s it look?

ornate jasper
#

instead of %s i do {s} and the rest kinda follows

#

also because args are passed as an anytype tuple you can refer to args by index or make the args a struct with named fields and use names, tho i forget the exact syntax since i almost never need it

#

and for alignment you can do like {x:0>16} which pads-left the thing to 16 chars with 0 as an example

#

if you use the format specified {f} then it calls a format method on whatever the value is

#

the real benefit over printf is not having to memorize all the stupid bullshit size prefixes that have no reason to exist

latent geode
ornate jasper
latent geode
#

you can kinda do it in c++ with reflection

#

but it's not pretty

ornate jasper
#

if the value is known at compile time there is comptimePrint tho

prime wraith
#

Wow, there's a bug in clang if you have code in multiple program headers the resulting .eh_frame_hdr is unsorted

#

basically everything in later program headers comes before

#

so entry 58 onwards is below 0..57

latent geode
prime wraith
#

Sort of what? It's linker generated data

latent geode
#

oh .eh_frame_hdr

prime wraith
#

😭

#

i guess im gonna put init_text in .text program header then idk

#

Oh ok that's what clanker said:

This continuation of the table perfectly isolates the exact bug. It is a **linker bug**, but not necessarily related to program headers. The data you provided clearly reveals an **unsigned sorting bug on signed relative offsets**.

Here is exactly what is happening under the hood.

### The Smoking Gun: raw_pc
The .eh_frame_hdr table doesn't store absolute addresses like 0xffffffff800390c0. Instead, to save space and remain position-independent, it often stores **relative offsets** (usually as signed 32-bit integers, denoted in DWARF as sdata4). 

If we look at your raw_pc column, we can calculate the exact base address the table is relative to:
*   **Entry 0:** pc = 0xffffffff800390c0, raw_pc = 59880 
    0xffffffff800390c0 - 59880 = 0xffffffff8002a6d8 (This is our Base Address)
*   **Entry 57:** pc = 0xffffffff8003e160, raw_pc = 80520
    0xffffffff8003e160 - 80520 = 0xffffffff8002a6d8
*   **Entry 58:** pc = 0xffffffff80000000, raw_pc = -173784
    0xffffffff8002a6d8 - 173784 = 0xffffffff80000000

### The Bug: Unsigned Sorting
Because your functions from Entry 0 to 57 are located *after* the .eh_frame_hdr base address in memory, their raw_pc offsets are **positive**.
Because your thunks from Entry 58 to 61 (<VIRTUAL_BASE>, <debug_thunk>, etc.) are located at 0xffffffff80000000, which is *before* the .eh_frame_hdr base address in memory, their raw_pc offsets are **negative**.

Whoever generated this table (likely lld or ld.bfd) sorted the entries using an **unsigned comparison** instead of a **signed comparison** on these 32-bit relative offsets:
1.  **Entry 57 relative PC:** 80520 (Hex: 0x00013A88)
2.  **Entry 58 relative PC:** -173784 (Hex representation: 0xFFFD5928)
#

i mean it makes sense that way lol

#

yeah moving .free_after_init before .eh_frame_hdr fixes it

prime wraith
#

cooking hypervisor detection

prime wraith
#

I'll detect all other hypervisors for fun i think, even though they have 0 paravirt

#
static bool bios_version_check(const char *prefix)
{
    struct smbios_id bios_version;

    if (!smbios_get_id(SMBIOS_ID_BIOS_VERSION, &bios_version))
        return false;

    return strstr(bios_version.str, prefix) == bios_version.str;
}

static u32 bochs_detect(void)
{
    return bios_version_check("Bochs");
}

static u32 vbox_detect(void)
{
    return bios_version_check("VirtualBox");
}

HYPERVISOR s_tcg = {
    .name = "QEMU+TCG",
    .cpuid_signature = "TCGTCGTCGTCG",
    .max_function = DEFAULT_MAX_HYPERVISOR_FUNCTION,
};

HYPERVISOR s_bochs = {
    .name = "Bochs",
    .detect = bochs_detect,
};

HYPERVISOR s_vbox = {
    .name = "VirtualBox",
    .detect = vbox_detect,
};

Since it's very simple anyway

#

maybe i could abuse something when they're detected

#

like xchg bx,bx on bochs etc

sinful river
#

what does xchg bx,bx do

prime wraith
#

breaks into the bochs debugger

#

same as like int3 in userspace code

sterile kayak
#

like the sdm says Hardware vendors may use the INT1 instruction for hardware debug. For that reason, Intel recommends software vendors instead use the INT3 instruction for software breakpoints.

prime wraith
#

but u know bochs

eternal sparrow
#

and int1 could? be used by the system it’s self no? For debug register things

#

I’d need to test on QEMU what happens

carmine token
#

bochs in general is quite accurate, isn't it? or at least it used to be

eternal sparrow
#

Fails to even boot Linux astral or my kernel

carmine token
#

does it fail due to cpu emulation or device emulation?

prime wraith
#

nah bochs is quite accurate

#

its a lot more accurate than tcg qemu

#

it just doesnt have much implemented

eternal sparrow
prime wraith
#

and it depends a lot on how u configure it

eternal sparrow
#

Not a bad thing just confusing

prime wraith
#

probably because its driven by random contributors rather than corporations

#

like qemu

eternal sparrow
#

IIRC I couldn’t even get my kernel to even recognize FRED under bochs

#

And I compiled with it all from source etc

dusky kraken
eternal sparrow
#

did it ever get into SSE code?

prime wraith
#

since managarm has userspace drivers pretty sure that it does

eternal sparrow
#

strange

haughty notch
#

my kernel worked on bochs the last time I checked

#

(except that my PCI code is a mess)

#

(and that didn't work I think )

#

so like not bochs' skill issue trl

eternal sparrow
#

@prime wraith i got thoes USBs in the mail

#

got an ISO for me to test on the eeepc?

prime wraith
#

ill get u one tmrw, since im in bed rn

eternal sparrow
#

kk

prime wraith
#

thx btw

eternal sparrow
#

no problem

#

sorry pressed my yubikey

prime wraith
#

lol

#

u can disable that behavior btw

eternal sparrow
#

Ahh true true

#

I’ve got the laptop and charger all set when your ready tho 🤞

eternal sparrow
#

@prime wraith

prime wraith
#

cool thanks

eternal sparrow
#

No problem ^^

#

Is that what you expected or so?

prime wraith
#

which eeepc is this?

prime wraith
eternal sparrow
prime wraith
#

cool

wicked juniper
eternal sparrow
#

For bootloader workaround stuff

prime wraith
wicked juniper
#

i have this too if you wanna try, lol

eternal sparrow
#

What would have to be done on this laptop in that case

prime wraith
#

i assume 1024x768 atm

eternal sparrow
#

So assume very low native res
Attempt to pick modes from the top bottom?

prime wraith
#

yeah the way the algo works atm:

  • get EDID, if no EDID assume 1024x768
  • Pick the highest <= native video mode && highest >= user_requested
#

This will have to be wrapped in a loop where we assume a lower native res each time

#

or just pick the highest lowest one anyway i guess and ignore user specified constraint

haughty notch
haughty notch
wicked juniper
haughty notch
#

But not core 2 duo?

wicked juniper
#

lemme go seee

haughty notch
#

So like p6 level

#

Because iirc core 2 duo is like a relatively sane x86_64

#

which is boring

wicked juniper
#

it has so many ports XD

#

lemme see if i can find its power supply

haughty notch
#

I think my parents have latitude e6400 somehwere

wicked juniper
#

well, no OS yet

#

wait, it has an IR port???

haughty notch
#

lol

#

my first laptop had an ir port

prime wraith
#

I've studied linux timekeeping code for like 5 hours today

#

ill try to maybe go for NO_HZ_FULL right away

#

or maybe NO_HZ_IDLE is good enough

#

these are the modes they have

haughty notch
#

Yeah

#

A lot of legacy bs

carmine token
#

why is it so janky?

#

under which conditions does NO_HZ_FULL fail to be tickless even when only one thread is running?

haughty notch
#

did linux use pit periodic mode in some of its early versions, or something?

carmine token
#

also, why is this weird boot parameter needed?

prime wraith
carmine token
#

why does it introduce overhead?

carmine token
#

this sounds like a linux skill issue

prime wraith
#

it says there is one

prime wraith
haughty notch
#

wdym

prime wraith
#

u used to have only pit

haughty notch
#

oh

prime wraith
#

no other options

#

so yes

haughty notch
#

pit one shot?

prime wraith
#

it did use it

prime wraith
carmine token
#

okay reading the linux docs it seems that this is indeed a skill issue

prime wraith
#

what do they say

haughty notch
#

Like you could do RTC timekeeping + PIC one shot

prime wraith
#

doesnt it have like second resolution lol

carmine token
#

At least one non-adaptive-tick CPU must remain online to handle timekeeping tasks in order to ensure that system calls like gettimeofday() returns accurate values on adaptive-tick CPUs. (This is not an issue for CONFIG_NO_HZ_IDLE=y because there are no running user processes to observe slight drifts in clock rate.) Note that this means that your system must have at least two CPUs in order for CONFIG_NO_HZ_FULL=y to do anything for you.

#

???

#

Finally, adaptive-ticks CPUs must have their RCU callbacks offloaded. This is covered in the “RCU IMPLICATIONS” section below.

haughty notch
carmine token
#

???

haughty notch
#

Like you estimate time with PIT + calibrate against RTC

carmine token
#

Managarm doesn't have these issues and it always runs in the equivalent of NO_HZ_FULL on all CPUs

prime wraith
#

pit overflows every 50ms or so

carmine token
#

Hm?

haughty notch
prime wraith
#

how does it work on managarm

#

how does it bypass those issues

haughty notch
carmine token
#

For gettimeofday() equivalent it uses a clock source that's synchronized over all CPUs

haughty notch
#

I mean if you use ACPI PM or 32 bit HPET you have to poll it periodically

#

But I think I do it once a second

carmine token
#

for RCU, idk how you even run into the problem that linux has

haughty notch
#

Jiffies?

carmine token
#

Managarm runs RCU work in a thread context that is just woken up like any other thread

haughty notch
#

(wtf even is jiffies?)

#

My kernel just runs RCU stuff on every entry/exit trl

prime wraith
prime wraith
#

its like the fallback clocksource if you dont have anything high res + its used in code where u dont need super precise timestamps

carmine token
#

solution: just don't have that meme

prime wraith
#

u could rely on always having a high res timer ig

carmine token
#

or, alternatively, just schedule ticks on one CPU even though it's in tickless mode

#

instead of preventing the user from setting it to tickless mode

prime wraith
carmine token
#

well yeah, but:

By default, no CPU will be an adaptive-ticks CPU. The “nohz_full=” boot parameter specifies the adaptive-ticks CPUs. For example, “nohz_full=1,6-8” says that CPUs 1, 6, 7, and 8 are to be adaptive-ticks CPUs. Note that you are prohibited from marking all of the CPUs as adaptive-tick CPUs: [...]

prime wraith
#

yeah thats kind of stupid

#

like cant u select the damn cpu yourself?

carmine token
#

I think this is done for RT but instead of having nohz_full= you could simply have nohz_force=

#

and let the kernel decide for all non-forced CPUs

prime wraith
#

yeah

#

looks like ill need to make some sort of a timer wheel system

#

/proc/timer_list is pretty informative

sinful river
#

Timer wheel?

prime wraith
#

basically this

ornate jasper
#

reminds me that i got to figure out timer stuff someday

sinful river
#

Just use a pairing heap

eternal sparrow
sinful river
prime wraith
sinful river
#

Unironically

ornate jasper
#

my kernel is fully ticking atm and frankly idk if i want to make it be tickless but even with my being shit at reasoning about this type of thing it still seems like a skill issue on linux's part lmao

carmine token
#

the "timer wheel" is what's known as a calendar queue in the literature

#

but ofc linux had to make up its own terminology

sinful river
#

My scheduler uses one

carmine token
#

ah actually it seems that the name timer wheel also comes from literature, so that was an unjust comment

#

the two papers are from '87 and '88 respectively so they probably just discovered this independently

prime wraith
#

pvclock init... OK

#

also added msi ext dst capability detection for kvm/bhyve since it was easy

#

next ill design how that knowledge is going to tie into tsc calibration code

#

then i guess vmware support since that just straight up gives u the tsc freq

prime wraith
#

support for 32k cpus without having to add iommu support

#

extends the msi dest field

sinful river
#

Huh

prime wraith
# sinful river Huh
guest checks this feature bit before using extended destination ID bits in MSI address bits 11-5.
prime wraith
#

Linux code is truly insane sometimes:

static void ap_calibrate_delay(void)
{
    /*
     * Calibrate the delay loop and update loops_per_jiffy in cpu_data.
     * identify_secondary_cpu() stored a value that is close but not as
     * accurate as the value just calculated.
     *
     * As this is invoked after the TSC synchronization check,
     * calibrate_delay_is_known() will skip the calibration routine
     * when TSC is synchronized across sockets.
     */
    calibrate_delay();
    cpu_data(smp_processor_id()).loops_per_jiffy = loops_per_jiffy;
}

This code is executed in parallel by all APs if parallel bringup is enabled for x86.

  1. calls into generic calibrate_delay(), which writes the result into a global variable called loops_per_jiffy
  2. stores it into a per-cpu loops_per_jiffy variable
  3. This is not in any way synchronized with other APs, so the global variable is raced with all other APs
  4. The generic calibrate_delay() already stores the calibration result into a per-cpu variable anyway per_cpu(cpu_loops_per_jiffy, this_cpu) = lpj;
#

So they have both: a race and duplicated variables to store the same information

#

how do i resist the urge to unfuck their code

prime wraith
prime wraith
#
static ALWAYS_INLINE u64 rdtsc(void)
{
    u64 low, high;

    if (this_cpu_has(X86_FEATURE_RDTSCP)) {
        asm volatile("rdtscp" : "=a" (low), "=d" (high) :: "ecx");
    } else {
        asm volatile("lfence; rdtsc" : "=a" (low), "=d" (high));
    }

    return (high << 32) | low;
}

Bruh i reeeeeally dont wanna go on the alternatives tangent right now

#

but this is really ugly also

#

well not ugly but checking the feature bit every time its read is crazy

carmine token
#

just do lfence; rdtsc unconditionally

prime wraith
#

i wonder what the cycle diff is

#

if the load + check + branch is cheaper than lfence

#

since it will be predicted every time probably

carmine token
#

the cycle diff is not necessarily relevant, do benchmarks meme

prime wraith
#

korona wont give me a straight answer nooo

carmine token
#

idk it depends on how often your this_cpu_has is an L1/L2/L3 miss etc

#

you basically cannot know w/o benchmarking lol

prime wraith
#

fair fair

prime wraith
#
u32 pvclock_read_start(struct pvclock_vcpu_time_info *info)
{
    u32 version;

    do {
        version = atomic_load_relaxed(&info->version);
    } while (version & 1);

    barrier_acquire();
    return version;
}

u64 pvclock_cycles_to_ns(struct pvclock_vcpu_time_info *info, u64 tsc)
{
    u64 host_ns, elapsed_ticks, elapsed_ns;
    i8 shift;
    u32 mul;

    elapsed_ticks = tsc - atomic_load_relaxed(&info->host_tsc_timestamp);

    shift = atomic_load_relaxed(&info->guest_tsc_shift);
    if (shift < 0)
        elapsed_ticks >>= -shift;
    else
        elapsed_ticks <<= shift;

    mul = atomic_load_relaxed(&info->guest_tsc_mul);
    elapsed_ns = ((u128)elapsed_ticks * mul) >> 32;

    host_ns = atomic_load_relaxed(&info->host_ns_since_boot);

    barrier_acquire();
    return host_ns + elapsed_ns;
}

u64 pvclock_read_from(struct pvclock_vcpu_time_info *info)
{
    u32 version;
    u64 ns_since_boot;

    do {
        version = pvclock_read_start(info);
        ns_since_boot = pvclock_cycles_to_ns(info, rdtsc());  
    } while (atomic_load_relaxed(&info->version) != version);

    return ns_since_boot;
}

@carmine token is this correct atomics-wise?

#

lol seems to work nice

#
while (true) {
    u64 new = pvclock_read() / (1000 * 1000 * 1000);

    if (new != seconds) {
        seconds = new;
        pr_info("seconds since boot: %llu\n", seconds);
    }
}
loud radish
#

pvclock_read_start needs to load-acquire

prime wraith
loud radish
#

oh in the tsc read?

proper tulip
#

in pvclock_read_start

prime wraith
#

in the code lol

loud radish
#

oh

#

bruh just load acquire lmao

#

i mean the two are equivalent on x86

#

i.e. it does nothing except compiler barriers

prime wraith
#

yeah but technically it can be a billion loads

#

we only care about the last one being acquire

loud radish
#

it doesnt matter its still a mov

#

on x86, acquire-load and relaxed-load are the same instruction

#

same with release-store and relaxed-store

prime wraith
#

ik ik

proper tulip
#

this code won't just run on x86 tho

prime wraith
#

pvclock only exists on x86 iirc

proper tulip
#

really?

#

well i don't see a problem with writing the code correctly even tho it will only run on x86

prime wraith
#

since it describes how to scale tsc to ns yeah

proper tulip
#

keep up the same standard you would throughout the rest of the codebase

prime wraith
#

also the C memory model kinda forces you to anyway

loud radish
#

acquire barriers are much more expensive than acquire loads on the one uarch i tested

#

which admittedly is the insane apple "yeah so LSE makes your code slower now lmao" firestorm uarch

loud radish
prime wraith
#

all of this stuff compiles to no-ops even at O0 and this code only runs on x86 KEKW

loud radish
#

yeah i mean in general

prime wraith
#

yeah thats fair i guess

prime wraith
loud radish
#

i think the apple m1 uarch is so fucked that no its not

prime wraith
#

what if you enable that reg that does the x86 memory model emulation lol

loud radish
#

well then obviously its cheaper to load lmao

#

since a normal ldr is acquire

prime wraith
#

thats still a thing on modern m chips right

loud radish
#

yes

#

idk how fast it is on !m1

prime wraith
#

make an aarch64 kernel that relies on loads being acquire trl

loud radish
#

no

prime wraith
#

that would be funny tbh

#

apple-exclusive kernel

loud radish
#

yeah but its a perf hit

prime wraith
loud radish
#

i have no idea

prime wraith
#

like if u forced the compiler to emit it like that

loud radish
#

i think no im pretty sure its only the stores that are more expensive or smth

prime wraith
#

probably is

#

hm

loud radish
#

you can see relaxed vs acquire load is 0 difference

#

release vs relaxed store is like a 2x hit if contended

prime wraith
#

damn thats interesting

haughty notch
prime wraith
#

we do a little trolling

prime wraith
#

I have 0 loc of kernel code ai generated but most of my tests are so I guess im staying here

#

Also might use it later anyway

#

For some algo stuff

#

Like rb trees

haughty notch
#

Idk, it's such a thin distinction

#

Like I had copilot on and was pressing tab on some of its suggestions, does it mean that a big chunk of my OS is ai generated?

ornate jasper
haughty notch
#

(I'm sorry for hijacking other threads)

haughty notch
ornate jasper
haughty notch
#

like idk, I just feel bad today about all of this and the announcements

ornate jasper
#

fair

#

id have preferred tags rather than separate forums esp since discord doesnt allow just moving a thread

haughty notch
#

No, my project is definitely not not in the vibecoded category, but I can't claim that 0% of code was written by ai