Linux_Kernel 源码注解 Sched_7

schedule -> __schedule -> update_rq_clock -> sched_clock_cpu -> sched_clock_remote / sched_clock_local

static u64 sched_clock_remote(struct sched_clock_data *scd)
{
	struct sched_clock_data *my_scd = this_scd();
	u64 this_clock, remote_clock;
	u64 *ptr, old_val, val;

#if BITS_PER_LONG != 64
again:

	this_clock = sched_clock_local(my_scd);

读取本地scd

remote_clock = cmpxchg64(&scd->clock, 0, 0);

读取传入cpu的scd,强制原子

#else
	sched_clock_local(my_scd);
again:
	this_clock = my_scd->clock;
	remote_clock = scd->clock;

64位内核读取属于原子操作,所以不强制原子

#endif
	if (likely((s64)(remote_clock - this_clock) < 0)) {

如果远程clock小于当前clock
当前cpu的clock刚刚更新,所以大概率比远程cpu的clock更多

	ptr = &scd->clock;
	old_val = remote_clock;
	val = this_clock;
} else {
	ptr = &my_scd->clock;
	old_val = this_clock;
	val = remote_clock;
}
	if (cmpxchg64(ptr, old_val, val) != old_val)
		goto again;

对比远程与本地cpu的clock:
如果远程 < 本地 那么设置远程clock为本地clock
如果远程 > 本地 那么设置本地clock为远程clokc

return val;

返回最新的clock

}
static u64 sched_clock_local(struct sched_clock_data *scd)
{
	u64 now, clock, old_clock, min_clock, max_clock, gtod;
	s64 delta;

again:
	now = sched_clock();

获取sced_clock
这里只是获取epoch_ns的值,epoch_ns会在update_sched_clock中更新
update_sched_clock主要在sched_clock_poll中执行
sched_clock_poll被注册到sched_clock_timer中
sched_clock_timer应该会定期触发

delta = now - scd->tick_raw;
if (unlikely(delta < 0))
	delta = 0;

当前clock如果小于tick_raw 没搞懂这是什么东西

old_clock = scd->clock;
	gtod = scd->tick_gtod + __gtod_offset;
	clock = gtod + delta;
	min_clock = wrap_max(gtod, old_clock);
	max_clock = wrap_max(old_clock, gtod + TICK_NSEC);

	clock = wrap_max(clock, min_clock);
	clock = wrap_min(clock, max_clock);

	if (cmpxchg64(&scd->clock, old_clock, clock) != old_clock)
		goto again;

	return clock;

不清楚这一大堆是啥,反正就是返回了个本地clock

}
unsigned long long notrace sched_clock(void)
{
	u64 cyc, res;
	unsigned int seq;
	struct clock_read_data *rd;
	do {
		seq = raw_read_seqcount(&cd.seq);

顺序锁

rd = cd.read_data + (seq & 1);

读read_data[0]或者read_data[1],read_data[1]可能是backup

cyc = (rd->read_sched_clock() - rd->epoch_cyc) &
	      rd->sched_clock_mask;

read_sched_clock立刻返回经过小修改的jiffies,
epoch_cyc也是jiffies,不过这里的epoch_cyc是在update_sched_clock中更新的
sched_clock_mask是一个掩码,这里貌似是32个1,
所以返回值cyc就是上一个update_sched_clock到当前时刻的延迟值

res = rd->epoch_ns + cyc_to_ns(cyc, rd->mult, rd->shift);

延迟cyc经过加工编程ns延迟,并更新epoch_ns
即(cyc * mult )>> shift
mult与shift是通过clocks_calc_mult_shift计算出来的

	} while (read_seqcount_retry(&cd.seq, seq));
	return res;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值