On Sat, Mar 1, 2014 at 2:32 AM, Peter Bergner <berg...@vnet.ibm.com> wrote: > I'd like to ask for permission to backport the following two LIBITM bug > fixes to the FSF 4.8 branch. Although these are not technically fixing > regressions, they do fix the libitm.c/reentrant.c testsuite failure on > s390 and powerpc (or at least it will when we finally get our power8 > code backported to FSF 4.8). It also fixes a real bug on x86 that is > latent because we don't currently have a test case that warms up the > x86's RTM hardware enough such that its xbegin succeeds exposing the > bug. I'd like this backport so that the 4.8 based distros won't need > to carry this as an add-on patch. > > It should also be fairly safe as well, since the fixed code is limited > to the arches (x86, s390 and powerpc) that define USE_HTM_FASTPATH, > so all others definitely won't see a difference.
Works for me in case nobody else objects within 24h. Thanks, Richard. > I'll note I CC'd some of the usual suspects interested in TM as well > as the normal RMs, because LIBITM doesn't seem to have a maintainer > or reviewer listed in the MAINTAINERS file. Is that an oversight or??? > > Peter > > Backport from mainline > 2013-06-20 Torvald Riegel <trie...@redhat.com> > > * query.cc (_ITM_inTransaction): Abort when using the HTM fastpath. > (_ITM_getTransactionId): Same. > * config/x86/target.h (htm_transaction_active): New. > > 2013-06-20 Torvald Riegel <trie...@redhat.com> > > PR libitm/57643 > * beginend.cc (gtm_thread::begin_transaction): Handle reentrancy in > the HTM fastpath. > > Index: libitm/beginend.cc > =================================================================== > --- libitm/beginend.cc (revision 208151) > +++ libitm/beginend.cc (working copy) > @@ -197,6 +197,8 @@ > // We are executing a transaction now. > // Monitor the writer flag in the serial-mode lock, and abort > // if there is an active or waiting serial-mode transaction. > + // Note that this can also happen due to an enclosing > + // serial-mode transaction; we handle this case below. > if (unlikely(serial_lock.is_write_locked())) > htm_abort(); > else > @@ -219,6 +221,14 @@ > tx = new gtm_thread(); > set_gtm_thr(tx); > } > + // Check whether there is an enclosing serial-mode transaction; > + // if so, we just continue as a nested transaction and don't > + // try to use the HTM fastpath. This case can happen when an > + // outermost relaxed transaction calls unsafe code that starts > + // a transaction. > + if (tx->nesting > 0) > + break; > + // Another thread is running a serial-mode transaction. Wait. > serial_lock.read_lock(tx); > serial_lock.read_unlock(tx); > // TODO We should probably reset the retry count t here, unless > Index: libitm/config/x86/target.h > =================================================================== > --- libitm/config/x86/target.h (revision 208151) > +++ libitm/config/x86/target.h (working copy) > @@ -125,6 +125,13 @@ > { > return begin_ret & _XABORT_RETRY; > } > + > +/* Returns true iff a hardware transaction is currently being executed. */ > +static inline bool > +htm_transaction_active () > +{ > + return _xtest() != 0; > +} > #endif > > > Index: libitm/query.cc > =================================================================== > --- libitm/query.cc (revision 208151) > +++ libitm/query.cc (working copy) > @@ -43,6 +43,15 @@ > _ITM_howExecuting ITM_REGPARM > _ITM_inTransaction (void) > { > +#if defined(USE_HTM_FASTPATH) > + // If we use the HTM fastpath, we cannot reliably detect whether we are > + // in a transaction because this function can be called outside of > + // a transaction and thus we can't deduce this by looking at just the > serial > + // lock. This function isn't used in practice currently, so the easiest > + // way to handle it is to just abort. > + if (htm_fastpath && htm_transaction_active()) > + htm_abort(); > +#endif > struct gtm_thread *tx = gtm_thr(); > if (tx && (tx->nesting > 0)) > { > @@ -58,6 +67,11 @@ > _ITM_transactionId_t ITM_REGPARM > _ITM_getTransactionId (void) > { > +#if defined(USE_HTM_FASTPATH) > + // See ITM_inTransaction. > + if (htm_fastpath && htm_transaction_active()) > + htm_abort(); > +#endif > struct gtm_thread *tx = gtm_thr(); > return (tx && (tx->nesting > 0)) ? tx->id : _ITM_noTransactionId; > } > >