/*
* klist.c - Routines for manipulating klists.
*
* Copyright (C) 2005 Patrick Mochel
*
* This file is released under the GPL v2.
*
* This klist interface provides a couple of structures that wrap around
* struct list_head to provide explicit list "head" (struct klist) and list
* "node" (struct klist_node) objects. For struct klist, a spinlock is
* included that protects access to the actual list itself. struct
* klist_node provides a pointer to the klist that owns it and a kref
* reference count that indicates the number of current users of that node
* in the list.
*
* The entire point is to provide an interface for iterating over a list
* that is safe and allows for modification of the list during the
* iteration (e.g. insertion and removal), including modification of the
* current node on the list.
*
* It works using a 3rd object type - struct klist_iter - that is declared
* and initialized before an iteration. klist_next() is used to acquire the
* next element in the list. It returns NULL if there are no more items.
* Internally, that routine takes the klist's lock, decrements the
* reference count of the previous klist_node and increments the count of
* the next klist_node. It then drops the lock and returns.
*
* There are primitives for adding and removing nodes to/from a klist.
* When deleting, klist_del() will simply decrement the reference count.
* Only when the count goes to 0 is the node removed from the list.
* klist_remove() will try to delete the node from the list and block until
* it is actually removed. This is useful for objects (like devices) that
* have been removed from the system and must be freed (but must wait until
* all accessors have finished).
*/
#include <linux/klist.h>
#include <linux/export.h>
#include <linux/sched.h>
/*
* Use the lowest bit of n_klist to mark deleted nodes and exclude
* dead ones from iteration.
*/
#define KNODE_DEAD 1LU
#define KNODE_KLIST_MASK ~KNODE_DEAD
static struct klist *knode_klist(struct klist_node *knode) //返回klist_node中的klist成员
{
return (struct klist *)
((unsigned long)knode->n_klist & KNODE_KLIST_MASK);//清零最低位 因为klist是4字节对齐,所以最低位为0
}
static bool knode_dead(struct klist_node *knode) //判断knode是否已经死亡(请求删除)
{
return (unsigned long)knode->n_klist & KNODE_DEAD; //判断knode中的n_klist的最低位是否为1,如果是1则已死亡
}
static void knode_set_klist(struct klist_node *knode, struct klist *klist) //设置klist_node中的n_klist成员
{
knode->n_klist = klist; //将knode->n_klist设置为传入的参数klist
/* no knode deserves to start its life dead */
WARN_ON(knode_dead(knode)); //如果knode已经被请求删除,则发出警告,内核还是继续运行
}
static void knode_kill(struct klist_node *knode) //将节点请求删除
{
/* and no knode should die twice ever either, see we're very humane */
WARN_ON(knode_dead(knode)); //如果节点已经被请求删除,则发出警告,内核继续运行
*(unsigned long *)&knode->n_klist |= KNODE_DEAD; //将knode->n_klist的最低位置1
}
/**
* klist_init - Initialize a klist structure.
* @k: The klist we're initializing.
* @get: The get function for the embedding object (NULL if none)
* @put: The put function for the embedding object (NULL if none)
*
* Initialises the klist structure. If the klist_node structures are
* going to be embedded in refcounted objects (necessary for safe
* deletion) then the get/put arguments are used to initialise
* functions that take and release references on the embedding
* objects.
*/
void klist_init(struct klist *k, void (*get)(struct klist_node *), //初始化一个klist
void (*put)(struct klist_node *))
{
INIT_LIST_HEAD(&k->k_list); //将k->k_list初始化,即将k->k_list->prev,next均指向自身
spin_lock_init(&k->k_lock); //初始化k中的自旋锁成员
k->get = get; //初始化k中的get函数和put函数
k->put = put;
}
EXPORT_SYMBOL_GPL(klist_init);
static void add_head(struct klist *k, struct klist_node *n) //将n链接到k的头部
{
spin_lock(&k->k_lock); //上锁
list_add(&n->n_node, &k->k_list); //通过k,n中的list_head成员进行连接
spin_unlock(&k->k_lock); //解锁
}
static void add_tail(struct klist *k, struct klist_node *n) //同上,只不过是将n链接到k的尾部
{
spin_lock(&k->k_lock);
list_add_tail(&n->n_node, &k->k_list);
spin_unlock(&k->k_lock);
}
static void klist_node_init(struct klist *k, struct klist_node *n) //knode初始化
{
INIT_LIST_HEAD(&n->n_node); //将k中的list_head成员初始化,指向自身
kref_init(&n->n_ref); //初始化k中的n_ref成员,计数值置1
knode_set_klist(n, k); //将n中的n->n_klist设置为k
if (k->get) //搞清楚klist里面的get和put到底是干嘛的 //如果get成员存在,则执行get函数
k->get(n);
}
/**
* klist_add_head - Initialize a klist_node and add it to front.
* @n: node we're adding.
* @k: klist it's going on.
*/
void klist_add_head(struct klist_node *n, struct klist *k) //1.调用klist_node_init将knode初始化(初始化knode中的n_node成员和n->n_ref成员)
{ //2.将knode插入到klist的头部
klist_node_init(k, n);
add_head(k, n);
}
EXPORT_SYMBOL_GPL(klist_add_head);
/**
* klist_add_tail - Initialize a klist_node and add it to back.
* @n: node we're adding.
* @k: klist it's going on.
*/
void klist_add_tail(struct klist_node *n, struct klist *k) //同上,只不过是加到尾部
{
klist_node_init(k, n);
add_tail(k, n);
}
EXPORT_SYMBOL_GPL(klist_add_tail);
/**
* klist_add_behind - Init a klist_node and add it after an existing node
* @n: node we're adding.
* @pos: node to put @n after
*/
void klist_add_behind(struct klist_node *n, struct klist_node *pos) //将n加到pos的后面
{
struct klist *k = knode_klist(pos); //获取pos所在的klist
klist_node_init(k, n); //初始化n
spin_lock(&k->k_lock); //上锁
list_add(&n->n_node, &pos->n_node); //将n中的n_node加入到pos中的n_node之后
spin_unlock(&k->k_lock); //解锁
}
EXPORT_SYMBOL_GPL(klist_add_behind);
/**
* klist_add_before - Init a klist_node and add it before an existing node
* @n: node we're adding.
* @pos: node to put @n after
*/
void klist_add_before(struct klist_node *n, struct klist_node *pos) //同上 加到前面
{
struct klist *k = knode_klist(pos);
klist_node_init(k, n);
spin_lock(&k->k_lock);
list_add_tail(&n->n_node, &pos->n_node);
spin_unlock(&k->k_lock);
}
EXPORT_SYMBOL_GPL(klist_add_before);
struct klist_waiter {
struct list_head list;
struct klist_node *node;
struct task_struct *process;
int woken;
};
static DEFINE_SPINLOCK(klist_remove_lock);
static LIST_HEAD(klist_remove_waiters); //==>static struct list_head klist_remove_waiters = {&klist_remove_waiters,&klist_remove_waiters};
static void klist_release(struct kref *kref)
{
struct klist_waiter *waiter, *tmp; //定义两个klist_waiter结构体 waiter用做轮询,tmp用作list_for_each_entry_safe的安全检查
struct klist_node *n = container_of(kref, struct klist_node, n_ref); //获取kref所在的klist_node n
WARN_ON(!knode_dead(n)); //当节点已经被请求删除时,发出警告
list_del(&n->n_node); //首先把n->n_node从所在的链表删除
spin_lock(&klist_remove_lock); //上锁
list_for_each_entry_safe(waiter, tmp, &klist_remove_waiters, list) { //1.寻找knode所在klist_waiter结构体(之前已经被请求删除了,被加入了klist_waiter体中,请求删除的线程被阻塞)
if (waiter->node != n) //2.如果找到了,就在该waiter从所在的链表中删除
continue; //3.将waiter中的woken成员置1
//4.保护
list_del(&waiter->list); //5.唤醒被阻塞的线程
waiter->woken = 1;
mb();
wake_up_process(waiter->process);
}
spin_unlock(&klist_remove_lock); //解锁
knode_set_klist(n, NULL); //将n中的n->klist指向为空
}
static int klist_dec_and_del(struct klist_node *n) // 调用kref_put将n的应用计数减一,如果为0,调用上面的klist_release
{
return kref_put(&n->n_ref, klist_release);
}
static void klist_put(struct klist_node *n, bool kill)
{
struct klist *k = knode_klist(n); //获得n所在klist给k
void (*put)(struct klist_node *) = k->put; //获得k中的put函数给put
spin_lock(&k->k_lock); //上锁
if (kill) //如果kill为真
knode_kill(n); //将n杀死
if (!klist_dec_and_del(n)) //将n->n_ref减1,如果已经减到0了(执行了klist_release)返回1,不然就是返回0
put = NULL; //case 1:返回0说明kref不为0,还有数据结构在使用它,将put=null,不执行k->put;
spin_unlock(&k->k_lock); //case 2: 返回1说明kref为0了,klist_release已经执行,这时候需要执行k->put;
if (put)
put(n);
}
/**
* klist_del - Decrement the reference count of node and try to remove. //减少节点的应用次数,并且尝试删除
* @n: node we're deleting.
*/
void klist_del(struct klist_node *n) //调用上面的函数 将kill == true
{
klist_put(n, true);
}
EXPORT_SYMBOL_GPL(klist_del);
/**
* klist_remove - Decrement the refcount of node and wait for it to go away.
* @n: node we're removing.
*/
void klist_remove(struct klist_node *n) //klistremove,提供给外部的API(没有static)
{
struct klist_waiter waiter; //首先定义了一个klist_waiter结构体
waiter.node = n; //用要删除的n来给waiter中的node赋值
waiter.process = current; //用当前线程的tast_struct给process赋值
waiter.woken = 0; //woken == 0;
spin_lock(&klist_remove_lock);
list_add(&waiter.list, &klist_remove_waiters); //将这个waiter加入到等待删除的waiter中
spin_unlock(&klist_remove_lock);
klist_del(n); //尝试删除这个knode
for (;;) { //无限循环
set_current_state(TASK_UNINTERRUPTIBLE); //设置当前线程为不可打断状态,阻塞
if (waiter.woken) //当线程被唤醒时检查woken是否为0;这句话是防止当前线程刚进入睡眠态之前,woken就已经变成1了
break;
schedule(); //调度
}
__set_current_state(TASK_RUNNING); //设置当前任务为运行态
}
EXPORT_SYMBOL_GPL(klist_remove);
/**
* klist_node_attached - Say whether a node is bound to a list or not.
* @n: Node that we're testing.
*/
int klist_node_attached(struct klist_node *n) //返回knode是否被绑定到一个klist上
{
return (n->n_klist != NULL);
}
EXPORT_SYMBOL_GPL(klist_node_attached);
/**
* klist_iter_init_node - Initialize a klist_iter structure. //初始化一个klist_iter结构体
* @k: klist we're iterating. //我们要迭代的klist
* @i: klist_iter we're filling. //我们要填充的klist_iter
* @n: node to start with. //开始跌迭代的节点
*
* Similar to klist_iter_init(), but starts the action off with @n,
* instead of with the list head.
*/
void klist_iter_init_node(struct klist *k, struct klist_iter *i,
struct klist_node *n)
{
i->i_klist = k; //用传入参数初始化klist_iter
i->i_cur = n;
if (n) //如果n存在,把n的引用次数加一
kref_get(&n->n_ref);
}
EXPORT_SYMBOL_GPL(klist_iter_init_node);
/**
* klist_iter_init - Iniitalize a klist_iter structure.
* @k: klist we're iterating.
* @i: klist_iter structure we're filling.
*
* Similar to klist_iter_init_node(), but start with the list head.
*/
void klist_iter_init(struct klist *k, struct klist_iter *i) //和上面类似,不过这个函数是从链表头开始的
{
klist_iter_init_node(k, i, NULL);
}
EXPORT_SYMBOL_GPL(klist_iter_init);
/**
* klist_iter_exit - Finish a list iteration.
* @i: Iterator structure.
*
* Must be called when done iterating over list, as it decrements the
* refcount of the current node. Necessary in case iteration exited before
* the end of the list was reached, and always good form.
*/
void klist_iter_exit(struct klist_iter *i) //这个函数主要是在迭代结束时,将kref减一,如果没有迭代到链表末尾则一定要调用,如果到了链表末尾,则无所谓调不调用
{
if (i->i_cur) {
klist_put(i->i_cur, false);
i->i_cur = NULL;
}
}
EXPORT_SYMBOL_GPL(klist_iter_exit);
static struct klist_node *to_klist_node(struct list_head *n)
{
return container_of(n, struct klist_node, n_node);
}
/**
* klist_next - Ante up next node in list.
* @i: Iterator structure.
*
* First grab list lock. Decrement the reference count of the previous
* node, if there was one. Grab the next node, increment its reference
* count, drop the lock, and return that next node.
*/
struct klist_node *klist_next(struct klist_iter *i)
{
void (*put)(struct klist_node *) = i->i_klist->put; //首先或者这个要迭代的knode所在的klist的put函数
struct klist_node *last = i->i_cur; //last指向当前跌代到的knode
struct klist_node *next; //next用来返回要访问的下一个knode
spin_lock(&i->i_klist->k_lock); //上锁
if (last) { //如果last存在,next就等于last所在klist的下一个knode
next = to_klist_node(last->n_node.next); //把last的kref减一
if (!klist_dec_and_del(last)) //如果last的kref变成0即已经被删除了,put == NULL
put = NULL;
} else
next = to_klist_node(i->i_klist->k_list.next);//如果last不存在,说明要从链表头开始遍历
i->i_cur = NULL; //把当前的klist_iter的i_cur置NULL
while (next != to_klist_node(&i->i_klist->k_list)) { //如果next knode不是没有被请求删除,把knode的ref加1,同时
if (likely(!knode_dead(next))) { //将遍历结构体的i_cur设置为nest,跳出循环
kref_get(&next->n_ref);
i->i_cur = next;
break;
}
next = to_klist_node(next->n_node.next);
}
spin_unlock(&i->i_klist->k_lock); //解锁
if (put && last) //如果put和last同时存在,说明last已经已经被删除了,执行put
put(last);
return i->i_cur;
}
EXPORT_SYMBOL_GPL(klist_next);
/* likely()与unlikely()在2.6内核中,随处可见,那为什么要用它们?它们之间有什么区别呢?
首先明确:
if (likely(value))等价于if (value)
if (unlikely(value))等价于if (value)
也就是说likely()和unlikely()从阅读和理解的角度是一样的。
这两个宏在内核中定义如下:
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
这里的__built_expect()函数是gcc(version >= 2.96)的内建函数,提供给程序员使用的,目的是将"分支转移"的信息提供给编译器,这样编译器对代码进行优化,以减少指令跳转带来的性能下降。
__buildin_expect((x), 1)表示x的值为真的可能性更大.
__buildin_expect((x), 0)表示x的值为假的可能性更大.
也就是说,使用likely(),执行if后面的语句的机会更大,使用unlikely(),执行else后面的语句机会更大一些。通过这种方式,编译器在编译过程中,会将可能性更大的代 */
自己查资料写的注释,有大佬看到的话,欢迎指出里面的漏误