pthread_spin_unlock 的实现不正确
ganlvtech opened this issue · 4 comments
UnityAndroidIl2cppPatchDemo-libboostrap/pthread_spin_lock.h
Lines 36 to 40 in c792861
https://stackoverflow.com/questions/12183311/difference-in-mfence-and-asm-volatile-memory
asm volatile ("" ::: "memory")
编译之后反编译看没有生成任何指令,它只是告诉编译器不要做指令重排吧
static inline int pthread_spin_unlock(pthread_spinlock_t *lock) {
__sync_sub_and_fetch(lock, 1);
return 0;
}
用 __sync_synchronize()
也可以,它会生成一个 ARM 的 __dmb(11) 的操作
不用的话就是啥也不管。
测试代码也做了一定的修改
void *thread_proc(void *arg) {
int thread_id = (int) (intptr_t) arg;
MY_INFO("thread %d start", thread_id);
for (int i = 0; i < LOOP_COUNT; i++) {
PthreadWriteGuard guard(g_test_mutex);
if (a != b || b != c || c != d) {
MY_ERROR("pthread unit test failed: thread %d: %d %d %d %d", thread_id, a, b, c, d);
}
a++;
b++;
c++;
d++;
}
MY_INFO("thread %d stop", thread_id);
pthread_exit(0);
return 0;
}
可以测出 asm volatile
和 __sync_sub_and_fetch
的差别
我可以提交一个 Pull Request
有理有据, 没啥意见, 提个pr吧
@ganlvtech 我想重现一下修改之前的错误测试, 我在虚拟机和P40上都没法重现,问问你的重现环境
@noodle1983 MI MAX 3,Unity 2018.4 的 android-r16b ndk,编译之后直接放到 /usr/local/tmp 中运行的。可以尝试使用旧的 lock 实现,跑新的 test 代码,不一定每次都能出现,多试几次可能就会出现 a != b 了。
@noodle1983 旧的 test 代码没法测出锁的问题,不清楚为什么,可能跟只有一个变量参与原子操作有关。
C++ 20 的原子操作,对于锁的实现应该使用 Sequentially-consistent ordering Memory Order,本条指令不允许被重排,并且该指令之前的所有内存操作必须被同步,不仅仅是当前 atomic 操作的内存。