void * _ITM_calloc(size_t nm, size_t size) { stm_tx_t *tx = tls_get_tx(); if (tx == NULL || !stm_active_tx(tx)) return calloc(nm, size); return stm_calloc_tx(tx, nm, size); }
_ITM_transaction * _ITM_CALL_CONVENTION _ITM_getTransaction(void) { struct stm_tx *tx = tls_get_tx(); if (unlikely(tx == NULL)) { /* Thread not initialized: must create transaction */ tx = abi_init_thread(); } return (_ITM_transaction *)tx; }
void _ITM_free(void *ptr) { stm_tx_t *tx = tls_get_tx(); if (tx == NULL || !stm_active_tx(tx)) { free(ptr); return; } #ifdef NO_WRITE_ON_FREE stm_free_tx(tx, ptr, 0); #else stm_free_tx(tx, ptr, block_size(ptr)); #endif }
static INLINE stm_tx_t * abi_init_thread(void) { stm_tx_t *tx = tls_get_tx(); if (tx == NULL) { /* Make sure that the main initilization is done */ if (ATOMIC_LOAD(&global_abi.status) != ABI_INITIALIZED) _ITM_initializeProcess(); //t->thread_id = (int)ATOMIC_FETCH_INC_FULL(&global_abi.thread_counter); tx = stm_init_thread(); } return tx; }
static INLINE stm_tx_t * abi_init_thread(void) { stm_tx_t *tx = tls_get_tx(); if (tx == NULL) { /* Make sure that the main initilization is done */ if (ATOMIC_LOAD(&global_abi.status) != ABI_INITIALIZED) _ITM_initializeProcess(); //t->thread_id = (int)ATOMIC_FETCH_INC_FULL(&global_abi.thread_counter); tx = stm_init_thread(); #ifdef STACK_CHECK get_stack_attr(&t->stack_addr_low, &t->stack_addr_high); #endif /* STACK_CHECK */ } return tx; }
/* * Catch signal (to emulate non-faulting load). */ static void signal_catcher(int sig) { sigset_t block_signal; stm_tx_t *tx = tls_get_tx(); /* A fault might only occur upon a load concurrent with a free (read-after-free) */ PRINT_DEBUG("Caught signal: %d\n", sig); /* TODO: TX_KILLED should be also allowed */ if (tx == NULL || tx->attr.no_retry || GET_STATUS(tx->status) != TX_ACTIVE) { /* There is not much we can do: execution will restart at faulty load */ fprintf(stderr, "Error: invalid memory accessed and no longjmp destination\n"); exit(1); } /* Unblock the signal since there is no return to signal handler */ sigemptyset(&block_signal); sigaddset(&block_signal, sig); pthread_sigmask(SIG_UNBLOCK, &block_signal, NULL); /* Will cause a longjmp */ stm_rollback(tx, STM_ABORT_SIGNAL); }
/* * Get current transaction descriptor. */ _CALLCONV stm_tx_t * stm_current_tx(void) { return tls_get_tx(); }
sigjmp_buf * hytm_start(TXPARAMS stm_tx_attr_t attr) { TX_GET; unsigned long err; tx->retries = 0; /* Set status */ UPDATE_STATUS(tx->status, TX_ACTIVE); stm_check_quiesce(tx); /* copy attributes if need to switch to software mode */ tx->attr = attr; tx->start = rdtsc(); hytm_restart: /* All registers are lost when ASF aborts, thus we discard registers */ asm volatile (ASF_SPECULATE :"=a" (err) : :"memory","rbp","rbx","rcx","rdx","rsi","rdi", "r8", "r9","r10","r11","r12","r13","r14","r15" ); tx = tls_get_tx(); if (unlikely(asf_status_code(err) != 0)) { /* Set status to ABORTED */ SET_STATUS(tx->status, TX_ABORTED); tx->retries++; /* Error management */ if (asf_status_code(err) == ASF_STATUS_CONTENTION) { if (tx->retries > ASF_ABORT_THRESHOLD) { /* There is too many conflicts, software will not help, start irrevocability. */ stm_set_irrevocable(TXARGS 1); /* Set irrevocable serial */ #if defined(TM_DTMC) || defined(TM_GCC) stm_set_irrevocable(TXARGS -1); /* Acquire irrevocability */ UPDATE_STATUS(tx->status, TX_IRREVOCABLE); LONGJMP(tx->env, 0x02); /* ABI 0x02 = runUninstrumented */ #else /* ! defined(TM_DTMC) && ! defined(TM_GCC) */ /* Non-tm compiler doesn't have path without instrumentation. */ tx->software = 1; #endif /* ! defined(TM_DTMC) && ! defined(TM_GCC) */ } } else if (asf_status_code(err) == ASF_STATUS_ABORT) { if (asf_abort_code(err) == ASF_FORCE_SOFTWARE) { tx->software = 1; #ifdef IRREVOCABLE_ENABLED } else if(asf_abort_code(err) == ASF_RETRY_IRREVOCABLE) { # if defined(TM_DTMC) || defined(TM_GCC) if (tx->irrevocable != 0) { stm_set_irrevocable(TXARGS -1); UPDATE_STATUS(tx->status, TX_IRREVOCABLE); LONGJMP(tx->env, 0x02); /* ABI 0x02 = runUninstrumented */ } # else /* ! defined(TM_DTMC) || defined(TM_GCC) */ /* Non-tm compiler doesn't have path without instrumentation. */ tx->software = 1; # endif /* ! defined(TM_DTMC) || defined(TM_GCC) */ #endif /* IRREVOCABLE_ENABLED */ } else { if (tx->retries > ASF_ABORT_THRESHOLD) { tx->software = 1; } } } else { /* Other cases are critical and needs software mode */ tx->software = 1; } if (tx->software) { /* Start a software transaction (it cannot use attr since the register/stack can be corrupted) */ stm_start(TXARGS tx->attr); /* Restoring the context */ #if defined(TM_DTMC) LONGJMP(tx->env, 0x01); /* ABI 0x01 = runInstrumented, DTMC explicitly needs 1 */ #else /* ! defined(TM_DTMC) */ LONGJMP(tx->env, 0x09); /* ABI 0x09 = runInstrumented + restoreLiveVariable */ #endif /* ! defined(TM_DTMC) */ } else { uint64_t cur = (uint64_t)rdtsc(); uint64_t wait = cur + (random() % (cur - tx->start)); /* XXX random but maybe not reliable */ /* Waiting... */ while (rdtsc() < wait); UPDATE_STATUS(tx->status, TX_ACTIVE); /* Check quiesce before to restart */ stm_check_quiesce(tx); goto hytm_restart; } } /* Reset write set */ tx->w_set.nb_entries = 0; if (tx->retries > 0) { /* Restoring registers for retry */ #if defined(TM_DTMC) LONGJMP(tx->env, 0x01); /* ABI 0x01 = runInstrumented, DTMC explicitly needs 1 */ #else /* ! defined(TM_DTMC) */ LONGJMP(tx->env, 0x09); /* ABI 0x09 = runInstrumented + restoreLiveVariable */ #endif /* ! defined(TM_DTMC) */ } return &tx->env; }