# Flags
Flags represent scheduler capabilities that can be independently
enabled or disabled. The `#[derive(Scheduler)]` macro defines typed
flags from enum variants, generating compile-time checked constants
and `FlagDecl` statics.
Schedulers have optional features (LLC awareness, work stealing, CPU
borrowing) toggled via CLI arguments. Flags let you test every valid
combination automatically -- the gauntlet generates one test variant per
flag combination, ensuring the scheduler works with any subset of
features enabled.
## Defining flags
Annotate an enum with `#[derive(Scheduler)]`. Each variant becomes a
flag. `#[flag(args)]` lists CLI arguments passed to the scheduler when
the flag is active. `#[flag(requires)]` declares dependencies on other
variants.
```rust,ignore
use ktstr::prelude::*;
#[derive(Scheduler)]
#[scheduler(name = "my_sched", binary = "scx_my_sched", topology(2, 4, 1))]
#[allow(dead_code)]
enum MySchedFlag {
#[flag(args = ["--enable-llc-awareness"])]
Llc,
#[flag(args = ["--enable-borrowing"])]
Borrow,
#[flag(args = ["--enable-work-stealing"], requires = [Llc])]
Steal,
}
```
The derive macro generates:
- A `static FlagDecl` for each variant with the flag's kebab-case name,
CLI args, and dependency references.
- `impl MySchedFlag { pub const LLC: &'static str = "llc"; pub const BORROW: &'static str = "borrow"; ... }`
-- typed string constants for each variant.
- `const MY_SCHED: Scheduler` -- a `Scheduler` const derived from the
enum name (strip `Flag`/`Flags` suffix, convert to
`SCREAMING_SNAKE_CASE`).
Variant names are converted to kebab-case: `Llc` becomes `"llc"`,
`RejectPin` becomes `"reject-pin"`.
## Using flags in tests
`#[ktstr_test]` accepts `required_flags` and `excluded_flags` to
constrain which flag profiles a test runs with. Both path expressions
and string literals work:
```rust,ignore
// Path expressions -- typos are compile errors
#[ktstr_test(
scheduler = MY_SCHED,
required_flags = [MySchedFlag::LLC],
excluded_flags = [MySchedFlag::BORROW],
)]
fn needs_llc(ctx: &Ctx) -> Result<AssertResult> { /* ... */ }
// String literals -- also work
#[ktstr_test(scheduler = MY_SCHED, required_flags = ["llc"])]
fn also_needs_llc(ctx: &Ctx) -> Result<AssertResult> { /* ... */ }
```
Path expressions are preferred: `MySchedFlag::LLC` is checked by the
compiler, while `"llc"` is not.
## Flag profiles and gauntlet
A `FlagProfile` is a sorted set of active flag names. Its display name
is the flags joined with `+` (e.g. `"llc+borrow"`), or `"default"`
when empty.
The gauntlet generates all valid flag combinations from the scheduler's
flag declarations and the test's constraints. For a scheduler with 6
flags and one dependency (`steal` requires `llc`), unconstrained
generation produces 48 profiles (2^6 = 64 minus 16 combinations where
`steal` is active without `llc`).
`required_flags` forces flags into every profile. `excluded_flags`
removes flags from consideration. The remaining flags are combined in
all valid subsets.
See [Gauntlet flag profiles](../running-tests/gauntlet.md#flag-profiles).
## Dependencies
`requires = [Llc]` on a variant means that variant is only active in
profiles where `Llc` is also active. Profile generation rejects any
combination where a flag's dependencies are missing.
```rust,ignore
#[flag(args = ["--enable-work-stealing"], requires = [Llc])]
Steal,
```
Every generated profile containing `steal` also contains `llc`.
Requiring `steal` in a test (`required_flags = [MySchedFlag::STEAL]`)
implicitly forces `llc` into all profiles for that test.
## Underlying mechanism (advanced)
The derive macro generates `FlagDecl` statics and a flags array that
the `Scheduler` const references. Most users never need to write
`FlagDecl` manually -- the macro handles it. The generated code is
equivalent to:
```rust,ignore
static __MY_SCHED_FLAG_DECL_LLC: FlagDecl = FlagDecl {
name: "llc",
args: &["--enable-llc-awareness"],
requires: &[],
};
static __MY_SCHED_FLAG_DECL_STEAL: FlagDecl = FlagDecl {
name: "steal",
args: &["--enable-work-stealing"],
requires: &[&__MY_SCHED_FLAG_DECL_LLC],
};
```
See [`ktstr-macros/src/lib.rs`](https://github.com/likewhatevs/ktstr/blob/main/ktstr-macros/src/lib.rs)
for the macro source.