我将描述的情况是发生在iPad 4(ARMv7s),使用POSIX库至互斥锁定/解锁。 我见过的其他ARMv7的设备类似的事情,但(见下文),所以我想任何解决方案都需要在互斥和内存栅栏对ARMv7的行为更普遍的样子。
为方案的伪代码:
线程1 -生产数据:
void ProduceFunction() {
MutexLock();
int TempProducerIndex = mSharedProducerIndex; // Take a copy of the int member variable for Producers Index
mSharedArray[TempProducerIndex++] = NewData; // Copy new Data into array at Temp Index
mSharedProducerIndex = TempProducerIndex; // Signal consumer data is ready by assigning new Producer Index to shared variable
MutexUnlock();
}
线程2 -消费数据:
void ConsumingFunction () {
while (mConsumerIndex != mSharedProducerIndex) {
doWorkOnData (mSharedArray[mConsumerIndex++]);
}
}
先前(当问题在iPad 2冒出),I相信mSharedProducerIndex = TempProducerIndex
没有被原子方式执行,并且因此改变了使用一个AtomicCompareAndSwap
分配mSharedProducerIndex
。 这工作直到这一点,但事实证明我错了,错误已经回来了。 我想“修复”只是改变了一些时间。
我现在已经得出的结论是,实际的问题是一个不折不扣的互斥锁,即在写操作的顺序执行的,如果编译器或者硬件决定重新排序:
mSharedArray[TempProducerIndex++] = NewData; // Copy new Data into array at Temp Index
mSharedProducerIndex = TempProducerIndex; // Signal consumer data is ready by assigning new Producer Index to shared variable
... 至:
mSharedProducerIndex = TempProducerIndex; // Signal consumer data is ready by assigning new Producer Index to shared variable
mSharedArray[TempProducerIndex++] = NewData; // Copy new Data into array at Temp Index
...然后消费者交错生产者,数据也不会尚未当消费者试图读取它写的。
记忆障碍,一些看完后,所以我想我会尝试的信号移到外面消费者mutex_unlock
,相信解锁会产生记忆障碍/栅栏能保证mSharedArray
已被写入:
mSharedArray[TempProducerIndex++] = NewData; // Copy new Data into array at Temp Index
MutexUnlock();
mSharedProducerIndex = TempProducerIndex; // Signal consumer data is ready by assigning new Producer Index to shared variable
然而,这仍然失败,并导致我的问题,如果一个mutex_unlock
肯定会作为一个写围栏或不?
我也看到了惠普的一篇文章这表明,编译器可以移动代码到(但不出来的) crit_sec
秒。 因此,即使上述变更后的写mSharedProducerIndex
可能是障碍了。 是否有任何里程达到这个理论?
通过增加一个明确的围墙问题消失:
mSharedArray[TempProducerIndex++] = NewData; // Copy new Data into array at Temp Index
OSMemoryBarrier();
mSharedProducerIndex = TempProducerIndex; // Signal consumer data is ready by assigning new Producer Index to shared variable
因此,我想我明白这个问题,那就是需要一个围栏,但任何洞察解锁行为,以及为什么它似乎并没有被执行的障碍将是非常有用的。
编辑:
对缺乏在消费者线程互斥的:我依靠的写int mSharedProducerIndex
是一个单一的指令,因此希望消费者会读无论是新的还是旧的价值。 无论是有效状态,并提供mSharedArray
写入序列(即写之前mSharedProducerIndex
),这将是好的,但是从已经表示,到目前为止,我不能在此回复。
由相同的逻辑似乎电流阻挡溶液也有缺陷,因为mSharedProducerIndex
写入可以在屏障内部移动,并可能因此可能被不正确地重新排序。
它是建议一个互斥体加给消费者,只是作为一个读屏障,或者是有一个pragma
对生产者禁止乱序执行,像或指令EIEIO
上PPC?