点击(此处)折叠或打开
- /*
- * Iterate task_group tree rooted at *from, calling @down when first entering a
- * node and @up when leaving it for the final time.
- *
- * Caller must hold rcu_lock or sufficient equivalent.
- */
- // 巧妙的树遍历 树的遍历[20141120 gliethttp]
- // O0
- // ↓
- // O1 - O2 - O10 - O11
- // ↓
- // O3 - O6
- // | ↓
- // ↓ O7 - O8 - O9
- // O4 - O5
- // 遍历顺序为<node有children的话, 递归找到该node级联的所有child node的最左侧的node开始遍历>
- // 1. O0 -> down(from = O0)
- // 2. O1 -> down(O0的children, O1临时变为parent)
- // 3. O1 -> up(因为O1没有children), parent回退指向O0, child指向O1, 然后goto up:继续执行O1所在的siblings
- // 4. O2 -> down(O2临时变为parent)
- // 5. O3 -> down(O2的children, O3临时变为parent)
- // 6. O4 -> down(O3的children, O4临时变为parent)
- // 7. O4 -> up(因为O4没有children), parent回退指向O3, child指向O4, 然后goto up:继续执行O4所在的siblings
- // 8. O5 -> down(O4的siblings, O5临时变为parent)
- // 9. O5 -> up(因为O5没有children), parent回退指向O3, child指向O5, 然后goto up:继续执行O5所在的siblings
- //10. O3 -> up(因为O3->children已经到达结尾O5), parent回退指向O2, child指向O3, 然后goto up:继续执行O3所在的siblings
- //11. O6 -> down(O3的siblings, O6临时变为parent)
- //12. O7 -> down(O6的children, O7临时变为parent)
- //13. O7 -> up(因为O7没有children), parent回退指向O6, child指向O7, 然后goto up:继续执行O7所在的siblings
- //14. O8 -> down(O7的siblings, O8临时变为parent)
- //15. O8 -> up(因为O8没有children), parent回退指向O6, child指向O8, 然后goto up:继续执行O8所在的siblings
- //16. O9 -> down(O8的siblings, O9临时变为parent)
- //17. O9 -> up(因为O9没有children), parent回退指向O6, child指向O9, 然后goto up:继续执行O9所在的siblings
- //18. O6 -> up(因为O6->children已经到达结尾O9), parent回退指向O2, child指向O6, 然后goto up:继续执行O6所在的siblings
- //19. O2 -> up(因为O2->children已经到达结尾O6), parent回退指向O0, child指向O2, 然后goto up:继续执行O2所在的siblings
- //20. O10-> down(O2的siblings, O10临时变为parent)
- //21. O10-> up(因为O10没有children), parent回退指向O0, child指向O10, 然后goto up:继续执行O10所在的siblings
- //22. O11-> down(O10的siblings, O11临时变为parent)
- //21. O11-> up(因为O11没有children), parent回退指向O0, child指向O11, 然后goto up:继续执行O11所在的siblings
- //22. O0 -> up(因为O0->children已经到达结尾O11), parent == from, 然后goto out;所以树的遍历至此结束[gliethttp]
- int walk_tg_tree_from(struct task_group *from,
- tg_visitor down, tg_visitor up, void *data)
- {
- struct task_group *parent, *child;
- int ret;
- parent = from;
- down:
- ret = (*down)(parent, data);
- if (ret)
- goto out;
- list_for_each_entry_rcu(child, &parent->children, siblings) {
- parent = child;
- goto down;
- up:
- continue;
- }
- ret = (*up)(parent, data);
- if (ret || parent == from)
- goto out;
- child = parent;
- parent = parent->parent;
- if (parent)
- goto up;
- out:
- return ret;
- }