UncleBen has quit [Quit: ____________________________________________________________________________________________________________________________________________]
janemba has quit [Ping timeout: 252 seconds]
UncleBen has joined #osdev
Burgundy has joined #osdev
UncleBen has quit [Quit: ____________________________________________________________________________________________________________________________________________]
<zid>
I used to install linux by dd'ing the install cd images to a dos partition
<zid>
because burning CDs is lame, just keep 1GB of space on a random drive to use :P
<cyao>
Wait what about I give up the cdrom and make my OS be only able to install and run on a hard disk :)
<mrvn>
heat: iso doesn't work on harddrives, but they do have unused spaces where your harddrive partition table would be. So you can make hybrid images that are both harddisk and iso images.
<zid>
also works fine, and is basically identical
<zid>
make a bootable filesystem image, done
<heat>
grub2 needs to know what the hard drive actually is on
<cyao>
Ok im going to switch to grub after using like a month to make my own bootloader XD
<heat>
it uses system topology and shit (ahci vs ide, gpt vs msdos) to find the root partition
<heat>
s/root/boot/
<cyao>
@heat wdym by knowing what is hard drive actually is on
<zid>
chainload a grub1 from a grub2 :P
<heat>
there's no easy, safe way to grub2-install to a disk image
<heat>
it WILL break
<heat>
believe me, I have a workflow for that, it breaks very easily
<cyao>
Ok let me just continue to debug my bootloader
<cyao>
bye~~
<heat>
grub2-mkrescue just works because 1) it's the best 2) it's the best
<mrvn>
heat: "search --no-floppy --fs-uuid --set=root 9b412972faee0354" Where does the topology come into that?
<zid>
That's why I prefer just bundling a hardcoded grub1, they can add it to their grub2 env if they want
<zid>
or they can just dd it to an entire drive and it'll boot
<zid>
sort of like how you boot windows
<heat>
mrvn, no search in early grub
<mrvn>
heat: search has been around for years so that's ok
<heat>
no search in early boot grub
sham1 has quit [Ping timeout: 252 seconds]
<mrvn>
heat: ahh, for stage2 you mean. yes, that needs a blocklist
<bslsk05>
github.com: Onyx/grub-early.cfg at master · heatd/Onyx · GitHub
cyao has quit []
<mrvn>
It always bugged me that PC don't have a bios call to read from the boot device, whatever that device happens to be.
sham1 has joined #osdev
<heat>
efi does
<heat>
all praise the extensible firmware interface
<mrvn>
heat: but EFI can only use FAT16 on removable devices and FAT32 on harddisk. So you can't boot the same image from different devices.
<heat>
yes you can
<mrvn>
Stick your harddisk into an USB enclosure and it no longer boots
<heat>
not true
<mrvn>
(unless your EFI implements more than specs)
<zid>
maybe I should switch to including freedos and lilo
<zid>
instead of grub
<mrvn>
zid: isolinux
<mrvn>
heat: read the specs. if you only implement what's required you end up with the above mess
<heat>
"The EFI firmware must support the FAT32, FAT16, and FAT12 variants of the EFI file system."
<mrvn>
heat: yes, but not on every device
<heat>
"Removable media may contain a standard FAT12, FAT16, or FAT32 file system."
<heat>
Wrong
<mrvn>
heat: what version of the specs is that? Did they actually fix that?
<heat>
i'm looking at the latest
<mrvn>
wow. someone with cloud must have complained their big USB storage devices where too big for FAT16
<heat>
wrong
<heat>
"Removable media may contain a standard FAT12, FAT16, or FAT32 file system." UEFI spec 2.0 dated 2006
<heat>
"Removable media may contain a standard FAT12, FAT16, or FAT32 file system." EFI spec v1.1 dated december 1st 2002
<heat>
almost as old as me!
<heat>
even going back to 1.02 you don't have this specific wording but merely a "The firmware automatically creates handles for any block device that supports the following file system formats: FAT12, FAT16, FAT32"
<zid>
"They however, do not work right"
<zid>
"We're still working on that bit sorry"
<mrvn>
heat: can't find the old specs or the palce in current ones. But check for what combinations of FS and devices are required. I do know it's a real problem because I have stupid hardware that has this exact problem. Maybe it's a broken implementation though.
puck has quit [Excess Flood]
puck has joined #osdev
<heat>
i just did
<heat>
proved you wrong up until 1.02
<heat>
the year 2000!
<heat>
might be broken implementations, they're not that uncommon
<heat>
but I do know that tianocore makes no distinction, so unless the IBVs have been fucking around the FAT driver (not uncommon) it should've always worked
<mrvn>
heat: the problem isn't that the efi doesn't support FAT32, it's that it won't recognize it on USB, only on harddisk.
<mrvn>
And harddisks are clearly far to big tor FAT12 so it never tries that on harddisk.
<heat>
I am aware. I gave you specific quotes to the spec that explicitly say you must support every FAT for every block devices
<ddevault>
opening up the aarch64 mmu can of worms again
<ddevault>
adjust your path to AAVMF_CODE as necessary
<kof123>
"It always bugged me that PC don't have a bios call to read from the boot device" not a call, but i thought it stuck a magical number into a register? whether things trash that, how someone not writing a bootloader can get to that, is another story perhaps
<mrvn>
ddevault: getting boot.S and the kernel wokring till you have printf working in higher half is the hardest.
<ddevault>
well, I do have printf working in the lower half :)
<mrvn>
kof123: afaik the basic calls you tell it to read from 80 (first disk) or 81 (second disk). Reading from thrid disk? Nobody has 3 harddisk, are you insane?
<kof123>
or, the calls themselves? hmm
<kof123>
*oh
<mrvn>
kof123: oh, and the bios has a list of harddisk geometries you can pick from. Because there will never be more than the 64 or so disk types we hardcoded. :)
<ddevault>
I am very annoyed that qemu does not add -initrd parameters to the dtb
<ddevault>
and similarly annoyed that edk2 does not provide a device tree via EFI
<heat>
qemu does add them
<ddevault>
not so far as I could tell
<ddevault>
read the qemu code, too
<ddevault>
(I) read; past tense
<heat>
maybe it's because you're not pretending to be linux?
<heat>
qemu (annoyingly) hides a lot of nice stuff behind that on arm64 and riscv
<ddevault>
yeah, maybe not
<ddevault>
am I missing the arm mmu setup code in the LK tree?
<ddevault>
yes I was, found it
<j`ey>
ok repro'd
<kof123>
"it would be nice if any of the PDF viewers I had handy could open the ARM manual" out of curiosity 1) crash 2) throw an error 3) use tons of ram and cpu ?
<kof123>
*iousity ?
<ddevault>
zathura: fails to render pages; evince: unusably slow, then crashes; pdf.js: loads forever
<heat>
evince works fine for me
<kof123>
yeah. i just recently used pdfimages (from "poppler"?) to generate 3 pngs per page (maybe are supposed to be one, it splits color channels or something). 40x space needed, but can browse on an old system (although image viewers vary widely too, how much cpu and ram they need to show ~2M png file)
<kof123>
*for another PDF. xpdf may be slightly lighter, but ...
<kof123>
on an old system, still takes a long time to generate those images lol
<kof123>
and lots of ram
<mrvn>
if it's doing antializing cheaply it might just render a 16 times larger image and then scale down.
<GeDaMo>
Maybe use a command line tool to split out smaller sets of pages?
<ddevault>
yeah, I might
<ddevault>
breaks references though
<mrvn>
I use xpdf and evince
<ddevault>
currently just living from references I find online instead
<ddevault>
oh nice xpdf seems to manage
<mrvn>
I'm still looking for a pdf reader with tabs so I can follow a refernece in a new tab and then easily switch back and forth.
<ddevault>
I sometimes fake that with pdf.js in firefox
<ddevault>
middle clicking refresh dupes the tab with the same page open
<ddevault>
then I click the reference
<mrvn>
but that's so damn slow
__fastcall has joined #osdev
__fastcall has quit [Client Quit]
<kof123>
archive.org is particularly annoying because the outer cover is many times some blurred swirl color that always take a bit of time to render. zero text on that. thanks for scanning the swirl
<ddevault>
zathura can also do tags
<epony>
10K pages arm SoC docs ;-) such fun
<ddevault>
marks*
<ddevault>
mX to set quickmark X, 'X to go back to X
k0valski18891 has joined #osdev
sham1 has joined #osdev
<j`ey>
Jump to kernel entry @ ffff800000024000 (TODO)
<j`ey>
needs more fs ddevault
<ddevault>
hm?
<j`ey>
0xFFFFFF0000000000
<ddevault>
err, maybe
<ddevault>
but in any case the code hasn't got that far yet
<ddevault>
or did you manage to fix the mmu and get past the page fault?
<j`ey>
yes it has, it just printed that for me ;)
<ddevault>
err, wait
<ddevault>
why two extra F's
<j`ey>
40 bits
<ddevault>
maybe this is why my page fault is happening
<ddevault>
I thought it was the top 16 bits that picked the higher/lower half
<j`ey>
it is!
<j`ey>
the top bits of what you set the TxSZ to have to be 0 of 1
<ddevault>
hm
<ddevault>
interesting
<ddevault>
I'll look into that once I get off of the phone
<j`ey>
you set 40 bit T1SZ, so need those extras
<j`ey>
I hacked qemu, and it gets past the assert
<heat>
man j`ey really is the arm
<j`ey>
I do have an arm or two
<mrvn>
and two legs
<ddevault>
where in the ARM manual can I read about this, j`ey?
<ddevault>
if you know off hand
ALowther has joined #osdev
<ddevault>
well I'll be
<ddevault>
higher half works with 0xFFFFFF
<ddevault>
but now I have to rethink my whole memory map
<j`ey>
or use 48-bit TSZ?
<heat>
actually this is the only scheme that makes sense
<j`ey>
and I dunno where it is in the manual
<heat>
else you wouldn't have simple canonicality checks
<ddevault>
yeah, or change TSZ
<ddevault>
can I expect 48-bits to be useful on most aarch64 platforms?
<heat>
yes
<ddevault>
nice
<mrvn>
ddevault: it's always top bits set for higher half unless you use tagged pointers. Then the upper 8 bit are used for other stuff.
<ddevault>
and now the MMU works
<ddevault>
woo!
<ddevault>
thanks j`ey :)
<mrvn>
ddevault: told you to check you actually test the right address.
<heat>
j`ey, j`ey is the professional arm
<ddevault>
it was the right address!
<ddevault>
but the wrong address translation configuration
<heat>
or (also possible) arm has a weird quirk there
<ddevault>
not sure I'm following you
* j`ey
rm -r /tmp/drew
<ddevault>
you mean I need 4 levels of page tables with this configuration?
<ddevault>
for 4K pages at the bottom
<heat>
if your page tables cover 48-bits, considering 4K pages, you have 48 - 12 = 36 radix bits, each 4K page covers 512 entries (so each page table level uses 9 bits as an index), 36/9 = 4
<mrvn>
kaichiuchi: and then you derive the callbacks with their data from that
<kaichiuchi>
that seems a little strange to me
<kaichiuchi>
doesn't that end up using dynamic dispatch? or not, because it's pure virtual
<heat>
yes it does
<mrvn>
kaichiuchi: it will do a virtual function call.
<zid>
is it 10pm yet
<mrvn>
kaichiuchi: basically the same as C style struct Callback { fn_t (*fn)(void *); void *data; };
<zid>
is monday, is book day
<kaichiuchi>
mrvn: i see what you're getting at now
<kaichiuchi>
I guess from an optimization standpoint, this will get devirtualized if the compiler sees that this is only ever set once ever
<mrvn>
kaichiuchi: if it's in the same compilation unit or LTO
<mrvn>
but then why do you have a callback if it's only ever used with one function? Just include that code directly.
<kaichiuchi>
well, not "only ever used with one function", let me clarify it a little better
<kaichiuchi>
essentially, the call looks something like this: `scheduler_.AddEvent(Scheduler::Events::whatever, timeout, []() { ... });`
<mrvn>
if you have something like "sort(range, compare)" and the compiler inlines the sort then the compare callback likely disappears.
<kaichiuchi>
yes
<kaichiuchi>
that's what I'm geteting at
<kaichiuchi>
getting*
<zid>
gcc's really crap at that from my experience, idk why
<zid>
it seems like it should be simple
<mrvn>
If you store the callback and later call it then I would say it's near certain it doesn't get optimized out.
<mrvn>
zid: inlining the function and then eliminating the callback? I guess it often goes over the inline limit.
<mrvn>
zid: plus you have a top - down - up relation in the code and the inliner / optimizer only works one way. Iirc up for gcc and down for clang.
<kaichiuchi>
"derive the callbacks with their data from that"
<kaichiuchi>
please tell me the solution isn't to make _another_ class
<mrvn>
kaichiuchi: can't. That's what the solution. Hence why you have lambda now to do this at a fraction of noise.
<mrvn>
+was
<ddevault>
always the parts I think will be simple that aren't
<kaichiuchi>
could I just get a time machine and convince bjarne stoustroup not to do this to the planet
<heat>
kaichiuchi, can you just reimplement std::function and be done with it?
<kaichiuchi>
no
<heat>
your decision
<kaichiuchi>
also
<mrvn>
heat: he could but can one do that in time without loosing once mind?
<heat>
you're upset because things aren't magical enough for you
<kaichiuchi>
yeah kind of
gareppa has joined #osdev
<heat>
i guess that's what happens when the language is low level and there are no _Uppercase nerds to write your fun shit for you
<ddevault>
what was that qemu flag to debug faults on aarch64?
<ddevault>
-d int, I guess
<heat>
don't forget you're mostly working with C-like C++ here
<kaichiuchi>
yes
<heat>
C and C++ aren't too different if you don't have anything built on top
<kaichiuchi>
and in C I would've passed a function pointer and then cried myself to sleep
<mrvn>
kaichiuchi: Note that if you use the C (void * data) case then you also need a second wrapper struct or have to write the callback with a void * arg and cast it yourself in the code.
<kaichiuchi>
that's it, that's it, I'm gouging out my eyeballs with a fondue fork this very SECOND
<mrvn>
kaichiuchi: Most people cheat there and cal the function pointer with the void* arg while the function takes a different type but that's UB.
<heat>
i've never seen anyone do that
<kaichiuchi>
what, gouge out their eyeballs with a fondue fork?
<mrvn>
heat: it works until you have an arch where pointer representations aren't all the same.
<heat>
no shit
<heat>
again, I haven't seen anyone (sane) cast a function pointer
<kaichiuchi>
i'm still a little bit lost here
* geist
whistles
<kaichiuchi>
there is no constructor
<kaichiuchi>
so
<heat>
geist, henlo poltergeist
<kaichiuchi>
`class Callback : public FuncCallback { public: void operator()() { how the fuck can I pass the lambda here? } }
<ddevault>
I do this cheat but it's not UB for me :3
<heat>
kaichiuchi, you can't, you would need a Callback<T>
<geist>
though i can't be bothered to read the full scrollback to see what precisely the 'cheat' is
<mrvn>
heat: so you don't write "int comapre(const struct Foo *left, const struct Foo *right);" and pass that to qsort?
<heat>
no
<heat>
wtf
<geist>
oh gosh i do that stuffall the time
<kaichiuchi>
heat: please stop this... I can't take it anymore
<ddevault>
geist: cast a function pointer so its paramters are a generic type
<kaichiuchi>
okay, I will do that because I thought that was the answer and I was hoping you'd tell me I was wrong
<geist>
oh yeah i do that allthe time, but i also know if/when the abi is going to be upset
<ddevault>
exactly
<mrvn>
kaichiuchi: With a template. But why would you use a callable class to call a lambda. The lambda is there to replace the callable class.
<geist>
like, say, returning a value from a function that then gets treated as a void
gareppa has quit [Remote host closed the connection]
<heat>
kaichiuchi, didn't we write something similar-ish a few days ago?
<mrvn>
kaichiuchi: either use lambda or a class, not both.
<kaichiuchi>
my goodness
<geist>
that's fine up until you return something 'big' and then the inner function will probably trash the stack
<heat>
please mrvn you're not helping
<kaichiuchi>
heat: yes
* geist
smiles and also tries not to add noise
<heat>
kaichiuchi, so here's the deal: you want to call $thing, you need some way to do type erasure and call $thing
<kaichiuchi>
but the problem is now I have an array of Events (struct), and inside this Event struct contains a function call, which, I want to work with lambdas
<heat>
that would traditionally be done with a std::function helper
<heat>
Hint: maybe implement a std::function
<kaichiuchi>
the problem is I don't know how
<mrvn>
kaichiuchi: have you ever implemented type erasture?
<kaichiuchi>
I have no idea how you can figure out how any of it works and be 20 years old and still communicate like a normal human being and shower
<kaichiuchi>
no
<heat>
YOURE NOT HELPING
<kaichiuchi>
I have never done any of this
<mrvn>
kaichiuchi: then maybe start watching some youtube videos about type erasure. What it is, why you need it and how to do it.
<kaichiuchi>
this sounds like a lot of "you must be a language lawyer to pass a lambda"
<mrvn>
kaichiuchi: after that you should be able to implement a simple std::function.
<heat>
so std::function uses for its implementation something like a class invokeable<ReturnType, Args> { virtual ReturnType operator()(Args... args) = 0; }
<heat>
this is the base of erasing the actual type
<mrvn>
kaichiuchi: passing one lambda is fine. Storing 2 lambdas, which you need for your use case, is hard.
<heat>
you're not helping part 2
<kaichiuchi>
i am listening to both
<kaichiuchi>
continue, please
<heat>
because then you implement a invokeable for each kind of thing you need to implement: 1) normal raw pointers (simple) 2) lambdas/callables 3) member functions 4) probably something else
<heat>
you need to do this because a function pointer, callable objects (objects with an operator()), member function pointers are all very different from each other in terms of code gen and memory layout
<heat>
if you were hand-doing this in C you would still need to do this shit
<geist>
but in C you can just badger-cast it to whatever you want
<geist>
badger badger badger
<kaichiuchi>
yes
<geist>
(i really just wanted to say badger)
<mrvn>
Hint: you only need to implement the case you actually use. Not every corner case.
* geist
stops not helping
<kaichiuchi>
okay, okay, I will try
<mrvn>
.oO(no callables and no member function pointers in C)
seer has quit [Quit: quit]
<kaichiuchi>
i will try and write my own gbstl::function
<heat>
a function pointer is just 8 bytes to which you jump directly, a callable object is $object_size bytes (where you need to call object_class::operator()), a member function pointer is 16 bytes (direct pointer to the function and the "this")
<geist>
possibly covered farther up, but i *think* a lot of the machinery of std::function probably relies on std::type_traits
<geist>
which let you select different impls based on this or that
<geist>
at compile time
<mrvn>
heat: huh? A member function pointer is 8 byte, the offset of the member. Did you mean a bound member function pointer?
<kaichiuchi>
(to be clear, I'm not ungrateful, I am just frustrated)
<kaichiuchi>
this is important for me to learn
<heat>
a useful member function pointer is 16 bytes
seer has joined #osdev
<kaichiuchi>
I think type_traits does have the fancy _builtin compiler support for it
<heat>
geist, possibly, although it's possible you can easily get away with a templated operator=
bgs has quit [Remote host closed the connection]
<geist>
yah, though thats where you get into that type specialization stuff that i barely understand
<geist>
ie, partially specialze based on the type matching this trait, etc
<geist>
that's the threshold where my head starts to explode
<heat>
yeah
<kaichiuchi>
i wonder what I was doing when I was 20
<mrvn>
geist: it kind of sucks that C/C++ doesn't mandate the representation of pointers to be type independent. Is there even any arch out there where the types differ?
<CompanionCube>
perhaps something like segmented memory or CHERI?
<mrvn>
CompanionCube: with segments a short* and int* are still the same. CHERI iirc add tag bits, right?
<CompanionCube>
ah, yes
<mrvn>
short* and int* would have the same representation, just different values in the tag.
<kaichiuchi>
hm...
<kaichiuchi>
I just realized something..
<kaichiuchi>
no, fuck, I don't think that'll work
<mrvn>
kaichiuchi: do you even have more than one user supplied argument to the callback? Maybe just pass the data as argument to a lambda without capture, because then it's just a function pointer
<kaichiuchi>
essentially, all of them have this sort of setup: `[this](const int cycles_late) noexcept { ... }`
<mrvn>
the C style function pointer + void*data except with lambdas instead of named functions.
<kaichiuchi>
yeah
<mrvn>
kaichiuchi: then you just need a wrapper that takes the void*data and casts it back to typeof(this) and calls the right function.
<mrvn>
==> see type erasure for how to do that
<kaichiuchi>
okay
<geist>
yeah decorated pointers with extra type field might classify
<mrvn>
decorated pointers wouldn't be a problem though. When you cast T* to void* and back you wouldn't change the decoration.
<geist>
unless i'm just completely off (which i hope), what i hope is that the semi standard idiom of returning a constructed object from a 'new' method and then stuffing it in a box is supposed to do better than that
<geist>
now, with -O2 it smashes ost of it, so it's possible that the whole point is is you really *must* inline constructors
<geist>
notably the place where it puts a struct in a box it constructs an etire one on the stack, *then* allocates space, then memcopies it in
<geist>
but in a fully inlined version it constructs the object on the already allocated block, like you'd expect
<geist>
it news it on the stack, then allocs, then copies
<geist>
but at least the new routine constructs the object in a hidden first arg, which is what i'd expect
<geist>
but in general as i piddle with features, i see quite a bit of missed opportunites, which is fine, but what makes me extremely worried is things like this where it'd temporarily burn a lot of stack if you're alloocating something large *in the heap*
<geist>
the whole point being that you're allocating a heap object, dont use the stack!
<j`ey>
patrick walton has a recent patch for review to aim to remove more memcpys in LLVM, it *may* help in this case, not sure
<geist>
yah and of course these optimization choices are probably generally fine for user programs, i'm looking for places where weird misoptimizations are going to be hard on kernel environments, where there is minimal stack, for example
<geist>
and i'm sure there's a way to work around it, the more unsafe {} or whatnot you go
<j`ey>
but yeah, it's a known issue
<geist>
like i saw some mention of slapping structs in uninitialized memory, or badger casting pointers via unsafe {}
<j`ey>
the person working on the M1 GPU driver wrote a macro to do it, since they were hitting stack issues like this
<zid>
what's a badger cast? some old ibm mainframe term?
<zid>
google is like "Best I can do is give you the cast of the children's TV series bodger and badger, take it or leave it"
<geist>
oh i dunno, someone at work calls it that when you just reinterpret cast X as Y
<geist>
you badger it into place
<zid>
oh a type pun?
<zid>
or a value whatsit
<geist>
really just reinterpet_cast
<zid>
that's a value whatsit?
<geist>
i dunno, i dunno what a value whatsit is
<zid>
type pun is "bits of this, as bits of that", like 0xFEC000 -> -1, value whatsit is 0xFEC000 -> 1278392.000000000
<geist>
i think it's morelike 'i know this pointer to an X is really a Y so i'll just make it so'
<zid>
-1.0*
<zid>
I should really have looked up what -1 was as a float before startin that sentence tbh
<zid>
0xbf800000
<geist>
and yeah what i said is a reinterpret_ast, but i think the idea is 'badger cast' is language neutral
<geist>
like, whatever you do in whatever language you are in to make it happen
<zid>
I don't use that language, nor have heard that term, so it was a struggle for me both ways :P
<geist>
also you dont have a television, and you only drink rainwater
<zid>
Correct
<zid>
if by rainwater you mean dr pepper
<zid>
C spec just says stuff like 'object representation of the value is reinterpreted as an object representation in a new type' which doesn't really roll off the tongue, so then goes "Which is sometimes called type punning"
<geist>
yah and then C++ had to go make it complicated by coming up with 4 different types of casts
<geist>
but they each have a reason. reinterpret_cast is the lowest level one. treat this bag of bits as that
<zid>
casting is when you do the value to value thing, 0xBE -> 0xFFFFFFFFFBE, type punning is when you keep the representation but treat it as a different type
<kaichiuchi>
but reinterpret_cast<>() is bad news now
<geist>
which is almost exactly the C cast but not exactly in all cases, etc
<kaichiuchi>
they want you to use std::bit_cast
<geist>
oh probably. there's always some new thing
<zid>
don't forget to do the weird thing where you can tell it to forget aliases
<kaichiuchi>
it's literally just memcpy under the hood as far as I'm aware
<zid>
I forget what's that called, someone mentioned it to me a while back, for use in writing allocators
<geist>
well if it's a memcpy then it's not casting, that's a bitwise copy
<kaichiuchi>
restrict?
<zid>
no
<kaichiuchi>
geist: right
<geist>
there are extension attributes that say 'this memory is new and came from the heap'
<geist>
so that the compiler can optimize as such because among other things it knows the pointer isn't aliasing anything else
<zid>
[[no_unique_address]] is the context in which it came up
<geist>
ah
<geist>
this is where rust's lifetime stuff is pretty neat. it's a first class citizen in the language
<geist>
it's annoying, dont get me wrong, but it is kinda neat
<zid>
placement new
<zid>
is the term I was looking for I think
<zid>
std::launder
<zid>
which is the best name
<kaichiuchi>
that's... I didn't put two and two together
<geist>
yah placement new is basically just a way to invoke a constructor on a pointer, since otherwise there's no real way to 'get to' a constructor
<kaichiuchi>
placement is part of the money laundering process
<geist>
since constructors in C++ are all tied up with 'new' operators
<zid>
is it? til
<kaichiuchi>
yep
<zid>
launderin the address is exactly what you're doing
<zid>
even if the placement thing is accidental, or isn't, doesn't matter
<zid>
launder's still a great jargon metaphor word for it
<geist>
note you *can* call the destructor on an object directly
<geist>
ie, the opposite of placement new
<geist>
but for whatever reason they didn't call it something like placement_delete, so it looks a bit inconsistent
<zid>
good waste of 10 mins, few more mins until my book chapter releases, ty
<geist>
most likely the latter existed before the former, or something, so they added it later and coukldn't redo the earlier thing
lkurusa has joined #osdev
<j`ey>
zid: book DLC?
<zid>
yep
<mrvn>
geist: C++ screws this up with new/construct_at too. There is a return value optimization but no argument value optimzation for passing objects into the allocation so they can be constructed in place.
<mrvn>
I thin c++ must invoke the copy constructor
<zid>
bam it's here, see ya later nerds
<geist>
mrvn: AFAIK that's not true, there ar emultiple constructors defined for the ABI, some that do take the target pointer and some that dont
<geist>
ie, the compiler can generate multipl versions
<geist>
it's defined in the machine ABIs. i've bumped into it in embedded space because it ends up chewing up more text with multiepl constructors for a single object
<geist>
i think the primary reason you need different ones is when aconstructor is run as part of an inheritance chain, it needs to get the pointer passed in to construct in place
<mrvn>
geist: there is stuff like make_shared that will constrcut the outermost object in place. But the arguments to the constructor of that object will be constructed as temporary objects and not in-place.
<geist>
nah not true. but you might only see the other constructors if the linker decides to keep them around (ie, some inheritance happens), otherwise the linker probably strips em
<mrvn>
geist: I'm saying there shouldn't even be different constructors. The compiler should be alowed to opimize out the copy operastor and call the constructor for the sub objects in-place.
<geist>
true,but the ABI says you need to stick to the rules for external linkage
<geist>
hence why they define multiple hidden implementations so the linker/compiler can pick
<mrvn>
geist: this isn't about linkage. you see this will all the source in a single file.
<geist>
in that case it's different rules. if it's inlined, or local the compiler can do whatever it wants
<geist>
i'm talking about in the case where it can't bend the rules (ie, external linkage)
<mrvn>
geist: except not skip the copy constructor if it has an observable effect. Unlike on return
<geist>
okay. anyway, i've seen it, and it's actually frustrating if you're trying to maximize space
<geist>
usual idiom there is have your constructor call an internal separate method, so the compiler can merge them nicely
<mrvn>
And the copy construct requires you have a source and destination. So you do get a temporary on the stack that is then copied to the heap.
<geist>
though modern compilers may be better at merging the different constructors (or destructors) by using aliased symbols
<geist>
again i'm talking about multiple *implementations* of a single source level constructor
<geist>
copy/move/etc is a different set of issues
<mrvn>
geist: can you give an example where the compiler generates 2 constructors? I never heard of that.
<geist>
but i think there's another case. iirc C++ abi defines i think 3
<geist>
there's a separate name mangling for it too, it's just usually flattened to 'constructor' but godbolt there is showing you the full version ('base object constructor' and 'complete object constructor')
<mrvn>
geist: oh yeah. That's just the past that sets the vtable. Nothing to do with allocating the arguments on the stack.
<mrvn>
s/past/part/
<geist>
well i never said that. i'm saying there ar emultiple types of constructors
<mrvn>
it's odd though. a while ago someone said the base class would have the vtable set to the base classes vtable during construction.
<geist>
ah actually without virtual it you see the multiple types
<geist>
note how the compiler has generated one constructor the 'base object constructor' but then the bleh() function is calling the 'complete object constructor'?
<geist>
i think if you look in the symbol table those are aliases for each other when the compiler decides it doesn't need a different version
<mrvn>
yes. without vtable they alias to the same thing.
<geist>
in older GCCs i think the problem was it generated separate ones and didn't merge them
<geist>
which was annoying for embedded
<mrvn>
older (oldest :) gcc didn't merge any template code at all. Horrible code bloat.
<mrvn>
any generic would have N copies of identical code
<geist>
i remember at the time the problem was not gcc as much as gdb. there was some issue with debuggers and merged symbols like that
<geist>
so there was some consternation as to whether or not it was okay to alias them
<geist>
i guess they sorted it out
<zid>
okay book dlc done :(
<geist>
and yeah maybe the generic merging problem got solved at the same time
<zid>
I'm one of you again
<mrvn>
I don't see why 2 symbols shouldn't have the same address. bad GDB. bad.
<kaichiuchi>
i'm about to make mrvn and heat very sad
<bslsk05>
github.com: gameboy/timer.c at master · zid/gameboy · GitHub
<kaichiuchi>
yes
<zid>
Yea that code is basically just i++ and a mod 256, with a setter and getter for a reload value
<heat>
oh yeah have you guys followed C23?
<kaichiuchi>
yes
<zid>
yea it's mainly shit as usua
<heat>
checked arithmetic operations
<heat>
are you joking? shit?
<zid>
but has the mandatory 1 interesting thing
<heat>
come on
<zid>
C99 had designated initializers, but you got complex.h in exchange, etc
<zid>
C11 had anonymous unions, but.. whatever the hell 400 pages of nonsense we also got
<mrvn>
heat: I know there was something interesting but now I can't rember what
<heat>
nullptr
<heat>
[[attributes]]
* zid
cringes
<zid>
at least K&R decs are dead
<heat>
decimal floating point, u8 chars and strings, #elifdef
<heat>
= {}; is now standard
<heat>
strdup
<zid>
still no macro for endian
<heat>
finally memset_explicit
<heat>
a bunch of standard utf8 support for the libc
<heat>
I can't see how this isn't a major win in all aspects
<j`ey>
zid: only bookworm i know is some debian thing
<zid>
90% of this is just posix, 8% is nonsense from C++ I won't use, 1% complex.h improvements
<zid>
normal C standard
<heat>
"wN and wfN length modifiers for [u]intN_t and [u]int_fastN_t respectively"
<heat>
no need to PRIu28283u82u38wu3e232
<heat>
(who thought that was a good idea???)
<zid>
That came through another normal C standard
TkTech has joined #osdev
<zid>
don't redesign anything, don't improve anything, bolt something on through an addendum that's so generic and useless that it can't fail to pass comittee
<zid>
"idk just make some standard macro names for it, it's better than nothing and won't break anything"
nyah has quit [Quit: leaving]
<gog>
never improve
<zid>
It's *vital* we have __bool_true_false_are_defined, knowing if your structs are ordered correctly, knowing the length of an enum or size of an array? useless.
<gog>
only add characteristics
<gog>
i agree with this vibe
<heat>
geist, are you going to refactor the fdt reserved mem stuff I pointed out?
<kaichiuchi>
well...
<kaichiuchi>
my idea did not work
<kaichiuchi>
and I should've known it wouldn't have worked
<kaichiuchi>
god.
<kaichiuchi>
that would've been great.
<zid>
C91: NULL cannot be int, ENUMTAG_MAX is automatically defined, etc
<zid>
just fix the bullshit, add the things everybody writes macros to implement etc
<zid>
we learned a lot about what the shortcomings with trivial fixes are in 40 years
<kaichiuchi>
actually
<kaichiuchi>
this will still work
<kaichiuchi>
with the ugliest fucking using directive ever.
<mrvn>
Ahh, wasn't that new in C23? nullptr being a distinct type?
<bslsk05>
lore.kernel.org: [linus:master] will-it-scale.per_thread_ops -40.2% regression in mmap1 benchmark - kernel test robot
<zid>
breaking auto is going to be a huge fucking headache for some people too
<zid>
but tbh they probably deserve it for using auto
<mrvn>
take a train
<heat>
zid, auto is the greatest thing ever
<heat>
which auto? yes
<zid>
:D
<zid>
auto auto x;
<heat>
omg yes please
<heat>
i want a keyword that changes meaning depending on its position
<zid>
heat: why are you so gung ho over {} btw, it saves two characters
<\Test_User>
<C> auto char x = 5; // valid
<\Test_User>
<C> I make you specify types for a reason, no evading it
<heat>
zid, saves one
<heat>
but it's still nice
<zid>
yea I guess 1
<heat>
also a GCC extension
<zid>
no
<heat>
yes
<zid>
not a gcc extension at all
<mrvn>
\Test_User: what part is auto there? "const"?
<\Test_User>
mrvn: static/auto/register part you mean?
<heat>
auto or (until C++11)no specifier - automatic storage duration.
<mrvn>
Who uses the return type specifyer on the right for functions? -> type iirc
<mrvn>
isn't register 200% obsolete?
<zid>
all subobjects that are not initialized explicitly shall be initialized implicitly the same as
<zid>
objects that have static storage duration.
<\Test_User>
auto is 5000% obsolete
<heat>
auto is NOT obsolete
<zid>
it then says the exact same thing again
<heat>
I use it in my aoc 2022 stuff
<zid>
If there are fewer initializers in a brace-enclosed list than there are elements..
<zid>
which part of this is a gcc extension?
Burgundy has joined #osdev
<\Test_User>
heat: C auto
<heat>
\Test_User, I am aware
<heat>
C auto bestttttttt
<heat>
how else would you know where it lives!
<heat>
zid, {} required at least an element in the initializer list (so usually = {0} was the standard pattern)
<zid>
yes
<kaichiuchi>
man...
<heat>
{} was a GNU extension
<zid>
hence {} saying one character
<kaichiuchi>
I *almost fucking have this*
<zid>
saving*
<heat>
correct
<heat>
{} was a GNU extension
<zid>
okay that's not what I got from what you said
<zid>
"saves 1, but nice, also a gcc extension"
<kaichiuchi>
except I can't do `class K { public: K(A& a) : a_(a) {} }; template<typename B> class A { ... }`
<kaichiuchi>
because I *have* to pass the template parameters to the K ctor
<kaichiuchi>
and I have no idea how to do that cleanly without `using`
<mrvn>
kaichiuchi: Since K has no template args on it's own you can just prefix it with template<typename B>
<mrvn>
kaichiuchi: If you don't want K to have template args ==> type erasure
<kaichiuchi>
oh lord
<kaichiuchi>
see, this idea came about upon this realization
<kaichiuchi>
event A is fired, it's *ALWAYS* going to call the same function `Klass::HandleA()`, if event B is fired, it's *ALWAYS* going to call the same function `Klass2::HandleB()`
<kaichiuchi>
*always*
<mrvn>
why is that handleA and handleB?
<kaichiuchi>
I mean, it doesn't HAVE to be
<kaichiuchi>
here
<mrvn>
If they are different classes then just call operator()
<mrvn>
If you want the option to use the same object for both events and have it call different handle functions then you might want to look into bound member function pointers.
<mrvn>
Which is some magic type that's basically a pair of this and member function pointer.
<kaichiuchi>
yeah, I think it's time I had a stroke
<kaichiuchi>
every single thing I want to do it's "write another 100 fucking lines"
<zid>
my entire file is 100 lines :P
<kaichiuchi>
you see
<kaichiuchi>
first I had to rewrite std::array, which wasn't bad at all
<zid>
I could even make half of it a macro I use 4 times
<kaichiuchi>
now I have to implement some of type_traits and functional
<kaichiuchi>
it's depressing
<heat>
std::array is depressing
<kaichiuchi>
I don't get you either
<kaichiuchi>
I really don't
<kaichiuchi>
you're one of the people who talk an enormous amount of shit on C++ but Onyx is written in it
<kaichiuchi>
though
<kaichiuchi>
I guess that gives you the right to say shit about it
<mrvn>
461 1358 13820 /usr/include/c++/11/array
<mrvn>
That sounds rather simple
<kaichiuchi>
array is simple, yes
<kaichiuchi>
that's not the trouble spot
<kaichiuchi>
I think I've been bitching about reimplementing std::function for two days
<mrvn>
stripping out all the noise and traits: typename _AT_Type::_Type _M_elems;
<heat>
modern C++ is bad, C++ itself has always been kinda meh, but still I find it much easier to use than C
<heat>
I like C but C is also bonkers in many ways
<kaichiuchi>
and it gets worse every time I need to do something that should be basic
<mrvn>
iterators, operator[], at, done
<heat>
I also don't have the needed eyes to make my project correct in C; memory allocation, reference counts, etc are all a PITA
<heat>
it would be *doable* if I had more eyes on things
<kaichiuchi>
see, I like a lot of what C++ has to offer
<kaichiuchi>
but man
<kaichiuchi>
you two are telling me I need to write like a 250+ line wrapper and watch a dozen youtube videos
<heat>
if you look at C++ it's very obvious there are a ton of big issues
<heat>
how do you print an array?
<heat>
how do you *not use* exceptions but still use the STL?
<heat>
I shit on C++ but I also shit on C
<mrvn>
heat: std::expected to the rescue
<heat>
expected doesn't fix 30 years of bonkers interfaces
<mrvn>
heat: no, it needs all the exception based interfaces to be duplicated with std::expected as return type
<mrvn>
print an array? foreach the array with a petty_printer?
<zid>
C++ accepted every single addendum proposal ever, and it's too much work to write cleanups, and they'd never pass comittee
<mrvn>
zid: can't clean up stuff, that would break existing source
<mrvn>
adding more crap, no problem. removing broken stuff, no way.
<heat>
C++ has also tried over 30 years to do, what, 3 programming paradigms?
<heat>
it's a shit language, but it's the best I can come up with
<heat>
particularly when it comes to RAII and classes, it's a blessing
<kaichiuchi>
yes
<zid>
I like the idea of classes
<kaichiuchi>
there are again, a number of features which make C++ attractive
<zid>
I *hate* C++'s idea of classes
<heat>
C is mostly ok but I don't want to manually micromanage everything with goto out;
<mrvn>
zid: do you want type classes?
<geist>
heat: yeah hard agree. goto and lightweight RAII is honestly why i'm doing more general conversion of C to C++ nowadays
<geist>
though i dont like that RAII tends to make me write less efficient code, so it's a tradeoff
<geist>
ie, harder to scope locks *precisely* the way you want them sometimes
<kaichiuchi>
at this point though I'm convinced c++ people are drug addicted _geniuses_
<bslsk05>
'CppCon 2015: Andrei Alexandrescu “Declarative Control Flow"' by CppCon (01:07:34)
<zid>
they're not geniuses, they've got stockholm syndrome
<zid>
of they're battered spouses
<geist>
and/or just have had towork with it for a long time
<geist>
it's not rocket science, it's just complicated. more so than most languages
<geist>
but as you learn more of it you'll learn what you do and dont know and that makes it a lot easier
<geist>
just like osdev basically
<kaichiuchi>
yeah but think about it from my perspective
<zid>
There are genuinely people who love C++ and see nothing wrong with it, I am convinced these people are basically like, "well it was hard to learn, so it was worth learning"
<mrvn>
I love that you can e.g. open a FD and on the next line you say: SCOPE_EXIT { close(fd); } and you know the FD won't leak.
<geist>
it just seems like a bunch of trees at first but onc eyou get your bearings you start to figure out the lay of the forest. still a huge problem but you at least know what you do and dont know
<kaichiuchi>
I wanted to write a gameboy emulator in C++, right?
<zid>
"if it's hard to use it's because I am not good enough at using it, and I should spend even more time learning it"
<geist>
kaichiuchi: well no. i dont but okay.
<kaichiuchi>
I want it to work on my 386/486, and my eval board that my coworker gave me, seemed like a fun project
<kaichiuchi>
but for me to do things "idiomatically" in C++, I have to write wrappers
<kaichiuchi>
at this point I'm basically just a broken record
<kaichiuchi>
but I've spent more time writing wrappers than actually solving the problem
<heat>
well, yes, you're thinking about C++ in an "idiomatic" standard library way
<geist>
exactly
<heat>
in my kernel if there's something "idiomatic" C++ it's because I wrote it
<kaichiuchi>
but I mean, I don't know what else to say
<heat>
C++ in its bare bones doesn't give you many more tools than C
<heat>
it is, deep down, kind of like C with classes
<geist>
there are a bazillion ways to look at C++, and honeslty the way i *dont* look at it is to start at the std library. i like to know a language from bottom up, and think of things like std:: as just some helper lib
<geist>
vs the other way around
<geist>
and i think that approach helps for low level programming, in general
<kaichiuchi>
yeah, and I get that completely
<kaichiuchi>
probably what I should be doing
<geist>
it's what i'm doing with rust now too. trying to avoid too many helper things and use them as helpers as i grok the lower levels. it's a harder slog but you have much more of a handle on things when you get to the end
<kaichiuchi>
what I'm hearing is: "yeah if that's your goal fuck the standard library"
<geist>
bingo.
<kaichiuchi>
hm..
<mrvn>
kaichiuchi: you should look at the STL as an example for interfaces. Then thow out 99% of the special cases and trimm stuff like std::function down to actual uses cases you have.
<geist>
but then i assume you're trying to write an OS or bare metal, in which case that'sa decent strtegy
<mrvn>
kaichiuchi: you don't need something that's universally working.
<kaichiuchi>
mrvn: geist: yeah, I think my mistake was trying to think of... everything
<kaichiuchi>
and trying to write a wrapper that works for everything
<mrvn>
exactly.
<heat>
well, it's not a mistake
<kaichiuchi>
I guess perhaps what I should do is
<geist>
that's the 'forest for the trees' thing i'm talking about
<mrvn>
Start with the one use case you have now. Then next month you find a second and you add that.
<geist>
when you get started all you see is trees and you dont know which one is more and more important
<heat>
if you want to have something that works everywhere, write it
<geist>
so it seems like a huge wall. but over time you start to feel for what does and doesn't matter
<geist>
OTOH if you try to make everything work everywhere that's a huge time sink/trap
<geist>
similar to the 'i'll write the best floppy bootloader ever' problem that we see here too
<geist>
where folks want to take things one step at a time and completely minmax exactly what they're working on right in front of them
<geist>
a trap lots of folks fall into that you have to avoid if you want to actually make progress
<heat>
well tbf you can actually enjoy writing a standard library
<heat>
but the big question is: do you?
<kaichiuchi>
if that was the intended goal I'd probably enjoy it
<kaichiuchi>
but for now, that isn't my intended goal
<geist>
right. it depends on what your goal is. OTOH kaichiuchi doesn't seem to be enjoying it and wants to get somewhere
<kaichiuchi>
again, you're right
<kaichiuchi>
I think I should solve the problem and later on identify what could be done more "C++ like"
<kaichiuchi>
I think I'm just trying to optimize too hard right now
<geist>
i'd advise learning a bit of it. basic class stuff. basic object oriented stuff
<geist>
use some of the basic features, those are very useful
<kaichiuchi>
I mean, I can write C++
<kaichiuchi>
I've just never done it without the STL
<kaichiuchi>
and as you can see I am helpless
<heat>
that's fair
<heat>
it's not easy to write the STL from scratch