您的位置:首页 > 其它

模块API之try_module_get

2017-11-03 09:23 387 查看
try_module_get的作用是如果一个模块处于活动状态,则对其引用计数加1.
在kernel中使用的例程如下:
struct file *anon_inode_getfile(const char *name,
const struct file_operations *fops,
void *priv, int flags)
{
struct qstr this;
struct path path;
struct file *file;

if (IS_ERR(anon_inode_inode))
return ERR_PTR(-ENODEV);

if (fops->owner && !try_module_get(fops->owner))
return ERR_PTR(-ENOENT);

}
其源码如下:
bool try_module_get(struct module *module)
{
bool ret = true;
//首先这个模块不能为null
if (module) {
// 由于要增加模块的引用计数,因此需要通过preempt_disable()/preempt_enable()来禁止内核抢占
preempt_disable();
/* Note: here, we can fail to get a reference */
// 首先通过module_is_live 判读模块处于活动状态,这个函数其实就是判断模块的flag是否是MODULE_STATE_GOING。然后通过atomic_inc_not_zero来增加模块的引用计数
if (likely(module_is_live(module) &&
atomic_inc_not_zero(&module->refcnt) != 0))
trace_module_get(module, _RET_IP_);
else
ret = false;

preempt_enable();
}
return ret;
}
我们来看看atomic_inc_not_zero的实现
#ifndef atomic_inc_not_zero
#define atomic_inc_not_zero(v)		atomic_add_unless((v), 1, 0)
#endif
继续看atomic_add_unless
static inline int atomic_add_unless(atomic_t *v, int a, int u)
{
return __atomic_add_unless(v, a, u) != u;
}
替换一下等于调用
__atomic_add_unless(v, 1, 0) != 0;
其源码如下:
#ifndef __atomic_add_unless
static inline int __atomic_add_unless(atomic_t *v, int a, int u)
{
int c, old;
//首先读取v这个地址里面的值,首先v这个地址里面的值不能是u,这里u等于0,因为前面已经判断过模块是活动的,因此这c肯定不等于0
// 然后调用atomic_cmpxchg
c = atomic_read(v);
while (c != u && (old = atomic_cmpxchg(v, c, c + a)) != c)
c = old;
return c;
}
#endif
#define atomic_cmpxchg(v, old, new)	(cmpxchg(&((v)->counter), (old), (new)))
#ifndef cmpxchg64_local
#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
#endif

#define cmpxchg(ptr, o, n)	cmpxchg_local((ptr), (o), (n))

static inline u64 __cmpxchg64_local_generic(volatile void *ptr,
u64 old, u64 new)
{
u64 prev;
unsigned long flags;

raw_local_irq_save(flags);
prev = *(u64 *)ptr;
if (prev == old)
*(u64 *)ptr = new;
raw_local_irq_restore(flags);
return prev;
}
原来__cmpxchg64_local_generic的作用首先读取ptr这个地址里面的值,如果这个值等于old,就给ptr 赋值为new,但是返回ptr之前的旧值old
回到__atomic_add_unless 中的atomic_cmpxchg,就是先读取v里面的值,如果值等于1的话,这时c就等于1,然后给v加1,这个时候v里面的值是2,返回c的值,也就是1
最后总结一下:
static inline int atomic_add_unless(atomic_t *v, int a, int u)
{
return __atomic_add_unless(v, a, u) != u;
}
可以简单的认为: @a to @v, so long as @v was not already @u.Returns non-zero if @v was not @u, and zero otherwise.也就是返回非零表示v已经加上a了.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: