Scope-based resource management for the kernel(基于域的内核资源管理)
参考
- https://lwn.net/Articles/934679/
- Scope-based Cleanup Helpers
- Automatic Cleanup 1/2
- Automatic Cleanup 2/2
- 下面是network子系统对使用guard的建议:
常用的API
FREE
kfree
DEFINE_FREE(kfree, void *, if (!IS_ERR_OR_NULL(_T)) kfree(_T))
kvfree
DEFINE_FREE(kvfree, void *, if (!IS_ERR_OR_NULL(_T)) kvfree(_T))
put_task
DEFINE_FREE(put_task, struct task_struct *, if (_T) put_task_struct(_T))
free_cpumask_var
DEFINE_FREE(free_cpumask_var, struct cpumask *, if (_T) free_cpumask_var(_T));
bitmap
DEFINE_FREE(bitmap, unsigned long *, if (_T) bitmap_free(_T))
fput
DEFINE_FREE(fput, struct file *, if (!IS_ERR_OR_NULL(_T)) fput(_T))
put_device
DEFINE_FREE(put_device, struct device *, if (_T) put_device(_T))
device_del
DEFINE_FREE(device_del, struct device *, if (_T) device_del(_T))
firmware
DEFINE_FREE(firmware, struct firmware *, release_firmware(_T))
free_percpu
DEFINE_FREE(free_percpu, void __percpu *, free_percpu(_T))
CLASS
find_get_task
DEFINE_CLASS(find_get_task, struct task_struct *, if (_T) put_task_struct(_T),
find_get_task(pid), pid_t pid)
fd/fd_raw
DEFINE_CLASS(fd, struct fd, fdput(_T), fdget(fd), int fd)
DEFINE_CLASS(fd_raw, struct fd, fdput(_T), fdget_raw(fd), int fd)
get_unused_fd
DEFINE_CLASS(get_unused_fd, int, if (_T >= 0) put_unused_fd(_T),
get_unused_fd_flags(flags), unsigned flags)
Guard/Lock
raw_spinlock
DEFINE_LOCK_GUARD_1(raw_spinlock, raw_spinlock_t,
raw_spin_lock(_T->lock),
raw_spin_unlock(_T->lock))
raw_spinlock_try
DEFINE_LOCK_GUARD_1_COND(raw_spinlock, _try, raw_spin_trylock(_T->lock))
raw_spinlock_nested
DEFINE_LOCK_GUARD_1(raw_spinlock_nested, raw_spinlock_t,
raw_spin_lock_nested(_T->lock, SINGLE_DEPTH_NESTING),
raw_spin_unlock(_T->lock))
raw_spinlock_irq
DEFINE_LOCK_GUARD_1(raw_spinlock_irq, raw_spinlock_t,
raw_spin_lock_irq(_T->lock),
raw_spin_unlock_irq(_T->lock))
raw_spinlock_irq_try
DEFINE_LOCK_GUARD_1_COND(raw_spinlock_irq, _try, raw_spin_trylock_irq(_T->lock))
raw_spinlock_irqsave
DEFINE_LOCK_GUARD_1(raw_spinlock_irqsave, raw_spinlock_t,
raw_spin_lock_irqsave(_T->lock, _T->flags),
raw_spin_unlock_irqrestore(_T->lock, _T->flags),
unsigned long flags)
raw_spinlock_irqsave_try
DEFINE_LOCK_GUARD_1_COND(raw_spinlock_irqsave, _try,
raw_spin_trylock_irqsave(_T->lock, _T->flags))
spinlock
DEFINE_LOCK_GUARD_1(spinlock, spinlock_t,
spin_lock(_T->lock),
spin_unlock(_T->lock))
spinlock_try
DEFINE_LOCK_GUARD_1_COND(spinlock, _try, spin_trylock(_T->lock))
spinlock_irq
DEFINE_LOCK_GUARD_1(spinlock_irq, spinlock_t,
spin_lock_irq(_T->lock),
spin_unlock_irq(_T->lock))
spinlock_irq_try
DEFINE_LOCK_GUARD_1_COND(spinlock_irq, _try,
spin_trylock_irq(_T->lock))
spinlock_irqsave
DEFINE_LOCK_GUARD_1(spinlock_irqsave, spinlock_t,
spin_lock_irqsave(_T->lock, _T->flags),
spin_unlock_irqrestore(_T->lock, _T->flags),
unsigned long flags)
spinlock_irqsave_try
DEFINE_LOCK_GUARD_1_COND(spinlock_irqsave, _try,
spin_trylock_irqsave(_T->lock, _T->flags))
read_lock
DEFINE_LOCK_GUARD_1(read_lock, rwlock_t,
read_lock(_T->lock),
read_unlock(_T->lock))
read_lock_irq
DEFINE_LOCK_GUARD_1(read_lock_irq, rwlock_t,
read_lock_irq(_T->lock),
read_unlock_irq(_T->lock))
read_lock_irqsave
DEFINE_LOCK_GUARD_1(read_lock_irqsave, rwlock_t,
read_lock_irqsave(_T->lock, _T->flags),
read_unlock_irqrestore(_T->lock, _T->flags),
unsigned long flags)
write_lock
DEFINE_LOCK_GUARD_1(write_lock, rwlock_t,
write_lock(_T->lock),
write_unlock(_T->lock))
write_lock_irq
DEFINE_LOCK_GUARD_1(write_lock_irq, rwlock_t,
write_lock_irq(_T->lock),
write_unlock_irq(_T->lock))
write_lock_irqsave
DEFINE_LOCK_GUARD_1(write_lock_irqsave, rwlock_t,
write_lock_irqsave(_T->lock, _T->flags),
write_unlock_irqrestore(_T->lock, _T->flags),
unsigned long flags)
mutex
DEFINE_GUARD(mutex, struct mutex *, mutex_lock(_T), mutex_unlock(_T))
DEFINE_GUARD_COND(mutex, _try, mutex_trylock(_T))
DEFINE_GUARD_COND(mutex, _intr, mutex_lock_interruptible(_T) == 0)
irq、irqsave
DEFINE_LOCK_GUARD_0(irq, local_irq_disable(), local_irq_enable())
DEFINE_LOCK_GUARD_0(irqsave,
local_irq_save(_T->flags),
local_irq_restore(_T->flags),
unsigned long flags)
rwsem
DEFINE_GUARD(rwsem_read, struct rw_semaphore *, down_read(_T), up_read(_T))
DEFINE_GUARD_COND(rwsem_read, _try, down_read_trylock(_T))
DEFINE_GUARD_COND(rwsem_read, _intr, down_read_interruptible(_T) == 0)
DEFINE_GUARD(rwsem_write, struct rw_semaphore *, down_write(_T), up_write(_T))
DEFINE_GUARD_COND(rwsem_write, _try, down_write_trylock(_T))
local_lock
DEFINE_GUARD(local_lock, local_lock_t __percpu*,
local_lock(_T),
local_unlock(_T))
DEFINE_GUARD(local_lock_irq, local_lock_t __percpu*,
local_lock_irq(_T),
local_unlock_irq(_T))
DEFINE_LOCK_GUARD_1(local_lock_irqsave, local_lock_t __percpu,
local_lock_irqsave(_T->lock, _T->flags),
local_unlock_irqrestore(_T->lock, _T->flags),
unsigned long flags)
DEFINE_GUARD(local_lock_nested_bh, local_lock_t __percpu*,
local_lock_nested_bh(_T),
local_unlock_nested_bh(_T))
rtnl
DEFINE_LOCK_GUARD_0(rtnl, rtnl_lock(), rtnl_unlock())
core_lock
DEFINE_LOCK_GUARD_1(core_lock, int,
sched_core_lock(*_T->lock, &_T->flags),
sched_core_unlock(*_T->lock, &_T->flags),
unsigned long flags)
rq_lock
DEFINE_LOCK_GUARD_1(rq_lock, struct rq,
rq_lock(_T->lock, &_T->rf),
rq_unlock(_T->lock, &_T->rf),
struct rq_flags rf)
rq_lock_irq
DEFINE_LOCK_GUARD_1(rq_lock_irq, struct rq,
rq_lock_irq(_T->lock, &_T->rf),
rq_unlock_irq(_T->lock, &_T->rf),
struct rq_flags rf)
rq_lock_irqsave
DEFINE_LOCK_GUARD_1(rq_lock_irqsave, struct rq,
rq_lock_irqsave(_T->lock, &_T->rf),
rq_unlock_irqrestore(_T->lock, &_T->rf),
struct rq_flags rf)
double_raw_spinlock
#define DEFINE_LOCK_GUARD_2(name, type, _lock, _unlock, ...) \
__DEFINE_UNLOCK_GUARD(name, type, _unlock, type *lock2; __VA_ARGS__) \
static inline class_##name##_t class_##name##_constructor(type *lock, type *lock2) \
{ class_##name##_t _t = { .lock = lock, .lock2 = lock2 }, *_T = &_t; \
_lock; return _t; }
static inline void double_raw_lock(raw_spinlock_t *l1, raw_spinlock_t *l2)
{
if (l1 > l2)
swap(l1, l2);
raw_spin_lock(l1);
raw_spin_lock_nested(l2, SINGLE_DEPTH_NESTING);
}
static inline void double_raw_unlock(raw_spinlock_t *l1, raw_spinlock_t *l2)
{
raw_spin_unlock(l1);
raw_spin_unlock(l2);
}
DEFINE_LOCK_GUARD_2(double_raw_spinlock, raw_spinlock_t,
double_raw_lock(_T->lock, _T->lock2),
double_raw_unlock(_T->lock, _T->lock2))
double_rq_lock
DEFINE_LOCK_GUARD_2(double_rq_lock, struct rq,
double_rq_lock(_T->lock, _T->lock2),
double_rq_unlock(_T->lock, _T->lock2))
task_rq_lock
DEFINE_LOCK_GUARD_1(task_rq_lock, struct task_struct,
_T->rq = task_rq_lock(_T->lock, &_T->rf),
task_rq_unlock(_T->rq, _T->lock, &_T->rf),
struct rq *rq; struct rq_flags rf)
cpus_read_lock
DEFINE_LOCK_GUARD_0(cpus_read_lock, cpus_read_lock(), cpus_read_unlock())
device
static inline int device_trylock(struct device *dev)
{
return mutex_trylock(&dev->mutex);
}
static inline void device_unlock(struct device *dev)
{
mutex_unlock(&dev->mutex);
}
DEFINE_GUARD(device, struct device *, device_lock(_T), device_unlock(_T))
task_lock
DEFINE_GUARD(task_lock, struct task_struct *, task_lock(_T), task_unlock(_T))
pci_dev
DEFINE_GUARD(pci_dev, struct pci_dev *, pci_dev_lock(_T), pci_dev_unlock(_T))
disable_irq
DEFINE_LOCK_GUARD_1(disable_irq, int,
disable_irq(*_T->lock), enable_irq(*_T->lock))
HARDIRQ
#define HARDIRQ_ENTER() \
local_irq_disable(); \
__irq_enter(); \
lockdep_hardirq_threaded(); \
WARN_ON(!in_irq());
#define HARDIRQ_EXIT() \
__irq_exit(); \
local_irq_enable();
DEFINE_LOCK_GUARD_0(HARDIRQ, HARDIRQ_ENTER(), HARDIRQ_EXIT())
NOTTHREADED_HARDIRQ
DEFINE_LOCK_GUARD_0(NOTTHREADED_HARDIRQ,
do {
local_irq_disable();
__irq_enter();
WARN_ON(!in_irq());
} while(0), HARDIRQ_EXIT())
SOFTIRQ
DEFINE_LOCK_GUARD_0(SOFTIRQ, SOFTIRQ_ENTER(), SOFTIRQ_EXIT())
RCU
/* Define RCU guards, should go away when RCU has its own guard definitions */
DEFINE_LOCK_GUARD_0(RCU, rcu_read_lock(), rcu_read_unlock())
DEFINE_LOCK_GUARD_0(RCU_BH, rcu_read_lock_bh(), rcu_read_unlock_bh())
DEFINE_LOCK_GUARD_0(RCU_SCHED, rcu_read_lock_sched(), rcu_read_unlock_sched())
srcu
DEFINE_LOCK_GUARD_1(srcu, struct srcu_struct,
_T->idx = srcu_read_lock(_T->lock),
srcu_read_unlock(_T->lock, _T->idx),
int idx)
preempt
DEFINE_LOCK_GUARD_0(preempt, preempt_disable(), preempt_enable())
DEFINE_LOCK_GUARD_0(preempt_notrace, preempt_disable_notrace(), preempt_enable_notrace())
DEFINE_LOCK_GUARD_0(migrate, migrate_disable(), migrate_enable())
示例
guard
guard(mutex)(&data->mutex);
guard(mutex)(&reset_gpio_lookup_mutex);
guard(rwsem_write)(&pwrseq->rw_lock);
guard(rwsem_read)(&pwrseq->rw_lock);
guard(raw_spinlock)(&dl_b->lock);
guard(raw_spinlock_irq)(&p->pi_lock);
guard(raw_spinlock_irqsave)(&priv->lock);
guard(preempt)();
guard(rcu)();
guard(srcu)(&lr->gdev->srcu);
guard(task_rq_lock)(p); // struct task_struct *p
guard(rq_lock_irqsave)(rq); // struct rq *rq
guard(irq)();
guard(double_rq_lock)(dst, src); // struct rq *dst, *src
guard(core_lock)(&cpu); // unsigned int cpu
guard(cpus_read_lock)();
CLASS
struct gpio_chip_guard {
struct gpio_device *gdev;
struct gpio_chip *gc;
int idx;
};
DEFINE_CLASS(gpio_chip_guard,
struct gpio_chip_guard,
srcu_read_unlock(&_T.gdev->srcu, _T.idx),
({
struct gpio_chip_guard _guard;
_guard.gdev = desc->gdev;
_guard.idx = srcu_read_lock(&_guard.gdev->srcu);
_guard.gc = srcu_dereference(_guard.gdev->chip,
&_guard.gdev->srcu);
_guard;
}),
struct gpio_desc *desc)
CLASS(gpio_chip_guard, guard)(desc);
scoped_guard
scoped_guard (mutex, &st->lock) {}
scoped_guard (rwsem_write, &pwrseq_sem) {}
scoped_guard (rwsem_read, &namespace_sem) {}
scoped_guard (raw_spinlock_irqsave, &p->pi_lock) {}
scoped_guard (rcu) {}
scoped_guard (srcu, &desc->gdev->desc_srcu) {}
scoped_guard (srcu, &gpio_devices_srcu) {}
scoped_guard (irqsave) {}
scoped_guard (rq_lock_irqsave, rq) {}
scoped_guard (rq_lock, rq) {}
scoped_guard (spinlock, &lr->wait.lock) {}
scoped_guard (write_lock_irq, &tasklist_lock) {}
scoped_cond_guard
scoped_cond_guard(mutex_intr, return -EINTR, &pcu->cmd_mutex) {}
本文来自博客园,作者:摩斯电码,未经同意,禁止转载