繁体   English   中英

出现中断时,读存储器屏障如何工作?

[英]How can a read memory barrier work in the presence of interrupts?

关于内存屏障的使用,我有些不了解,我希望澄清一下。

因此,假设我们有一个Treibers堆栈,但是我们正在使用SMR,那么每个指针都没有计数器关联-我们必须在原子操作中正确获取指针(这与ABA无关-我们正在使用SMR,处理ABA,这不是问题的一部分)。

现在,假设我们正在研究Intel(x86 / x64),因此每个CAS都带有完整的内存屏障。 认为 ,当CASing发生时,缓存行被锁定,发出读取屏障,从而清除了无效队列,因此缓存行被加载了最新版本的缓存行,发生了比较,然后写屏障发生了发出后,刷新存储缓冲区,最后我们释放缓存行锁。

因此,我们有以下用于pop的代码;

BARRIER_PROCESSOR_READ;

original_top = stack_state->top;

do
{
  if( original_top == NULL )
    return( 0 );

  copy_of_original_top = original_top;

  original_top = compare_and_swap( &stack_state->top, original_top->next, original_top );
}
while( copy_of_original_top != original_top );

*user_data = original_top->user_data;

因此,我们首先发出读取屏障-这确保我们刷新无效队列。 但是这样做与读取state_state-> top之间存在差距。 在清除无效队列和读取state_stack-> top之间, 可能发生任何事情 内核可以为中断服务,具有总线争用并且速度很慢,您可以这样命名-无效的缓存行可以重新加载(并由另一个处理器重新使无效)。 基本上-无效队列可以重新填充。 这意味着我们实际上不能相信original_top的值; 我们可能正在读取实际上是错误的本地缓存行(我们尚未使它失效),然后这样做,错误地认为其值为NULL并返回0。

因此,基本上,我看不到阅读障碍如何提供帮助 ,因为在障碍之后但在您希望执行的实际阅读之前,仍然会发生任何事情。

我在这里想念什么?

我无法完全理解您的问题,但我强烈怀疑您缺少详细信息。

内存防护用于保证更改的可见性,而不是同步过程。 单独使用防护并不能锁定对数据的访问。

另一方面,原子操作和锁(例如互斥锁或临界区或信号灯或任何其他同步原语)都将保证只有一个线程可以访问给定的内存区域(假设所有的访问都被编码为在您拥有时发生)这样的锁或原子锁)。 但是它们不保证有序的可见性。

如果需要两者,则既需要互斥访问需要屏蔽(请注意:屏蔽通常已经作为互斥量之类的高级同步原语的一部分实现,因此,如果使用它们,则不必显式担心屏蔽)。

我不能完全确定我是否理解您的问题,但是在发出读取屏障后,肯定会在屏障之前发生的读取之后对所有后续读取进行排序。 根据确切的定义BARRIER_PROCESS_READ的方式,它也可能会强制随后的读取从共享内存而不是处理器特定的缓存行中提取数据,从而使其他处理器上执行的写操作可见(假定这些写操作之后紧跟着适当的写操作)。写障碍!)。

在存在中断的情况下,这些情况仍然适用。 即使在读取屏障之后立即从中断处理程序中填充高速缓存行,从这些高速缓存行进行读取仍将为您提供一个相对于读取屏障语义而言有效的值。

我怀疑在您提供的代码示例中,读取屏障的目的实际上是使其他处理器的写入可见,以确保下一行original_top = stack_state->top; -检索新值,而不是读取在屏障之前发生的读取之后在本地缓存的值。 如果中断处理程序读取相同的地址,则此约束将仍然为true。 读取的值不会“新鲜”,但至少不会是已无限期缓存的值。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM