Message ID | 20121212195033.GE2315@tucnak.redhat.com |
---|---|
State | New |
Headers | show |
Jakub Jelinek <jakub@redhat.com> writes: > PR sanitizer/55508 > * builtin-attrs.def (ATTR_TMPURE_NOTHROW_LEAF_LIST, > ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST): New. > * asan.c (ATTR_TMPURE_NOTHROW_LEAF_LIST, > ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST): Define. > * sanitizer.def: Make __asan_report_* and __asan_handle_no_return > builtins tm pure. This looks OK to me, if no one else objects.
On Wed, Dec 12, 2012 at 08:50:33PM +0100, Jakub Jelinek wrote: > Hi! > > Various TM tests ICE when built with -fgnu-tm -fsanitizer=address. > The problem is that asan.c pass adds calls to builtins that weren't there > before and TM is upset about it. The __asan_report* are all like > abort, in correctly written program they shouldn't have a user visible > effect, in bad program they will terminate the process, but in any case > it doesn't matter how many times they are retried as part of a transaction, > there is no state to roll back on transaction cancellation. > __asan_handle_no_return, while not being noreturn, just marks the stack as > unprotected, so again in correctly written application no effect, in bad app > might result in some issues being undetected, but still, it can be done many > times and isn't irreversible. > > The following patch fixes the ICEs by making all of these transaction pure. Jakub, Are the tm.exp scan-tree-dump-times failures with... make -k check RUNTESTFLAGS="tm.exp --target_board=unix'{-fsanitize=address}'" expected? I see... FAIL: gcc.dg/tm/memopt-3.c scan-tree-dump-times tmmark "logging: lala.x\\[i_4\\]" 1 FAIL: gcc.dg/tm/memopt-4.c scan-tree-dump-times tmedge "tm_save.[0-9_]+ = lala.x\\[55\\]" 1 FAIL: gcc.dg/tm/memopt-4.c scan-tree-dump-times tmedge "lala.x\\[55\\] = tm_save" 1 FAIL: gcc.dg/tm/memopt-5.c scan-tree-dump-times tmedge "ITM_LU[0-9] \\(&lala.x\\[55\\]" 1 FAIL: gcc.dg/tm/memopt-7.c scan-tree-dump-times tmedge "tm_save.[0-9_]+ = lala" 1 FAIL: gcc.dg/tm/memopt-7.c scan-tree-dump-times tmedge "lala = tm_save" 1 FAIL: g++.dg/tm/noexcept-5.C scan-tree-dump-times tmmark "ITM_RU" 1 on x86_64-apple-darwin12 with your patch applied to current gcc trunk. Jack > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? > > As for TSAN, no idea what to do, TSAN diagnostics could be in a similar > category, there is nothing to reverse, but as the library doesn't understand > transactions, perhaps better would be not to tsan instrument anything inside > of transactions, until the library is made TM aware. > > 2012-12-12 Jakub Jelinek <jakub@redhat.com> > > PR sanitizer/55508 > * builtin-attrs.def (ATTR_TMPURE_NOTHROW_LEAF_LIST, > ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST): New. > * asan.c (ATTR_TMPURE_NOTHROW_LEAF_LIST, > ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST): Define. > * sanitizer.def: Make __asan_report_* and __asan_handle_no_return > builtins tm pure. > > --- gcc/builtin-attrs.def.jj 2012-10-22 08:42:23.000000000 +0200 > +++ gcc/builtin-attrs.def 2012-12-12 11:56:54.942938879 +0100 > @@ -263,6 +263,11 @@ DEF_ATTR_TREE_LIST (ATTR_TMPURE_MALLOC_N > DEF_ATTR_TREE_LIST (ATTR_TMPURE_NOTHROW_LIST, > ATTR_TM_TMPURE, ATTR_NULL, ATTR_NOTHROW_LIST) > > +DEF_ATTR_TREE_LIST (ATTR_TMPURE_NOTHROW_LEAF_LIST, > + ATTR_TM_TMPURE, ATTR_NULL, ATTR_NOTHROW_LEAF_LIST) > +DEF_ATTR_TREE_LIST (ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST, > + ATTR_TM_TMPURE, ATTR_NULL, ATTR_NORETURN_NOTHROW_LEAF_LIST) > + > /* Construct a tree for a format_arg attribute. */ > #define DEF_FORMAT_ARG_ATTRIBUTE(FA) \ > DEF_ATTR_TREE_LIST (ATTR_FORMAT_ARG_##FA, ATTR_FORMAT_ARG, \ > --- gcc/asan.c.jj 2012-12-11 13:05:36.000000000 +0100 > +++ gcc/asan.c 2012-12-12 11:57:59.626550534 +0100 > @@ -1611,8 +1611,13 @@ initialize_sanitizer_builtins (void) > #define BT_FN_VOID_VPTR_I16_INT BT_FN_VOID_VPTR_IX_INT[4] > #undef ATTR_NOTHROW_LEAF_LIST > #define ATTR_NOTHROW_LEAF_LIST ECF_NOTHROW | ECF_LEAF > +#undef ATTR_TMPURE_NOTHROW_LEAF_LIST > +#define ATTR_TMPURE_NOTHROW_LEAF_LIST ECF_TM_PURE | ATTR_NOTHROW_LEAF_LIST > #undef ATTR_NORETURN_NOTHROW_LEAF_LIST > #define ATTR_NORETURN_NOTHROW_LEAF_LIST ECF_NORETURN | ATTR_NOTHROW_LEAF_LIST > +#undef ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST > +#define ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST \ > + ECF_TM_PURE | ATTR_NORETURN_NOTHROW_LEAF_LIST > #undef DEF_SANITIZER_BUILTIN > #define DEF_SANITIZER_BUILTIN(ENUM, NAME, TYPE, ATTRS) \ > decl = add_builtin_function ("__builtin_" NAME, TYPE, ENUM, \ > --- gcc/sanitizer.def.jj 2012-12-11 11:28:10.000000000 +0100 > +++ gcc/sanitizer.def 2012-12-12 11:57:12.714833945 +0100 > @@ -32,25 +32,25 @@ DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_INIT > /* Do not reorder the BUILT_IN_ASAN_REPORT* builtins, e.g. cfgcleanup.c > relies on this order. */ > DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_LOAD1, "__asan_report_load1", > - BT_FN_VOID_PTR, ATTR_NORETURN_NOTHROW_LEAF_LIST) > + BT_FN_VOID_PTR, ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST) > DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_LOAD2, "__asan_report_load2", > - BT_FN_VOID_PTR, ATTR_NORETURN_NOTHROW_LEAF_LIST) > + BT_FN_VOID_PTR, ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST) > DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_LOAD4, "__asan_report_load4", > - BT_FN_VOID_PTR, ATTR_NORETURN_NOTHROW_LEAF_LIST) > + BT_FN_VOID_PTR, ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST) > DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_LOAD8, "__asan_report_load8", > - BT_FN_VOID_PTR, ATTR_NORETURN_NOTHROW_LEAF_LIST) > + BT_FN_VOID_PTR, ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST) > DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_LOAD16, "__asan_report_load16", > - BT_FN_VOID_PTR, ATTR_NORETURN_NOTHROW_LEAF_LIST) > + BT_FN_VOID_PTR, ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST) > DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE1, "__asan_report_store1", > - BT_FN_VOID_PTR, ATTR_NORETURN_NOTHROW_LEAF_LIST) > + BT_FN_VOID_PTR, ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST) > DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE2, "__asan_report_store2", > - BT_FN_VOID_PTR, ATTR_NORETURN_NOTHROW_LEAF_LIST) > + BT_FN_VOID_PTR, ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST) > DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE4, "__asan_report_store4", > - BT_FN_VOID_PTR, ATTR_NORETURN_NOTHROW_LEAF_LIST) > + BT_FN_VOID_PTR, ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST) > DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE8, "__asan_report_store8", > - BT_FN_VOID_PTR, ATTR_NORETURN_NOTHROW_LEAF_LIST) > + BT_FN_VOID_PTR, ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST) > DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE16, "__asan_report_store16", > - BT_FN_VOID_PTR, ATTR_NORETURN_NOTHROW_LEAF_LIST) > + BT_FN_VOID_PTR, ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST) > DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REGISTER_GLOBALS, > "__asan_register_globals", > BT_FN_VOID_PTR_PTRMODE, ATTR_NOTHROW_LEAF_LIST) > @@ -59,7 +59,7 @@ DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_UNRE > BT_FN_VOID_PTR_PTRMODE, ATTR_NOTHROW_LEAF_LIST) > DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_HANDLE_NO_RETURN, > "__asan_handle_no_return", > - BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST) > + BT_FN_VOID, ATTR_TMPURE_NOTHROW_LEAF_LIST) > > /* Thread Sanitizer */ > DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_INIT, "__tsan_init", > > Jakub
On 12/12/2012 11:50 AM, Jakub Jelinek wrote: > 2012-12-12 Jakub Jelinek <jakub@redhat.com> > > PR sanitizer/55508 > * builtin-attrs.def (ATTR_TMPURE_NOTHROW_LEAF_LIST, > ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST): New. > * asan.c (ATTR_TMPURE_NOTHROW_LEAF_LIST, > ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST): Define. > * sanitizer.def: Make __asan_report_* and __asan_handle_no_return > builtins tm pure. Ok. Agreed about we need another solution for tsan + tm. r~
On Wed, Dec 12, 2012 at 11:50 PM, Jakub Jelinek <jakub@redhat.com> wrote: > Hi! > > Various TM tests ICE when built with -fgnu-tm -fsanitizer=address. > The problem is that asan.c pass adds calls to builtins that weren't there > before and TM is upset about it. The __asan_report* are all like > abort, in correctly written program they shouldn't have a user visible > effect, in bad program they will terminate the process, but in any case > it doesn't matter how many times they are retried as part of a transaction, > there is no state to roll back on transaction cancellation. > __asan_handle_no_return, while not being noreturn, just marks the stack as > unprotected, so again in correctly written application no effect, in bad app > might result in some issues being undetected, but still, it can be done many > times and isn't irreversible. Hi! I was only loosely following tm-languages discussions. Does gcc tm model guarantees strong consistency for all memory accesses? I mean there are tm implementations that allow transient inconsistencies, than are detected later and trx is restarted. Can't asan trigger false positives in this case? Also, what is the order of instrumentation in tm+asan setting? I mean that neither tm must instrument asan instrumentation, nor asan must instrument tm instrumentation. Is it the case? There also can be conflicts related to ordering of instrumentation in the following case: asan_check(); speculative_load(); tm_check(); In this case tm hopes to detect inconsistent speculative load afterwards, but asan will crash the program before tm has a chance to abort and retry (it is related to the first point). Sorry, I don't know how gcc tm works. But I just suspect that it can be very tricky. > The following patch fixes the ICEs by making all of these transaction pure. > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? > > As for TSAN, no idea what to do, TSAN diagnostics could be in a similar > category, there is nothing to reverse, but as the library doesn't understand > transactions, perhaps better would be not to tsan instrument anything inside > of transactions, until the library is made TM aware. > > 2012-12-12 Jakub Jelinek <jakub@redhat.com> > > PR sanitizer/55508 > * builtin-attrs.def (ATTR_TMPURE_NOTHROW_LEAF_LIST, > ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST): New. > * asan.c (ATTR_TMPURE_NOTHROW_LEAF_LIST, > ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST): Define. > * sanitizer.def: Make __asan_report_* and __asan_handle_no_return > builtins tm pure. > > --- gcc/builtin-attrs.def.jj 2012-10-22 08:42:23.000000000 +0200 > +++ gcc/builtin-attrs.def 2012-12-12 11:56:54.942938879 +0100 > @@ -263,6 +263,11 @@ DEF_ATTR_TREE_LIST (ATTR_TMPURE_MALLOC_N > DEF_ATTR_TREE_LIST (ATTR_TMPURE_NOTHROW_LIST, > ATTR_TM_TMPURE, ATTR_NULL, ATTR_NOTHROW_LIST) > > +DEF_ATTR_TREE_LIST (ATTR_TMPURE_NOTHROW_LEAF_LIST, > + ATTR_TM_TMPURE, ATTR_NULL, ATTR_NOTHROW_LEAF_LIST) > +DEF_ATTR_TREE_LIST (ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST, > + ATTR_TM_TMPURE, ATTR_NULL, ATTR_NORETURN_NOTHROW_LEAF_LIST) > + > /* Construct a tree for a format_arg attribute. */ > #define DEF_FORMAT_ARG_ATTRIBUTE(FA) \ > DEF_ATTR_TREE_LIST (ATTR_FORMAT_ARG_##FA, ATTR_FORMAT_ARG, \ > --- gcc/asan.c.jj 2012-12-11 13:05:36.000000000 +0100 > +++ gcc/asan.c 2012-12-12 11:57:59.626550534 +0100 > @@ -1611,8 +1611,13 @@ initialize_sanitizer_builtins (void) > #define BT_FN_VOID_VPTR_I16_INT BT_FN_VOID_VPTR_IX_INT[4] > #undef ATTR_NOTHROW_LEAF_LIST > #define ATTR_NOTHROW_LEAF_LIST ECF_NOTHROW | ECF_LEAF > +#undef ATTR_TMPURE_NOTHROW_LEAF_LIST > +#define ATTR_TMPURE_NOTHROW_LEAF_LIST ECF_TM_PURE | ATTR_NOTHROW_LEAF_LIST > #undef ATTR_NORETURN_NOTHROW_LEAF_LIST > #define ATTR_NORETURN_NOTHROW_LEAF_LIST ECF_NORETURN | ATTR_NOTHROW_LEAF_LIST > +#undef ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST > +#define ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST \ > + ECF_TM_PURE | ATTR_NORETURN_NOTHROW_LEAF_LIST > #undef DEF_SANITIZER_BUILTIN > #define DEF_SANITIZER_BUILTIN(ENUM, NAME, TYPE, ATTRS) \ > decl = add_builtin_function ("__builtin_" NAME, TYPE, ENUM, \ > --- gcc/sanitizer.def.jj 2012-12-11 11:28:10.000000000 +0100 > +++ gcc/sanitizer.def 2012-12-12 11:57:12.714833945 +0100 > @@ -32,25 +32,25 @@ DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_INIT > /* Do not reorder the BUILT_IN_ASAN_REPORT* builtins, e.g. cfgcleanup.c > relies on this order. */ > DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_LOAD1, "__asan_report_load1", > - BT_FN_VOID_PTR, ATTR_NORETURN_NOTHROW_LEAF_LIST) > + BT_FN_VOID_PTR, ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST) > DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_LOAD2, "__asan_report_load2", > - BT_FN_VOID_PTR, ATTR_NORETURN_NOTHROW_LEAF_LIST) > + BT_FN_VOID_PTR, ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST) > DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_LOAD4, "__asan_report_load4", > - BT_FN_VOID_PTR, ATTR_NORETURN_NOTHROW_LEAF_LIST) > + BT_FN_VOID_PTR, ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST) > DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_LOAD8, "__asan_report_load8", > - BT_FN_VOID_PTR, ATTR_NORETURN_NOTHROW_LEAF_LIST) > + BT_FN_VOID_PTR, ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST) > DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_LOAD16, "__asan_report_load16", > - BT_FN_VOID_PTR, ATTR_NORETURN_NOTHROW_LEAF_LIST) > + BT_FN_VOID_PTR, ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST) > DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE1, "__asan_report_store1", > - BT_FN_VOID_PTR, ATTR_NORETURN_NOTHROW_LEAF_LIST) > + BT_FN_VOID_PTR, ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST) > DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE2, "__asan_report_store2", > - BT_FN_VOID_PTR, ATTR_NORETURN_NOTHROW_LEAF_LIST) > + BT_FN_VOID_PTR, ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST) > DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE4, "__asan_report_store4", > - BT_FN_VOID_PTR, ATTR_NORETURN_NOTHROW_LEAF_LIST) > + BT_FN_VOID_PTR, ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST) > DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE8, "__asan_report_store8", > - BT_FN_VOID_PTR, ATTR_NORETURN_NOTHROW_LEAF_LIST) > + BT_FN_VOID_PTR, ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST) > DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE16, "__asan_report_store16", > - BT_FN_VOID_PTR, ATTR_NORETURN_NOTHROW_LEAF_LIST) > + BT_FN_VOID_PTR, ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST) > DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REGISTER_GLOBALS, > "__asan_register_globals", > BT_FN_VOID_PTR_PTRMODE, ATTR_NOTHROW_LEAF_LIST) > @@ -59,7 +59,7 @@ DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_UNRE > BT_FN_VOID_PTR_PTRMODE, ATTR_NOTHROW_LEAF_LIST) > DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_HANDLE_NO_RETURN, > "__asan_handle_no_return", > - BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST) > + BT_FN_VOID, ATTR_TMPURE_NOTHROW_LEAF_LIST) > > /* Thread Sanitizer */ > DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_INIT, "__tsan_init", > > Jakub
On Thu, Dec 13, 2012 at 1:58 AM, Richard Henderson <rth@redhat.com> wrote: > On 12/12/2012 11:50 AM, Jakub Jelinek wrote: >> 2012-12-12 Jakub Jelinek <jakub@redhat.com> >> >> PR sanitizer/55508 >> * builtin-attrs.def (ATTR_TMPURE_NOTHROW_LEAF_LIST, >> ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST): New. >> * asan.c (ATTR_TMPURE_NOTHROW_LEAF_LIST, >> ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST): Define. >> * sanitizer.def: Make __asan_report_* and __asan_handle_no_return >> builtins tm pure. > > Ok. > > Agreed about we need another solution for tsan + tm. What type of bugs do you expect tsan catch in transactional setting? Are we talking about data races between transactional and non-transactional code? Does atomic transactions permitted by gcc? I mean can I use mutexes and atomics inside of transactions to synchronize with non-transactional code?
On Thu, Dec 13, 2012 at 10:38:13AM +0400, Dmitry Vyukov wrote: > On Wed, Dec 12, 2012 at 11:50 PM, Jakub Jelinek <jakub@redhat.com> wrote: > > Various TM tests ICE when built with -fgnu-tm -fsanitizer=address. > > The problem is that asan.c pass adds calls to builtins that weren't there > > before and TM is upset about it. The __asan_report* are all like > > abort, in correctly written program they shouldn't have a user visible > > effect, in bad program they will terminate the process, but in any case > > it doesn't matter how many times they are retried as part of a transaction, > > there is no state to roll back on transaction cancellation. > > __asan_handle_no_return, while not being noreturn, just marks the stack as > > unprotected, so again in correctly written application no effect, in bad app > > might result in some issues being undetected, but still, it can be done many > > times and isn't irreversible. > > I was only loosely following tm-languages discussions. Does gcc tm > model guarantees strong consistency for all memory accesses? I mean > there are tm implementations that allow transient inconsistencies, Will leave this to Torvald. > than are detected later and trx is restarted. Can't asan trigger false > positives in this case? I can't imagine any. > Also, what is the order of instrumentation in tm+asan setting? I mean > that neither tm must instrument asan instrumentation, nor asan must > instrument tm instrumentation. Is it the case? There also can be > conflicts related to ordering of instrumentation in the following > case: > asan_check(); > speculative_load(); > tm_check(); I'm not aware of TM having speculative loads, libgtm certainly doesn't install a SIGSEGV handler (and testing whether some memory is readable/writable without actually dereferencing would be terribly slow). If a memory load or store segfaults, whether in a transaction or outside of it, it is a program bug and it is right if asan terminates the program. Jakub
On Thu, Dec 13, 2012 at 1:02 PM, Jakub Jelinek <jakub@redhat.com> wrote: >> > Various TM tests ICE when built with -fgnu-tm -fsanitizer=address. >> > The problem is that asan.c pass adds calls to builtins that weren't there >> > before and TM is upset about it. The __asan_report* are all like >> > abort, in correctly written program they shouldn't have a user visible >> > effect, in bad program they will terminate the process, but in any case >> > it doesn't matter how many times they are retried as part of a transaction, >> > there is no state to roll back on transaction cancellation. >> > __asan_handle_no_return, while not being noreturn, just marks the stack as >> > unprotected, so again in correctly written application no effect, in bad app >> > might result in some issues being undetected, but still, it can be done many >> > times and isn't irreversible. >> >> I was only loosely following tm-languages discussions. Does gcc tm >> model guarantees strong consistency for all memory accesses? I mean >> there are tm implementations that allow transient inconsistencies, > > Will leave this to Torvald. > >> than are detected later and trx is restarted. Can't asan trigger false >> positives in this case? > > I can't imagine any. > >> Also, what is the order of instrumentation in tm+asan setting? I mean >> that neither tm must instrument asan instrumentation, nor asan must >> instrument tm instrumentation. Is it the case? There also can be >> conflicts related to ordering of instrumentation in the following >> case: >> asan_check(); >> speculative_load(); >> tm_check(); > > I'm not aware of TM having speculative loads, libgtm certainly doesn't > install a SIGSEGV handler (and testing whether some memory is > readable/writable without actually dereferencing would be terribly slow). > If a memory load or store segfaults, whether in a transaction or outside of > it, it is a program bug and it is right if asan terminates the program. OK, thanks. AFAIR tl2 installs SIGSEGV and uses non-failing loads.
On Thu, 2012-12-13 at 10:02 +0100, Jakub Jelinek wrote: > On Thu, Dec 13, 2012 at 10:38:13AM +0400, Dmitry Vyukov wrote: > > On Wed, Dec 12, 2012 at 11:50 PM, Jakub Jelinek <jakub@redhat.com> wrote: > > > Various TM tests ICE when built with -fgnu-tm -fsanitizer=address. > > > The problem is that asan.c pass adds calls to builtins that weren't there > > > before and TM is upset about it. The __asan_report* are all like > > > abort, in correctly written program they shouldn't have a user visible > > > effect, in bad program they will terminate the process, but in any case > > > it doesn't matter how many times they are retried as part of a transaction, > > > there is no state to roll back on transaction cancellation. > > > __asan_handle_no_return, while not being noreturn, just marks the stack as > > > unprotected, so again in correctly written application no effect, in bad app > > > might result in some issues being undetected, but still, it can be done many > > > times and isn't irreversible. > > > > I was only loosely following tm-languages discussions. Does gcc tm > > model guarantees strong consistency for all memory accesses? I mean > > there are tm implementations that allow transient inconsistencies, > > Will leave this to Torvald. This has two parts: (1) how TM fits into the C++11/C11 memory model, and (2) which guarantees the compiler and the TM runtime library agree on at the level of the TM ABI that we use in GCC. Regarding the first part, all transactions provide guarantees similar to a global lock. Specifically, there are virtual transaction start/end events that take part in sequenced-before (similar to acquisition and release of the global lock), whose are then guaranteed to execute (without transactions interleaving with each other) in a global total order (let's call this order TO). TO then contributes to happens-before. On the ABI level, the TM runtime is allowed to execute speculatively as long as (1) it does not expose any speculative execution to nontransactional code and (2) speculation doesn't violate the language's as-if rules (i.e., no visible side effects other than the abstract machine; no signals due to seg faults etc.). This means that, for example, the TM will not access data at a wider granularity than what nontransactional code that conforms to the C++11 memory model does would do. Second, transactions can have a tentative position in TO, but they will only expose final TO choices to nontxnal code. So, each transaction will execute code that would be valid when executed in isolation -- but it is possible that several transactions noncommitted transactions are in flight concurrently that may conflict with each other. The TM ensures that such speculative execution is safe and not visible to a race-free program. So, when a transaction commits at a certain position in TO, it will make sure that all other active transactions reach consensus on TO (up to this position) before it returns to the execution of nontxnal code. Those active transactions will either see that they would be still valid at a new TO position (after the committing txn), or they abort and then signal that they agree to this TO. That means that the nontxnal code will not be affected by any speculative execution, even if the prior txn privatized some data (this is called privatization safety in TM jargon). The sort-of counterpart to privatization safety is publication safety (ie, transactions can safely make some data shared). While privatization safety is handled by the TM runtime, publication safety is ensured by the compiler by not allowing any dangerous load/load reordering, basicallly. Publication safety is not yet ensured always, but Aldy is working on this. > > than are detected later and trx is restarted. Can't asan trigger false > > positives in this case? > > I can't imagine any. I also don't see any, because all loads/stores of all transactions, even those with a tentative TO position, would be a valid execution. For malloc/free in transactions, AFAIR, ASAN hooks into malloc/free directly, so when libitm handles those including rollback of an allocation, there shouldn't be false positives. However, there might be false negatives in case of free() because deallocations are deferred until transaction commit (they can't be rolled back). Could we tell ASAN about free() directly using a call added by the TM instrumentation pass? That would at least help catch the false negatives for all free()-like functions that the compiler knows about. All of this is different for TSAN, of course, because there a memory access does alter the state that TSAN keeps, so if we roll back the accesses in the TM we would also have to roll back the TSAN state. > > Also, what is the order of instrumentation in tm+asan setting? I mean > > that neither tm must instrument asan instrumentation, nor asan must > > instrument tm instrumentation. Is it the case? There also can be > > conflicts related to ordering of instrumentation in the following > > case: > > asan_check(); > > speculative_load(); > > tm_check(); The ordering of instrumentation is an interesting question, but I think that putting the ASAN check before the TM load/store is the right thing to do. It will catch any illegal access before it's performed. It doesn't suffer from false positives because the TM will only allow valid (even though speculative) executions. For this ordering to not be valid (ie, tm_check before asan_check), transactions would need to be able to prevent access to a certain variable by writing to them (which doesn't work). Other cases in which the transaction would perform the access because of values of other variables that it loaded previously are covered by privatization safety. > I'm not aware of TM having speculative loads, libgtm certainly doesn't > install a SIGSEGV handler (and testing whether some memory is > readable/writable without actually dereferencing would be terribly slow). > If a memory load or store segfaults, whether in a transaction or outside of > it, it is a program bug and it is right if asan terminates the program. Right, memory accesses performed by the TM are only speculative to the extent described above. Torvald
On Fri, 2012-12-14 at 13:44 +0400, Dmitry Vyukov wrote: > On Thu, Dec 13, 2012 at 1:02 PM, Jakub Jelinek <jakub@redhat.com> wrote: > >> > Various TM tests ICE when built with -fgnu-tm -fsanitizer=address. > >> > The problem is that asan.c pass adds calls to builtins that weren't there > >> > before and TM is upset about it. The __asan_report* are all like > >> > abort, in correctly written program they shouldn't have a user visible > >> > effect, in bad program they will terminate the process, but in any case > >> > it doesn't matter how many times they are retried as part of a transaction, > >> > there is no state to roll back on transaction cancellation. > >> > __asan_handle_no_return, while not being noreturn, just marks the stack as > >> > unprotected, so again in correctly written application no effect, in bad app > >> > might result in some issues being undetected, but still, it can be done many > >> > times and isn't irreversible. > >> > >> I was only loosely following tm-languages discussions. Does gcc tm > >> model guarantees strong consistency for all memory accesses? I mean > >> there are tm implementations that allow transient inconsistencies, > > > > Will leave this to Torvald. > > > >> than are detected later and trx is restarted. Can't asan trigger false > >> positives in this case? > > > > I can't imagine any. > > > >> Also, what is the order of instrumentation in tm+asan setting? I mean > >> that neither tm must instrument asan instrumentation, nor asan must > >> instrument tm instrumentation. Is it the case? There also can be > >> conflicts related to ordering of instrumentation in the following > >> case: > >> asan_check(); > >> speculative_load(); > >> tm_check(); > > > > I'm not aware of TM having speculative loads, libgtm certainly doesn't > > install a SIGSEGV handler (and testing whether some memory is > > readable/writable without actually dereferencing would be terribly slow). > > If a memory load or store segfaults, whether in a transaction or outside of > > it, it is a program bug and it is right if asan terminates the program. > > > OK, thanks. > AFAIR tl2 installs SIGSEGV and uses non-failing loads. I think the original implementation didn't, but other TL2 implementations might if they want to avoid providing full privatization safety without relying on any sandboxing attempts. Sandboxing is hard to get right (e.g., if the architecture doesn't provide nonfaulting loads), and if you try it, you end up with a much more intrusive solution (e.g., you need to ensure that the program doesn't override your signal handlers). Therefore, libitm ensures privatization safety by a quiescence-based approach (i.e., a privatizing transaction waits until all other active reading transactions are guaranteed to have observed the privatizer's updates). Torvald
On Thu, 2012-12-13 at 10:40 +0400, Dmitry Vyukov wrote: > On Thu, Dec 13, 2012 at 1:58 AM, Richard Henderson <rth@redhat.com> wrote: > > On 12/12/2012 11:50 AM, Jakub Jelinek wrote: > >> 2012-12-12 Jakub Jelinek <jakub@redhat.com> > >> > >> PR sanitizer/55508 > >> * builtin-attrs.def (ATTR_TMPURE_NOTHROW_LEAF_LIST, > >> ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST): New. > >> * asan.c (ATTR_TMPURE_NOTHROW_LEAF_LIST, > >> ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST): Define. > >> * sanitizer.def: Make __asan_report_* and __asan_handle_no_return > >> builtins tm pure. > > > > Ok. > > > > Agreed about we need another solution for tsan + tm. > > > What type of bugs do you expect tsan catch in transactional setting? > Are we talking about data races between transactional and > non-transactional code? Right. And it would be good if TSAN can detect these cases. I don't think we need TSAN to detect races in the TM runtime library implementation itself, which would probably need a lot of special cases because of (restricted, see my other post) speculative execution by the TM. > Does atomic transactions permitted by gcc? I mean can I use mutexes > and atomics inside of transactions to synchronize with > non-transactional code? Such operations, called "unsafe code", are not allowed in atomic transactions (currently--that choice is determined by several factors such as likely runtime overheads and intrusiveness of TM implementations). But they are allowed in relaxed transactions. Before relaxed transactions execute such unsafe code, they will switch to serial execution of transactions, which we could make visible to TSAN if that would help. Torvald
resend in plain text On Mon, Dec 17, 2012 at 1:50 PM, Dmitry Vyukov <dvyukov@google.com> wrote: > > On Fri, Dec 14, 2012 at 5:43 PM, Torvald Riegel <triegel@redhat.com> wrote: > > On Thu, 2012-12-13 at 10:02 +0100, Jakub Jelinek wrote: > >> On Thu, Dec 13, 2012 at 10:38:13AM +0400, Dmitry Vyukov wrote: > >> > On Wed, Dec 12, 2012 at 11:50 PM, Jakub Jelinek <jakub@redhat.com> wrote: > >> > > Various TM tests ICE when built with -fgnu-tm -fsanitizer=address. > >> > > The problem is that asan.c pass adds calls to builtins that weren't there > >> > > before and TM is upset about it. The __asan_report* are all like > >> > > abort, in correctly written program they shouldn't have a user visible > >> > > effect, in bad program they will terminate the process, but in any case > >> > > it doesn't matter how many times they are retried as part of a transaction, > >> > > there is no state to roll back on transaction cancellation. > >> > > __asan_handle_no_return, while not being noreturn, just marks the stack as > >> > > unprotected, so again in correctly written application no effect, in bad app > >> > > might result in some issues being undetected, but still, it can be done many > >> > > times and isn't irreversible. > >> > > >> > I was only loosely following tm-languages discussions. Does gcc tm > >> > model guarantees strong consistency for all memory accesses? I mean > >> > there are tm implementations that allow transient inconsistencies, > >> > >> Will leave this to Torvald. > > > > This has two parts: (1) how TM fits into the C++11/C11 memory model, and > > (2) which guarantees the compiler and the TM runtime library agree on at > > the level of the TM ABI that we use in GCC. > > > > Regarding the first part, all transactions provide guarantees similar to > > a global lock. Specifically, there are virtual transaction start/end > > events that take part in sequenced-before (similar to acquisition and > > release of the global lock), whose are then guaranteed to execute > > (without transactions interleaving with each other) in a global total > > order (let's call this order TO). TO then contributes to > > happens-before. > > > > On the ABI level, the TM runtime is allowed to execute speculatively as > > long as (1) it does not expose any speculative execution to > > nontransactional code and (2) speculation doesn't violate the language's > > as-if rules (i.e., no visible side effects other than the abstract > > machine; no signals due to seg faults etc.). This means that, for > > example, the TM will not access data at a wider granularity than what > > nontransactional code that conforms to the C++11 memory model does would > > do. > > Second, transactions can have a tentative position in TO, but they will > > only expose final TO choices to nontxnal code. So, each transaction > > will execute code that would be valid when executed in isolation -- but > > it is possible that several transactions noncommitted transactions are > > in flight concurrently that may conflict with each other. The TM > > ensures that such speculative execution is safe and not visible to a > > race-free program. So, when a transaction commits at a certain position > > in TO, it will make sure that all other active transactions reach > > consensus on TO (up to this position) before it returns to the execution > > of nontxnal code. Those active transactions will either see that they > > would be still valid at a new TO position (after the committing txn), or > > they abort and then signal that they agree to this TO. That means that > > the nontxnal code will not be affected by any speculative execution, > > even if the prior txn privatized some data (this is called privatization > > safety in TM jargon). > > The sort-of counterpart to privatization safety is publication safety > > (ie, transactions can safely make some data shared). While > > privatization safety is handled by the TM runtime, publication safety is > > ensured by the compiler by not allowing any dangerous load/load > > reordering, basicallly. Publication safety is not yet ensured always, > > but Aldy is working on this. > > > >> > than are detected later and trx is restarted. Can't asan trigger false > >> > positives in this case? > >> > >> I can't imagine any. > > > > I also don't see any, because all loads/stores of all transactions, even > > those with a tentative TO position, would be a valid execution. For > > malloc/free in transactions, AFAIR, ASAN hooks into malloc/free > > directly, so when libitm handles those including rollback of an > > allocation, there shouldn't be false positives. However, there might be > > false negatives in case of free() because deallocations are deferred > > until transaction commit (they can't be rolled back). Could we tell > > ASAN about free() directly using a call added by the TM instrumentation > > pass? That would at least help catch the false negatives for all > > free()-like functions that the compiler knows about. > > I do not think that false positive is super important. We have a similar false negative in case of racy use after free, when the free the just happen to happen after the use. > > However, it must be possible to support, because in case of asan we do can "rollback" free. > But won't it lead to false positives in case of: > > __transaction { > free(p); > p = 0; > } > > __transaction { > r = 0; > if (p) > r = p->x; > ... > > } > ? > > > > All of this is different for TSAN, of course, because there a memory > > access does alter the state that TSAN keeps, so if we roll back the > > accesses in the TM we would also have to roll back the TSAN state. > > > I think the simplest way to solve it for now, it to use... well, single global lock. > I.e. replace __txn_start() with global pthread_mutex_t acquisition, __txn_commit() with lock release. And no transactional instrumentation inside of the trx. It should be correct transformation, right. However, I am not sure what to do with __txn_abort()... > > > > > >> > Also, what is the order of instrumentation in tm+asan setting? I mean > >> > that neither tm must instrument asan instrumentation, nor asan must > >> > instrument tm instrumentation. Is it the case? There also can be > >> > conflicts related to ordering of instrumentation in the following > >> > case: > >> > asan_check(); > >> > speculative_load(); > >> > tm_check(); > > > > The ordering of instrumentation is an interesting question, but I think > > that putting the ASAN check before the TM load/store is the right thing > > to do. It will catch any illegal access before it's performed. It > > doesn't suffer from false positives because the TM will only allow valid > > (even though speculative) executions. For this ordering to not be valid > > (ie, tm_check before asan_check), transactions would need to be able to > > prevent access to a certain variable by writing to them (which doesn't > > work). Other cases in which the transaction would perform the access > > because of values of other variables that it loaded previously are > > covered by privatization safety. > > > >> I'm not aware of TM having speculative loads, libgtm certainly doesn't > >> install a SIGSEGV handler (and testing whether some memory is > >> readable/writable without actually dereferencing would be terribly slow). > >> If a memory load or store segfaults, whether in a transaction or outside of > >> it, it is a program bug and it is right if asan terminates the program. > > > > Right, memory accesses performed by the TM are only speculative to the > > extent described above. > > There was a project called Transactional Locking II, if you are interested: > > https://github.com/daveboutcher/tl2-x86-mp/blob/master/tl2.c > /* > * Fetch tentative value > * Use either SPARC non-fault loads or complicit signal handlers. > * If the LD fails we'd like to call TxAbort() > * TL2 does not permit zombie/doomed txns to run > */ > volatile vwLock* LockFor = PSLOCK(Addr); > vwLock rdv = LDLOCK(LockFor) & ~LOCKBIT; > MEMBARLDLD(); > Valu = LDNF(Addr); > MEMBARLDLD(); > if (rdv <= Self->rv && LDLOCK(LockFor) == rdv) { > if (!Self->IsRO) { > if (!TrackLoad(Self, LockFor)) { > PROF_STM_READ_END(); > TxAbort(Self); > } > } > PROF_STM_READ_END(); > return Valu; > } > >
On Mon, 2012-12-17 at 13:52 +0400, Dmitry Vyukov wrote: > resend in plain text > > On Mon, Dec 17, 2012 at 1:50 PM, Dmitry Vyukov <dvyukov@google.com> wrote: > > > > On Fri, Dec 14, 2012 at 5:43 PM, Torvald Riegel <triegel@redhat.com> wrote: > > > On Thu, 2012-12-13 at 10:02 +0100, Jakub Jelinek wrote: > > >> On Thu, Dec 13, 2012 at 10:38:13AM +0400, Dmitry Vyukov wrote: > > >> > On Wed, Dec 12, 2012 at 11:50 PM, Jakub Jelinek <jakub@redhat.com> wrote: > > >> > > Various TM tests ICE when built with -fgnu-tm -fsanitizer=address. > > >> > > The problem is that asan.c pass adds calls to builtins that weren't there > > >> > > before and TM is upset about it. The __asan_report* are all like > > >> > > abort, in correctly written program they shouldn't have a user visible > > >> > > effect, in bad program they will terminate the process, but in any case > > >> > > it doesn't matter how many times they are retried as part of a transaction, > > >> > > there is no state to roll back on transaction cancellation. > > >> > > __asan_handle_no_return, while not being noreturn, just marks the stack as > > >> > > unprotected, so again in correctly written application no effect, in bad app > > >> > > might result in some issues being undetected, but still, it can be done many > > >> > > times and isn't irreversible. > > >> > > > >> > I was only loosely following tm-languages discussions. Does gcc tm > > >> > model guarantees strong consistency for all memory accesses? I mean > > >> > there are tm implementations that allow transient inconsistencies, > > >> > > >> Will leave this to Torvald. > > > > > > This has two parts: (1) how TM fits into the C++11/C11 memory model, and > > > (2) which guarantees the compiler and the TM runtime library agree on at > > > the level of the TM ABI that we use in GCC. > > > > > > Regarding the first part, all transactions provide guarantees similar to > > > a global lock. Specifically, there are virtual transaction start/end > > > events that take part in sequenced-before (similar to acquisition and > > > release of the global lock), whose are then guaranteed to execute > > > (without transactions interleaving with each other) in a global total > > > order (let's call this order TO). TO then contributes to > > > happens-before. > > > > > > On the ABI level, the TM runtime is allowed to execute speculatively as > > > long as (1) it does not expose any speculative execution to > > > nontransactional code and (2) speculation doesn't violate the language's > > > as-if rules (i.e., no visible side effects other than the abstract > > > machine; no signals due to seg faults etc.). This means that, for > > > example, the TM will not access data at a wider granularity than what > > > nontransactional code that conforms to the C++11 memory model does would > > > do. > > > Second, transactions can have a tentative position in TO, but they will > > > only expose final TO choices to nontxnal code. So, each transaction > > > will execute code that would be valid when executed in isolation -- but > > > it is possible that several transactions noncommitted transactions are > > > in flight concurrently that may conflict with each other. The TM > > > ensures that such speculative execution is safe and not visible to a > > > race-free program. So, when a transaction commits at a certain position > > > in TO, it will make sure that all other active transactions reach > > > consensus on TO (up to this position) before it returns to the execution > > > of nontxnal code. Those active transactions will either see that they > > > would be still valid at a new TO position (after the committing txn), or > > > they abort and then signal that they agree to this TO. That means that > > > the nontxnal code will not be affected by any speculative execution, > > > even if the prior txn privatized some data (this is called privatization > > > safety in TM jargon). > > > The sort-of counterpart to privatization safety is publication safety > > > (ie, transactions can safely make some data shared). While > > > privatization safety is handled by the TM runtime, publication safety is > > > ensured by the compiler by not allowing any dangerous load/load > > > reordering, basicallly. Publication safety is not yet ensured always, > > > but Aldy is working on this. > > > > > >> > than are detected later and trx is restarted. Can't asan trigger false > > >> > positives in this case? > > >> > > >> I can't imagine any. > > > > > > I also don't see any, because all loads/stores of all transactions, even > > > those with a tentative TO position, would be a valid execution. For > > > malloc/free in transactions, AFAIR, ASAN hooks into malloc/free > > > directly, so when libitm handles those including rollback of an > > > allocation, there shouldn't be false positives. However, there might be > > > false negatives in case of free() because deallocations are deferred > > > until transaction commit (they can't be rolled back). Could we tell > > > ASAN about free() directly using a call added by the TM instrumentation > > > pass? That would at least help catch the false negatives for all > > > free()-like functions that the compiler knows about. > > > > I do not think that false positive is super important. We have a similar false negative in case of racy use after free, when the free the just happen to happen after the use. > > > > However, it must be possible to support, because in case of asan we do can "rollback" free. > > But won't it lead to false positives in case of: > > > > __transaction { > > free(p); > > p = 0; > > } > > > > __transaction { > > r = 0; > > if (p) > > r = p->x; > > ... > > > > } > > ? (First, sorry for the late reply.) You raise a good point. For the thread executing the free(), the free() should take immediate effect in the realm of asan checking. For other threads, it's more complicated because they can virtually execute at older TO positions (see above). The simplest solution would probably be again to execute transactions serially. Otherwise, we could use an STM with visible reads, which doesn't switch TO position during execution of transactions (but there's no STM method with visible reads implemented in libitm yet); or, we could invisible reads and replay all memory accesses whenever a transaction switches it's TO position. > > > > > > > All of this is different for TSAN, of course, because there a memory > > > access does alter the state that TSAN keeps, so if we roll back the > > > accesses in the TM we would also have to roll back the TSAN state. > > > > > > I think the simplest way to solve it for now, it to use... well, single global lock. > > I.e. replace __txn_start() with global pthread_mutex_t acquisition, __txn_commit() with lock release. And no transactional instrumentation inside of the trx. It should be correct transformation, right. However, I am not sure what to do with __txn_abort()... This is already an execution mode supported by libitm. It can be forced by setting an env var: LIBITM_DEFAULT_METHOD=serial Should we just tell users (in the docs) to set this env var when using TSAN, or can TSAN set it, or should there be a way for TSAN to set the mode using another mechanism? > > >> > Also, what is the order of instrumentation in tm+asan setting? I mean > > >> > that neither tm must instrument asan instrumentation, nor asan must > > >> > instrument tm instrumentation. Is it the case? There also can be > > >> > conflicts related to ordering of instrumentation in the following > > >> > case: > > >> > asan_check(); > > >> > speculative_load(); > > >> > tm_check(); > > > > > > The ordering of instrumentation is an interesting question, but I think > > > that putting the ASAN check before the TM load/store is the right thing > > > to do. It will catch any illegal access before it's performed. It > > > doesn't suffer from false positives because the TM will only allow valid > > > (even though speculative) executions. For this ordering to not be valid > > > (ie, tm_check before asan_check), transactions would need to be able to > > > prevent access to a certain variable by writing to them (which doesn't > > > work). Other cases in which the transaction would perform the access > > > because of values of other variables that it loaded previously are > > > covered by privatization safety. > > > > > >> I'm not aware of TM having speculative loads, libgtm certainly doesn't > > >> install a SIGSEGV handler (and testing whether some memory is > > >> readable/writable without actually dereferencing would be terribly slow). > > >> If a memory load or store segfaults, whether in a transaction or outside of > > >> it, it is a program bug and it is right if asan terminates the program. > > > > > > Right, memory accesses performed by the TM are only speculative to the > > > extent described above. > > > > There was a project called Transactional Locking II, if you are interested: > > > > https://github.com/daveboutcher/tl2-x86-mp/blob/master/tl2.c > > /* > > * Fetch tentative value > > * Use either SPARC non-fault loads The only architecture that has non-faulting loads is SPARC, AFAIK. > or complicit signal handlers. The signal handlers are probably too fragile in practice. The TM runtime library would have to prevent all other parts of the program from overwriting the handler, and the faults are still visible in the OS and thus perhaps visible to other components. I've not seen a rock-solid, practical implementation of masking such faults yet. Privatization safety can avoid this issue, and it's necessary anyway with time-based STMs such as TL2 (which don't provide privatization safety). This trade-off might be different for single-orec STM algorithms such as NOrec which provide privatization safety except this issue of pending loads. Torvald
On Thu, Jan 24, 2013 at 9:29 PM, Torvald Riegel <triegel@redhat.com> wrote: > On Mon, 2012-12-17 at 13:52 +0400, Dmitry Vyukov wrote: >> resend in plain text >> >> On Mon, Dec 17, 2012 at 1:50 PM, Dmitry Vyukov <dvyukov@google.com> wrote: >> > >> > On Fri, Dec 14, 2012 at 5:43 PM, Torvald Riegel <triegel@redhat.com> wrote: >> > > On Thu, 2012-12-13 at 10:02 +0100, Jakub Jelinek wrote: >> > >> On Thu, Dec 13, 2012 at 10:38:13AM +0400, Dmitry Vyukov wrote: >> > >> > On Wed, Dec 12, 2012 at 11:50 PM, Jakub Jelinek <jakub@redhat.com> wrote: >> > >> > > Various TM tests ICE when built with -fgnu-tm -fsanitizer=address. >> > >> > > The problem is that asan.c pass adds calls to builtins that weren't there >> > >> > > before and TM is upset about it. The __asan_report* are all like >> > >> > > abort, in correctly written program they shouldn't have a user visible >> > >> > > effect, in bad program they will terminate the process, but in any case >> > >> > > it doesn't matter how many times they are retried as part of a transaction, >> > >> > > there is no state to roll back on transaction cancellation. >> > >> > > __asan_handle_no_return, while not being noreturn, just marks the stack as >> > >> > > unprotected, so again in correctly written application no effect, in bad app >> > >> > > might result in some issues being undetected, but still, it can be done many >> > >> > > times and isn't irreversible. >> > >> > >> > >> > I was only loosely following tm-languages discussions. Does gcc tm >> > >> > model guarantees strong consistency for all memory accesses? I mean >> > >> > there are tm implementations that allow transient inconsistencies, >> > >> >> > >> Will leave this to Torvald. >> > > >> > > This has two parts: (1) how TM fits into the C++11/C11 memory model, and >> > > (2) which guarantees the compiler and the TM runtime library agree on at >> > > the level of the TM ABI that we use in GCC. >> > > >> > > Regarding the first part, all transactions provide guarantees similar to >> > > a global lock. Specifically, there are virtual transaction start/end >> > > events that take part in sequenced-before (similar to acquisition and >> > > release of the global lock), whose are then guaranteed to execute >> > > (without transactions interleaving with each other) in a global total >> > > order (let's call this order TO). TO then contributes to >> > > happens-before. >> > > >> > > On the ABI level, the TM runtime is allowed to execute speculatively as >> > > long as (1) it does not expose any speculative execution to >> > > nontransactional code and (2) speculation doesn't violate the language's >> > > as-if rules (i.e., no visible side effects other than the abstract >> > > machine; no signals due to seg faults etc.). This means that, for >> > > example, the TM will not access data at a wider granularity than what >> > > nontransactional code that conforms to the C++11 memory model does would >> > > do. >> > > Second, transactions can have a tentative position in TO, but they will >> > > only expose final TO choices to nontxnal code. So, each transaction >> > > will execute code that would be valid when executed in isolation -- but >> > > it is possible that several transactions noncommitted transactions are >> > > in flight concurrently that may conflict with each other. The TM >> > > ensures that such speculative execution is safe and not visible to a >> > > race-free program. So, when a transaction commits at a certain position >> > > in TO, it will make sure that all other active transactions reach >> > > consensus on TO (up to this position) before it returns to the execution >> > > of nontxnal code. Those active transactions will either see that they >> > > would be still valid at a new TO position (after the committing txn), or >> > > they abort and then signal that they agree to this TO. That means that >> > > the nontxnal code will not be affected by any speculative execution, >> > > even if the prior txn privatized some data (this is called privatization >> > > safety in TM jargon). >> > > The sort-of counterpart to privatization safety is publication safety >> > > (ie, transactions can safely make some data shared). While >> > > privatization safety is handled by the TM runtime, publication safety is >> > > ensured by the compiler by not allowing any dangerous load/load >> > > reordering, basicallly. Publication safety is not yet ensured always, >> > > but Aldy is working on this. >> > > >> > >> > than are detected later and trx is restarted. Can't asan trigger false >> > >> > positives in this case? >> > >> >> > >> I can't imagine any. >> > > >> > > I also don't see any, because all loads/stores of all transactions, even >> > > those with a tentative TO position, would be a valid execution. For >> > > malloc/free in transactions, AFAIR, ASAN hooks into malloc/free >> > > directly, so when libitm handles those including rollback of an >> > > allocation, there shouldn't be false positives. However, there might be >> > > false negatives in case of free() because deallocations are deferred >> > > until transaction commit (they can't be rolled back). Could we tell >> > > ASAN about free() directly using a call added by the TM instrumentation >> > > pass? That would at least help catch the false negatives for all >> > > free()-like functions that the compiler knows about. >> > >> > I do not think that false positive is super important. We have a similar false negative in case of racy use after free, when the free the just happen to happen after the use. >> > >> > However, it must be possible to support, because in case of asan we do can "rollback" free. >> > But won't it lead to false positives in case of: >> > >> > __transaction { >> > free(p); >> > p = 0; >> > } >> > >> > __transaction { >> > r = 0; >> > if (p) >> > r = p->x; >> > ... >> > >> > } >> > ? > > (First, sorry for the late reply.) > > You raise a good point. For the thread executing the free(), the free() > should take immediate effect in the realm of asan checking. For other > threads, it's more complicated because they can virtually execute at > older TO positions (see above). > The simplest solution would probably be again to execute transactions > serially. Otherwise, we could use an STM with visible reads, which > doesn't switch TO position during execution of transactions (but there's > no STM method with visible reads implemented in libitm yet); or, we > could invisible reads and replay all memory accesses whenever a > transaction switches it's TO position. > >> > >> > >> > > All of this is different for TSAN, of course, because there a memory >> > > access does alter the state that TSAN keeps, so if we roll back the >> > > accesses in the TM we would also have to roll back the TSAN state. >> > >> > >> > I think the simplest way to solve it for now, it to use... well, single global lock. >> > I.e. replace __txn_start() with global pthread_mutex_t acquisition, __txn_commit() with lock release. And no transactional instrumentation inside of the trx. It should be correct transformation, right. However, I am not sure what to do with __txn_abort()... > > This is already an execution mode supported by libitm. It can be forced > by setting an env var: LIBITM_DEFAULT_METHOD=serial > > Should we just tell users (in the docs) to set this env var when using > TSAN, or can TSAN set it, or should there be a way for TSAN to set the > mode using another mechanism? Tsan can set LIBITM_DEFAULT_METHOD during initialization. Other modes won't work with tsan, and users don't usually read docs. Users must not be able to override the mode. Does somebody tried to execute some transactional code with tsan? Does it work at all (with LIBITM_DEFAULT_METHOD=serial)? >> > >> > Also, what is the order of instrumentation in tm+asan setting? I mean >> > >> > that neither tm must instrument asan instrumentation, nor asan must >> > >> > instrument tm instrumentation. Is it the case? There also can be >> > >> > conflicts related to ordering of instrumentation in the following >> > >> > case: >> > >> > asan_check(); >> > >> > speculative_load(); >> > >> > tm_check(); >> > > >> > > The ordering of instrumentation is an interesting question, but I think >> > > that putting the ASAN check before the TM load/store is the right thing >> > > to do. It will catch any illegal access before it's performed. It >> > > doesn't suffer from false positives because the TM will only allow valid >> > > (even though speculative) executions. For this ordering to not be valid >> > > (ie, tm_check before asan_check), transactions would need to be able to >> > > prevent access to a certain variable by writing to them (which doesn't >> > > work). Other cases in which the transaction would perform the access >> > > because of values of other variables that it loaded previously are >> > > covered by privatization safety. >> > > >> > >> I'm not aware of TM having speculative loads, libgtm certainly doesn't >> > >> install a SIGSEGV handler (and testing whether some memory is >> > >> readable/writable without actually dereferencing would be terribly slow). >> > >> If a memory load or store segfaults, whether in a transaction or outside of >> > >> it, it is a program bug and it is right if asan terminates the program. >> > > >> > > Right, memory accesses performed by the TM are only speculative to the >> > > extent described above. >> > >> > There was a project called Transactional Locking II, if you are interested: >> > >> > https://github.com/daveboutcher/tl2-x86-mp/blob/master/tl2.c >> > /* >> > * Fetch tentative value >> > * Use either SPARC non-fault loads > > The only architecture that has non-faulting loads is SPARC, AFAIK. > >> or complicit signal handlers. > > The signal handlers are probably too fragile in practice. The TM > runtime library would have to prevent all other parts of the program > from overwriting the handler, and the faults are still visible in the OS > and thus perhaps visible to other components. I've not seen a > rock-solid, practical implementation of masking such faults yet. > > Privatization safety can avoid this issue, and it's necessary anyway > with time-based STMs such as TL2 (which don't provide privatization > safety). This trade-off might be different for single-orec STM > algorithms such as NOrec which provide privatization safety except this > issue of pending loads. Agree.
On Thu, 2013-01-24 at 21:44 +0400, Dmitry Vyukov wrote: > On Thu, Jan 24, 2013 at 9:29 PM, Torvald Riegel <triegel@redhat.com> wrote: > > On Mon, 2012-12-17 at 13:52 +0400, Dmitry Vyukov wrote: > >> > I think the simplest way to solve it for now, it to use... well, single global lock. > >> > I.e. replace __txn_start() with global pthread_mutex_t acquisition, __txn_commit() with lock release. And no transactional instrumentation inside of the trx. It should be correct transformation, right. However, I am not sure what to do with __txn_abort()... > > > > This is already an execution mode supported by libitm. It can be forced > > by setting an env var: LIBITM_DEFAULT_METHOD=serial > > > > Should we just tell users (in the docs) to set this env var when using > > TSAN, or can TSAN set it, or should there be a way for TSAN to set the > > mode using another mechanism? > > Tsan can set LIBITM_DEFAULT_METHOD during initialization. Other modes > won't work with tsan, and users don't usually read docs. Users must > not be able to override the mode. The only way to influence the mode is through the env var, so if Tsan sets it before the first transaction is executed, this should be fine I guess. > Does somebody tried to execute some transactional code with tsan? Does > it work at all (with LIBITM_DEFAULT_METHOD=serial)? I haven't yet. Torvald
--- gcc/builtin-attrs.def.jj 2012-10-22 08:42:23.000000000 +0200 +++ gcc/builtin-attrs.def 2012-12-12 11:56:54.942938879 +0100 @@ -263,6 +263,11 @@ DEF_ATTR_TREE_LIST (ATTR_TMPURE_MALLOC_N DEF_ATTR_TREE_LIST (ATTR_TMPURE_NOTHROW_LIST, ATTR_TM_TMPURE, ATTR_NULL, ATTR_NOTHROW_LIST) +DEF_ATTR_TREE_LIST (ATTR_TMPURE_NOTHROW_LEAF_LIST, + ATTR_TM_TMPURE, ATTR_NULL, ATTR_NOTHROW_LEAF_LIST) +DEF_ATTR_TREE_LIST (ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST, + ATTR_TM_TMPURE, ATTR_NULL, ATTR_NORETURN_NOTHROW_LEAF_LIST) + /* Construct a tree for a format_arg attribute. */ #define DEF_FORMAT_ARG_ATTRIBUTE(FA) \ DEF_ATTR_TREE_LIST (ATTR_FORMAT_ARG_##FA, ATTR_FORMAT_ARG, \ --- gcc/asan.c.jj 2012-12-11 13:05:36.000000000 +0100 +++ gcc/asan.c 2012-12-12 11:57:59.626550534 +0100 @@ -1611,8 +1611,13 @@ initialize_sanitizer_builtins (void) #define BT_FN_VOID_VPTR_I16_INT BT_FN_VOID_VPTR_IX_INT[4] #undef ATTR_NOTHROW_LEAF_LIST #define ATTR_NOTHROW_LEAF_LIST ECF_NOTHROW | ECF_LEAF +#undef ATTR_TMPURE_NOTHROW_LEAF_LIST +#define ATTR_TMPURE_NOTHROW_LEAF_LIST ECF_TM_PURE | ATTR_NOTHROW_LEAF_LIST #undef ATTR_NORETURN_NOTHROW_LEAF_LIST #define ATTR_NORETURN_NOTHROW_LEAF_LIST ECF_NORETURN | ATTR_NOTHROW_LEAF_LIST +#undef ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST +#define ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST \ + ECF_TM_PURE | ATTR_NORETURN_NOTHROW_LEAF_LIST #undef DEF_SANITIZER_BUILTIN #define DEF_SANITIZER_BUILTIN(ENUM, NAME, TYPE, ATTRS) \ decl = add_builtin_function ("__builtin_" NAME, TYPE, ENUM, \ --- gcc/sanitizer.def.jj 2012-12-11 11:28:10.000000000 +0100 +++ gcc/sanitizer.def 2012-12-12 11:57:12.714833945 +0100 @@ -32,25 +32,25 @@ DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_INIT /* Do not reorder the BUILT_IN_ASAN_REPORT* builtins, e.g. cfgcleanup.c relies on this order. */ DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_LOAD1, "__asan_report_load1", - BT_FN_VOID_PTR, ATTR_NORETURN_NOTHROW_LEAF_LIST) + BT_FN_VOID_PTR, ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST) DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_LOAD2, "__asan_report_load2", - BT_FN_VOID_PTR, ATTR_NORETURN_NOTHROW_LEAF_LIST) + BT_FN_VOID_PTR, ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST) DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_LOAD4, "__asan_report_load4", - BT_FN_VOID_PTR, ATTR_NORETURN_NOTHROW_LEAF_LIST) + BT_FN_VOID_PTR, ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST) DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_LOAD8, "__asan_report_load8", - BT_FN_VOID_PTR, ATTR_NORETURN_NOTHROW_LEAF_LIST) + BT_FN_VOID_PTR, ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST) DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_LOAD16, "__asan_report_load16", - BT_FN_VOID_PTR, ATTR_NORETURN_NOTHROW_LEAF_LIST) + BT_FN_VOID_PTR, ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST) DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE1, "__asan_report_store1", - BT_FN_VOID_PTR, ATTR_NORETURN_NOTHROW_LEAF_LIST) + BT_FN_VOID_PTR, ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST) DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE2, "__asan_report_store2", - BT_FN_VOID_PTR, ATTR_NORETURN_NOTHROW_LEAF_LIST) + BT_FN_VOID_PTR, ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST) DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE4, "__asan_report_store4", - BT_FN_VOID_PTR, ATTR_NORETURN_NOTHROW_LEAF_LIST) + BT_FN_VOID_PTR, ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST) DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE8, "__asan_report_store8", - BT_FN_VOID_PTR, ATTR_NORETURN_NOTHROW_LEAF_LIST) + BT_FN_VOID_PTR, ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST) DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE16, "__asan_report_store16", - BT_FN_VOID_PTR, ATTR_NORETURN_NOTHROW_LEAF_LIST) + BT_FN_VOID_PTR, ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST) DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REGISTER_GLOBALS, "__asan_register_globals", BT_FN_VOID_PTR_PTRMODE, ATTR_NOTHROW_LEAF_LIST) @@ -59,7 +59,7 @@ DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_UNRE BT_FN_VOID_PTR_PTRMODE, ATTR_NOTHROW_LEAF_LIST) DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_HANDLE_NO_RETURN, "__asan_handle_no_return", - BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST) + BT_FN_VOID, ATTR_TMPURE_NOTHROW_LEAF_LIST) /* Thread Sanitizer */ DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_INIT, "__tsan_init",