Summary: | XABORT not implemented | ||
---|---|---|---|
Product: | [Developer tools] valgrind | Reporter: | Joël Krähemann <joel> |
Component: | vex | Assignee: | Julian Seward <jseward> |
Status: | RESOLVED FIXED | ||
Severity: | normal | CC: | mark, samuel.thibault |
Priority: | NOR | Keywords: | usability |
Version: | unspecified | ||
Target Milestone: | --- | ||
Platform: | Fedora RPMs | ||
OS: | Linux | ||
Latest Commit: | Version Fixed In: | ||
Sentry Crash Report: | |||
Attachments: | Patch to implement xabort as nop |
Description
Joël Krähemann
2013-11-26 09:38:07 UTC
trylock seems to just want to try to abort any pending transaction using xabort. When there isn't a transaction (as is always the case with valgrind atm, since xbegin just immediately goes into the fallback path), then xabort acts as a NOP. Created attachment 83780 [details]
Patch to implement xabort as nop
XABORT can be called even when there is no current transaction.
In such a case XABORT acts as a NOP. Implement xabort as nop.
Committed as VEX r2800 with the addition of a check for opc == 0xC7 (xbegin) and opc == 0xC6 (for xabort) as discussed on irc with Julian to make the front end simpler and clearer. It seems to behave badly with glibc: pthread_mutex_t m; int main(int argc, char *argv[]) { int err; pthread_mutex_trylock(&m); pthread_mutex_unlock(&m); if ((err = pthread_mutex_destroy(&m))) *(int*)0 = 0; return 0; } will crash, this is the state of the mutex: $2 = {__data = {__lock = 0x0, __count = 0x0, __owner = 0x0, __nusers = 0xffffffff, __kind = 0x0, __spins = 0x0, __elision = 0x3, __list = {__prev = 0x0, __next = 0x0}}, __size = { 0x0 <repeats 12 times>, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0 <repeats 17 times>}, __align = 0x0} so apparently glibc did avoid locking on trylock, and didn't avoid unlocking on unlock, thus ending up with a bogus nusers. (In reply to Samuel Thibault from comment #4) > It seems to behave badly with glibc: > > pthread_mutex_t m; > int main(int argc, char *argv[]) { > int err; > pthread_mutex_trylock(&m); > pthread_mutex_unlock(&m); > if ((err = pthread_mutex_destroy(&m))) > *(int*)0 = 0; > return 0; > } > > will crash, this is the state of the mutex: > > $2 = {__data = {__lock = 0x0, __count = 0x0, __owner = 0x0, __nusers = > 0xffffffff, __kind = 0x0, > __spins = 0x0, __elision = 0x3, __list = {__prev = 0x0, __next = 0x0}}, > __size = { > 0x0 <repeats 12 times>, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, > 0x0, 0x3, > 0x0 <repeats 17 times>}, __align = 0x0} > > so apparently glibc did avoid locking on trylock, and didn't avoid unlocking > on unlock, thus ending up with a bogus nusers. That is consistent with running on actual hardware that has tsx. I am seeing the same on a i7-4600U with the rtm cpuid flag set and glibc-2.18-12 running that program directly and under valgrind svn. So you get a crash on hardware supporting RTM? Actually 2.18 glibc doesn't yet contain the TSX elission code. Let me try to find a hadware setup with TSX that has a newer glibc. But given that the pthread_mutex_destroy seems to fail with EBUSY there might be something wrong with the program anyway. Could you provide a bit more context where the program crashes exactly on which instruction and any differences with or without running under valgrind? Well, in the execution within valgrind, what is wrong is that nusers has become -1, and thus destroy thinks the mutex is busy, while it's clearly not from the source code. I believe I have found the bug, in glibc in the trylock case, where trylock does elision, but unlock doesn't (because it's not aware that trylock did). I'll report on the libc-alpha list. (I know, in my test program, I didn't bother initializing the mutex, since PTHREAD_MUTEX_INITIALIZER is actually zeroes in nptl) Reported and patch proposed on: https://sourceware.org/ml/libc-alpha/2014-08/msg00464.html |