Commit Graph

17 Commits

Author SHA1 Message Date
Bananymous 9eb3834ae5 Kernel: Add syscall-less clock_gettime
If the processor has invariant TSC it can be used to measure time. We
keep track of the last nanosecond and TSC values and offset them based
on the current TSC. This allows getting current time in userspace.

The implementation maps a single RO page to every processes' address
space. The page contains the TSC info which gets updated every 100 ms.
If the processor does not have invariant TSC, this page will not
indicate the capability for TSC based timing.

There was the problem about how does a processor know which cpu it is
running without doing syscall. TSC counters may or may not be
synchronized between cores, so we need a separate TSC info for each
processor. I ended up adding sequence of bytes 0..255 at the start of
the shared page. When a scheduler gets a new thread, it updates the
threads gs/fs segment to point to the byte corresponding to the current
cpu.

This TSC based timing is also used in kernel. With 64 bit HPET this
probably does not bring much of a benefit, but on PIT or 32 bit HPET
this removes the need to aquire a spinlock to get the current time.

This change does force the userspace to not use gs/fs themselves and
they are both now reserved. Other one is used for TLS (this can be
technically used if user does not call libc code) and the other for
the current processor index (cannot be used as kernel unconditionally
resets it after each load balance).

I was looking at how many times timer's current time was polled
(userspace and kernel combined). When idling in window manager, it was
around 8k times/s. When running doom it peaked at over 1 million times
per second when loading and settled at ~30k times/s.
2026-01-08 17:13:59 +02:00
Bananymous 793cca423b Kernel: Fix system timer disabling
I was actually not disabling system timer (HPET, PIT) when using lapic
timers for scheduling. This made BSB get too many timer interrupts :D
2025-07-16 20:02:04 +03:00
Bananymous ebb87ccdde Kernel: Add asserts for overflow checks with ms -> ns conversions 2024-09-24 16:28:44 +03:00
Bananymous a489be0e05 Kernel: Allow parallel LAPIC timer initialization with HPET
HPET supports reading LAPIC counter without locks, so it can be done in
parallel. This makes booting much faster. Previously initializing every
timer took 100 ms, so 16 CPUs took total of 1.6 seconds. This allows
doing it all in 100 ms.
2024-09-19 14:41:59 +03:00
Bananymous 539afb329a Kernel: All processors use LAPIC timer when running with APIC
This makes scheduler preemption much cleaner as bsb does not have to
send smp messages to notify other processes about timer interrupt.

Also PIT percision is now "full" 0.8 us instead of 1 ms that I was using
before.
2024-07-23 02:28:52 +03:00
Bananymous f8261c60c0 Kernel: Rewrite the whole scheduler and re-architecture SMP handling
Change Semaphore -> ThreadBlocker
  This was not a semaphore, I just named it one because I didn't know
  what semaphore was. I have meant to change this sooner, but it was in
  no way urgent :D

Implement SMP events. Processors can now be sent SMP events through
IPIs. SMP events can be sent either to a single processor or broadcasted
to every processor.

PageTable::{map_page,map_range,unmap_page,unmap_range}() now send SMP
event to invalidate TLB caches for the changed pages.

Scheduler no longer uses a global run queue. Each processor has its own
scheduler that keeps track of the load on the processor. Once every
second schedulers do load balancing. Schedulers have no access to other
processors' schedulers, they just see approximate loads. If scheduler
decides that it has too much load, it will send a thread to another
processor through a SMP event.

Schedulers are currently run using the timer interrupt on BSB. This
should be not the case, and each processor should use its LAPIC timer
for interrupts. There is no reason to broadcast SMP event to all
processors when BSB gets timer interrupt.

Old scheduler only achieved 20% idle load on qemu. That was probably a
very inefficient implementation. This new scheduler seems to average
around 1% idle load. This is much closer to what I would expect. On my
own laptop idle load seems to be only around 0.5% on each processor.
2024-07-22 00:33:50 +03:00
Bananymous dfe5a2d665 All: Cleanup all files
Add newline to end of files and remove whitespace from end of lines
2024-01-24 15:53:38 +02:00
Bananymous 75fdf4c3c6 Kernel: Add Timer::ns_since_boot() 2023-10-12 21:16:39 +03:00
Bananymous 9d827037ca Kernel: Fix timer includes 2023-09-22 17:20:35 +03:00
Bananymous 5d0a6e7b08 Kernel: HPET is now used in legacy mode when PIC is forced 2023-08-10 22:01:30 +03:00
Bananymous 96c0ad0d3d Kernel: Remove get_unix_timestamp from SystemTimer
Kernel now uses the percise real_time() and time_since_boot()
2023-08-09 08:57:50 +03:00
Bananymous 3df97c36e6 Kerne: SystemTimer can now output the current real time 2023-08-04 16:06:47 +03:00
Bananymous c732297623 Kernel: Rename TimerHandler to SystemTimer
I changed SystemTimer to only handle the "best" supported timer
it can initialize.
2023-08-04 16:06:47 +03:00
Bananymous ca5a097ef5 Kernel: Add function to retrieve boot time as timespec 2023-08-04 16:06:47 +03:00
Bananymous ea4a70c3b3 Kernel: Move sleep() implementation to TimerHandler 2023-08-04 15:15:00 +03:00
Bananymous 7eb2c140fe Kernel: Move RTC to Timer directory
PIT ms counter seems to be off by multiple seconds/minute. I will
be probably changing to HPET for system time
2023-08-04 11:12:16 +03:00
Bananymous 659adb89a6 Kernel: Start work on abstracting Timers 2023-08-04 10:29:42 +03:00