33 个版本
使用旧的 Rust 2015
0.2.25 | 2019 年 10 月 20 日 |
---|---|
0.2.23 | 2019 年 7 月 13 日 |
0.2.20 | 2019 年 3 月 24 日 |
0.2.16 | 2018 年 12 月 9 日 |
0.0.1 | 2015 年 5 月 9 日 |
#86 在 #safety
每月 52 次下载
27KB
577 行
tag_safe
这是一个最初为与内核一起使用而设计的检查器,其中函数需要标记为 "IRQ 安全"(意味着它们可以在中断处理程序中调用,并处理它们可能中断自己的情况)。
详细说明
如果一个函数被注解为 #[req_safe(ident)]
(其中 ident
可以是任何内容,并定义了安全类型)此检查器将检查该函数调用的所有函数要么带有相同的注解,要么带有 #[is_safe(ident)]
,或者它们不调用带有相反 #[is_unsafe(ident)]
注解的函数。
默认情况下,此检查器是一个警告,如果您想将其设置为错误,请添加 #[deny(not_tagged_safe)]
外部 crate 导入可以使用 #[tagged_safe(tag="path/to/list.txt")
注解,从外部文件加载标记的方法列表。路径相对于 rustc 被调用的位置(目前),包含一个默认标签(true 或 false),后跟一个换行符分隔的方法列表。
示例
本文件标注了libstd中所有函数为安全,除了 std::io::_print
(它是 print!
的后端)
true
std::io::_print
用法
以下是一个使用此标志来防止在中断处理程序中意外使用非中断安全方法的示例。(假设 acquire_irq_spinlock
使用的锁与 acquire_non_irq_spinlock
获取的锁不同)
#![feature(custom_attribute,plugin)]
#![plugin(tag_safe)]
/// RAII primitive spinlock
struct Spinlock;
/// Handle to said spinlock
struct HeldSpinlock(&'static Spinlock);
/// RAII IRQ hold
struct IRQLock;
/// Spinlock that also disables IRQs
struct IrqSpinlock(Spinlock);
static S_NON_IRQ_SPINLOCK: Spinlock = Spinlock;
static S_IRQ_SPINLOCK: IrqSpinlock = IrqSpinlock(Spinlock);
#[deny(not_tagged_safe)] // Make the lint an error
#[req_safe(irq)] // Require this method be IRQ safe
fn irq_handler()
{
// The following line would error if it were uncommented, as the
// acquire_non_irq_spinlock method has been marked as irq-unsafe.
// If this method was called without protection, the CPU could deadlock.
//let _lock = acquire_non_irq_spinlock(&S_NON_IRQ_SPINLOCK);
// However, this will not error, this method is marked as IRQ safe
let _lock = acquire_irq_spinlock(&S_IRQ_SPINLOCK);
}
// This method handles IRQ safety internally, and hence makes
// this lint allowable.
#[is_safe(irq)]
fn acquire_irq_spinlock(l: &'static IrqSpinlock) -> (IRQLock,HeldSpinlock)
{
// Prevent IRQs from firing
let irql = hold_irqs();
// and acquire the spinlock
(irql, acquire_non_irq_spinlock(&l.0))
}
// Stop IRQs from firing until the returned value is dropped
#[is_safe(irq)]
fn hold_irqs() -> IRQLock
{
IRQLock
}
// Not safe to call in an IRQ without protection (as that can lead to a
// uniprocessor deadlock)
#[not_safe(irq)]
fn acquire_non_irq_spinlock(l: &'static Spinlock) -> HeldSpinlock
{
HeldSpinlock(l)
}
依赖
~175KB