天津网站建设怎么样,网站建设公司广州增城,星链seo管理,怎么介绍自己的名字四、调度域
SDTL结构
linux内核使用SDTL结构体来组织CPU的层次关系
struct sched_domain_topology_level {sched_domain_mask_f mask; //函数指针#xff0c;用于指定某个SDTL的cpumask位图sched_domain_flags_f sd_flags; //函数指针#xff0c;用于指定某个SD…四、调度域
SDTL结构
linux内核使用SDTL结构体来组织CPU的层次关系
struct sched_domain_topology_level {sched_domain_mask_f mask; //函数指针用于指定某个SDTL的cpumask位图sched_domain_flags_f sd_flags; //函数指针用于指定某个SDTL的标志位int flags; int numa_level;struct sd_data data;
#ifdef CONFIG_SCHED_DEBUGchar *name;
#endif
};标志位
#define SD_BALANCE_NEWIDLE 0x0001 /* Balance when about to become idle */
#define SD_BALANCE_EXEC 0x0002 /* Balance on exec */
#define SD_BALANCE_FORK 0x0004 /* Balance on fork, clone */
#define SD_BALANCE_WAKE 0x0008 /* Balance on wakeup */
#define SD_WAKE_AFFINE 0x0010 /* Wake task to waking CPU */
#define SD_ASYM_CPUCAPACITY 0x0020 /* Domain members have different CPU capacities */
#define SD_SHARE_CPUCAPACITY 0x0040 /* Domain members share CPU capacity */
#define SD_SHARE_POWERDOMAIN 0x0080 /* Domain members share power domain */
#define SD_SHARE_PKG_RESOURCES 0x0100 /* Domain members share CPU pkg resources */
#define SD_SERIALIZE 0x0200 /* Only a single load balancing instance */
#define SD_ASYM_PACKING 0x0400 /* Place busy groups earlier in the domain */
#define SD_PREFER_SIBLING 0x0800 /* Prefer to place tasks in a sibling domain */
#define SD_OVERLAP 0x1000 /* sched_domains of this level overlap */
#define SD_NUMA 0x2000 /* cross-node balancing */SD_BALANCE_NEWIDLE当CPU变为空闲后做负载均衡调度SD_BALANCE_EXEC进程调用exec是会重新选择一个最优的CPU的来执行参考sched_exec()函数SD_BALANCE_FORKfork出新进程后会选择最优CPU参考wake_up_new_task()函数SD_BALANCE_WAKE唤醒时负载均衡参考wake_up_process()函数SD_WAKE_AFFINE支持wake affine特性SD_ASYM_CPUCAPACITY该调度域有不同架构的CPU如大/小核cpuSD_SHARE_CPUCAPACITY调度域中的CPU都是可以共享CPU资源的描述SMT调度层级SD_SHARE_POWERDOMAIN该调度域中的CPU可以共享电源域SD_SHARE_PKG_RESOURCES该调度域中的CPU可以共享高速缓存SD_ASYM_PACKING描述SMT调度层级相关的一些例外SD_NUMA描述NUMA调度层级SD_SERIALIZESD_OVERLAPSD_PREFER_SIBLING
调度组是负载均衡的最小单位。
五、CPU调度域拓扑
CPU的调度域拓扑结构可以参考以下三张图图来自互联网
六、负载均衡
load-balance的逻辑比较复杂可以参考我整理的如下图的整体逻辑框架
lb_env()结构体
struct lb_env {struct sched_domain *sd;struct rq *src_rq;int src_cpu;int dst_cpu;struct rq *dst_rq;struct cpumask *dst_grpmask;int new_dst_cpu;enum cpu_idle_type idle;long imbalance;/* The set of CPUs under consideration for load-balancing */struct cpumask *cpus;unsigned int flags;unsigned int loop;unsigned int loop_break;unsigned int loop_max;enum fbq_type fbq_type;enum migration_type migration_type;struct list_head tasks;
};类型成员作用struct sched_domain *sd指向当前调度域intdst_cpu当前CPU(后续可能要把任务迁移到该CPU上)struct rq*dst_rq当前CPU对应的就绪度列struct cpumask *dst_grpmask当前调度域里的第一个调度组的CPU位图unsigned intloop_break表示本地最多迁移32个进程(sched_nr_migrate_break默认值是32)struct cpumask *cpusload_balance_mask位图
find_busiest_group()函数
首先是两个数据结构
sd_lb_stats 用于描述调度域里的相关信息以及sg_lb_stats用于描述调度组里的相关信息
/** sd_lb_stats - Structure to store the statistics of a sched_domain* during load balancing.*/
struct sd_lb_stats {struct sched_group *busiest; /* Busiest group in this sd */struct sched_group *local; /* Local group in this sd */unsigned long total_load; /* Total load of all groups in sd */unsigned long total_capacity; /* Total capacity of all groups in sd */unsigned long avg_load; /* Average load across all groups in sd */unsigned int prefer_sibling; /* tasks should go to sibling first */struct sg_lb_stats busiest_stat;/* Statistics of the busiest group */struct sg_lb_stats local_stat; /* Statistics of the local group */
};/** sg_lb_stats - stats of a sched_group required for load_balancing*/
struct sg_lb_stats {unsigned long avg_load; /*Avg load across the CPUs of the group */unsigned long group_load; /* Total load over the CPUs of the group */unsigned long group_capacity;unsigned long group_util; /* Total utilization over the CPUs of the group */unsigned long group_runnable; /* Total runnable time over the CPUs of the group */unsigned int sum_nr_running; /* Nr of tasks running in the group */unsigned int sum_h_nr_running; /* Nr of CFS tasks running in the group */unsigned int idle_cpus;unsigned int group_weight;enum group_type group_type;unsigned int group_asym_packing; /* Tasks should be moved to preferred CPU */unsigned long group_misfit_task_load; /* A CPU has a task too big for its capacity */
#ifdef CONFIG_NUMA_BALANCINGunsigned int nr_numa_running;unsigned int nr_preferred_running;
#endif
};6.1 负载均衡机制的触发
负载均衡机制是从注册软中断开始的
6.1.1 软中断注册
#mermaid-svg-KCdGnNT0ZDwGO6aN {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-KCdGnNT0ZDwGO6aN .error-icon{fill:#552222;}#mermaid-svg-KCdGnNT0ZDwGO6aN .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-KCdGnNT0ZDwGO6aN .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-KCdGnNT0ZDwGO6aN .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-KCdGnNT0ZDwGO6aN .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-KCdGnNT0ZDwGO6aN .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-KCdGnNT0ZDwGO6aN .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-KCdGnNT0ZDwGO6aN .marker{fill:#333333;stroke:#333333;}#mermaid-svg-KCdGnNT0ZDwGO6aN .marker.cross{stroke:#333333;}#mermaid-svg-KCdGnNT0ZDwGO6aN svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-KCdGnNT0ZDwGO6aN .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-KCdGnNT0ZDwGO6aN .cluster-label text{fill:#333;}#mermaid-svg-KCdGnNT0ZDwGO6aN .cluster-label span{color:#333;}#mermaid-svg-KCdGnNT0ZDwGO6aN .label text,#mermaid-svg-KCdGnNT0ZDwGO6aN span{fill:#333;color:#333;}#mermaid-svg-KCdGnNT0ZDwGO6aN .node rect,#mermaid-svg-KCdGnNT0ZDwGO6aN .node circle,#mermaid-svg-KCdGnNT0ZDwGO6aN .node ellipse,#mermaid-svg-KCdGnNT0ZDwGO6aN .node polygon,#mermaid-svg-KCdGnNT0ZDwGO6aN .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-KCdGnNT0ZDwGO6aN .node .label{text-align:center;}#mermaid-svg-KCdGnNT0ZDwGO6aN .node.clickable{cursor:pointer;}#mermaid-svg-KCdGnNT0ZDwGO6aN .arrowheadPath{fill:#333333;}#mermaid-svg-KCdGnNT0ZDwGO6aN .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-KCdGnNT0ZDwGO6aN .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-KCdGnNT0ZDwGO6aN .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-KCdGnNT0ZDwGO6aN .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-KCdGnNT0ZDwGO6aN .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-KCdGnNT0ZDwGO6aN .cluster text{fill:#333;}#mermaid-svg-KCdGnNT0ZDwGO6aN .cluster span{color:#333;}#mermaid-svg-KCdGnNT0ZDwGO6aN div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-KCdGnNT0ZDwGO6aN :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}start_kernelsched_initinit_sched_fair_classopen_softirq注册SCHED_SOFTIRQrun_rebalance_domainsrest_initkenrel_init, 1号进程kernel_init_freeablesmp_initidle_initBringing up secondary CPUs...__init void init_sched_fair_class(void)
{
#ifdef CONFIG_SMPopen_softirq(SCHED_SOFTIRQ, run_rebalance_domains);#ifdef CONFIG_NO_HZ_COMMONnohz.next_balance jiffies;nohz.next_blocked jiffies;zalloc_cpumask_var(nohz.idle_cpus_mask, GFP_NOWAIT);
#endif
#endif /* SMP */
}void open_softirq(int nr, void (*action)(struct softirq_action *))
{softirq_vec[nr].action action;
}注册了SCHED_SOFTIRQ的软中断中断处理函数是run_rebalance_domains。
6.1.2 软中断触发
由scheduler_tick()在每个时钟节拍中会去检查是否需要load balance。
#mermaid-svg-lxdtUw2wM8syKGWo {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-lxdtUw2wM8syKGWo .error-icon{fill:#552222;}#mermaid-svg-lxdtUw2wM8syKGWo .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-lxdtUw2wM8syKGWo .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-lxdtUw2wM8syKGWo .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-lxdtUw2wM8syKGWo .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-lxdtUw2wM8syKGWo .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-lxdtUw2wM8syKGWo .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-lxdtUw2wM8syKGWo .marker{fill:#333333;stroke:#333333;}#mermaid-svg-lxdtUw2wM8syKGWo .marker.cross{stroke:#333333;}#mermaid-svg-lxdtUw2wM8syKGWo svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-lxdtUw2wM8syKGWo .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-lxdtUw2wM8syKGWo .cluster-label text{fill:#333;}#mermaid-svg-lxdtUw2wM8syKGWo .cluster-label span{color:#333;}#mermaid-svg-lxdtUw2wM8syKGWo .label text,#mermaid-svg-lxdtUw2wM8syKGWo span{fill:#333;color:#333;}#mermaid-svg-lxdtUw2wM8syKGWo .node rect,#mermaid-svg-lxdtUw2wM8syKGWo .node circle,#mermaid-svg-lxdtUw2wM8syKGWo .node ellipse,#mermaid-svg-lxdtUw2wM8syKGWo .node polygon,#mermaid-svg-lxdtUw2wM8syKGWo .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-lxdtUw2wM8syKGWo .node .label{text-align:center;}#mermaid-svg-lxdtUw2wM8syKGWo .node.clickable{cursor:pointer;}#mermaid-svg-lxdtUw2wM8syKGWo .arrowheadPath{fill:#333333;}#mermaid-svg-lxdtUw2wM8syKGWo .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-lxdtUw2wM8syKGWo .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-lxdtUw2wM8syKGWo .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-lxdtUw2wM8syKGWo .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-lxdtUw2wM8syKGWo .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-lxdtUw2wM8syKGWo .cluster text{fill:#333;}#mermaid-svg-lxdtUw2wM8syKGWo .cluster span{color:#333;}#mermaid-svg-lxdtUw2wM8syKGWo div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-lxdtUw2wM8syKGWo :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}scheduler_ticktrigger_load_balanceraise_softirqnohz_balancer_kick/** Trigger the SCHED_SOFTIRQ if it is time to do periodic load balancing.*/
void trigger_load_balance(struct rq *rq)
{/* Dont need to rebalance while attached to NULL domain */if (unlikely(on_null_domain(rq)))return;if (time_after_eq(jiffies, rq-next_balance)) //需要判断是否到了负载均衡的时间点raise_softirq(SCHED_SOFTIRQ);nohz_balancer_kick(rq); //该函数作用是什么
}nohz_balancer_kick用来触发nohz idle balance的这是后面两个章节要仔细描述的内容。这里看起似乎注释不对因为这个函数不但触发的周期性均衡也触发了nohz idle balance。然而其实nohz idle balance本质上也是另外一种意义上的周期性负载均衡只是因为CPU进入idle无法产生tick因此让能产生tick的busy CPU来帮忙触发tick balance。而实际上tick balance和nohz idle balance都是通过SCHED_SOFTIRQ的软中断来处理最后都是执run_rebalance_domains这个函数。
七、exec进程
#mermaid-svg-mUDh5qMPNEQrv4k8 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-mUDh5qMPNEQrv4k8 .error-icon{fill:#552222;}#mermaid-svg-mUDh5qMPNEQrv4k8 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-mUDh5qMPNEQrv4k8 .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-mUDh5qMPNEQrv4k8 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-mUDh5qMPNEQrv4k8 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-mUDh5qMPNEQrv4k8 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-mUDh5qMPNEQrv4k8 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-mUDh5qMPNEQrv4k8 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-mUDh5qMPNEQrv4k8 .marker.cross{stroke:#333333;}#mermaid-svg-mUDh5qMPNEQrv4k8 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-mUDh5qMPNEQrv4k8 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-mUDh5qMPNEQrv4k8 .cluster-label text{fill:#333;}#mermaid-svg-mUDh5qMPNEQrv4k8 .cluster-label span{color:#333;}#mermaid-svg-mUDh5qMPNEQrv4k8 .label text,#mermaid-svg-mUDh5qMPNEQrv4k8 span{fill:#333;color:#333;}#mermaid-svg-mUDh5qMPNEQrv4k8 .node rect,#mermaid-svg-mUDh5qMPNEQrv4k8 .node circle,#mermaid-svg-mUDh5qMPNEQrv4k8 .node ellipse,#mermaid-svg-mUDh5qMPNEQrv4k8 .node polygon,#mermaid-svg-mUDh5qMPNEQrv4k8 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-mUDh5qMPNEQrv4k8 .node .label{text-align:center;}#mermaid-svg-mUDh5qMPNEQrv4k8 .node.clickable{cursor:pointer;}#mermaid-svg-mUDh5qMPNEQrv4k8 .arrowheadPath{fill:#333333;}#mermaid-svg-mUDh5qMPNEQrv4k8 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-mUDh5qMPNEQrv4k8 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-mUDh5qMPNEQrv4k8 .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-mUDh5qMPNEQrv4k8 .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-mUDh5qMPNEQrv4k8 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-mUDh5qMPNEQrv4k8 .cluster text{fill:#333;}#mermaid-svg-mUDh5qMPNEQrv4k8 .cluster span{color:#333;}#mermaid-svg-mUDh5qMPNEQrv4k8 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-mUDh5qMPNEQrv4k8 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}core.csched_classselect task rq函数, fair.c, rt.c, deadline.c, stoptask.c/** sched_exec - execve() is a valuable balancing opportunity, because at* this point the task has the smallest effective memory and cache footprint.*/
void sched_exec(void)
{struct task_struct *p current;unsigned long flags;int dest_cpu;raw_spin_lock_irqsave(p-pi_lock, flags); //这里获取了p-pi_lock,后面migration_cpu_stop中会涉及该锁dest_cpu p-sched_class-select_task_rq(p, task_cpu(p), SD_BALANCE_EXEC, 0); //这里选择目的cpuif (dest_cpu smp_processor_id()) //如果dest_cpu就是当前cpu可以释放锁并返回goto unlock;if (likely(cpu_active(dest_cpu))) {struct migration_arg arg { p, dest_cpu };raw_spin_unlock_irqrestore(p-pi_lock, flags);stop_one_cpu(task_cpu(p), migration_cpu_stop, arg); //这里进行目的cpu的进程迁移return;}
unlock:raw_spin_unlock_irqrestore(p-pi_lock, flags);
}stop_one_cpu(task_cpu(p), migration_cpu_stop, arg);这句函数的作用是什么。
stop_one_cpu是停止某个cpu的运行非SMP和SMP下实现不一样。非SMP下stop_one_cpu的实现其实就是关抢占、执行函数、开抢占。
SMP架构下stop_one_cpu实现
该函数是在执行完函数fn之后再返回但是不能保证执行fn的时候cpu还一直在线。
int stop_one_cpu(unsigned int cpu, cpu_stop_fn_t fn, void *arg)
{struct cpu_stop_done done;struct cpu_stop_work work { .fn fn, .arg arg, .done done };cpu_stop_init_done(done, 1);if (!cpu_stop_queue_work(cpu, work))return -ENOENT;/** In case cpu smp_proccessor_id() we can avoid a sleepwakeup* cycle by doing a preemption:*/cond_resched();wait_for_completion(done.completion);return done.ret;
}migration_cpu_stop函数
主要是两个拿锁的地方未能理解为何需要那样的判断rq-lock以及p-pi_lock
/** migration_cpu_stop - this will be executed by a highprio stopper thread* and performs thread migration by bumping thread off CPU then* pushing onto another runqueue.*/
static int migration_cpu_stop(void *data)
{struct migration_arg *arg data;struct task_struct *p arg-task;struct rq *rq this_rq();struct rq_flags rf;/** The original target CPU might have gone down and we might* be on another CPU but it doesnt matter.*/local_irq_disable();/** We need to explicitly wake pending tasks before running* __migrate_task() such that we will not miss enforcing cpus_ptr* during wakeups, see set_cpus_allowed_ptr()s TASK_WAKING test.*/flush_smp_call_function_from_idle();raw_spin_lock(p-pi_lock);rq_lock(rq, rf);/* 这个地方为何一定要task_rq rq才能去迁移呢rq是当前正在执行任务的cpu的rq其rq-lock拿着与task_rq(p) ! rq有何冲突没能理解。会不会是迁移操作时需要获取p所在rq的lock以及目标rq的lock那样的话假设task_rq(p)不等于rq拿两个rq-lock不就好了* If task_rq(p) ! rq, it cannot be migrated here, because were* holding rq-lock, if p-on_rq 0 it cannot get enqueued because* were holding p-pi_lock.*/if (task_rq(p) rq) { //必须是p所在的rq与当前cpu的rq是同一个才能迁移if (task_on_rq_queued(p)) //必须p是on rq才能迁移rq __migrate_task(rq, rf, p, arg-dest_cpu);elsep-wake_cpu arg-dest_cpu;}rq_unlock(rq, rf);raw_spin_unlock(p-pi_lock);local_irq_enable();return 0;
}八、fork进程
#mermaid-svg-Zk5xRxIeyTa7jAKi {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-Zk5xRxIeyTa7jAKi .error-icon{fill:#552222;}#mermaid-svg-Zk5xRxIeyTa7jAKi .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Zk5xRxIeyTa7jAKi .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-Zk5xRxIeyTa7jAKi .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Zk5xRxIeyTa7jAKi .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Zk5xRxIeyTa7jAKi .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Zk5xRxIeyTa7jAKi .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Zk5xRxIeyTa7jAKi .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Zk5xRxIeyTa7jAKi .marker.cross{stroke:#333333;}#mermaid-svg-Zk5xRxIeyTa7jAKi svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Zk5xRxIeyTa7jAKi .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-Zk5xRxIeyTa7jAKi .cluster-label text{fill:#333;}#mermaid-svg-Zk5xRxIeyTa7jAKi .cluster-label span{color:#333;}#mermaid-svg-Zk5xRxIeyTa7jAKi .label text,#mermaid-svg-Zk5xRxIeyTa7jAKi span{fill:#333;color:#333;}#mermaid-svg-Zk5xRxIeyTa7jAKi .node rect,#mermaid-svg-Zk5xRxIeyTa7jAKi .node circle,#mermaid-svg-Zk5xRxIeyTa7jAKi .node ellipse,#mermaid-svg-Zk5xRxIeyTa7jAKi .node polygon,#mermaid-svg-Zk5xRxIeyTa7jAKi .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Zk5xRxIeyTa7jAKi .node .label{text-align:center;}#mermaid-svg-Zk5xRxIeyTa7jAKi .node.clickable{cursor:pointer;}#mermaid-svg-Zk5xRxIeyTa7jAKi .arrowheadPath{fill:#333333;}#mermaid-svg-Zk5xRxIeyTa7jAKi .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Zk5xRxIeyTa7jAKi .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Zk5xRxIeyTa7jAKi .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-Zk5xRxIeyTa7jAKi .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-Zk5xRxIeyTa7jAKi .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Zk5xRxIeyTa7jAKi .cluster text{fill:#333;}#mermaid-svg-Zk5xRxIeyTa7jAKi .cluster span{color:#333;}#mermaid-svg-Zk5xRxIeyTa7jAKi div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Zk5xRxIeyTa7jAKi :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}_do_forkwake_up_new_taskselect_task_rq/** wake_up_new_task - wake up a newly created task for the first time.** This function will do some initial scheduler statistics housekeeping* that must be done for every newly created context, then puts the task* on the runqueue and wakes it.*/
void wake_up_new_task(struct task_struct *p)
{struct rq_flags rf;struct rq *rq;raw_spin_lock_irqsave(p-pi_lock, rf.flags);p-state TASK_RUNNING;
#ifdef CONFIG_SMP/** Fork balancing, do it here and not earlier because:* - cpus_ptr can change in the fork path* - any previously selected CPU might disappear through hotplug** Use __set_task_cpu() to avoid calling sched_class::migrate_task_rq,* as were not fully set-up yet.*/p-recent_used_cpu task_cpu(p);rseq_migrate(p);__set_task_cpu(p, select_task_rq(p, task_cpu(p), SD_BALANCE_FORK, 0));
#endifrq __task_rq_lock(p, rf);update_rq_clock(rq);post_init_entity_util_avg(p);activate_task(rq, p, ENQUEUE_NOCLOCK);trace_sched_wakeup_new(p);check_preempt_curr(rq, p, WF_FORK);
#ifdef CONFIG_SMPif (p-sched_class-task_woken) {/** Nothing relies on rq-lock after this, so its fine to* drop it.*/rq_unpin_lock(rq, rf);p-sched_class-task_woken(rq, p);rq_repin_lock(rq, rf);}
#endiftask_rq_unlock(rq, p, rf);
}