why sibling list is used to get the task_struct while fetching the children of a process

In order to organize data as linked list using struct list_head you have to declare list root and declare list entry for linkage. Both root and child entries are the same type (struct list_head). children entry of struct task_struct entry is a root. sibling entry of struct task_struct is a list entry. To see the differences, you have to read code, where children and sibling are used. Usage of list_for_each for children means what children is a root. Usage of list_entry for sibling means what sibling is a list entry.

You can read more about linux kernel lists here.

Question: What is the reason we are passing "sibling" here which eventually a different list with different offset?

Answer:

If the list was created this way:

list_add(&subtask->sibling, &current->children);

Than

list_for_each(list, &current->children)

Will initialize list pointers to sibling, so you have to use subling as parameter to list_entry. That's how linux kernel lists API designed.

But, If the list was created in another (wrong) way:

list_add(&subtask->children, &current->sibling);

Than you have to iterate the list this (wrong) way:

list_for_each(list, &current->sibling)

And now you have to use children as parameter for list_entry.

Hope, this helps.


Following is the pictorial representation that might help someone in future. The top box represents a parent, and the bottom two boxes are it's children

enter image description here


Here is a picture in addition to the previous answers. The same process can be both a parent and a child (as Parent1 on the picture), and we need to distinguish between these two roles.

Intuitively, if children of Parent0 would point to children of Parent1, then Parent0.children.next->next (green circle on the picture), which is the same as Parent1.children.next, would point to a child of Parent1 instead of a next child of Parent0.

enter image description here