Migration is when a thread, usually after a context switch, receives a scheduled schedule on a different processor than previously planned.
EDIT 1 :
Read more about Wikipedia on migration: https://en.wikipedia.org/wiki/Process_migration
Here is the kernel code incrementing the counter: https://github.com/torvalds/linux/blob/master/kernel/sched/core.c#L1175
if (task_cpu(p) != new_cpu) { ... p->se.nr_migrations++;
EDIT 2 :
A thread can go to another CPU in the following cases:
- During
exec() - During
fork() - While waking up a stream.
- If the thread merge mask has changed.
- When the current processor goes offline.
For more information, check out the set_task_cpu() , move_queued_task() , migrate_tasks() functions in the same source file: https://github.com/torvalds/linux/blob/master/kernel/sched/core.c
Listed below are the policy planners in select_task_rq() , which depend on the scheduler class you are using. The main version of the policeman:
if (p->nr_cpus_allowed > 1) cpu = p->sched_class->select_task_rq(p, cpu, sd_flags, wake_flags); else cpu = cpumask_any(&p->cpus_allowed);
Source: https://github.com/torvalds/linux/blob/master/kernel/sched/core.c#L1534
So, to avoid migration, set the processor affinity mask for your threads using the sched_setaffinity(2) system call or the corresponding POSIX API pthread_setaffinity_np(3) .
Here is the definition of select_task_rq () for a completely fair scheduler: https://github.com/torvalds/linux/blob/master/kernel/sched/fair.c#L5860
The logic is quite complicated, but basically we either select the sibling idle CPU or find the least loaded new one.
Hope this answers your question.