patch3: After the previous change to flat nesting by default, checkpoints, and thus having only a single gtm_transaction object per thread, we can move the local_tid field to gtm_transaction too. As a result, we don't have to access gtm_thread in GTM_begin_transaction anymore.
patch4: A small fix that adds a missing set-up call for gtm_thread. And a matching test case, which tests that the functions in query.cc work even if no transaction has been executed so far in this thread. OK for branch?
commit 33c3c869c7cb986bcca3f3f44b0412278e880a82 Author: Torvald Riegel <trie...@redhat.com> Date: Fri Jul 29 16:09:05 2011 +0200 Move local_tid from gtm_thread to gtm_transaction. * config/generic/tls.h (gtm_thread): Move local_tid from here ... * libitm_i.h (local_tid): ... to here. * beginend.cc (GTM::gtm_transaction::begin_transaction): Same. (GTM::gtm_transaction::operator new): Set up gtm_thread if necessary. diff --git a/libitm/beginend.cc b/libitm/beginend.cc index d336d60..a16c3f9 100644 --- a/libitm/beginend.cc +++ b/libitm/beginend.cc @@ -43,7 +43,7 @@ static _ITM_transactionId_t global_tid; void * GTM::gtm_transaction::operator new (size_t s) { - gtm_thread *thr = gtm_thr (); + gtm_thread *thr = setup_gtm_thr (); void *tx; assert(s == sizeof(gtm_transaction)); @@ -112,8 +112,6 @@ GTM::gtm_transaction::begin_transaction (uint32_t prop, const gtm_jmpbuf *jb) if (unlikely(prop & pr_undoLogCode)) GTM_fatal("pr_undoLogCode not supported"); - gtm_thread *thr = setup_gtm_thr (); - tx = gtm_tx(); if (tx == NULL) { @@ -214,18 +212,18 @@ GTM::gtm_transaction::begin_transaction (uint32_t prop, const gtm_jmpbuf *jb) // As long as we have not exhausted a previously allocated block of TIDs, // we can avoid an atomic operation on a shared cacheline. - if (thr->local_tid & (tid_block_size - 1)) - tx->id = thr->local_tid++; + if (tx->local_tid & (tid_block_size - 1)) + tx->id = tx->local_tid++; else { #ifdef HAVE_64BIT_SYNC_BUILTINS tx->id = __sync_add_and_fetch (&global_tid, tid_block_size); - thr->local_tid = tx->id + 1; + tx->local_tid = tx->id + 1; #else pthread_mutex_lock (&global_tid_lock); global_tid += tid_block_size; tx->id = global_tid; - thr->local_tid = tx->id + 1; + tx->local_tid = tx->id + 1; pthread_mutex_unlock (&global_tid_lock); #endif } diff --git a/libitm/config/generic/tls.h b/libitm/config/generic/tls.h index 82d7c66..8a39b80 100644 --- a/libitm/config/generic/tls.h +++ b/libitm/config/generic/tls.h @@ -50,12 +50,6 @@ struct gtm_thread void *free_tx[MAX_FREE_TX]; unsigned free_tx_idx, free_tx_count; - // In order to reduce cacheline contention on global_tid during - // beginTransaction, we allocate a block of 2**N ids to the thread - // all at once. This number is the next value to be allocated from - // the block, or 0 % 2**N if no such block is allocated. - _ITM_transactionId_t local_tid; - // The value returned by _ITM_getThreadnum to identify this thread. // ??? At present, this is densely allocated beginning with 1 and // we don't bother filling in this value until it is requested. diff --git a/libitm/libitm_i.h b/libitm/libitm_i.h index 97f535a..7d475be 100644 --- a/libitm/libitm_i.h +++ b/libitm/libitm_i.h @@ -168,6 +168,12 @@ struct gtm_transaction // A bitmask of the above. uint32_t state; + // In order to reduce cacheline contention on global_tid during + // beginTransaction, we allocate a block of 2**N ids to the thread + // all at once. This number is the next value to be allocated from + // the block, or 0 % 2**N if no such block is allocated. + _ITM_transactionId_t local_tid; + // Data used by eh_cpp.c for managing exceptions within the transaction. uint32_t cxa_catch_count; void *cxa_unthrown;
commit 22c19978ba11c0ae0321449d8809260ab5f97741 Author: Torvald Riegel <trie...@redhat.com> Date: Fri Jul 29 16:19:41 2011 +0200 Fix missing setup of gtm_thread if no transaction has run yet. * query.cc (_ITM_getThreadnum): Set up gtm_thread if necessary. * testsuite/libitm.c/notx.c: New file. diff --git a/libitm/query.cc b/libitm/query.cc index 9a95211..02f1813 100644 --- a/libitm/query.cc +++ b/libitm/query.cc @@ -67,7 +67,7 @@ int ITM_REGPARM _ITM_getThreadnum (void) { static int global_num; - struct gtm_thread *thr = gtm_thr(); + struct gtm_thread *thr = setup_gtm_thr(); int num = thr->thread_num; if (num == 0) diff --git a/libitm/testsuite/libitm.c/notx.c b/libitm/testsuite/libitm.c/notx.c new file mode 100644 index 0000000..92ae3e1 --- /dev/null +++ b/libitm/testsuite/libitm.c/notx.c @@ -0,0 +1,36 @@ +/* These tests all check whether initialization happens properly even if no + transaction has been used in the current thread yet. */ +#include <stdlib.h> +#include <pthread.h> +#include <libitm.h> + +static void *test1 (void *dummy __attribute__((unused))) +{ + if (_ITM_inTransaction() != outsideTransaction) + abort(); + return NULL; +} + +static void *test2 (void *dummy __attribute__((unused))) +{ + if (_ITM_getTransactionId() != _ITM_noTransactionId) + abort(); + return NULL; +} + + +int main() +{ + pthread_t thread; + + if (_ITM_getThreadnum() != 1) + abort(); + + pthread_create(&thread, NULL, test1, NULL); + pthread_join(thread, NULL); + + pthread_create(&thread, NULL, test2, NULL); + pthread_join(thread, NULL); + + return 0; +}