首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在一个多核的corepack上寻找种族状态的原因

在一个多核的corepack上寻找种族状态的原因
EN

Stack Overflow用户
提问于 2015-10-08 20:45:26
回答 1查看 79关注 0票数 0

我使用一个基于写索引和读索引的简单软件队列。

详细介绍;语言: C,编译器: GCC优化:带有额外参数的-O3,体系结构: Armv7a,CPU:多核,2 Cortex A-15,L2缓存:共享和启用,L1缓存:每个CPU,启用,体系结构应该是缓存一致性。

CPU 1负责写作,CPU 2负责阅读。下面是非常简单的示例代码。您可以假设索引的初始值为零。

共同:

代码语言:javascript
复制
#define QUE_LEN 4

unsigned int my_que_write_index = 0; //memory
unsigned int my_que_read_index = 0; //memory

struct my_que_struct{
  unsigned int param1;
  unsigned int param2;
};

struct my_que_struct my_que[QUE_LEN]; //memory

CPU 1运行:

代码语言:javascript
复制
void que_writer
{
unsigned int write_index_local;

write_index_local = my_que_write_index; //my_que_write_index is in memory
my_que[write_index_local].param1 = 16; //my_que is my queue and stored in memory also
my_que[write_index_local].param2 = 32;
//similar writing stuff

++write_index_local;
if(write_index_local == QUE_LEN) write_index_local = 0;

my_que_write_index = write_index_local;
}

CPU 2运行:

代码语言:javascript
复制
void que_reader()
{
unsigned int read_index_local, param1, param2;

read_index_local = my_que_read_index; //also in memory
while(read_index_local != my_que_write_index)
 {
   param1 = my_que[read_index_local].param1;

   if(param1 == 0) FATAL_ERROR;

   param2 = my_que[read_index_local].param2;
   //similar reading stuff

   my_que[read_index_local].param1 = 0;

   ++read_index_local;
   if(read_index_local == QUE_LEN) read_index_local = 0;
 }

my_que_read_index = read_index_local;
}

好的,在正常情况下,绝对不应该发生致命错误,因为队列的param1总是以16的常量存储。但是,不知怎么的,队列的param1发生了0,并且发生了致命错误。

很明显,这在某种程度上是一个种族状况的问题,但我不知道它是如何发生的。索引由CPU单独更新。

如果不了解问题的核心,我就不想用内存障碍填充我的代码。你知道这是怎么回事吗?

详细信息:这是一个裸金属系统,这些代码是中断禁用的,没有抢占或任务切换。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-10-08 21:23:12

编译器和CPU可以根据需要重新安排存储和加载(即,只要单个线程程序无法观察到差异)。当然,对于多线程程序来说,这些效果是可以观察到的。

例如,这段代码

代码语言:javascript
复制
write_index_local = my_que_write_index;
my_que[write_index_local].param1 = 16;
my_que[write_index_local].param2 = 32;
++write_index_local;
if(write_index_local == QUE_LEN) write_index_local = 0;
my_que_write_index = write_index_local;

可能会像这样重新排序

代码语言:javascript
复制
a = my_que_write_index;
my_que_write_index = write_index_local == QUE_LEN - 1 ? 0 : a + 1;
my_que[a].param1 = 16;
my_que[a].param2 = 32;

要正确处理这些东西,就需要原子和屏障来避免这种重排序。查看Preshing的一系列关于atomics的优秀博客文章,这篇文章可能是一个很好的开始:http://preshing.com/20120612/an-introduction-to-lock-free-programming/,但是也可以查看下面的文章。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33025642

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档