https://bugs.kde.org/show_bug.cgi?id=518159
Bug ID: 518159
Summary: pth_once issues on Darwin
Classification: Developer tools
Product: valgrind
Version First 3.27 GIT
Reported In:
Platform: Other
OS: macOS
Status: REPORTED
Severity: normal
Priority: NOR
Component: drd
Assignee: [email protected]
Reporter: [email protected]
Target Milestone: ---
drd/tests/pth_once fails on macOS Intel (all versions that I can test). There
are two parts to the problem,
1. Use of 128 but CAS that DRD does not handle.
2. pthread_once uses internal locking mechanisms that are not visible to DRD.
For point 1, this assert fires
drd: drd_load_store.c:391 (void instr_trace_mem_store(IRSB *const, IRExpr
*const, IRExpr *, IRExpr *, IRExpr *const)): Assertion '!data_expr_hi ||
typeOfIRExpr(bb->tyenv, data_expr_hi) == Ity_I32' failed.
while the guest is executing
==10638== at 0x10C8EC8A3: pthread_rwlock_destroy (in
/usr/lib/system/libsystem_pthread.dylib)
That is due to
3af1: 48 0f c7 0e cmpxchg16b (%rsi)
If point 1 is resolved then there are 2 locations causing 6 conflicting loads.
==30658== Conflicting load by thread 3 at 0x10003b4b0 size 8
==30658== at 0x100010F78: test106::Worker1() (tsan_unittest.cpp:5098)
==30658== by 0x10001C9F6: MyThread::ThreadBody(void*)
(tsan_thread_wrappers_pthread.h:375)
==30658== by 0x10C2C0CF8: vgDrd_thread_wrapper
(drd_pthread_intercepts.c:519)
==30658== by 0x10C7E32EA: _pthread_body (in
/usr/lib/system/libsystem_pthread.dylib)
==30658== by 0x10C7E6248: _pthread_start (in
/usr/lib/system/libsystem_pthread.dylib)
==30658== by 0x10C7E240C: thread_start (in
/usr/lib/system/libsystem_pthread.dylib)
==30658== Location 0x10003b4b0 is 0 bytes inside global var "GLOB"
==30658== declared at tsan_unittest.cpp:5084
==30658== Other segment start (thread 2)
==30658== (thread finished, call stack no longer available)
==30658== Other segment end (thread 2)
==30658== (thread finished, call stack no longer available)
Fixes
====
The first one is fairly easy. With a 128bit CAS hi ans lo are both 64bit, so
change the assert to handle that
tl_assert(!data_expr_hi
|| typeOfIRExpr(bb->tyenv, data_expr_hi) == Ity_I32
|| typeOfIRExpr(bb->tyenv, data_expr_hi) == Ity_I64);
and also handle the larger size
if (data_expr_hi)
size *= 2;
The second one I'm not quite certain as to what the right solution is.
On macOS pthread_once is implemented using a some _os_once* functions. The
once_control structure contains a 'sig' field that is used for several pthread
'signals' or events. In the case of pthread_once two values are used
_PTHREAD_ONCE_SIG_init (0x30B1BCBA) meaning initialised but no thread has
execute the once function and _PTHREAD_ONCE_SIG (0x4F4E4345) meaning that the
once has fired.
It's the second aspect of pthread_once that is causing the conflicts. The
'winner' thread gets to set 'sig' atomically and call the controlled functions.
Loser thread(s) have to wait for the winner if it is still running. This
waiting is controlled by __ulock_wait and __ulock_wake. These functions are not
visible to Valgrind.
So I think that the solution is to add a HB edge using the pthread_once
context:
#if defined(VGO_darwin)
ANNOTATE_HAPPENS_BEFORE(once_control);
ANNOTATE_HAPPENS_AFTER(once_control);
#endif
at the end of pthread_once_intercept
I'll clean all of this up and make a patch for review.
#endif
--
You are receiving this mail because:
You are watching all bug changes.