linux时间子系统 - hrtimer

1. hrtimer对象


1.1 hrtimer结构体

struct hrtimer {
    struct timerqueue_node      node;----------------------------红黑树的节点
    ktime_t             _softexpires;----------------------------到期时间
    enum hrtimer_restart        (*function)(struct hrtimer *);---hrtimer对象的函数
    struct hrtimer_clock_base   *base;
    u8              state;
    u8              is_rel;
#ifdef CONFIG_TIMER_STATS
    int             start_pid;
    void                *start_site;
    char                start_comm[16];
#endif
};

1.2 hrtimer对象的创建

主要工作是初始化一个hrtimer对象,并把hrtimer加入到hrtimer_cpu_base的红黑树中

extern void hrtimer_init(struct hrtimer *timer, clockid_t which_clock,
             enum hrtimer_mode mode);
                          |
                         \|/
static void __hrtimer_init(struct hrtimer *timer, clockid_t clock_id,
               enum hrtimer_mode mode)
{
    struct hrtimer_cpu_base *cpu_base;
    int base;

    memset(timer, 0, sizeof(struct hrtimer));

    cpu_base = raw_cpu_ptr(&hrtimer_bases);

    if (clock_id == CLOCK_REALTIME && mode != HRTIMER_MODE_ABS)
        clock_id = CLOCK_MONOTONIC;

    base = hrtimer_clockid_to_base(clock_id);
    timer->base = &cpu_base->clock_base[base];
    timerqueue_init(&timer->node);------------------------加入到红黑树

#ifdef CONFIG_TIMER_STATS
    timer->start_site = NULL;
    timer->start_pid = -1;
    memset(timer->start_comm, 0, TASK_COMM_LEN);
#endif
}

2. hrtimer_cpu_base


2.1 hrtimer_cpu_base结构体

struct hrtimer_cpu_base {
    raw_spinlock_t          lock;
    seqcount_t          seq;
    struct hrtimer          *running;-----------------正在运行的hrtimer
    unsigned int            cpu;
    unsigned int            active_bases;
    unsigned int            clock_was_set_seq;
    bool                migration_enabled;
    bool                nohz_active;
#ifdef CONFIG_HIGH_RES_TIMERS
    unsigned int            in_hrtirq   : 1,
                    hres_active : 1,
                    hang_detected   : 1;
    ktime_t             expires_next;-----------------下一次到期时间
    struct hrtimer          *next_timer;--------------下一个要运行的hrtimer
    unsigned int            nr_events;
    unsigned int            nr_retries;
    unsigned int            nr_hangs;
    unsigned int            max_hang_time;
#endif
    struct hrtimer_clock_base   clock_base[HRTIMER_MAX_CLOCK_BASES];---时钟类型
} ____cacheline_aligned;

时钟类型

enum  hrtimer_base_type {
    HRTIMER_BASE_MONOTONIC,
    HRTIMER_BASE_REALTIME,
    HRTIMER_BASE_BOOTTIME,
    HRTIMER_BASE_TAI,
    HRTIMER_MAX_CLOCK_BASES,
};

在系列文章时间有介绍

2.2 hrtimer_bases

每个cpu都有一个hrtimer_cpu_base结构,用于管理各自的hrtimer

DEFINE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases) =
{
    .lock = __RAW_SPIN_LOCK_UNLOCKED(hrtimer_bases.lock),
    .seq = SEQCNT_ZERO(hrtimer_bases.seq),
    .clock_base =
    {
        {
            .index = HRTIMER_BASE_MONOTONIC,
            .clockid = CLOCK_MONOTONIC,
            .get_time = &ktime_get,
        },
        {
            .index = HRTIMER_BASE_REALTIME,
            .clockid = CLOCK_REALTIME,
            .get_time = &ktime_get_real,
        },
        {
            .index = HRTIMER_BASE_BOOTTIME,
            .clockid = CLOCK_BOOTTIME,
            .get_time = &ktime_get_boottime,
        },
        {
            .index = HRTIMER_BASE_TAI,
            .clockid = CLOCK_TAI,
            .get_time = &ktime_get_clocktai,
        },
    }
};

2.3 hrtimer的红黑树结构

struct timerqueue_head {
    struct rb_root head;--------------红黑树节点
    struct timerqueue_node *next;
};

TODO:红黑树

3. hrtimer运行机制


hrtimer的运行有重要的两步:

  1. 更新当前时间:hrtimer_update_base
  2. 调用到期的hrtimer :__hrtimer_run_queues

下面主要介绍第二步

static void __hrtimer_run_queues(struct hrtimer_cpu_base *cpu_base, ktime_t now)
{
    struct hrtimer_clock_base *base = cpu_base->clock_base;
    unsigned int active = cpu_base->active_bases;

    for (; active; base++, active >>= 1) {
        struct timerqueue_node *node;
        ktime_t basenow;

        if (!(active & 0x01))
            continue;

        basenow = ktime_add(now, base->offset);

        while ((node = timerqueue_getnext(&base->active))) {----------遍历每一个到期的hrtimer
            struct hrtimer *timer;

            timer = container_of(node, struct hrtimer, node);

            /*
             * The immediate goal for using the softexpires is
             * minimizing wakeups, not running timers at the
             * earliest interrupt after their soft expiration.
             * This allows us to avoid using a Priority Search
             * Tree, which can answer a stabbing querry for
             * overlapping intervals and instead use the simple
             * BST we already have.
             * We don't add extra wakeups by delaying timers that
             * are right-of a not yet expired timer, because that
             * timer will have to trigger a wakeup anyway.
             */
            if (basenow.tv64 < hrtimer_get_softexpires_tv64(timer))
                break;

            __run_hrtimer(cpu_base, base, timer, &basenow);----------运行到期的hrtimer
        }
    }
}

change log


datecontentlinux
2017.1.8初稿linux4.6.3
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值