https://elixir.bootlin.com/linux/v6.10.3/source/kernel/sched/sched.h#L1795
extern void [**init_numa_balancing**](<https://elixir.bootlin.com/linux/v6.10.3/C/ident/init_numa_balancing>)(unsigned long [**clone_flags**](<https://elixir.bootlin.com/linux/v6.10.3/C/ident/clone_flags>), struct [**task_struct**](<https://elixir.bootlin.com/linux/v6.10.3/C/ident/task_struct>) *p);
https://elixir.bootlin.com/linux/v6.10.3/source/kernel/sched/fair.c#L3442
void init_numa_balancing(unsigned long clone_flags, struct task_struct *p)
{
int mm_users = 0;
struct mm_struct *mm = p->mm;
if (mm) {
mm_users = atomic_read(&mm->mm_users);
if (mm_users == 1) {
mm->numa_next_scan = jiffies + msecs_to_jiffies(sysctl_numa_balancing_scan_delay);
mm->numa_scan_seq = 0;
}
}
p->node_stamp = 0;
p->numa_scan_seq = mm ? mm->numa_scan_seq : 0;
p->numa_scan_period = sysctl_numa_balancing_scan_delay;
p->numa_migrate_retry = 0;
/* Protect against double add, see task_tick_numa and task_numa_work */
p->numa_work.next = &p->numa_work;
p->numa_faults = NULL;
p->numa_pages_migrated = 0;
p->total_numa_faults = 0;
RCU_INIT_POINTER(p->numa_group, NULL);
p->last_task_numa_placement = 0;
p->last_sum_exec_runtime = 0;
init_task_work(&p->numa_work, task_numa_work);
/* New address space, reset the preferred nid */
if (!(clone_flags & CLONE_VM)) {
p->numa_preferred_nid = NUMA_NO_NODE;
return;
}
/*
* New thread, keep existing numa_preferred_nid which should be copied
* already by arch_dup_task_struct but stagger when scans start.
*/
if (mm) {
unsigned int delay;
delay = min_t(unsigned int, task_scan_max(current),
current->numa_scan_period * mm_users * NSEC_PER_MSEC);
delay += 2 * TICK_NSEC;
p->node_stamp = delay;
}
}
새 프로세스를 만들 때, 즉 fork가 일어날 때 일어난다.
callstack
출처 : http://www.iamroot.org/xe/index.php?mid=Note&document_srl=220522
init_numa_balancing(unsigned long clone_flags, struct task_struct *p)
unsigned long clone_flags
: _do_fork()
호출 시 전달되는 인자1가 여기에도 전달