noodle1983/UnityAndroidIl2cppPatchDemo-libboostrap

pthread_spin_unlock 的实现不正确

ganlvtech opened this issue · 4 comments

static inline int pthread_spin_unlock(pthread_spinlock_t *lock) {
__asm__ __volatile__ ("" ::: "memory");
*lock = 0;
return 0;
}

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 的差别

test_mutex

我可以提交一个 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 操作的内存。