1. 数据结构
struct sched_info {
/* cumulative counters */
unsigned long cpu_time, /* time spent on the cpu */
run_delay, /* time spent waiting on a runqueue */
pcnt; /* # of timeslices run on this cpu */
/* timestamps */
unsigned long last_arrival, /* when we last ran on a cpu */
last_queued; /* when we were last queued to run */
};
2. 场景解析
场景:进程离开活跃任务队列,获取到cpu资源,记录进程的run_delay, last_arrival, pcnt, 重置last_queued。
/*
* Called when a process is dequeued from the active array and given
* the cpu.
* This function is only called from sched_info_arrive(), rather than
* dequeue_task(). Even though a task may be queued and dequeued multiple
* times as it is shuffled about, we're really interested in knowing how
* long it was from the *first* time it was queued to the time that it
* finally hit a cpu.
*/
static inline void sched_info_dequeued(task_t *t)
{
t->sched_info.last_queued = 0;
}
/*
* Called when a task finally hits the cpu. We can now calculate how
* long it was waiting to run. We also note when it began so that we
* can keep stats on how long its timeslice is.
*/
static inline void sched_info_arrive(task_t *t)
{
unsigned long now = jiffies, diff = 0;
struct runqueue *rq = task_rq(t);
if (t->sched_info.last_queued)
diff = now - t->sched_info.last_queued;
sched_info_dequeued(t);
t->sched_info.run_delay += diff;
t->sched_info.last_arrival = now;
t->sched_info.pcnt++;
if (!rq)
return;
rq->rq_sched_info.run_delay += diff;
rq->rq_sched_info.pcnt++;
}
场景:进程释放CPU资源,记录进程的CPU占用时间cpu_time。
/*
* Called when a process ceases being the active-running process, either
* voluntarily or involuntarily. Now we can calculate how long we ran.
*/
static inline void sched_info_depart(task_t *t)
{
struct runqueue *rq = task_rq(t);
unsigned long diff = jiffies - t->sched_info.last_arrival;
t->sched_info.cpu_time += diff;
if (rq)
rq->rq_sched_info.cpu_time += diff;
}