Repository navigation
Context Switching - #28
Merged
Merged
Conversation
The spinlock, the mutex and the seqlock were in the kernel root for lack of a home, and the reader-writer locks to come would have joined them there. The headers move to <locking/>. Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
The header split going forward is going to work like the following:
- include/ -> public API
- include/private -> private API (for neighbor subsystems)
- include/private/arch -> private API that is meant to be called or
implemented by the architecture's "half" of
a generic subsystem
- include/detail -> private API, but may be leaked via the public
header because it needs either fields or other
helpers to be available inline
- include/arch/ -> public, arch-specific API
- include/arch/private -> private arch-specific API
- include/arch/detail -> the arch-specific "half" of the implementation
of a generic subsystem
Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
Leaking private headers via the public ones completely invalidates the whole idea behind having private headers, so check that we don't do that. Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
A statement expression macro must indent its body once and put the closing }) in the first colum. Check it, and convert RUNTIME_COMPARE() to follow this rule. Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
d-tatianin
force-pushed
the
ctx-switching
branch
2 times, most recently
from
November 11, 2026 22:15
1b0eb8c to
8f1ab01
Compare
A DEFINE_*() or DECLARE_*() macro must leave the semicolon to its users, so that a use reads like any other definition. Check it, and convert DEFINE_MUTEX() and DEFINE_SPINLOCK() to follow this rule. Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
Nothing is declared in it anymore and both of its includes are already reached through memory/io.h. Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
Callers only hold an io window and hand it back, its layout is an implementation detail. Move it out of the public header together with the pio address type and the io type enum, and the arch header that defines them into arch/detail/. Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
Only the spin_*() helpers touch its fields, so spinlock.h keeps a forward declaration and the definition moves out of the way. Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
Only the mutex_*() helpers touch its fields, so mutex.h keeps the documented forward declaration and the definition moves out of the way. Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
The initial state of each lock was written twice, in its initializer macro and in its init function, so a new field had to be added to both. Going forward, an init function is defined through the macro next to it, e.g. *lock = SPINLOCK_INIT(*lock). The time keeper passed the address of its lock and sequence count instead of the objects, which only built because neither macro uses its argument. Pass the objects. Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
struct log_ring is defined in detail/log_ring.h, so log_ring.h never said the type exists to its reader. Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
Only the subsystem and its arch half use the table entry, its flags and the entry point of the exception handlers, so the public header has no readers. Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
The statement expression declares its own ret, which shadows the ret every caller assigns the result to. Rename it to consume_ret so that -Wshadow can be enabled. Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
The old device's final reading is declared in an inner block under the same name as the new device's. Rename it to old_cycles. Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
SEQLOCK_INIT() builds a struct seqlock, but seqlock is a typedef of an anonymous struct, so the macro fails to compile on its first use. It also hands the whole seqlock to SEQCOUNT_INIT() and SPINLOCK_INIT() instead of its members. Nothing uses it yet. Name the struct like struct seqcount, drop the typedef and initialize each member from its own field. Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
do_tick() converts the cycles since the previous tick to nanoseconds, rounds down and throws the remainder away. The keeper falls behind the counter by up to a nanosecond per tick, and ns_since_boot() can go back by one: a reader that sampled the counter after the tick did, but still saw the previous base, gets the time without the rounding. Keep the remainder in units of the device's shift and add it to the next conversion. A device switch rounds it off once, since the next device has a different shift. Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
A shadowed variable compiles silently and is easy to mistake for the outer one. Nothing in the tree shadows anymore, so keep it that way. Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
irq_* prefixed APIs are going to be reserved for actual interaction with IRQ lines and hardware, not CPU flags. Rename to reflect that and to avoid confusion about what this API does. Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
The flag was a static in the stub header, so every translation unit had its own copy, and a lock taken with interrupts disabled in spinlock.c left them enabled as far as the test could tell. Define it once in kernel_helpers.cpp. Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
So that generic code doesn't have to use the arch_* variant directly. Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
A handler interrupting the panic could log into the ring being dumped or block on a lock the panic path holds. Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
Assembly is about to need MSR numbers, but msr.h is C and its digit separators do not assemble. Keep the numbers as plain defines in a header of their own, which msr.h includes. Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
Going forward, the contract with the arch-specific code is going to be that upon calling the generic entry() per-cpu variables are already online and usable on the BSP. Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
Cover locking, static initialization, try-lock and the interrupt state around the irq-saving variants, which the tests can observe now that the emulated interrupt state is shared. Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
They were compound assignments on a gs-qualified lvalue, which only becomes a single instruction with optimizations on. A debug build loads, modifies and stores, so an interrupt updating the same variable in between loses its update. Spell them out as one instruction. The gs prefix is written explicitly since clang drops it for a gs-qualified memory operand. Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
A convenience macro to walk all CPUs. Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
BIT_UNIT_FIND_FIRST_SET() takes a long, so BIT_FIELD_SHIFT() would truncate a u64 mask where long is 32-bit. Replace it with a helper for a value of any integer type, which picks the builtin by the size of the value. Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
CPU numbers were plain u32 next to APIC IDs of the same type, and loops over the CPUs used u32 and size_t interchangeably. Give logical CPU numbers and counts of CPUs a type of their own, printed with %u. Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
The kernel parses its command line in entry.c and nowhere else, so cmdline_parse(), cmdline_parse_tables() and struct param_table are not something the author of a parameter uses. Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
Modules need parameters that do not clash with each other. The key is module.name, so the parser needs no new table and plain parameters are unaffected. Init parameters get no module variant: they belong to the boot of the kernel itself and would mean nothing to a module loaded after it. In a runtime module an init parameter is an unused entry, so a driver that has one still builds either way. Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
The image's command line was fixed, so trying a parameter meant editing the script. --cmdline extends a baremetal job's command line as well, which makes --baremetal-cmdline redundant, so build.py drops it. Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
Let code outside the scheduler read how many context switches a CPU has done without reaching into its runqueue. Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
Nothing exercises the scheduler with many threads. Every rocket and particle is a thread that sleeps for a frame between draws, which keeps thousands of threads waking 60 times a second, and the log gets switch rate and wakeup latency every two seconds. Exclusive with the framebuffer console and built with --config fireworks. fireworks.runtime-seconds=<n> makes it stop and print its totals. The demo is a tristate module, so it can be loaded at runtime once the kernel has a module loader. Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
Only kthread_stop() could wait for a kernel thread to exit, and it also asks the thread to stop. Add kthread_wait_for_exit() for a thread that ends on its own, and use it in kthread_stop(). Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
A framework for testing kernel features that require the real kernel environment. Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
A case that hangs would stall the whole run. Each case now gets 30 s unless KTEST_CASE_WITH_TIMEOUT() says otherwise, after which it fails and its thread is left running. A result that arrives after its case finished is reported as late and not counted. Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
Running every case is slow when working on one subsystem. ktest.run= now takes a comma-separated list of suites and suite.case names, "all" still runs everything. Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
A helper for starting a number of threads that all run the same function with an index per-thread. Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
A run that waits for a result has to end once the kernel printed it. qemu_watch() can now stop at the first match of a pattern, which it looks for with the color escapes of the console removed, and returns the match after a short drain of the remaining output. Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
Use download() from build_utils instead, which the toolchain build already uses, it retries a failed download and only moves the file into place once it is complete. Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
A kernel that builds can still crash early in boot. --boot-test boots it headless and exits 0 once it idles, 1 on a panic, a BUG or an oops, and 2 when it never got that far. The output is judged by criteria.json, like a plain baremetal run. --baremetal-criteria becomes --criteria and picks the criteria for both. Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
This boots the tests headless and exits with 0 when everything passed, 1 on a failure or a crash and 2 when the run never finished. The output is judged by criteria-ktest.json, the same criteria as a baremetal run. --ktest always builds the ktest preset and uses its criteria, so it can't be combined with --config or --criteria. Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
A preset fixes the optimization level and whether LTO is used, so building a preset with another combination meant editing its .config by hand. Add --optimization-level and --lto/--no-lto to override them. The options only apply to the build that is given them. They win over the preset and over a value changed by hand in .config, and build.py records the values they replace in the build directory, so that a later build without them restores those values. Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
On a cache miss, both GCC legs of the build matrix built the toolchain at the same time. Build it once in a toolchain job that the build job waits for, with the toolchain steps in a composite action that both jobs use. Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
A successful build doesn't mean that the kernel boots, undefined behavior can still crash it early. Boot every kernel the job builds with --boot-test, and rename the job to build-and-boot. Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
The AST checks of the linter only see the code the linted build compiles, and the default preset leaves out everything behind an option it doesn't enable. Lint every preset in configs/ instead. Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
Cover timed sleeps, equal priority spinners sharing the CPU, wakeup preemption by a higher priority but not an equal one, and kthread_stop() on a sleeping and on a never started thread. Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
Cover hundreds of timers expiring at the same time, cancellation, a callback rearming its own timer and the clock never stepping back between two readers. Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
Cover mutual exclusion between contending threads, a waiter not starved by a thread that keeps retaking the lock, and try-lock failing only while the lock is held. Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
Add the counterpart of str_starts_with(). Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
Check each describer on various memory types: - A function and a variable in the image - Per-CPU variable on every CPU - Heap object and a large allocation - Block and a struct page - The whole chain through %pMEM Signed-off-by: Daniil Tatianin <99danilt@gmail.com>
d-tatianin
force-pushed
the
ctx-switching
branch
from
November 12, 2026 22:09
8f1ab01 to
857b886
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.