#Ilobilix - a linux compatible kernel
1 messages ยท Page 2 of 1
yeah that script is shite
just install xmake
should be in your distro's repo
bruh
bruh
I have some fixing to do
tbh i just wanted a compile_commands json so i can search through the source code
I can't reproduce either of those errors
can you try cloning with --recursive instead of updating after?
the xmake one might have been a github thing because v3.0.0 was released only a few minutes ago
smh
okay everything should be fixed
?????
๐ญ
๐ญ do you have a ci
like bruh
can you just send me your compile_commands.json
idk if that works
maybe the paths are absolute
you'll need to change /home/ilobilo/Documents/projects/ilobilix to your cloned path
what option were you trying to change?
I regret using xmake
what xmake version is that and how did you install it?
ah
yea works
nice
hmm yeah
ok im gonna look at your vfs code now
@chilly pond what is a vfs::path?
combination of a mountpoint and a dentry/vnode
when do you need that
when going up from a mountpoint to parent dentry
that solves the multiple mounts for single fs issue
right
@chilly pond wth is this input parameter
source
source?
yes like /dev/sda1
but i thought path stores an entry and struct mount
it does
no
struct dentry {
...
std::optional<std::shared_ptr<mount>> mount;
};
no because there could be multiple paths with different mounts all referring to the same file
so the thing is
the very same dentry in memory is used for two different mount points of the same filesystem
that shouldn't be a reference
it was shared_ptr before and I probably left it
also unmount() on a fs::instance doesn't make sense, right?
I don't understand what you mean
path contains a struct entry and a struct mount
yes
why exactly are you passing a struct mount to the mount() function
huh true
i would expect to pass just an entry
just dentry should work fine
more stuff like this might come up when I do a real filesystem :P
i don't get this
different paths would be different dentry's
they can point to the same inode
no, then you would need to duplicate every dentry of the filesystem
/dev/sda1 mounted on /abcd/mnt1 and /home/user/mnt2
one path could be mount: /abcd/mnt1 and dentry: {/dev/sda1}/file.txt while other path can be mount: /home/user/mnt2 but the same dentry
no
two paths are different if path.mount differs or path.dentry differs
bruh
from looking at the code, it seems like entrys are basically always connected with a mount point
which code?
shitobilix code
i think i'm actually being filtered by this shit
filtered?
filtered: When a subject and/or class, usually in [higher education] scientific fields, is so [convoluted] and hard to follow, that it is impossible for one to...
in my mind a dentry is the result of a URI path conversion to a hierarchical structure
that would be vfs::path
no that's just the representation
so /home/user/mnt2 would be a different entry than /abcd/mnt1
because mnt1 has abcd as a parent
I get why windows uses that shitty simple mount system
dentries of mnt1 and mnt2 would be different, but the children of the filesystem that's mounted on them are the same
oh yea but as a vfs you shouldn't care about that
the inodes should be the same
but not the dentry's
then you have as many duplicates of dentries as you have mounts
that is simply inefficient
i mean you also have a dentry for every failed lookup
I don't
also how would you even synchronise them between mountpoints?
if a file is deleted from under one mounpoint, how does another one know that it's deleted? you would need some hacky workarounds
the inode is what's being deleted
if you want to access an inode from a dentry you have to validate it first
so you keep the dentry allocated until you access it? what if you never do so?
if a file is never accessed, nothing gets allocated
accessed once, allocated, inode deleted, multiple dentries stay under multiple mountpoints
they stay but the fs instance can update a dentry and invalidate it
how?
in every dentry in every mountpoint?
yes I understand what you mean
but as I see it that's inefficient and slow
and tricky to get right
as @light cosmos told me, linux does what I do
I don't see anything about dentries for same inode under different mounts
this is indeed complicated, took me a bit to get how it works
damn
i can see that linux records the mounts in the struct superblock
and not in a dentry
ah good to hear that because I thought I was doing that part wrong :P
wait i'm dumb
i have the tanenbaum bible
maybe they can explain it
oh nahhh i forgor it's the german version
unlink takes in an inode and the name of a file within that directory. dentry is just a nice way to package that name of the file. the filesystem driver doesn't really have to care all that much about VFS shenanigans, apart from knowing that the dentry has a name, and it is that name which should be unlinked from the directory.
right
iirc: the thing that d_invalidate does is it removes the dentry from the hash table so it cannot be found in a lookup (it only does this if there are any other live references to the dentry). this mitigates certain types of TOCTOU where a task opens a path (e.g. O_PATH), checks something, and the inode under that dentry is unlinked and replaced with a new inode (because the new inode will be installed in another dentry instead).
oh and fyi @chilly pond
your mount() prototype makes no sense :3
remind me again when you have a block fs working ๐
wdym?
where does it get the source from
then im misunderstanding your struct names
i get that part
but fs::mount doesn't take a source parameter
does the fs just not care about it?
it does though
where
I'm so confused again

linux' mount needs a device path, a mount path, an fs name and flags
mount is a function, struct and a method inside struct filesystem

appropriate reaction
yeah that's the syscall
a filesystem driver really only needs the device path and flags
maybe calling everything the same isn't the best idea
I just never thought anyone else would be reading my code
bad mentality smh

after more than a month of not working, I added kallsyms for symbol lookup
hopefully I'll continue doing stuff
Time to make an async lockless logger
lol
I have encountered a little issue
modules need mangled names for symbol resolution
I have demangled names for kallsyms
smh
Lol
if only I could demangle without allocation
| c++filt
You can't?
I thought you could
at runtime
I couldn't find anything
you can just pipe output of qemu through c++filt in your makefile or something
I'm not writing an entire demangler ๐
#1324404719183069358 message
true but I might not have serial somewhere else, like on bare metal
You can't have all three, pick at most two:
- Don't make it yourself
- Non-alloc
- Runs in kernel
it's hard to demange anything without allocating but i might write a demangler that can output using a callback
or do std::format<MangledSymbol> :^)
You can do it even without recursion if you hate yourself enough.
IMO the best option is still to do | c++filt
You can do that if you're using some command-line serial monitor just fine.
hmm I'll do that
I might try to modify llvm's demangler to use a callback, if it's possible
Output 600 char long name in the backtrace ๐
I found one that was 2390 characters long in debug mode (demangled)
the stuff that happens when you overuse templates and namespaces.
there's no such thing as overusing templates 
it was a libstdc++ thing anyway
smart pointers and construct()
I still left in the runtime demangler, so if I ever need it, I can just uncomment one line
I love C++ (not an actual line from source)
lib::locked_ptr<filesystem::instance, lib::mutex> instance = lib::make_locked<tmpfs::fs::instance, lib::mutex>();
then I can do instance.lock()->stuff
or if it's a rwlock instance.read_lock() or instance.write_lock()
basically rust mutex + arc
this seems like a prime candidate for auto
yes, it's just an example
i hope it does an optimization like make_shared by embedding the mutex inside the struct itself and doing one single allocation
I'm guessing that this is not so much a "smart" pointer as it is a wrapper type coupling the pointer with a hold on the Mutex.
or nevermind
I misread.
stupid pointer
anyway this is what instance.lock() would return. :-)
maga pointer
I'm trying to do that but I also need to be able to assign locked_ptr<derived class> to locked_ptr<base class>
and base class can be abstract
indeed
how does it make sense to assign a unique ptr?
it's shared, not unique
oh
I need to be allocating base and derived classes, not some storage type containing them, otherwise ub will smite me
if that makes sense
placement new?
sure, but I'm stuck on coming up with ideas
tbh placement new solves a different problem
I think I did it
"think" because it works but I feel like something is not right
@light cosmos could you take a look, please?
especially class storage part
you are mistakenly assuming that my judgement of others' templated C++ code is trustworthy
but yeah sure, I'm having a look
on lines where I use alignof I would prefer to have used offsetof if I could make it work with non-pod types
Is the storage::storage(make_locked_tag_t, Args &&...); constructor exception-safe?
The requires(std::is_base_of_v(...)) storage(...) etc. "casting" constructors are definitely worth making sure that they are correct.
yes, most of my doubts are with those 2 constructors
Your class locker stores objects and locks adjacent to each other --- which is fine, except when you cast from/to something which is not at offset zero from the parent class
This can happen with multi inheritance
sorry I don't quite understand what you mean
If you have this:
struct Foo { void *foo; };
struct Bar { void *bar; }
struct Baz : Foo, Bar { /* ... */ };
one of Foo, Bar is stored at an offset from Baz (i.e. (Bar *) baz == (Bar *) ((uintptr_t) baz + 8) or something)
sure
currently, with the way your 'buffer' works, this breaks
this is one of the reasons why std::shared_ptr has separate CB and object pointers.
so that the object pointer can point "into" the object
I don't get how though
ah I do
e.g. with this, Bar might be at offset 8 from Baz
but you don't account for that when moving/copying the pointer
If you want correctness, I would advise you to move the Lock into your own "control block" of sorts, using the same approach as shared_ptr does.
This might require writing your own shared_ptr because I don't think there's a way to expand the control block with your own stuff.
I could store it in the deleter object

isn't that part of the control block? (I checked: yes)
possibly
but can you get a hold of the deleter for when you need to... take the lock?
std::get_deleter<type>(shared_ptr)
I don't understand how I would solve the probem with a control block though
do I store the offset in it?
how would I get that
no, so the way shared_ptr works is you have basically this:
class shared_ptr {
control_block *cb;
T *ptr;
};
in the typical scenario, (uintptr_t) ptr == (uintptr_t) (cb + 1) (i.e. they are allocated next to each other)
if you cast a shared_ptr, cb stays the same but ptr may change
this is actually pretty cool if you can get it to work.
basically you would implement shared_ptr semantics yourself (with your own refcounting etc.) but include a Lock in the control block.
apparently static_cast can correctly convert Baz* to either Bar* or Foo*
but I still need the lock to be in the control block, to fix those two horrendous constructors
yes it can
although I expect things to break if you cast it via a void * or uintptr_t
I use the correct types there
e.g. static_cast<Bar *>(static_cast<void *>(baz));.
this can break
but this is one thing which is very good to be aware of.
It breaks because you first cast to void * -- no offset applied, then you cast from void * and you have effectively forgotten to apply the offset.
it's not possible to do it with a single allocation only while using a custom deleter
What will you be doing instead?
IMO using what you've written here and disallowing multi-inheritance (since it is a very uncommon thing anyways) is a valid approach.
find a workaround of course
I believe using allocate_shared with a custom allocator will do the trick
{
struct abcd
{
int a;
abcd(int b) : a { b } { log::println("constructor"); }
~abcd() { log::println("destructor"); }
};
auto obj = lib::make_locked<abcd, lib::spinlock>(5);
log::println("value: {}", obj.lock().value().a);
log::println("value: {}", obj.lock().value().a = 23);
log::println("value: {}", obj.lock().value().a);
}
output:
allocating
constructor
value: 5
value: 23
value: 23
deallocating
destructor
@light cosmos
This is some advanced lifetime extension bullshit
I'll test it with multiple inheritence as well, but should work fine
All this effort just for a mutex?
I will admit it's pretty cool to see work though
yeah this is the nasty case
this I expected to work with the original code you linked.
indeed, but this is single allocation
{
struct base1 { int a; };
struct base2 { int b; };
struct der : base1, base2 { int c; };
auto derived = lib::make_locked<der, lib::spinlock>();
{
auto locked = derived.lock();
locked->a = 1;
locked->b = 2;
locked->c = 3;
}
log::println("derived->a = {}", derived.lock()->a);
log::println("derived->b = {}", derived.lock()->b);
log::println("derived->c = {}", derived.lock()->c);
{
lib::locked_ptr<base1, lib::spinlock> base1_ptr { derived };
log::println("\nbase1_ptr->a = {}", base1_ptr.lock()->a);
base1_ptr.lock()->a = 4;
}
{
lib::locked_ptr<base2, lib::spinlock> base2_ptr { derived };
log::println("base2_ptr->b = {}\n", base2_ptr.lock()->b);
base2_ptr.lock()->b = 5;
}
log::println("derived->a = {}", derived.lock()->a);
log::println("derived->b = {}", derived.lock()->b);
log::println("derived->c = {}", derived.lock()->c);
}
I believe this should cover it, right?
yeah probably
with the old gist implementation this would probably give not the results you expect (it's fun to try it actually)
derived->a = 1
derived->b = 2
derived->c = 3
base1_ptr->a = 1
base2_ptr->b = 2
derived->a = 4
derived->b = 5
derived->c = 3
works just fine
with this code?
nope, with the new one
I still think it can be improved
the size of the locked_ptr is 32 bytes compared to 16 for the old one
because the lock pointer has two shared_ptrs now?
it has one shared ptr and two pointers pointing to the data inside that shared_ptr
shared_ptr is 16 bytes
yeah... if you want to cut it down to two pointers, you can implement shared ptr semantics yourself
you can reuse the shared_ptr as the pointer to the object
multiple inheritance strikes one again
the object that it's currently accessing isn't necessarily at the address of the data that shared_ptr holds
yeah but shared_ptr can deal with that
shared_ptr points to the control block (which you don't use), an object within the allocation (which you would use with this scheme), you have an external raw pointer to a Lock within the same allocation. this is one possible solution.
AKA:
struct lockable_shared_ptr {
shared_ptr<T *> object;
Lock *lock;
T *get_pointer()
{
return object.get();
}
Lock *get_lock()
{
return lock;
}
};
I reduced it to 24 bytes by just putting the lock at the start of the held data, instead of storing a pointer to it without knowing it's location
error: cannot yet mangle expression type OffsetOfExpr


use a shell script 
.sh team ๐
what are you using currently
xmake
oh, never heard of it
autotools
anything but xmake'
why do you need modules
because they're nice
would you use headers if you had the option to use modules?
also cmake has modules now
what's the diff
include is just text paste
with modules you export only what you want
this seems like headers with extra steps
or rather, what rust does
this is why i hate c++
what
Some fucked up thing that was used to compile x11 apps
there's a trillion ways to do the same thing, but with worse syntax
it's a new feature bru
Only time I saw it was when porting xfishtank for astral
And the fact that I chose to just manually compile the c files says a lot about imake cross compiling
the thing is that I have never written anything in cmake
so I'd have to learn it first
Different names for the same thing
nah uh
modules speed up compile times as well
you don't have to recompile code from included headers for every source file
I can just do import std and I have everything i need
I started working on a very very simple vmm
and I updated the scheduler a bit
it should be a bit less bad (it allocated in the scheduler before), but I'm no expert
hmmm if the current thread vruntime is the lowest in all threads, should I still switch to a new thread or continue executing the current one until it's vruntime gets high enough?
currently I still switch, regardless of the vruntime of the thread that was just running
my reasoning is that if the current thread was sleeping for a long time and has just woken up, it would block every other thread from running for a while.
switching anyway gives other threads some chance to run as well
does this make sense?
I'm pretty sure CFS handled this by clamping the vruntime of newly woken tasks to the minimum and maximum vruntime in a queue, plus minus some window of allowance, not sure what they do nowadays though.
hmm makes sense
should I check for timeout and wake up threads from the scheduler itself or have some other worker thread for them like the one for dead threads?
why does this look so sus
wdym
nvm you won't understand this
dead body reported
oh lol
tbh instead of reap i read rape (accidentally) ๐ญ
It's best not to tie timeouts directly to the scheduler core itself but to have a generic wake_up_thread that you can use for this. Typically you keep some kind of global queue of threads sorted by timeout, possibly instantiate it per CPU (but you need to remove entries on remote CPUs in case a thread migrates when waking up), and use some generic timer infrastructure to drive it.
is bug_if_not a bad name for assert?
because my previous name (ensure) doesn't really explain what the check is for
no
why not BUG_ON(!condition)?
I was too lazy to add ! to every existing assert :P
maybe I'll change it
okay I renamed it
isn't ensure is better than bug_on or bug_if_not
ensure has a slightly different definition compared to assert or bug_on(!
That's a thing in Linux right
I've seen DIE_UNLESS I think
@chilly pond do you use slabs and if so how did you get slabs to go 8 mil on uacpi
I switched to frigg's slab allocator as it was faster than mine
I don't know how I got 8 million
keep in mind that it was on 9950x3d
I wrote slabs down to the paper and I still dont really get good scores, maybe I am doing something wrong elsewhere
have you profiled the uacpi kernel api functions?
maybe spinlocks or mutexes are slow
Like a long time ago, my kernel and uacpi changed a lot since then so maybe I should do that again
hmmm
you can also optimise your memcpy for certain sized copies like managarm does
phd memcpy
and O3
Hmmm
what's your current maximum score?
The one in the uacpi leadrrboard
Like 4 mil
the real trick is "hey @ infy could you test this iso on your 9950x3d?"

I get 4 mil on my cpu
On my cpu I get like 1.5 mil ๐
But I think I know what might be up, it might be my uacpi_kernel_map
I could probably make that faster and it, alongside unmap, are called a ton I think
I need to benchmark to be sure
btw, do you do magazines?
I do
we BACK 
pfndb done
now I need to modify my buddy allocator so I can actually coalesce buddies
1 mib used for mapping pfndb for every 4 gigs of ram with 16 byte struct page seems correct
does it?
yeah like thats like two pointers
hmm I can fit a physical page address in 36 bits can't I
Yeah mine is about that, about 20 byte page struct
but what if the user has 2^52 bytes of ram 
I wonder how much money that would cost
Chat gpt is good for bullshit like this lol
I hope this works on the first try
(it wont
)
well
unexpected but it appears to be working on the first try
good enough :P
41 bits used in the struct page
I haven't thought of a way of doing it with fewer bits
are these extra delays acceptable for sleep(1s)?
it's a bit more than 1 second
I want it to be accurate
don't forget actually printing also takes some time
not that much
the delay was lower when I was waking them up from the scheduler itself, not from a separate thread
what's your timer interrupt frequency?
6 ms so 1000/6
ideally you should be within one tick of it, e.g. if you drive the lAPIC at 1000HZ and you wait for 1000ms, you should be no later than 1001ms when load is low
in that case, this LGTM
this is not completely abandoned
I added hard and soft links
:P
and set up jinx and minimal userspace
vmm worksโข (it can map)
Fancy
I don't understand this gif
what is rbtree
where do you use it
Inspired by frigg lil vro
well just template<typename Type, rbtree_hook Type::*Member, typename Less>
how else would I use a hook intrusively
Idk I dont speak c++ lmao I was just joking cuz of that
I still need to implement a red black for astral and to switch a few things over to it
me neither
Nice to see
you're calling initialize twice
or it's garbage to begin with
that line is in mlibc interpretermain
yeah that was the issue
I wasn't clearing the memory between filesz and memsz
is ilobilix alive now
Having creat() as a separate syscall than open is an interesting choice
linux has a separate syscall for creat as well
backwards compatibility i'd guess
:P
I'm doing linux syscalls
Linux compat friend?
yep
tbh it's easier to follow a design that's already made, instead of coming up with a new one
Fair
I'll do process groups, sessions and tty next
I do have midterms this week so we'll see
when bash port
mlibc
already have it
I just need to implement a few more syscalls
I'll push when I get home
isnt these syscalls are enough for bash
maybe but I don't have a tty yet :P
I get div by zero somewhere in mlibc
I need to fix that as well
18553 loc and doesn't even run bash 
Sounds like uacpi
lol
how do you have so many loc
stuff
Astral has like 30k sloc
my kernel has 10k loc
It runs like literally everything
Not a (good) web browser 
Also no kde I guess 

astral chromium marathon when
Astral needs a drm impl ngl
i've never seen anyone run kde in a hobby os
i'd love to see that someday
Speech is graticious, mail modifications
Yes because it requires a lot of stuff
Lmfao
managarm has kde apps
Idk how drm works at all
true
device in /dev/dri and a few ioctls some of them GPU specific some generic
Some ioctls just do modesets, some allocate buffers, some submit userspace command buffers to the GPU
Thats kinda it
You dont even need the command submission part technically, a lot of stuff works with dumb framebuffers
So just the modeset api
Like managarm
Minecraft in astral with virtio gpu hardware accel 2026

Damn thatd be insane
i wonder how minecraft 4k runs rn
yk, the 4kb version
Fullscreen on a 1024xsomething it ran at like 10-20 fps I think
oh you tried it already?
lol
13k here
Couldn't be me ๐ (14 kloc so far)
I made a clanker make mermaid diagrams for my 2 initgraphs
one running before the scheduler and the other on a kernel thread
what is causing this?
it's supposed to be a file instead of \x1d
is my ld.so loading wrong?
hours debugging an issue with locks only to realise that I shouldn't have used a lock there
what changes?
is it simpler to use?
ah, to cmake
and it's considerably slower
write own
Reject advanced build systems use makefiles
cmake uses makefiles TooTroll
Ilobilix running Minecraft when
probably never
ninja
required for c++ modules

begone rust user
go back to the crate from whence you came
Get oxidized
Wtf first time I hear of xmake
Is it like imake thats something very used in olden unix
why are you panicking on this
i mean exit_group
real
have you considered implementing symbol compression?
I have it
wtf
I have a string passed in as a template argument and I think it's encoded in the symbol
it's quite unnecessary
I could remove it
is that a __user pointer i see?
yea
damn
__attribute__((address_space(1)))
you can't access it unless you cast it using (__attribute__((force)) type *)ptr
and I do that in copy_from/to_user
oh that's fun
What the fuck c++ moment
I learned about it from @worn sierra actually
me when do_the_thing<"oh wait i can pass a fucking string as a template argument">();
i thought that was a linux kernel sparse thing
constexpr comptime_string panic_message { "an unfortunate occurrence, which was definitively supposed to have been avoided or precluded, has regrettably come to fruition in the present temporal reality." };
lmao
no
well not exactly
it's a clang extension
which does the same thing as in sparse
yea
hmmmm
what if I use thread_local for cpu local stuff
instead of whatever the hell I have currently
or both
cc @limpid seal 
it seems surprisingly easy
I could use gsbase for thread struct to access is from a syscall handler after swapgs
because I don't think there is such thing as swapfs 
yea just a few dozen lines
The problem with it is that compilers assume that gsbase never changes
So if the code ever gets scheduled on another core, even if you have a compiler barrier, it might still use the value it got before
gsbase?
or fsbase?
any way solve that problem?
this can be done. however you will effectively have per-thread, not per-cpu data in gsbase now. (can be worked around by pointing to per-cpu data in the per thread data)
yes I currently have that
I think I worded the original sentence wrong
"then I'll use gsbase just for thread struct to access is from a syscall handler after swapgs"
hmmm I don't quite get this
you mean if a kernel thread is migrated to another core?
yeah. the compiler can and will cache the value of GSBASE and it will screw you over.
then I'll just not move kthreads :P
which is why it's okay to use thread_local for thread-local data but not CPU-local data
imagine hat after inline and optimizations you have a function like so, and that the barrier is basically a schedule of the code into another core
even if you had correctly disabled preemption around each of the accesses, the compiler would still cache the base
if you can ensure that the same code path will never run on a different core, then you can use it
but otherwise you risk running into really really weird bugs
linux does have cpu_read_stable() as well which mimics this behavior
but its only used for get_current() on x86
(and a few other misc helpers)
it uses inline asm for it
and by default its always just __seg_gs deref
I don't think this is worth it
ilobilix supports aarch64 ???
well
I don't think it builds anymore
I haven't maintained it
my arch abstraction is so shit
nothing is designed properly
I still haven't fully set up the new build system
there's currently no way to run the os or build the modules
I just hooked up a basic console (just write) (because I don't have a tty) to see if it even worked
it does
how can a module be noarch
it's not a noarch binary
it's for modules that are not for a specific architecture
I don't get why setting process group is failing with EBADF
setpgid is succeeding
/dev/tty missing?
the ever-dreaded todo list grows larger every passing moment
๐ฅ ๐ฅ ๐ฅ
My pselect is a mlibc wrapper ๐ญ
I don't even implement a wrapper in the kernel
Oh but this is doing Linux compat right
i mean
is this such a bad idea
Nah
sounds like something I should do
Since you're doing Linux compat just do epoll
good idea
:P
I don't have the energy to actually implement this rn
hmmm I tried running musl and I'm getting a page fault before any syscall is called
probably a problem with elf loading
yep
I was loading interpreter at a wrong address
I'm thinking if I should use buildroot and musl instead
it's shrimply so much easier
I already do mlibc
using musl while doing linux compat is an interesting choice :P
@polar lance does it
you can pick between using a complete libc or helping the community and by choosing musl you do neither
iirc its only because hes too lazy to implement syscalls it needs
lol
Indeed
just stub futex syscalls
they can be required only for pthreads
me when the
its optional
we've talked about it quite a lot on the maestro's page i think
or thread ig
its not that bad to implement
prs are welcome 
what syscall table are you searching that doesnt include it
i use https://filippo.io/linux-syscall-table/ which is up to date
A searchable Linux system call table for the x86-64 architecture, with arguments and links to manual and implementation.
it doesnt show the arguments in the table though it has links to both the manpage and the linux source
not a problem
wait i might be stupid
Double click on a row to reveal the arguments list. Search using the fuzzy filter box.
lol
yea
I still didn't implement it 
I think I have tty basics all implemented
I just need to do line discipline and hook up some way to input characters
probably from serial
having coreutils installed makes bash invoke pipe2
I've got to implement that too
then clone, futex, ppoll, pselect
pselect when you have ppoll is waste of time
insanity
that looks like it'll be fun to debug ๐
why
wdym why
what's this doing
different kinds of ringbuffers
single/multi producer/consumer
for example some things don't need to be atomic depending on the type
so it's better optimised like this
This is overoptimized tbh
Have you profiled and ran into ringbuffers being an issue? I bet not.
I haven't even utilised those ringbuffers yet
printk ringbuffer when
20k loc for a hello world 
rookie numbers
gotta do sys clone
and I still haven't written that tty line discipline thingy
and I need to write a proper vmm
the one I have currently sucks
probably doesn't even work properly
for what?
well, you could just implement fork
true
pthreads
init: error while loading shared libraries: /lib64/librc.so.1: unsupported version 0 of Verneed record
hmmmmmmmmmmmmmmmmmmmmmmmmmm
what could cause this?
I was overwriting the modules memmap
(where initramfs was loaded)
well I haven't tried running openrc yet
I just fixed that
yeah still doesn't work
Yes
I just edited my printf/putc to detect \n shove a \r before flanterm
Let me find the message
Crap canโt find it 
Canโt even find the commit
flanterm is a terminal, not a line discipline
I started working on tty line discipline
with some "inspiration" from toaruos
I just need to do read and write and it should be done
oh and ioctl
then maybe I'll write a quick ttyS driver
can't forget ptys
maybe glibc bash after that 
that needs futexes iirc
speech bubble meme of that one person who copied toaruos
Who did that lmfao
sasdallas
time to get back to working on tty
I had to change a few things before doing read and write
okay read and write done
// TODO count is 73 and rising
TODO count never decreases in any good project 
lol
/dev/ttyS0
I'm pretty happy with how this turned out
whole thing is like 1.3k lines (without any ioctls implemented)
excluding any tty drivers like serial or pty
Nice
Damn
with MAP_FIXED right
one of the issues was with that, yes
i had a lot issues with this too
How ๐
my vmm was stucking when there's hint on already allocated memory and my unmap just frees all memory which was allocated for this mmap, not part of this
getdents works (no fork/clone or exec yet so I just pressed tab)
pselect6 as well
but I don't really like the implementation
I love it when stuff just works
Bash port?
Linux compat?
yes
big
hmmm the terminal is incredibly slow when printing from a scheduler thread
I don't know why
Do you have a lock on it or somthing?
what
Like a spinlock on the terminal?
Atleast for flanterm it is not thread safe so Iโm pretty sure you need a lock there
initramfs parsing is slow as well, I doubt it's the terminal
Ahhh sorry
bruh it booted up fine one (1) time
then it went back to being slow
damn it was because of smp
well, is
I've been tricked again by this


