contributed by < wang0630
>
Instead of using a function, using a macro has several advantages, including:
The program is slightly faster. Function calls often requires additional care, such as storing the old context in registers for later return, copying arguments and return values of a function, etc.
Note. this overhead can be dealed with inline keyword in C99 standard.
Macros accept most of types as their arguments. However, functions often only take particular types, making the latter is less generic than the former.
A interesting thing pointed out by https://notes.shichao.io/lkd/ch6/
We tend to define a node like this:
but linux kernel defines linked list as follow:
linux version of linked list wraps all elements to one nice and simple data structure.
The relationship can be described as:
ex. process a has process b,c as children
To iterate through the whole list of example above, we use the macro defined in linux/list.h
How does CFS determine a nice value to a task?
A nice value is defined by the vruntime field in the struct sched_entity
:
According to Operating system concept, ninth edition, sched_entity is the basic unit in linux CFS algorithm, and it is used to track how much time a task has been running by storing the virtual run time in vruntime field.
The virtual run time is associated to with a decay factor based on the priority of a task. lower-priority tasks have higher decay factor; hence, it's vruntime will grow and drop more rapidly than that of higher-priority tasks. For example, a normal task with nice value zero(default) has run for 200ms, and its vruntime will also be 200ms. However, if a lower-priority task runs for 200ms, its vruntime will be more than 200ms and vice versa.
For linked list usage, CFS keeps every running tasks in a red-black tree whose key is based on the value of vruntime. To select the next task to run, CFS simply chooses the task with the smallest vruntime, which will be the leftmost task in the RB-tree; Even more, since traversing through the whole RB tree takes complexity of O(logn), linux keeps a reference of the task with the smallest vruntime value in the field called rb_leftmost
linux keeps sched_entity
inside a queue called cfs_rq
, and use struct sched_entity __pick_next_entity
to pick next entity to run:
Enqueueing a new task by using __enqueue_entity