[]
= "0.1.6"
use ;
If it compiles, your IRQL transitions are valid.
How it works
#[irql(max = Dispatch)] adds a hidden IRQL type parameter bounded by IrqlCanRaiseTo<Dispatch>. call_irql! threads it through every call as a turbofish argument. The compiler checks every transition — trying to lower IRQL is a compile error:
error[E0277]: IRQL violation: cannot reach `Passive` from `Dispatch`
-- would require lowering
The #[irql()] attribute
| Form | Meaning |
|---|---|
#[irql(at = Level)] |
Fixed entry point — known IRQL, no generic |
#[irql(max = Level)] |
Callable from Level or below |
#[irql(min = A, max = B)] |
Callable in [A, B] |
Works on functions, impl blocks, and trait impl blocks.
IRQL levels
| Value | Type | Description |
|---|---|---|
| 0 | Passive |
Normal thread; paged memory OK |
| 1 | Apc |
APC delivery |
| 2 | Dispatch |
DPC / spinlock |
| 3–26 | Dirql |
Device interrupts |
| 27 | Profile |
Profiling timer |
| 28 | Clock |
Clock interrupt |
| 29 | Ipi |
Inter-processor interrupt |
| 30 | Power |
Power failure |
| 31 | High |
Highest — machine check |
Impl blocks
Apply #[irql] to an entire impl block — every method gets the constraint:
Function traits
IrqlFn, IrqlFnMut, IrqlFnOnce — IRQL-aware analogues of Fn, FnMut, FnOnce:
The macro rewrites IrqlFn<()> to IrqlFn<Passive, ()> automatically.
IRQL-aware allocation (nightly)
= { = "0.1.6", = ["alloc"] }
Requires nightly (allocator_api, vec_push_within_capacity, auto_traits, negative_impls).
Pool types
| Pool | Allocable at | Accessible at |
|---|---|---|
PagedPool |
Passive, Apc |
Passive, Apc |
NonPagedPool |
Passive, Apc, Dispatch |
Any IRQL |
IrqlBox::new and IrqlVec::new pick the cheapest legal pool automatically.
IrqlBox and IrqlVec
Drop safety
Paged-pool containers cannot be dropped at Dispatch or above. The #[irql] macro injects SafeToDropAt<Level> bounds on by-value parameters, so passing paged-pool memory into elevated-IRQL code is a compile error. References (&IrqlBox) are not gated. Use leak() or into_raw() to transfer ownership across IRQL boundaries.
Crate architecture
irql ← public facade (re-exports everything)
├── irql_core ← levels, hierarchy traits, function traits, SafeToDropAt
├── irql_macro ← #[irql] proc macro, call_irql! rewriter
└── irql_alloc ← IrqlBox, IrqlVec, pool allocator (optional, nightly)
Safety
All checks are compile-time only. You must ensure entry points (#[irql(at = …)]) match the actual runtime IRQL and that IRQL-raising operations are properly modelled.
License
MIT or Apache 2.0, at your option.