系统iowait和线程的iowait
系统iowait和线程的iowait
系统iowait时间统计
在系统时钟中断时,会调用account_process_tick,如果是user tick,则增加user time;否则如果current线程不是idle,则增加system time;否则增加idle时间,idle可以再分为iowait和纯粹的idle,如果当前cpu的runqueue的nr_iowait大于0,则增加iowait time,否则增加idle time
void account_process_tick(struct task_struct *p, int user_tick) { u64 cputime, steal; struct rq *rq = this_rq(); if (vtime_accounting_cpu_enabled()) return; if (sched_clock_irqtime) { irqtime_account_process_tick(p, user_tick, rq, 1); return; } cputime = TICK_NSEC; steal = steal_account_process_time(ULONG_MAX); if (steal >= cputime) return; cputime -= steal; if (user_tick) account_user_time(p, cputime); else if ((p != rq->idle) || (irq_count() != HARDIRQ_OFFSET)) account_system_time(p, HARDIRQ_OFFSET, cputime); else account_idle_time(cputime); }
void account_idle_time(u64 cputime) { u64 *cpustat = kcpustat_this_cpu->cpustat; struct rq *rq = this_rq(); if (atomic_read(&rq->nr_iowait) > 0) cpustat[CPUTIME_IOWAIT] += cputime; else cpustat[CPUTIME_IDLE] += cputime; }
线程的iowait
io_schedule_timeout/io_schedule函数里先调用io_schedule_prepare,在这个函数里将当前的task的in_iowait设置为1.
在update_stats_enqueue_sleeper判断如果task的in_iowait为1,则statistics.iowait_sum(可以在/proc/pid/sched里找到这个值)累加上这次iowait的时间delta,这里有个sched_stat_iowait trace,所以会记录一条sched_stat_iowait的trace,这条trace记录了这个线程这次iowait的时间delta。
static inline void update_stats_enqueue_sleeper(struct cfs_rq *cfs_rq, struct sched_entity *se) sleep_start = schedstat_val(se->statistics.sleep_start); block_start = schedstat_val(se->statistics.block_start); if (block_start) { u64 delta = rq_clock(rq_of(cfs_rq)) - block_start; __schedstat_set(se->statistics.block_start, 0); __schedstat_add(se->statistics.sum_sleep_runtime, delta); if (tsk) { if (tsk->in_iowait) { __schedstat_add(se->statistics.iowait_sum, delta); __schedstat_inc(se->statistics.iowait_count); trace_sched_stat_iowait(tsk, delta); } trace_sched_stat_blocked(tsk, delta);
系统iowait和线程的iowait两者的区别
系统的iowait是全局的,针对CPU而言,如果此CPU是在运行idle线程,则增加idle时间;如果是运行的idle线程,但是它的runqueue上有在等待io的线程,则是iowait,增加iowait的时间,此iowait时间在top cmd结果(wa or iowait)里会呈现;
线程的iowait是此线程因等待IO而调用了io_schedule_timeout/io_schedule,等待IO完成的这一段时间是该线程这次的iowait时间,sched_stat_iowait trace event里会呈现此时间。