https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=219399
--- Comment #119 from Don Lewis <truck...@freebsd.org> --- (In reply to Nils Beyer from comment #115) I have some suspicions about what might be going wrong with ryzen_segv_test, but I really don't understand the memory fence / serialization stuff well enough to be sure. An experiment that I performed to try to get a better idea of where things might be going off the rails was to add this code: if (func_set->func[func_set->offset] != 0x8b) { fprintf(stderr, "First opcode should be 0x8b, but found 0x%x\n", func_set->func[func_set->offset]); } to thread1() in between the pf = (func_t)(&func_set->func[ func_set->offset ]); and ret2 = pf(func_set); to verify that the expected opcode was actually where we plan to jump to. What was interesting is that the error never triggered, *but* the frequency of segfaults went way down. That led me to look at what the mfence instruction actually does: Acts as a barrier to force strong memory ordering (serialization) between load and store instructions preceding the MFENCE, and load and store instructions that follow the MFENCE. A weakly-ordered memory system allows the hardware to reorder reads and writes between the processor and memory. The MFENCE instruction guarantees that the system completes all previous memory accesses before executing subsequent accesses. The MFENCE instruction is weakly-ordered with respect to data and instruction prefetches. Note the last sentence! The mfence() at the end of the threadx() loop should flush all the pending writes out to cache associated with core A before the lock is unlocked and thread1() is permitted to do its work. It looks to me like the mfence() at the top of the thread1() loop would not do anything since there aren't any interesting loads or stores that might be outstanding for core B at that point. One would think that serialize() aka the cpuid instruction would prevent instruction prefetching of old stale data before that point, but maybe not. I just don't understand this well enough ... Next I tried moving mfence(); serialize(); from just after lock_enter*() to just before the call into the newly moved data array: ret2 = pf(func_set); This gives mfence() some memory loads to wait for, which allows the data to be migrated from the core A cache. With this change, I no longer get any segfaults. Ryzen bug? Just more aggressive prefetching? I don't know ... -- You are receiving this mail because: You are the assignee for the bug. _______________________________________________ freebsd-bugs@freebsd.org mailing list https://lists.freebsd.org/mailman/listinfo/freebsd-bugs To unsubscribe, send any mail to "freebsd-bugs-unsubscr...@freebsd.org"