/** @internal Shut down stack. */ void nua_stack_shutdown(nua_t *nua) { nua_handle_t *nh, *nh_next; int busy = 0; sip_time_t now = sip_now(); int status; char const *phrase; enter; if (!nua->nua_shutdown) nua->nua_shutdown = now; for (nh = nua->nua_handles; nh; nh = nh_next) { nua_dialog_state_t *ds = nh->nh_ds; nh_next = nh->nh_next; busy += nua_dialog_repeat_shutdown(nh, ds); if (nh->nh_soa) { soa_destroy(nh->nh_soa), nh->nh_soa = NULL; } if (nua_client_request_pending(ds->ds_cr)) busy++; if (nh_notifier_shutdown(nh, NULL, NEATAG_REASON("noresource"), TAG_END())) busy++; } if (!busy) SET_STATUS(200, "Shutdown successful"); else if (now == nua->nua_shutdown) SET_STATUS(100, "Shutdown started"); else if (now - nua->nua_shutdown < 30) SET_STATUS(101, "Shutdown in progress"); else SET_STATUS(500, "Shutdown timeout"); if (status >= 200) { for (nh = nua->nua_handles; nh; nh = nh_next) { nh_next = nh->nh_next; while (nh->nh_ds && nh->nh_ds->ds_usage) { nua_dialog_usage_remove(nh, nh->nh_ds, nh->nh_ds->ds_usage, NULL, NULL); } } su_timer_destroy(nua->nua_timer), nua->nua_timer = NULL; nta_agent_destroy(nua->nua_nta), nua->nua_nta = NULL; } nua_stack_event(nua, NULL, NULL, nua_r_shutdown, status, phrase, NULL); }
/* * Used below. */ static void cpu_irqonoff(void) { uint32_t x, xon, xoff; GET_STATUS(x); xon = x | CST_IEc; xoff = x & ~(uint32_t)CST_IEc; SET_STATUS(xon); __asm volatile("nop; nop; nop; nop"); SET_STATUS(xoff); }
static int nua_publish_client_response(nua_client_request_t *cr, int status, char const *phrase, sip_t const *sip) { nua_handle_t *nh = cr->cr_owner; nua_dialog_usage_t *du = cr->cr_usage; if (!cr->cr_terminated && du && sip) { struct publish_usage *pu = nua_dialog_usage_private(du); sip_expires_t const *ex = sip->sip_expires; /* Reset state */ pu->pu_published = 0; if (pu->pu_etag) su_free(nh->nh_home, pu->pu_etag), pu->pu_etag = NULL; if (status < 300) { pu->pu_published = 1; pu->pu_etag = sip_etag_dup(nh->nh_home, sip->sip_etag); if (!ex || ex->ex_delta == 0 || !pu->pu_etag) { cr->cr_terminated = 1; if (!ex || ex->ex_delta == 0) SET_STATUS(900, "Received Invalid Expiration Time"); else SET_STATUS1(NUA_ERROR_AT(__FILE__, __LINE__)); } else nua_dialog_usage_set_refresh(du, ex->ex_delta); } } return nua_base_client_response(cr, status, phrase, sip, NULL); }
/* * Interrupts on. */ void cpu_irqon(void) { uint32_t x; GET_STATUS(x); x |= CST_IEc; SET_STATUS(x); }
/* * Interrupts off. */ void cpu_irqoff(void) { uint32_t x; GET_STATUS(x); x &= ~(uint32_t)CST_IEc; SET_STATUS(x); }
/* * Check if transaction must block. */ static inline int stm_check_quiesce(stm_tx_t *tx) { stm_word_t s; /* Must be called upon start (while already active but before acquiring any lock) */ assert(IS_ACTIVE(tx->status)); ATOMIC_MB_FULL; if (ATOMIC_LOAD_ACQ(&quiesce) == 2) { s = ATOMIC_LOAD(&tx->status); SET_STATUS(tx->status, TX_IDLE); while (ATOMIC_LOAD_ACQ(&quiesce) == 2) { sched_yield(); } SET_STATUS(tx->status, GET_STATUS(s)); return 1; } return 0; }
nn_primitive_handle_t NN_API_CALL_CONVENTION nn_primitives_loss_f32_create_0( nn_device_t *device, /* IDLF device handle */ NN_LOSS_FUNCTION function, size_t input_size_x, size_t input_size_y, size_t input_size_z, size_t batch_size, NN_API_STATUS *status /* NN_API_STATUS_OK on success */ ) { SET_STATUS(NN_API_STATUS_OK); return new layer::loss_function_f32( function, input_size_x, input_size_y, input_size_z, batch_size, reinterpret_cast<nn_device_internal *>(device)); }
nn_primitive_handle_t NN_API_CALL_CONVENTION nn_primitives_dropout_f32_create_0( nn_device_t *device, /* IDLF device handle */ size_t input_size_x, size_t input_size_y, size_t input_size_z, size_t batch_size, float drop_rate, NN_API_STATUS *status /* NN_API_STATUS_OK on success */ ) { SET_STATUS(NN_API_STATUS_OK); return new layer::dropout_f32( input_size_x, input_size_y, input_size_z, batch_size, drop_rate, reinterpret_cast<nn_device_internal *>(device)); }
/* * Inserts a token in the hierarchical list. * \param local_ctx pointer to the structure holding all the information needed * by the algorithm * \param x the position in x of the concerned pixel * \param y the position in y of the concerned pixel * \param z the position in y of the concerned pixel * \param value the value determines in which list to insert it */ static INLINE void MB3D_InsertInHierarchicalList( MB3D_Watershed8_Ctx *local_ctx, int x, int y, int z, PIX8 value) { int position; PIX32 *p; int lx, ly, lz; MB_Image *im; /* The token corresponding to the pixel process is */ /* updated/created. */ position = x + y*local_ctx->width + z*local_ctx->width*local_ctx->height; local_ctx->TokensArray[position].nextx = MB_LIST_END; local_ctx->TokensArray[position].nexty = MB_LIST_END; local_ctx->TokensArray[position].nextz = MB_LIST_END; /* Insertion in the hierarchical list */ /* The value is normed as we do not want to process */ /* already flooded level */ value = (value < (local_ctx->current_water_level)) ? (local_ctx->current_water_level) : value; /* The token is inserted after the last value in the list */ lx = local_ctx->HierarchicalList[value].lastx; ly = local_ctx->HierarchicalList[value].lasty; lz = local_ctx->HierarchicalList[value].lastz; position = lx+ly*local_ctx->width+lz*local_ctx->width*local_ctx->height; if (position>=0) { /* There is a last value, the list is not empty*/ local_ctx->TokensArray[position].nextx = x; local_ctx->TokensArray[position].nexty = y; local_ctx->TokensArray[position].nextz = z; local_ctx->HierarchicalList[value].lastx = x; local_ctx->HierarchicalList[value].lasty = y; local_ctx->HierarchicalList[value].lastz = z; } else { /* The list is empty, so we create it.*/ local_ctx->HierarchicalList[value].firstx = x; local_ctx->HierarchicalList[value].firsty = y; local_ctx->HierarchicalList[value].firstz = z; local_ctx->HierarchicalList[value].lastx = x; local_ctx->HierarchicalList[value].lasty = y; local_ctx->HierarchicalList[value].lastz = z; } /* The marker image is updated with the tag value in the pixel position */ im = local_ctx->seq_marker[z]; p = (PIX32 *) (im->plines[y] + x*4); *p = SET_STATUS(p,QUEUED); }
nn_primitive_handle_t NN_API_CALL_CONVENTION nn_primitives_softmax_loss_f32_create_0( nn_device_t *device, /* IDLF device handle */ size_t num_features, /* number of input feature maps */ size_t batch_size, /* size of input batch */ const nn_primitives_softmax_hints_t *hints, NN_API_STATUS *status /* NN_API_STATUS_OK on success */ ) { SET_STATUS(NN_API_STATUS_OK); std::remove_const<std::remove_pointer<decltype(hints)>::type>::type hints_ = {}; if (hints != nullptr) hints_ = *hints; return new layer::softmax_loss_f32(num_features, batch_size, reinterpret_cast<nn_device_internal *>(device)); }
int hytm_commit(TXPARAM) { stm_word_t t; w_entry_t *w; int i; TX_GET; /* Release irrevocability */ #ifdef IRREVOCABLE_ENABLED if (tx->irrevocable) { ATOMIC_STORE(&_tinystm.irrevocable, 0); if ((tx->irrevocable & 0x08) != 0) stm_quiesce_release(tx); tx->irrevocable = 0; goto commit_end; } #endif /* IRREVOCABLE_ENABLED */ t = FETCH_INC_CLOCK + 1; /* Set new timestamp in locks */ w = tx->w_set.entries; for (i = tx->w_set.nb_entries; i > 0; i--, w++) { /* XXX Maybe no duplicate entries can improve perf? */ asf_lock_store64((long unsigned int *)w->lock, LOCK_SET_TIMESTAMP(t)); } /* Commit the hytm transaction */ asf_commit(); commit_end: tx->retries = 0; /* Set status to COMMITTED */ SET_STATUS(tx->status, TX_COMMITTED); /* TODO statistics */ return 1; }
/* * Controls that all the pixels are tagged and if not tags them as being part of * the watershed (at this point, untagged pixels are pixels completely surrounded * by watershed pixels). * \param local_ctx pointer to the structure holding all the information needed * by the algorithm */ static INLINE void MB3D_ControlPass(MB3D_Watershed8_Ctx *local_ctx) { Uint32 x,y,z; PIX32 *p; MB_Image *im; /* All the pixels are checked */ for(z=0; z<local_ctx->length; z++) { for(y=0; y<local_ctx->height; y++) { for(x=0; x<local_ctx->bytes_marker; x+=4) { im = local_ctx->seq_marker[z]; p = (PIX32 *) (im->plines[y] + x); switch ((*p)&0xFF000000) { case CANDIDATE: /* Untagged pixel */ *p = SET_STATUS(p,WTS_LAB); break; default: break; } } } } }
void verify_next_assertion(val_context_t * ctx, struct val_digested_auth_chain *as, struct val_digested_auth_chain *the_trust, u_int32_t flags) { struct rrset_rec *the_set; struct rrset_rr *the_sig; u_char *signby_name_n; u_int16_t signby_footprint_n; val_dnskey_rdata_t dnskey; int is_a_wildcard; struct rrset_rr *nextrr; struct rrset_rr *keyrr; u_int16_t tag_h; char name_p[NS_MAXDNAME]; if ((as == NULL) || (as->val_ac_rrset.ac_data == NULL) || (the_trust == NULL)) { val_log(ctx, LOG_INFO, "verify_next_assertion(): Cannot verify assertion - no data"); return; } the_set = as->val_ac_rrset.ac_data; dnskey.public_key = NULL; if (-1 == ns_name_ntop(the_set->rrs_name_n, name_p, sizeof(name_p))) snprintf(name_p, sizeof(name_p), "unknown/error"); if (the_set->rrs_sig == NULL) { val_log(ctx, LOG_INFO, "verify_next_assertion(): RRSIG is missing"); as->val_ac_status = VAL_AC_RRSIG_MISSING; return; } if (the_set->rrs_type_h != ns_t_dnskey) { /* * trust path contains the key */ if (the_trust->val_ac_rrset.ac_data == NULL) { val_log(ctx, LOG_INFO, "verify_next_assertion(): Key is empty"); as->val_ac_status = VAL_AC_DNSKEY_MISSING; return; } keyrr = the_trust->val_ac_rrset.ac_data->rrs_data; } else { /* * data itself contains the key */ if (the_set->rrs_data == NULL) { val_log(ctx, LOG_INFO, "verify_next_assertion(): Key is empty"); as->val_ac_status = VAL_AC_DNSKEY_MISSING; return; } keyrr = the_set->rrs_data; } for (the_sig = the_set->rrs_sig; the_sig; the_sig = the_sig->rr_next) { /* * do wildcard processing */ if (!check_label_count(the_set, the_sig, &is_a_wildcard)) { SET_STATUS(as->val_ac_status, the_sig, VAL_AC_WRONG_LABEL_COUNT); val_log(ctx, LOG_INFO, "verify_next_assertion(): Incorrect RRSIG label count"); continue; } /* * for each sig, identify key, */ if (VAL_NO_ERROR != identify_key_from_sig(the_sig, &signby_name_n, &signby_footprint_n)) { SET_STATUS(as->val_ac_status, the_sig, VAL_AC_INVALID_RRSIG); val_log(ctx, LOG_INFO, "verify_next_assertion(): Cannot extract key footprint from RRSIG"); continue; } tag_h = ntohs(signby_footprint_n); for (nextrr = keyrr; nextrr; nextrr = nextrr->rr_next) { int is_verified = 0; if (VAL_NO_ERROR != val_parse_dnskey_rdata(nextrr->rr_rdata, nextrr->rr_rdata_length, &dnskey)) { val_log(ctx, LOG_INFO, "verify_next_assertion(): Cannot parse DNSKEY data"); nextrr->rr_status = VAL_AC_INVALID_KEY; continue; } dnskey.next = NULL; if (dnskey.key_tag != tag_h) { if (dnskey.public_key != NULL) { FREE(dnskey.public_key); dnskey.public_key = NULL; } continue; } val_log(ctx, LOG_DEBUG, "verify_next_assertion(): Found potential matching DNSKEY for RRSIG"); /* * check the signature */ is_verified = do_verify(ctx, signby_name_n, &nextrr->rr_status, &the_sig->rr_status, the_set, the_sig, &dnskey, is_a_wildcard, flags); /* * There might be multiple keys with the same key tag; set this as * the signing key only if we dont have other status for this key */ SET_STATUS(as->val_ac_status, the_sig, the_sig->rr_status); if (nextrr->rr_status == VAL_AC_UNSET) { nextrr->rr_status = VAL_AC_SIGNING_KEY; } if (is_verified) { val_log(ctx, LOG_INFO, "verify_next_assertion(): Verified a RRSIG for %s (%s) using a DNSKEY (%d)", name_p, p_type(the_set->rrs_type_h), dnskey.key_tag); if ( as->val_ac_status == VAL_AC_TRUST || nextrr->rr_status == VAL_AC_TRUST_POINT) { /* we've verified a trust anchor */ as->val_ac_status = VAL_AC_TRUST; val_log(ctx, LOG_INFO, "verify_next_assertion(): verification traces back to trust anchor"); if (dnskey.public_key != NULL) { FREE(dnskey.public_key); dnskey.public_key = NULL; } return; } /* Check if we're trying to verify some key in the authentication chain */ if ( the_set->rrs_type_h == ns_t_dnskey && as != the_trust) { /* Check if we have reached our trust key */ /* * If this record contains a DNSKEY, check if the DS record contains this key * DNSKEYs cannot be wildcard expanded, so VAL_AC_WCARD_VERIFIED does not * count as a good sig * Create the link even if the DNSKEY algorithm is unknown since this * may be the provably insecure case */ /* * follow the trust path */ struct rrset_rr *dsrec = the_trust->val_ac_rrset.ac_data->rrs_data; while (dsrec) { val_ds_rdata_t ds; ds.d_hash = NULL; int retval = val_parse_ds_rdata(dsrec->rr_rdata, dsrec->rr_rdata_length, &ds); if(retval == VAL_NOT_IMPLEMENTED) { val_log(ctx, LOG_INFO, "verify_next_assertion(): DS hash not supported"); dsrec->rr_status = VAL_AC_ALGORITHM_NOT_SUPPORTED; } else if (retval != VAL_NO_ERROR) { val_log(ctx, LOG_INFO, "verify_next_assertion(): DS parse error"); dsrec->rr_status = VAL_AC_INVALID_DS; } else if (DNSKEY_MATCHES_DS(ctx, &dnskey, &ds, the_set->rrs_name_n, nextrr, &dsrec->rr_status)) { val_log(ctx, LOG_DEBUG, "verify_next_assertion(): DNSKEY tag (%d) matches DS tag (%d)", (&dnskey)->key_tag, (&ds)->d_keytag); /* * the first match is enough */ nextrr->rr_status = VAL_AC_VERIFIED_LINK; FREE(ds.d_hash); ds.d_hash = NULL; if (dnskey.public_key) { FREE(dnskey.public_key); dnskey.public_key = NULL; } val_log(ctx, LOG_INFO, "verify_next_assertion(): Key links upward"); return; } else { /* * Didn't find a valid entry in the DS record set * Not necessarily a problem, since there is no requirement that a DS be present * If none match, then we set the status accordingly. See below. */ nextrr->rr_status = VAL_AC_DS_NOMATCH; } if (ds.d_hash != NULL) FREE(ds.d_hash); dsrec = dsrec->rr_next; } } } if (dnskey.public_key != NULL) { FREE(dnskey.public_key); } dnskey.public_key = NULL; } val_log(ctx, LOG_INFO, "verify_next_assertion(): Could not link this RRSIG to a DNSKEY"); SET_STATUS(as->val_ac_status, the_sig, VAL_AC_DNSKEY_NOMATCH); } /* * If we reach here and we're a keyset, we either didn't verify the keyset or * didn't verify the link from the key to the DS */ if (the_set->rrs_type_h == ns_t_dnskey){ as->val_ac_status = VAL_AC_NO_LINK; } }
/* * Called by the CURRENT thread to commit a transaction. */ int stm_commit(TXPARAM) { w_entry_t *w; stm_word_t t; int i; TX_GET; PRINT_DEBUG("==> stm_commit(%p[%lu-%lu])\n", tx, (unsigned long)tx->start, (unsigned long)tx->end); /* Decrement nesting level */ if (--tx->nesting > 0) return 1; assert(IS_ACTIVE(tx->status)); /* A read-only transaction can commit immediately */ if (tx->w_set.nb_entries == 0) goto end; /* Update transaction */ /* Get commit timestamp (may exceed VERSION_MAX by up to MAX_THREADS) */ t = FETCH_INC_CLOCK + 1; /* Try to validate (only if a concurrent transaction has committed since tx->start) */ if (tx->start != t - 1 && !stm_validate(tx)) { /* Cannot commit */ tx->aborts_validate_commit++; stm_rollback(tx, STM_ABORT_VALIDATE); return 0; } /* Install new versions, drop locks and set new timestamp */ w = tx->w_set.entries; for (i = tx->w_set.nb_entries; i > 0; i--, w++) { if (w->mask != 0) ATOMIC_STORE(w->addr, w->value); /* Only drop lock for last covered address in write set */ if (w->next == NULL) ATOMIC_STORE_REL(w->lock, LOCK_SET_TIMESTAMP(t)); } end: tx->retries = 0; /* Callbacks */ if (nb_commit_cb != 0) { int cb; for (cb = 0; cb < nb_commit_cb; cb++) commit_cb[cb].f(TXARGS commit_cb[cb].arg); } /* Set status to COMMITTED */ SET_STATUS(tx->status, TX_COMMITTED); return 1; }
/* * Rollback transaction. */ static inline void stm_rollback(stm_tx_t *tx, int reason) { w_entry_t *w; int i; PRINT_DEBUG("==> stm_rollback(%p[%lu-%lu])\n", tx, (unsigned long)tx->start, (unsigned long)tx->end); assert(IS_ACTIVE(tx->status)); /* Drop locks */ i = tx->w_set.nb_entries; if (i > 0) { w = tx->w_set.entries; for (; i > 0; i--, w++) { if (w->next == NULL) { /* Only drop lock for last covered address in write set */ ATOMIC_STORE(w->lock, LOCK_SET_TIMESTAMP(w->version)); } } /* Make sure that all lock releases become visible */ ATOMIC_MB_WRITE; } tx->retries++; tx->aborts++; if (tx->retries == 1) tx->aborts_1++; else if (tx->retries == 2) tx->aborts_2++; if (tx->max_retries < tx->retries) tx->max_retries = tx->retries; /* Callbacks */ if (nb_abort_cb != 0) { int cb; for (cb = 0; cb < nb_abort_cb; cb++) abort_cb[cb].f(TXARGS abort_cb[cb].arg); } /* Set status to ABORTED */ SET_STATUS(tx->status, TX_ABORTED); /* Reset nesting level */ tx->nesting = 1; /* Wait until contented lock is free */ if (tx->c_lock != NULL) { /* Busy waiting (yielding is expensive) */ while (LOCK_GET_OWNED(ATOMIC_LOAD(tx->c_lock))) { sched_yield(); } tx->c_lock = NULL; } /* Reset field to restart transaction */ stm_prepare(tx); /* Jump back to transaction start */ if (tx->attr == NULL || !tx->attr->no_retry) siglongjmp(tx->env, reason); }
/* * Inserts the neighbors of pixel (x,y,z) in the hierarchical list so that they * can be flooded when the water reaches their level (FACE CENTERED CUBIC * GRID). Also evaluates to which basin the pixel belongs or if it is a point * of the watershed. * \param ctx pointer to the structure holding all the information needed * by the algorithm * \param x the x position of the pixel processed * \param y the x position of the pixel processed * \param z the z position of the pixel processed * * \return the function return the next token (pixel) that must be process */ static MB3D_Token MB3D_InsertNeighbors_fcc(void *ctx, int x, int y, int z) { Uint32 neighbor; PIX32 *p, *pix, tag; int nbx,nby,nbz,pos,dirSelect; MB_Image *im; MB3D_Watershed8_Ctx *local_ctx = (MB3D_Watershed8_Ctx *) ctx; /* Computing the directions to use depending on the y and z of the */ /* pixel */ dirSelect = ((z%3)<<1)+(y%2); /* The tag value is the value of the marker image in x,y */ im = local_ctx->seq_marker[z]; pix = (PIX32 *) (im->plines[y] + x*4); *pix = SET_STATUS(pix,RG_LAB); /* We will then look at its neighbors and it will help us decide to which */ /* marker the pixel belongs and also evaluates if the pixel might be in */ /* the watershed. The neighbors not yet processed or inserted will be put */ /* in the reinsert list to insert them later if the pixel is taggued at the */ /* end. */ /* The reinsert list is emptied */ MB3D_ClearReinsertList(local_ctx); /* For the 12 neighbors of the pixel */ for(neighbor=1; neighbor<13; neighbor++) { /* Position and value in the marker image */ nbx = x+fccNbDir[dirSelect][neighbor][0]; nby = y+fccNbDir[dirSelect][neighbor][1]; nbz = z+fccNbDir[dirSelect][neighbor][2]; /* The neighbor must be in the image*/ if (nbx>=0 && nbx<((int) local_ctx->width) && nby>=0 && nby<((int) local_ctx->height) && nbz>=0 && nbz<((int) local_ctx->length) ) { im = local_ctx->seq_marker[nbz]; p = (PIX32 *) (im->plines[nby] + nbx*4); if( IS_PIXEL(p, CANDIDATE) ) { /* The neighbor is not inserted into the list yet */ /* For the time being it is only put into the reinsert list */ MB3D_InsertInReinsertList(local_ctx, nbx, nby, nbz); } else if ( IS_PIXEL(p, RG_LAB) ) { /* The neighbor has already been processed and tagged */ tag = READ_LABEL(pix); if (tag==0) { /* First neighbor we met with a tag, we take it */ /* for our pixel */ *pix |= READ_LABEL(p); } else if ( tag!=READ_LABEL(p) ) { /* The tag of the neighbor is different that ours */ /* and the neighbor is not on the watershed */ /* the pixel belongs to the watershed */ *pix = SET_STATUS(pix,WTS_LAB); } } /* Other case means that the neighbor is in the list but not processed */ } } /* At this point, if the pixel does not belong to the watershed */ /* we insert its unprocessed and unlisted neighbor into the */ /* hierarchical list */ if( !IS_PIXEL(pix, WTS_LAB) ) { MB3D_ReinsertFromList(local_ctx); } /* What is the next token to process */ pos = x+y*local_ctx->width+z*local_ctx->width*local_ctx->height; return local_ctx->TokensArray[pos]; }
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; }