#EvalynOS
1 messages Β· Page 32 of 1
i mean? the kernel dosnt need FPU
It can do integer ops pretty fast
an X server is about the most heavy thing id ever wana attempt
https://www.digikey.com/en/products/detail/nxp-usa-inc/MC68LC060RC50/1167437 FINALLY A GOOD DATASHEET
THANK GOD
the horrible part may be emulating the fpu
put it in the fpga 
ah, f
Literally what i was reading just a moment ago
ah same thing
For reference: https://www.nxp.com/docs/en/data-sheet/M68040UM.pdf
this was the older one
you cannot even search
The MC68LC060 is a derivative of the MC68060. The MC68LC060 has the same execution unit and MMU as the MC68060, but has no FPU. The MC68LC060 is 100% pin compatible with the MC68060. Disregard all information concerning the FPU when reading this manual. The following difference exists between the MC68LC060 and the MC68060
- The MC68LC060 does not contain an FPU. When floating-point instructions are encountered, a floating-point disabled exception is taken.
- Bits 31β16 of the processor configuration register contain 0000010000110001, identifying the device as an MC68LC/EC060.
wish me luck π
ah they do provide the code needed for this though aparently
@hazy saddle can't you find this package?
it stopped being made in 98 π
wtf is this
the repo is an utter mess
fpsp.s dosnt even exist
wtf
π
is the 68060 even worth it over the 68040 atp??
archive.org dosnt even have a proper thing of this
@urban mulch
look at ts
π
m68k port?
Custom m68k PC that's cursed as shit
But the FPU emulation code is apparently annoying as fuck to get
Since I'm not paying 300bucks for an m68k
no shot a m68k is that expensive
.
honestly
could it be cheaper to just FPGA the m68k seperate from the sotubridge fpga π₯
i mean i am pretty sure someone made a m68k softcore
Apollo Core 68080 is a cisc CPU which is code compatible with the Motorola M68K and ColdFire families.
this also exists
π
aparently
and this
I do wonder if there is anything still fucking weird / old that's 32bit with an MMU/fpu
that could be workable for this
And not x86
Who knows how much it's been fucked with though?
Not to mention licencing
There's no licencing problems if you change the code just enough and nobody else knows 
Look how many lines it is
π
I think fpsp.asm is just like a weird decompiled/obfuscated version of 68060_lib/fpuemu/*
As that seems much more readable
Omg i found the counterpart of mpreg, fpreg
π
I guess thoes are the original files?
I wonder how hard porting this shit is
If we were to do the FPU less 060
Actually
Genuinely
Binder may have a good option on this
@spark fern since we are potentially building a m68k based machine should we go with the 68040 with MMU and FPU of go with the 68060 with the MMU but no FPU and use the software emulation libraries for it.
The goal is to hopefully port my kernel and run an X server or atleast bash and some basic tools.
The SBC would be using an FPGA to emulate alot of the non CPU core things like to give it 512mb of ddr2 along with UARTS display etc etc
I think binder got stuck on the 6502 era of commodore
He didn't get to touch the Amiga
So no m68k knowledge obviously

He did some m68k stuff iirc
Or atleast talked about it somewhat
also this is cursed and bad practise af
but iirc since i mamage the HHDM very cleanly
eg only ram is mapped with no overage
i could use the HHDM for MMIO

only issue is MMIO via HHDM would need a seperate helper due to LA64 using DMW's w/ the UC HHDM at a seperate offset
in theory this shouldnt have any issues, other than MMIO out of bounds on the memory map etc 
i could get the PLEN and reserve all of that
but thats wasteful
i could also just have a seperate allocator for managing MMIO regions in the kernel that gets a large virtual allocation and bump allocates it and refills when needed
since virtual memory (on 64bit arches) is free, and saving some memory on vmem segments could be good
I know you're interested in the hardware stuff, but qemu has an m68k system to get you started. I believe it's system emulations are reasonably accurate to the real things too.
True but 32bit is less of a priority so building hardware means I get to atleast wait a bit and have it potentially line up nicely
fair enough
I'm probably gonna try and get scheduling to work tomorrow
If I feel good enough
I barely could play any games today π
I am making some progress on the iotel stuff thankfully
you could be the fourth person in this server (afaik, probably not realistically) to port their kernel to m68k π
Shouldn't be too bad I presume
Hello fedi, I haven't posted here in a while but i have something interesting.
I have been investigating something that is utterly confusing and I need others to help find samples of this happening.
A certain set of intel CPUs apparently report the CPUID vendor string as GenuineIotel with the n in intel having a singular bit flipped making it an o.
This is listed on Wikipedia leading to one singular report of this and when contacting that person directly on bsky they were unable to provide more information on this. Along with me attempting to send a patch on the LKML to handle this and also maybe see if other have more info on this.
The LKML thread is a little inactive with me waiting on further instructions on how to handle it they way they wanted (halting/panicking along with a flag to bypass)
I have found a bunch of sparse reports over online separate from the one mainly cited but they are incomplete.
I need help from other nerds online to try and see if they have proceβ¦
Sent this to a bunch of friends
If it gets enough traction I can hopefully get some test subjects

good luck, it's an interesting thread to follow
Probably the worst part of the m68k thing on real hardware will be larping as a 90s PC bios
π
Since il have to make firmware
The Linux kernel one?
yeah
you could make the most batshit insane firmware ever 
give it AML
I would but I have nothing to use it for
make it boot limine kernels natively
But I did want to go on a somewhat UEFIish direction
The main crazy part will be it having a bunch of modern peripherals
Like a 16550 UART
SD cards
Etc
Yup
Will be quite funny
But it will also try and be somewhat simple for the kernel to use
Also 512mb of ddr2 
An FPGA will be the south bridge and handle alot of this stuff
I dont know if you've come across it yet but there was a boot protocol from the era (used by a few systems it seems) called "bootinfo".
I have this in my notes:
https://github.com/vivier/qemu-m68k/blob/m68k-virt/include/standard-headers/asm-m68k/bootinfo.h
i was thinking of just passing a dtbβ’
yeah that also works
Btw what do you think on this
Because this would keep the m68k it's self under 100 bucks to buy
I think summoning bindage was a big move 
And the other parts would maybe be 300 in total
Meaning it could be somewhat reasonable for people to built
π
verses 250 bucks for the cpu
it all sounds fine to me, just a bit anachronistic, but you're not trying to be era-faithful. If you're doing to do a direct map for the kernel maybe you want less ram?
I mean 512m is about the limit for a direct map
or if some of it is being dedicated as vram I guess that makes sense
And I actually will try and avoid a direct map
Il use recursive page tables for this arches paging routines
And other uses of HHDM will get split into using temp mappings on 32bit arches
that's cool, I assume you'll public all the files needed for people to build it themselves too?
Ofc
It is many people working on it
But il definitely be putting out all the Firmware files etc
Oh and the protocol will load the kernel into the upper half etc with paging ofc
Il probably make it give page tables that
- map you in the upper 256m
- gives 512m of direct map
- has a recursive set of page tables to use aswell
Which should fit in the upper 1g?
The goal is to make the most capable m68k machine (without paying 250 bucks for an old ass CPU so it may have to be a 68040 if we want FPU properly without the strange emulation library)
And to try and make it run as much software as possible and be usable
Eg hopefully an X server and a light DE as the final goal
it would also be funny to have a custom IRQ controller on here but also have a standard PIT timer that can do the CPU interrupt timer and the pc speaker 
goal is to also make a cursed board in some ways
fair, imo the 68040 is fine. I think the 060 is more of an upgrade for the peripherals than the main core?
that'd be cool
The 060 bumped the core up to pentium levels iirc
With the FPU falling behind still
hmm I see
The firmware I also want to have a menu for configuring boot and other things because it could be cool to get Linux working + a dual boot
Since the firmware would handle ext2 natively
Maybe it could also control some other system stuff / do POSTs
Which is probably useful to do tbh on such old of a CPU
If anyone wishes to test if they have the ioteld cpu they can simply run this command on Linux
awk -F': *' '/^vendor_id/ {print $2}' /proc/cpuinfo | sort | uniq -c | awk '{print $2 ": " $1}'
i would like to know which one then, lol
bc they have different pinouts
for general purpose use? I'd do the 68060. you don't need FP for lots of things. If you know you are going to do FP then the 68040
my first 486 did all soft float and was quite usable
is this a full super scalar with multiple pipelines?
is the fpga going to run so fast that it really doesn't matter?
yes
It should be able to pump enough data definitely
Yeah seems like that would be the choice then, hopefully finding and integrating the FP lib routines agent too bad
reference... I ran linux + xwindows in a 25mhz 486 with no fpu
this is what i ended up finding
I wouldn't imagine they would be hard to find
it was mentioned in the manual, was annoying to find anythibg beyond that
could probably also rip them out of linux/bsd
true, hopefuly the licencing on thoes is fine
eded up missing some things when doing la64 exception names abd decancering them
thankfully this pinout doesn't see so bad
I'm the wrong person for those sorts of questions
I wouldn't be surprised if the LLM couldn't whip up vaguely decent soft float routines
thank you for the help btw
, esp with the source of the other things
maybe so you can 'look' at the pint while it's in the socket?
I haven't looked at hardware specs much
oh god i hate how they placed the data pins
thanfully we are using an fpga
so we can mix and match the data lines
have you picked the fpga yet?
yes
this one
comes with DDR3 / LPDDR3 / LPDDR2 driver block too
and LVDS
and SPI
not familiar with that line
chose it bc of price, amount of cells, features and gpios
31k LE
you writing your own HDL impl?
we have to, lol
why?
well, i don't existing hdl code exists for this
?
there was talk about an port of apollo...
if the softfloat stuff was not feesible maybe but it should be
the FPGA mainly is goung to be a southbrdge to a real CPU if we can
We revive the Amiga with a clear roadmap. Learn more about how do we want to bring you Amiga back. Here is a complete list of our Vampire project goals. Today you can discover what matters to Amiga users around the world. We know how to make Amiga great again. Share your ideas with us and help to make that Amiga dream come true.
no.
Too late sorry

π π π
death
User-defined signals, controlled by the corresponding user attribute bits from the
address translation entry.
I guess extra things for page tables?
i'm still reading the docs, there are 20 pins i have never heard of π
i'm gonna ask clanker
These could be used to overlay MMIO ontop of normal ram right?
And translate differently on the FPGA
prob
Eg get more than 4gb of physical address space
Probably should wire them into the FPGA for later
Could also be used to map a page as returning hard wired zeros?
Or other useful things
What's the max amount of ram we could attach to the FPGA?
Yeah
x16, lemme check what that means
This is for the 68060 one right
8Gbit
yes
so 1Gbyte of ram
we are limited to only 512MB with ddr2
but 1GB with ddr3 / lpddr3
and i think the best method would be to just solder the ddr3 IC
Well we are using ddr2 anyways
Since ddr3 is too hard to wire right
And with only 512mb of ddr2,
We won't need UPAs for that specifically
ddr3 and ddr2 are very similar
- if i just solder the ddr3 chip it should be easier
oh wait
we cannot even use the full sodimm module π
we can only use a quarter
sticks use a 64 bit bus
we only have 16 bits
we could only use 2 sticks
or well
ICs srry
and they are 30 bucks each (if we don't steal them from sticks)
Can't we fit some ICs on a tiny board with a connector
i mean, we can just connect the whole sodimm and only use a quarter XD
But that would what a 2gb sodimm?
we can use any size i think
if we go like that
tho we would only be able to use /4 of it
But then we can only use a quarter?
ye
not really
We can just use a stick like this?
I'd ask Emma π
@urban mulch
lol
tho we could reach 2GB of ram if we spend 60 bucks for the single ICs
or steal some from sticks
and it should be safer than using sodimm
You said only a quarter could be used
Also thoes extra PTE pins may not work nice with the cache
Yes
well, here it is
x2 of these and we get 512MB
also, we can upgrade these later bc most ram ICs are pin to pin compatible
We should probably still have a mini socket for these
that would require another pcb
It could probably fit on a tiny cheap 2230 nvme right?
wdym
Like
Use that connector and form factor
But for socket able memory
prob yes
but it is more costly
like prob around 30 bucks for the extra pieces and pcb
It's both extra cursed and extra cool because it makes upgrading easier
And you can fit some extra things on the modules
To identity how much ram it has
The firmware could poke a register on the FPGA to check the ram size based on the modules reporting
Make it a little more PC like

if you like the extra price sure
@hazy saddle for interrupts, we only have this in the cpu
should we get a PIC if it can be connected? 
FPGA 
I wanted to actually make a custom really simple IRQ controller
But use the PIT timer
tho, would we have enougn LEs to actually make all that hardware, lol
whatchu guys doing
PIT inside fpga too?
A register for interrupts pending
A register to ACK them
And a register to finish the current interrupt and only send another if things are pending
something very cursed
which is..
m68k + modern hardwarer
woow a footprint of bga
pga
whatever I'm not electronics person
also @hazy saddle we gonna get usbc power delivery too XD
bc it might be the only way we can get that much power via usb
i could add a battery module too if you want 
Nah that's too expensive π
Maybe for a v2

V1 should try and be cheap
nah, battery stuff is like a few bucks
batteries are expensive tho
Let's leave that for making it a handheld π
XD
Meh
I need to work on actual kernel shit anyways now
Tomorrow if I don't feel poopy π
Maybe we could move the talk about this bullshit elsewhere
open a new project specific thread
It's not project specific though
it kinda is tho
me when i forgot to setup timers

so i cant do sched rn

well
i can make the code
and maybe test it ig
but it wont be able to preempt
Me when loongarch64 isn't bullshit and has a CPUID to tell you if the timer is constant and to tell you the frequency of it and setting up the timer to give interrupts isn't annoying shit
I mean it can still be non constant ig π
But I think I could just panic on that case?
Since there wouldn't be any other way to reliably get time
For riscv I'm gonna need more dtb shit
π
I'm also going to have to modify CPUlocal to store a self pointer (to the fixed region)
That way you can lock a lock etc
Okay yeah I'm going to need to add helpers to get pointers that go into CPU local to handle spinlocks there
lmao
another common gcc L
π
this only compiles via clang
Oh yeah I'm also gonna skip having it in the fixed CPU local
Interrupts are disabled here anyways
And for getting the current thread generically il just implement an assembly function anyways
I only really need the fixed CPU local for things touched by assembly that also has no temps
Which is only the current thread pointer
And not the spinlock
And this has an easy way to implement it arch generically
Il still need the pointer helpers though etc
Ended up reworking alot more of the CPU local
But scheduling works
And it should just work with preemptionβ’
Oh also it works for all the architectures

@tender mantle
If you want to steal the scheduling code too
You can
For your riscv port
Also scheduling is init properly before any memory management because of hyena sky
So it will have a thread marked active etc
Honestly I still have more refactors I wana do on this
Because of some half stupid decisions
I'm probably gonna push this
Do some GDT/IDT refactors
And some other various things
gdt refactor ok?
So the GDT stuff can working On APs
gdt refactor..... pending/async task
Main thing is having architecture spesisifc fixed CPU local is kind of stupid
And at this point only serves to save 16 bytes on x86
At the cost of some BULLSHIT with the abstractions
Still partly more expensive for things outside of the fixed region
But that's fine for shit like the GDT
Or like things that aren't too much needed to be ultra fast
if I properly make the fixed region generic other shit would be better
Multithreaded hhdm construction?? 
The point is so you can safely use mutexes
Iirc @urban vale advocates for this alot. And I think I did it right?
Interesting
I'm starting to get back into osdev again so I'll certainly reference the code 
Although I hope to get through task switching without needing to steal anything...
I mean
It's really simple
π
I would just give it to you
Lol I'm pretty sure that the reason Serpyntyne wouldn't task switch was something dumb
Ideally it'll disappear when I write task switching code again
; rdi = pointer to store old stack pointer at
; rsi = new stack pointer
arch_thread_switch:
push rbx
push rbp
push r12
push r13
push r14
push r15
; swap stacks
mov [rdi], rsp
mov rsp, rsi
; unlock the scheduler spinlock
mov dword [gs:rel fixed_cpu_local + 24], 0
; enable interrupts
sti
pop r15
pop r14
pop r13
pop r12
pop rbp
pop rbx
ret
plus this to setup a fresh stack to be able to get switched to
big scheduler lock π
why do you have it
why not a thread lock
actually
why does the queue lock protect the thread state
The amount of time the thing is locked is so tiny it dosnt really matter?
I'm not sure this is right
Literally the code I had π
This is what was in my old kernel
And it was working
And it's what solved several race conditions
I suspect I was setting them to have the same stack or something
Wtf
Well then what would you propose
typically to protect a thread switching out from its own stack u have a per thread lock
that you hold when you try to run into
sec
CPU0: thread goes to sleep
CPU0: queue lock is held
CPU0: switch():
CPU0: do whatever with regs
CPU1: thread wakes back up on another CPU
CPU1: acquire queue lock
CPU1: switch():
CPU1: do whatever with regs
CPU0: queue lock released
OOPS! CPU0 and CPU1 race on thread state
u cant do this unless you pin a thread to a CPU I believe
I'm think sure that lock was mostly to prevent it interrupting it's self which was something that was helping? Also since the queue is per CPU aswell this shouldn't happen?
When would you want to lock and unlock the thread specifically in this sequence though
On a switch to and then unlock after you swap stacks?
you take a thread lock when switching to it, you release it when switching from it
why
yeah i was thinking of that too
isnt it better to lock the runqueue
if you want to lock, lock the information regarding blocking
can you explain the deadlock
this is what i already do 
I have per-thread locks and all the blocking paths dont require some kind of dispatcher/runqueue lock
because I do the windows 7 thing where you have transition states for a thread
let me check what i have done and think a little bit
because i genuinely forgot
hmm, i use two locks: one lock for the runqueue, and another lock for the task state/blocking information (aka, which wait queue i am on)
when scheduling, lock the runqueue, pick next task, switch to it, unlock runqueue
the task lock is taken when changing the state (waking up, blocking), and when it is taken, shortly the runqueue lock is taken too for enqueuing or dequeuing
what do u do @wide mica ?
when preemption is required, take the queue lock and get the current thread, release the queue lock, acquire the current thread's lock, acquire the queue lock and insert the current thread back into a queue, release the queue lock, then switch into the next thread, which drops the current thread's lock
how do you get the next thread?
I have a per-cpu next thread field which is set when preemption is required (on timeslice or higher priority thread arrival)
okay, but i suppose those threads are in a list or smth
yeah, the clock() function is a DPC enqueued on timeslice timer expiry which sets the cpu.next_thread field, then after DPC dispatch I check whether or not cpu.next_thread is null, if it's not then I switch to it
when selecting a thread to run I hold both the current thread's lock and the queue lock
the next thread thing is very clever, I stole it from MINTIA which stole it from NT
I mean mine should work since no two things should have access to the thread struct.
It will only be in one CPU run que at a time and it won't be eligible for changing CPUs if it's in a running state. And the lock is only released when it's all proper?
i just dont understand why you take task locks for scheduling
unless your kernel is capable of letting tasks deque other tasks which are possibly in execution
not sure what that means
also the thread priority is updated under its lock
so i have to take it
I don't? I just protect the queue when things in it are in use. Bring the new current thread and the previous thread (which would probably cause issues if I don't have a way to signal it being not in use)
Oh yeah I do need a lock
I'm just too tired to know the proper spots to take and release them without deadlocking bullshit
why does recalculating the thread priority require you to lock the task?
If the previous thread happens to get taken by another core
Another core could be modifying it's state switching away from it
i guess it depends on where you recalculate the priority
the thread priority is updated under its lock
You need to lock it to stop it from changing where it is right now
(On a queue, attached to the NextThread link, not on a queue, etc)
will btw i fixed a race in my scheduler and i think i found one in yours unless it's intentional
Depending where it is, you might need to move it around. For example to unlink it from a priority queue and link it to the one for the new priority
What is it
sec
well, ig what locks you have to take or not depends on your kernel
in mine i dont have a use yet for a task lock to be taken during scheduling, however, there is a lock that is taken when waiting on a waitqueue or waking those tasks
https://github.com/xrarch/mintia2/blob/main/OS/Executive/Ke/KeDispatch.jkl#L639-L646 you compare against prb.CurrentThread which is not protected by anything u hold here, this could happen:
load CurrentThread = T just before a switch commits, T exits, the switch releases T's lock, the reaper frees T, then the deref lands on freed memory.
importantly this is because prb can be remote
ig it would be unlikely but it is racy
but you modify CurrentThread without holding the queue lock
Where
KepSwitchThread is called without the queue held no?
here
you'd have to move the current thread update under the queue lock ig or just not load remote CPU current threads
what i ended up doing is only relying on the stashed atomic thread priority
actually the coolest way to fix this would be to make the thread zone type-stable memory
it's still racy but worst case is that it's stale
The right solution i think is to use the stashed current thread priority & interactivity thing
Not sure why I wasn't
yeah
I believe making thread structures type stable is useful for other stuff though, like checking if a mutex owner is running without racing on freed memory
Relying on type stability only sounds good to me for stuff that is permanent anyway like pfndb
Otherwise I'd like to keep everything fluid
I agree that it doesn't sound good but I've seen a bunch of kernels do it at least for thread structures it seems
Which ones
Probably assuming that it won't grow unbounded without running out of memory from other stuff first
I've seen it in freebsd at least, which is where I learned the trick
xnu also does it, i think that is what they call sequestering
I mean I'm pretty sure they do eventually free the physical memory after some epoch has passed or something
They both do SMR pretty sure
yea but that is unrelated
that's for lock-free data structures
I dont understand what it's all doing but it doesnt seem to free here
this is freebsd
How are lock free data structures unrelated to lock free data structures
They don't read the thread structs in a read critical section through SMR
And the thread zones are not marked SMR anyway
sequestering is a security thing designed to protect against cross-zone attacks
is it similar to type-stable memory?
@wide mica I'm going to fix that race by grabbing ready queue lock while setting CurrentThread probably
wel there's a problem, it matters whether the current thread is the idle thread at thread insertion time
because any thread should preempt the idle thread, even another thread at idle priority which normally can't preempt anything
mhm you're right
this is a temporary issue and will get fixed by work stealing tho
for other cpus
Interresting. Which Features does it have?
Why not look at the code

It's pretty basic rn due to the rewrite
I mean i am not against viewing the code but i think it should have been written in README file
like any normal Project
I mean, it's a work in progress
Cause i am not sure i will understand any of this
It's just a basic overview and some instructions
(WARNING: Because not an OS Developer)
@wraith star I wonder what I should be doing to fix the lock issues
No i think it's a major responsiveness issue
I am still like partly unable to understand this after my nap 
And my brain loves to be slow somtimes
you should add better load averaging btw for load balancing
i sent a freebsd patch for this
my threads get reassigned to another cpu when they get switched, i need to fix it too, lol
i'll add a balancer thread
send a mintia2 patch
unironically i will
well, as i said, depends on how your kernel works

send it to claude or codex 
Bruh
sometimes it also comes down to feel 
i mean, they might be able to point you in the correct direction
i don't mean to make them make code
just point you in the right location to look
and then you fix it yourself
i know where it is
you should beable to solve this problem without any ai at all
I got bored of copy pasting mintia2 code at Claude and asking it what it thinks because it just kept going "This is a very well engineered piece of code, part of a sophisticated operating system kernel, that accounts for every case. One thing to flag: the comment above line 21 may not be completely up to date. On second thought, it is."
does your company pay claude
half the time i deal with a clanker the thing is so incompetent i have to do it myself
i find the petter griffin one funnier
ai is only good at basic refactors and to help explain stuff imo
copy pasting is probably not super useful , but if you throw a high effort model at the entire code base and ask for an html report it will make a relatively decent thing
and finding bugs
maybe if u use fable or something
nah, even 5.5
it helped me to find a deadlock that was preventing my os from booting in real hw
do you use ai like claude for bug fixing or idea generation?
i gotta say that claude is pretty good at creating websites with all the best and whistles
how does that work, you send your project in some format that llm can understand?
yeah see the css it made me https://rdmsr.github.io
i gave it a bunch of cool designs
No offense but your project is probably really simple
true
typically you have agents that read your files for you if you wanna do that kinda stuff
is it like 1 agent per file
no the agent reads files one by one
or uses grep
@hazy saddle Checking for libarchive >= 3.3.3 via pkg-config ... libarchive.pc file not found, exiting.
the llm has access to your filesystem, you tell it what you want, it then runs bash with all sorts of commands like find, grep, etc. then reads files it wants to understand what you need further
They know very little about my interests
and find resources online
Recently at work, I had to solve a problem for an important client. They had a lot of code written in Rust and Python, and a little in C. I know C well, but not Python, so Copilot came in handy for quickly getting up to speed on certain parts.
Evalyn pls add a list of packages that needs to be installed in the os
It uses jinx
it will fault if you don't have libssl or libarchive installed
You need it's deps
And it says that in the readme
It links to jinx
And that lists shit
it doesn't say those libs in there π
What are you even doing that's faulting
it was missing libarchive and libssl
but would claude be able to solve a kernel level problem
I: Configuring ifupdown...
I: Configuring libc-bin...
I: Configuring ca-certificates...
I: Base system installed successfully.
make: *** [Makefile 17 bootstrap] Error 1
is this correct?
What command started that
make bootstrap
it doesn't even tell me why it failed π
f
would removing the currently running thread from the queue fix this?
eg when switching to a task its popped off the list. and then after switching the previous thread is popped back on then it unlocks?
that way the queue when unlocked can never contain threads in progress/running?
this is what i do and it works ok
same
it would also make sense since for mutexes they shouldnt be in the run queue
issue would be moving the current thread there, and knowing to not move it back when putting in a mutex then rescheduling?
i keep the task in the queue because it eliminates complexity
if you are the highest priority process, next_task() will be yourself
i do a slightly weird thing and smuggle the old thread pointer through to the new thread and then the post-context switch part of yield/threadstart uses that pointer and some flags smuggled through to update the old thread's state after it stops being current so current doesnt become invalid
my yield also has a force flag and if thats false it does a peek first, and if the peek is lower priority it just aborts the yield. if force is true and youre still highest prio itll get requeued by the idle thread
i mean. thread needs to block -> puts that in the state -> but in mutex qeue -> calls reshcedule -> it ends up in both the runqeue and the mutex qeue
well, when you put in the mutex queue, dequeue yourself
yeah just dont put it in the runqueue?
and also disable irqs/put yourself to dispatch ipl
this would be whats putting it back
when you switch away from the task
you have a flag for what the new task state is yeah
and only push back on if new state is ready
imo, the scheduler should not care about task statuses in other places other than the after switch call
putting on the wait queue would set that to blocked so the status isnt ready and thus it doesnt get put back on the runqueue
So I should have task running and task blocked and task ready?
i have zombie and terminated too
Q eysknso oz l,o9$8 zozl
(theres a nuance to this that @wide mica can probably find the video about where you need a pending block status to work around race conditions if the wait is aborted)
maybe collapse task running with task ready if you don't really care about what tasks are executing in a given moment
i have this too
yeah the win 7 thing
yeah
but yeah the bottom line is it wont be on both wait and run queues because youll know from its status that it isnt ready to run and cant go onto the run queue
and overall, the scheduler itself shouldn't be doing enqueues and dequeues to any sort of runqueues
have the task blocking code do the enqueues and dequeues, have the task creating code do the enqueues
yeah
a task goes onto a run queue when its wait finishes, it is created, or its switched away from without blocking. it goes onto a wait queue when it starts waiting. and it goes onto a cleanup queue when terminated depending on how exactly you do that
i personally call it a ready queue instead of a run queue because its a queue of ready threads but naming is a personal decision so you do you
so i should modify this to take in the thread_t*s them self, then call a function on the new stack that will manage the run queue based on thread states and then return
and that should fix this??
yes exactly
exactly that
https://github.com/AtieP/taratos/blob/418ae10946a5687e33a1f31ace8490c091158909/kernel/src/task/sched.c#L75 if you do it properly, a sched loop looks exactly like this
the preempt needed probably looks a bit sus
I also keep redoing my CPU local partly because it's kinda borked for some shit π
(there is more complexity later about priority inversion and temporary boosting and other such fun details but what atie and i describe is a perfectly functional priority-round-robin scheduler)
yeah
The main issue now is that the run queues can be inconsistent with the previous thread inside of it and causing races
how so?
This should also work with priorities anyways right?,
@haughty acorn
or whatever its called when a low prio thing cant function because a high prio thing exists
I mean that's a separate issue
yeah thats what i meant. this handles priorities but not that
Oh I'm just trying to handle the race condition rn π
you put current thread in a cpulocal and not in the queue and i still dont see what the race is here?
you can release the queue lock in the post-yield
(oh and you also call the post-yield function as part of threadstart for this to work, the idea is that the beginning of threadstart looks like the post-swap part of context switch)
Oh no I haven't fixed that yet
Current thread also still exists in the queue
Along with the previous one etc
yeah
current should be a separate var
it is mostly just not removed from the list
that way when you push you can detect priority preempt conditions, you dont have to worry about whether to remove from list because it already was when it started running, etc
yeah, after swapping stacks prev gets pushed if needed and the new current is popped
well youd pop new current before swapping stacks
so you have it and know what stack to swap to
the prev thread gets left in limbo as a local smuggled through the stack swap in a register
the problem is the thread can wake back up
you have to have some kind of mechanism for the thread to stop swapping its stack
in my setup then the waker detects that its in wait_pending instead of wait_committed and changes its state back to ready (pending any waitany/waitall details) and the post-yield detects that and requeues it
the post-yield does a cmpxchg expecting wait_pending to wait_committed and if the old was instead ready then it queues it back up
then what are you referring to?
because thats the only case i can think of where a thread would be woken when not already post-stack-swap
in mine, waits and wakes are mutually exclusive by a spinlock in the task struct, and when waiting, the lock is held until after the context switch
i tried that and got deadlocked lmao
how?
i think my code was just shit
that is literally what i said you should do
and people keep roasting me
π
eg thread->switch_lock?
just thread->lock
oh i remember now my thing deadlocked because of a nested lock caused by trying to wake it from an interrupt handler running on the same core
you could have an atomic bool as well ig
eh i still think there are other issues with thr run qeeue i need to fix
someone didn't disable irqs :^)
when i did that the irq got completely dropped instead of delayed π
what is the IRQ were talking about
nvme command queue
the apic just completely forgot the interrupt instead of waiting when i disabled interrupts, even when i used TPR instead of cli/sti
uh
i still dont know why it happened and its 80% of why my motivation to keep working on my kernel is at a low
that's not good
correct!
This is why you have DPCs
are you doing eoi somewhere where you shouldn't?
i did that and started getting use-after-frees like crazy that i still dont understand
my entire sched and dpc and irq handling needs help badly
at the end of the interrupt handler? after the main handler body runs
as i say i still dont know what i fucked up and ended up just taking time off and now im in side-project-land with zaml instead of trying to debug this hell
for edge interrupts, the eoi has to be at the beginning
Was gus named after this cat @wide mica https://www.freebsddiary.org/cats/gus.php
The cats - Gus
otherwise you miss new irqs
are msi/x edge or level?
msis are always edge
ok that is likely at least part of the issue
idk but fun fact, the allocator and gus thing is by the ULE guy too
his coolness has no limits
at least its one msi per queue so repeat vs delay/combined nvme interrupts are idempotent
but yeah when i make more progress on or get bored of zaml ill go back to my thing and fix this shit lmao
btw this means i dont need a lock on the thread qeueue since the threads being swapped can never be grabbed?
the swapping ones cant but multiple can be queued at once possibly
(if say a semaphore or something like that gets a bunch released at once)
you do need a lock on the queues for remote enqueues
i mean only have the lock when its activly being modified
but that would fuck with alot of crap
since it would unlock and regrab right after anyways
Okay now I just wana cleanup my CPU local things
Because the previous stuff worked fine
But the schedular changes some things up
And it's a bit messy rn
Then blocking would just a preempt disable, set to blocked, add current thread to queue enable preemption then reschedule
@wide mica @wraith star @haughty acorn thanks for the help
How might that break?
disable preempt won't be enoug
Ig then mutexes need to disable IRQs when operating on them
it can be if you use DPCs/softirq/bh/whatever
no
Yeah this is precisely what DPCs are for
you typically NEVER wanna take a lock from an irq context unless it's some pathological case where you have no choice
np
Like making the CPU local layout non arch specific and paging reworks and some userspace things and timers
I'm probably gonna make structs for each subsystem to put into the CPU local thing, this will also make accessing parts of it much faster since it's always a fixed offset for the core kernel things
DPCs are just a queue of callbacks that get run asap with preempt disabled but not in an irq context
theyre p easy
Then drivers that need extra CPUlocal can do that seperate with the slower helpers
Actually I can solve that by just adding an extra data pointer to the timing system for the drivers that activate to have extra data for them
Holy fuck I over engineered the CPU local badly
π
(DPCs can be cpu-local or agnostic depending how you do them, if you schedule one from a thread you just run it immediately if you schedule one from an irq you run it as soon as you finish irq handling and turn irqs back on)
(the only DPC quirk is scheduling one from a dpc or onto a specific cpu from a different cpu but those arent hard to handle)
guys APC or DPC which is the best
APC could be a strong contender since like every kernel has them pretty much (maybe not linux idk) + they're slick, stealthy and cool
but DPCs are pretty cool too and more useful i feel like, its like a good friend you can always rely on
imagine having dpcs
and imagine having apcs
i like dpc vibes better because theyre easier to implement
my cpu local code also was broken on la64 bwcause half of it ended up with riscv assembly syntax and i never noticed it
π
F
Welp time to fix ts
And have a partly working scheduler
Well it won't be fully working until SMP on all architectures and I handle shoot downs and other bullshit
And thread migrations
?????????
lmfao
it was LTO tossing out my cpu local
π
I wonder if that was also causing other bullshit
symbol + footprint done
tis should be correct
im just finnalizing my scheduling sutff and cpu local reworks
it goes schedule() -> arch_thread_switch() -> schedule_finalize() -> arch_thread_switch()
and the arch_thread_switch does the final unlock and then restores things
i keep the lock held the entire time even if i dont FULLY need it
since locking unlocking and relocking and then unlocking would be dumb :p
and doing the unlock in assembly generates less instrictions than needing to use CPU_LOCAL_GET_SCHED_LOCK_PTR() etc
you'll probably want it in the future when you implement blocking.
In what way? Since the thread being blocked means it just gets dropped from the main thread queue since it should have been put into the mutex queue etc and then set to blocked
depending on your design it might be fine, but there's potential for race condiitons around waking a thread that is transitioning to blocking or is in the middle of a context switch.
I think I solved thoes kinds of race conditions by making sure the thread is only in the scheduler queue if it's eligible to be scheduled
if the thread isnt locked during context switch it might commit to a wait: but before it can complete it's context switch another cpu can satisfy the wait and wake the thread. The waking cpu places it in a run queue somewhere or it may preempt on the waking cpu and begin running immediately.
Ah this shouldn't be able to happen since the thread is owned by one thing at once here, eg it won't be in the schedule queue and the wait queue at the same time
right but what if its in the wait queue and currently executing (has committed to a wait but not yet switched to the next thread).
the current thread would be refered to by the current thread in cpu local, if its status is blocked it wont get added to the main qeueue, and grabbing a mutex would disable preemption to not race on thoes operations
yeah you wouldnt have this issue on UP, its an issue where one cpu wakes a thread was preparing to sleep on another.
so it should be fineβ’
it will prolly be a bit til i implement shootdowns and other things anyways like that
since im gonns wait for riscv and la64 smp for that
What if you get preempted in between the time you get the lock for the core your task is on and grab the lock
And another core steals the task calling schedule / the task calling schedule gets push migrated
Is it only called with interrupts/preemption disabled
also getting the lock is a single instruction
or at the very least should be impodent to not cause issues
since it either just gets tp and does a single add on riscs
or first loads the self pointer on x86
(Assuming your macro CPU_LOCAL_GET_SCHED_LOCK_PTR gets a per runqueue lock rather than one which is global) In between the time you read what lock to grab from it, and grabbing the lock itself, if preemption occurs, this may be bad if your task is migrated, as when it wakes up itβll grab the wrong lock (as then the queue which is read would be different)
Ofc, this isnβt an issue if schedule is called in a context where the task cannot be involuntarily preempted
i think il fix this by having irq/non irq locks
then just disable irqs seperatly
Thanks for pointing that out
You need to disable preemption before reading that value
Otherwise there's a race between reading the cpu and acquiring the lock
i fixed it like this, i dont have preemption at all rn so i diddnt setup the counter. and iirc i still want irqs disabled anyways, + its simpler on the asm side
spinlock_lock also is not not an irq lock and irq_spinlock_lock is
You don't want to disable irqs here
It is very rare that you need to disable interrupts
also same thing with finalize here
finalize is fine with how arch_thread_switch works
ah 
so i can just disable the preemption
i only take the scheduler lock so
wdym
the one for the thread qeueue?
Yeah but don't take it in an irq
but what if im trying to preempt from an IRQ?
DPC
i really still dont understand what the diffrence between running in a DPC is vs running in an IRQ context
DPC runs with interrupts enabled and preemption disabled
my IRQs also run with them enabled too?
im like 99% sure this would still fuck up badly :p
yeahb but its worse now because idk how the fuck its meant to be fixed without disabling irqs :p
You have to disable irqs for a very short time when disabling preemption
But the point is to not disable them across lock holds
that wasnt even what had made me worried about this
prev->preempt_disable_counter -= 1;
idk if there is a place for this that wont race?
If preemption is disabled then that shouldn't race no?
Well when the new active thread is set preemption would then get enabled?
unless i disable preemption on both threads??
Why is the counter per thread
Per thread preemption counts are kinda based
Why
Can allow ur task to get scheduled out if itβs preemption is disabled without side effects
True
But how useful this is, I donβt know
Yeah it's not really useful
Sounds like it'd kill latency
Or rather
Make it higher
il swap to a per core one. i could have sworn i heard it was meant top be thresad local
Afaik Linux and Xen both have it in gs (on x86 platforms)
virgin preempt counter vs chad irql/ipl
in linux the preempt counter is in current
I see
in x86
idk other arches
oh wait nvm it's a per core
in other arches it's in current
switch to a per core counter
you already have percpus set up in place, and in x86 you can do inc gs:whatever
in those other arches it is not possible to increase or decrease cpu locals, so the counter is in the task struct
I do have plenty of room on the CPU locals on other arches anyways
So it's fineβ’
And I can just do a quick enable / disable irq
nah
You can still disable irqs
Temporarily
eh
That is what I do
the value of current is always going to be stable in a task
(obviously)
so you can put the preempt counter in the task struct
and you know that you can only be interrupted in instruction boundaries, so you have either increased/decreased or nothing
so in theory would this work?
Anyway I think if you wanna do irqls you have to make it per cpu
if the irql for scheduling is the lowest one after irql=0, not really
Getting the current thread is always stable and one instruction so that won't race.
And then it can switch safely the tasks etc. then when it's finalizing it disables it and then it can race
I think I'd need to disable IRQs there?
Unless I preempt disable on next and then switch and then decrement both?
