c - xv6: reading ticks directly without taking the ticks lock?
问题描述
I'm working on an assignment in operating system course on Xv6. I need to implement a data status structure for a process for its creation time, termination time, sleep time, etc...
As of now I decided to use the ticks
variable directly without using the tickslock
because it seems not a good idea to use a lock and slow down the system for such a low priority objective.
Since the ticks variable only used like so: ticks++
, is there a way where I will try to retrieve the current number of ticks and get a wrong number?
I don't mind getting a wrong number by +-10 ticks but is there a way where it will be really off. Like when the number 01111111111111111 will increment it will need to change 2 bytes. So my question is this, is it possible that the CPU storing data in stages and another CPU will be able to fetch the data in that memory location between the start and complete of the store operation?
So as I see it, if the compiler will create a mov
instruction or an inc
instruction, what I want to know is if the store operation can be seen between the start and end of it.
解决方案
在 asm 中没有问题:在 x86 上使用单个指令完成的对齐加载/存储是原子的,最高可达 qword(8 字节)宽度。 为什么在 x86 上对自然对齐的变量进行整数赋值是原子的?
(在 486 上,保证仅适用于 4 字节对齐的值,甚至可能不适用于 386,所以这可能就是 Xv6 使用锁定的原因?我不确定它在 386 上是否应该是多核安全的;我的理解是罕见的 386 SMP 机器并没有完全实现现代 x86 内存模型(内存排序等)。)
但是C不是asm。 一次使用来自多个“线程”的普通非atomic
变量是未定义的行为,除非所有线程都只是在读取。这意味着编译器可以假设普通 C 变量不会被其他线程异步更改。
在 C 中使用ticks
循环将使编译器读取一次并重复使用相同的值。你需要一个READ_ONCE
像 Linux 内核使用的宏,例如*(volatile int*)&ticks
. 或者简单地将其声明为volatile unsigned ticks;
对于一个足够窄以适合一个整数寄存器的变量,可以安全地假设一个理智的编译器将使用单个 dword 存储来编写它,无论是 amov
或 memory-destinationinc
还是add dword [mem], 1
. (但是,您不能假设编译器将使用内存目标 inc/add,因此对于中断,您不能依赖于单核原子增量。)
对于一个作者和多个读者,是的,读者可以简单地阅读它,而无需任何类型的锁定,只要他们使用volatile
.
即使在可移植的ISO C 中,volatile sig_atomic_t
当由信号处理程序编写并由运行信号处理程序的线程读取时,也有一些非常有限的安全工作保证。(但不一定是其他线程:在 ISO Cvolatile
中并不能避免数据竞争 UB。但实际上在带有非敌对编译器的 x86 上这很好。)
(POSIX 信号相当于用户空间的中断。)
对于一个线程将更宽的计数器分成两半发布,您通常会使用 SeqLock。对于 1 个写入器和多个读取器,没有实际的锁定,如果写入与读取重叠,读取器只需重试。请参阅使用 32 位原子实现 64 位原子计数器
推荐阅读
- python - PyCharm SciView 未正确显示 DataFrame
- javascript - asp.net中水晶报表的空白结果问题
- javascript - 等待 Youtube 评论加载然后运行函数
- python - 为什么 Python 让我使用在没有“全局”关键字的嵌套块中分配的变量?
- java - 大输入的斐波那契数是负数
- python - 如何从循环中的列表中删除 2 元组 int/float?
- java - Android Studio 中的 Java 随机数
- javascript - Vuex 更新状态
- unity3d - 如何围绕另一个对象移动/旋转对象?
- database - 如何从 Rocket 的环境中建立数据库连接?