kenneth 你好,20200824问题已修复
大家好,从android 10开始,SDM710的CAF标签支持LongTermSupport。与其他标签不同的是,CodeAurora的贡献者在新的CAF里面合并Linux upstream。我认为这是好事,有的CodeAurora贡献者喜欢保留他们的代码风格,更变逻辑。SDM710这个CAF标签更新了很多新设备体系的和保留了很多纠正代码,独立于上游提前修复问题。这是我自己在进行合并Linux-stable时发现的其中一个问题。而他们codeauora贡献者不断在caf内更新,也引入了不少新的问题。于是我跟踪的一个问题,直到7月份的LA.UM.8.8.r1-07600-SDM710.0才得已修复。
贡献者在LA.UM.8.8.r1-07300-SDM710.0似乎忘了自己已经独立于Linux upstream修复了该问题,并加入了新的变量进行修改。
LA.UM.8.8.r1-07300-SDM710.0合并了v4.9.217 (CAF贡献者错误的更新)
@@ -892,7 +893,8 @@ static void __remove_hrtimer(struct hrtimer *timer,
//...
+ unsigned int state = timer->state;
//...
- if (!(timer->state & HRTIMER_STATE_ENQUEUED))
+ if (!(state & HRTIMER_STATE_ENQUEUED))
goto out;
+ /* Pairs with the lockless read in hrtimer_is_queued() */
+ WRITE_ONCE(timer->state, newstate);
//..
out:
timer->state = newstate | (timer->state & HRTIMER_STATE_PINNED);
如果if内容判断为真,编译器会直接优化内核为out下方的语句;
timer->state = newstate | (timer->state & HRTIMER_STATE_PINNED);
然后结束__remove_hrtimer函数。
可是我在Liunx-stable v4.9.208查看上游的更改,WRITE_ONCE()
是在if语句的上一行。
@@ -892,7 +893,8 @@ static void __remove_hrtimer(struct hrtimer *timer,
//...
- timer->state = newstate;
+ /* Pairs with the lockless read in hrtimer_is_queued() */
+ WRITE_ONCE(timer->state, newstate);
if (!(state & HRTIMER_STATE_ENQUEUED))
return
WRITE_ONCE()的作用:
- /* Pairs with the lockless read in hrtimer_is_queued() */
安全无锁一次性写入hrtimer_is_queued函数返回的变量。
他对现代化多线程处理的流水,能保护内存数据的一致性,起着非常重要的作用。
如果没有WRITE_ONCE()在if条件之上一行,timer->state与newstate在编译器共享内存中的数据会给state指针附上不吻合的变量值
1.手机在工作的时候,如果另外的代码在等待此处的响应,timer->state
会附上垃圾逻辑生成的值(非newstate或timer->state 与 HRTIMER_STATE_PINNED的变量值)并返回到编译器正在等待的线程当中,导致生成的内核asm逻辑改变了,内核工作在手机上会出现一系列异常。
来自[1]缓存一致性解释:
原始代码的逻辑,Z要重*A中获取值。
*A = Y;
Z = *A;
如果没有write_once(),Z直接就丢失了*A的数据,编译器会优化成Z=Y
*A = Y;
Z = Y;
这是我们不想看到的事情。
这个问题直到LA.UM.8.8.r1-07600-SDM710.0才被修复,他们选择了保留代码风格,不改变CAF原有的逻辑,删去了在if条件之下WRITE_ONCE(timer->state, newstate);
,选择goto out
去WRITE_ONCE()
,这也说明了CAF默许了if判断为真,希望newstate | (timer->state & HRTIMER_STATE_PINNED)
数据安全写入到timer->state
中,让代码在多线程下CAF逻辑被正常编译。这里不仅拥有了CAF逻辑,同时也保证了Linux-stream的更新。
以下是CAF在7600的修复更新。
LA.UM.8.8.r1-07600-SDM710.0 (caf又改回来了🤣)
- if (!(state & HRTIMER_STATE_ENQUEUED))
+ if (!(timer->state & HRTIMER_STATE_ENQUEUED))
goto out;
- /* Pairs with the lockless read in hrtimer_is_queued() */
- WRITE_ONCE(timer->state, newstate);
//...
out:
- timer->state = newstate | (timer->state & HRTIMER_STATE_PINNED);
+ /* Pairs with the lockless read in hrtimer_is_queued() */
+ WRITE_ONCE(timer->state,
+ newstate | (timer->state & HRTIMER_STATE_PINNED));
不仅仅是只有这一个例子,还有更多的。
由于LTS,不断的引入问题和修复问题,这样的不稳定标签并不是我想要的。
因此我将放慢内核的更新,不断观察与学习。
谢谢你的使用。
[1]Linux内核手册.缓存一致性CACHE COHERENCY VS MMIO: https://www.kernel.org/doc/html/latest/staging/index.html#memory-barriers