我正在阅读 allan cruse code 的 smphello.s 代码
在接下来的部分中,他尝试为每个处理器设置堆栈段。
关键是他在 xadd 的描述中使用了 xadd 而不使用 lock 前缀,如 here 。可能有一个锁前缀。
这是一个错误还是没关系?为什么?
# setup an exclusive stack-area for this processor
mov $0x1000, %ax # paragraphs in segment
xadd %ax, newSS # 'atomic' xchg-and-add
mov %ax, %ss # segment-address in SS
xor %esp, %esp # top-of-stack into ESP
最佳答案
没有 xadd
的 lock
是原子 wrt。在这个核心上中断,但不是wrt。在其他内核(或 DMA)上运行的代码。就像除 xchg
之外的所有其他内存目标 RMW 一样。请参阅 this answer ,其中涵盖了 cmpxchg
的相同问题。
如果此代码同时在多个内核上运行,则 2 个或更多内核可以读取 newSS
的相同值,从而有效地丢失增量并将相同的 ss:esp
分配给两个内核。或者,一个存储可能会被其他碰巧是连续的内核延迟到多个 xadd 之间,将计数器“倒带”到稍后加载看到的某个先前值。或任何问题的组合。 Can num++ be atomic for 'int num'?
假设 newSS
对齐,加载和存储分别是原子的,但不形成原子 RMW。
如果同时唤醒多个内核(是否可以广播 IPI?),这似乎很可能是一个真正的问题。如果没有,很可能每个 xadd
都会在下一个核心到达此代码之前完成。 (包括提交到 L1d 缓存的存储;变得全局可见。)但这只是一种“碰巧工作”的行为,除非核心唤醒功能在唤醒另一个核心之前等待收到来自一个核心的回复。
如果它想匹配关于原子增量的注释,它肯定需要 lock xadd
。 是原子的。如果线程从不并发运行,则中断很好,只能通过单个内核上的上下文切换。 (例如,主线程和信号处理程序之间的原子性,或同一核心上的中断处理程序)。但由于它的标题是 smphello.s
,单处理器假设似乎不太可能。
关于汇编:xadd 指令需要锁吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30130752/