中断处理时间统计 cpu_irqtime

本文详细介绍了Linux内核中的CPU中断时间会计机制,包括`cpu_irqtime`变量的定义、`irqtime_account_irq`函数的调用流程以及`enable_sched_clock_irqtime`和`disable_sched_clock_irqtime`的启用条件。该机制用于精细粒度的中断时间统计,通过`sched_clock_irqtime`变量控制,并在中断进入和退出时调整。文章还提及了`irq_count`函数用于统计当前处理的中断数量。

1. 定义

cpu_irqtime为per-cpu变量,定义在kernel/sched/cputime.c文件中

DEFINE_PER_CPU(struct irqtime, cpu_irqtime);

本功能的开启由config CONFIG_IRQ_TIME_ACCOUNTING控制,默认是开启状态

config IRQ_TIME_ACCOUNTING
        bool "Fine granularity task level IRQ time accounting"
        depends on HAVE_IRQ_TIME_ACCOUNTING && !VIRT_CPU_ACCOUNTING_NATIVE
        help
          Select this option to enable fine granularity task irq time
          accounting. This is done by reading a timestamp on each
          transitions between softirq and hardirq state, so there can be a
          small performance impact.

          If in doubt, say N here.

2. 调用

在系统中有三处调用位置:

2.1 irqtime_account_irq

首先看其实现:

/*
 * Called after incrementing preempt_count on {soft,}irq_enter
 * and before decrementing preempt_count on {soft,}irq_exit.
 */
void irqtime_account_irq(struct task_struct *curr, unsigned int offset)
{
        struct irqtime *irqtime = this_cpu_ptr(&cpu_irqtime);
        unsigned int pc;
        s64 delta;
        int cpu;

        if (!sched_clock_irqtime) //若未使能,直接退出
                return;

        cpu = smp_processor_id();
        delta = sched_clock_cpu(cpu) - irqtime->irq_start_time;
        irqtime->irq_start_time += delta;
        pc = irq_count() - offset; //减去本次正常处理的中断,将剩余中断赋值给临时变量pc

        /*
         * We do not account for softirq time from ksoftirqd here.
         * We want to continue accounting softirq time to ksoftirqd thread
         * in that case, so as not to confuse scheduler with a special task
         * that do not consume any time, but still wants to run.
         */
        if (pc & HARDIRQ_MASK) //若还有硬中断未处理完
                irqtime_account_delta(irqtime, delta, CPUTIME_IRQ);
        else if ((pc & SOFTIRQ_OFFSET) && curr != this_cpu_ksoftirqd()) //仍有软中断,并且当前task不是ksoftirqd
                irqtime_account_delta(irqtime, delta, CPUTIME_SOFTIRQ);
}

判断sched_clock_irqtime变量值,该变量的定义含义是:是否使能了clock_irqtime功能。

该变量值定义如下,并通过以下两个接口调用。

static int sched_clock_irqtime;

void enable_sched_clock_irqtime(void)
{
        sched_clock_irqtime = 1;
}

void disable_sched_clock_irqtime(void)
{
        sched_clock_irqtime = 0;
}

再继续向下,记录本cpu的本次的中断处理时长,赋值给delta,并更新irq_start_time。

根据中断标志位判断是否还有剩余的HARDIRQ or SOFTIRQ未处理(不在ksoftirqd调用),若有就更新如下变量

a. per-cpu kernel_cpustat->cpustat 区分中断类型

b. irqtime->total

c. irqtime->tick_delta

struct kernel_cpustat {
        u64 cpustat[NR_STATS];
};

DECLARE_PER_CPU(struct kernel_cpustat, kernel_cpustat);

#define kcpustat_this_cpu this_cpu_ptr(&kernel_cpustat)

static void irqtime_account_delta(struct irqtime *irqtime, u64 delta,
                                  enum cpu_usage_stat idx)
{
        u64 *cpustat = kcpustat_this_cpu->cpustat;

        u64_stats_update_begin(&irqtime->sync);
        cpustat[idx] += delta; //加入对应类型中断的cpustat中
        irqtime->total += delta; //加入total
        irqtime->tick_delta += delta; //加入tick_delta
        u64_stats_update_end(&irqtime->sync);
}

2.1.1 enable_sched_clock_irqtime

enable_sched_clock_irqtime的调用,对于arm/arm64架构来说只有一处:

kernel/time/sched_clock.c

static int irqtime = -1;

core_param(irqtime, irqtime, int, 0400);

void __init
sched_clock_register(u64 (*read)(void), int bits, unsigned long rate)
{
        ...
        /* Enable IRQ time accounting if we have a fast enough sched_clock() */
        if (irqtime > 0 || (irqtime == -1 && rate >= 1000000))
                enable_sched_clock_irqtime();
        ...
}

调用需要两个判断条件:

a. irqtime>0

        irqtime支持两种配置方式:

        cmdline

        echo -n ${value} > /sys/module/${modulename}/parameters/${parm}

b. (irqtime == -1 && rate >= 1000000)

        sched_clock_register在timer注册时调用,系统中最大rate为arch_timer为26M,>1000000。

2.1.2 disable_sched_clock_irqtime

在arm/arm64系统中无调用位置,忽略。

2.1.3 irq_count

统计此时处理的中断的数量。包括nmi中断,硬中断,软中断。

#define irq_count() (nmi_count() | hardirq_count() | softirq_count())

2.2 irqtime_tick_accounted

2.3 irq_time_read

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值