void UpdateEffectSlotProps(ALeffectslot *slot, ALboolean withstate) { struct ALeffectslotProps *props; ALeffectState *oldstate; /* Get an unused property container, or allocate a new one as needed. */ props = ATOMIC_LOAD(&slot->FreeList, almemory_order_acquire); if(!props) props = al_calloc(16, sizeof(*props)); else { struct ALeffectslotProps *next; do { next = ATOMIC_LOAD(&props->next, almemory_order_relaxed); } while(ATOMIC_COMPARE_EXCHANGE_WEAK(struct ALeffectslotProps*, &slot->FreeList, &props, next, almemory_order_seq_cst, almemory_order_consume) == 0); } /* Copy in current property values. */ ATOMIC_STORE(&props->Gain, slot->Gain, almemory_order_relaxed); ATOMIC_STORE(&props->AuxSendAuto, slot->AuxSendAuto, almemory_order_relaxed); ATOMIC_STORE(&props->Type, slot->Effect.Type, almemory_order_relaxed); memcpy(&props->Props, &slot->Effect.Props, sizeof(props->Props)); /* Swap out any stale effect state object there may be in the container, to * delete it. */ ATOMIC_STORE(&props->UpdateState, withstate, almemory_order_relaxed); oldstate = ATOMIC_EXCHANGE(ALeffectState*, &props->State, withstate ? slot->Effect.State : NULL, almemory_order_relaxed ); /* Set the new container for updating internal parameters. */ props = ATOMIC_EXCHANGE(struct ALeffectslotProps*, &slot->Update, props, almemory_order_acq_rel); if(props) { /* If there was an unused update container, put it back in the * freelist. */ struct ALeffectslotProps *first = ATOMIC_LOAD(&slot->FreeList); do { ATOMIC_STORE(&props->next, first, almemory_order_relaxed); } while(ATOMIC_COMPARE_EXCHANGE_WEAK(struct ALeffectslotProps*, &slot->FreeList, &first, props) == 0); } DELETE_OBJ(oldstate); }
ALvoid aluHandleDisconnect(ALCdevice *device) { ALCcontext *Context; device->Connected = ALC_FALSE; Context = ATOMIC_LOAD(&device->ContextList); while(Context) { ALvoice *voice, *voice_end; voice = Context->Voices; voice_end = voice + Context->VoiceCount; while(voice != voice_end) { ALsource *source = voice->Source; voice->Source = NULL; if(source && source->state == AL_PLAYING) { source->state = AL_STOPPED; ATOMIC_STORE(&source->current_buffer, NULL); source->position = 0; source->position_fraction = 0; } voice++; } Context->VoiceCount = 0; Context = Context->next; } }
static ALCboolean ALCwinmmPlayback_start(ALCwinmmPlayback *self) { ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; ALbyte *BufferData; ALint BufferSize; ALuint i; ATOMIC_STORE(&self->killNow, AL_FALSE, almemory_order_release); if(althrd_create(&self->thread, ALCwinmmPlayback_mixerProc, self) != althrd_success) return ALC_FALSE; InitRef(&self->WaveBuffersCommitted, 0); // Create 4 Buffers BufferSize = device->UpdateSize*device->NumUpdates / 4; BufferSize *= FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder); BufferData = calloc(4, BufferSize); for(i = 0;i < 4;i++) { memset(&self->WaveBuffer[i], 0, sizeof(WAVEHDR)); self->WaveBuffer[i].dwBufferLength = BufferSize; self->WaveBuffer[i].lpData = ((i==0) ? (CHAR*)BufferData : (self->WaveBuffer[i-1].lpData + self->WaveBuffer[i-1].dwBufferLength)); waveOutPrepareHeader(self->OutHdl, &self->WaveBuffer[i], sizeof(WAVEHDR)); waveOutWrite(self->OutHdl, &self->WaveBuffer[i], sizeof(WAVEHDR)); IncrementRef(&self->WaveBuffersCommitted); } return ALC_TRUE; }
static INLINE void abi_init(void) { /* thread safe */ reload: if (ATOMIC_LOAD_ACQ(&global_abi.status) == ABI_NOT_INITIALIZED) { if (ATOMIC_CAS_FULL(&global_abi.status, ABI_NOT_INITIALIZED, ABI_INITIALIZING) != 0) { /* TODO temporary to be sure to use tinySTM */ printf("TinySTM-ABI v%s.\n", _ITM_libraryVersion()); atexit((void (*)(void))(_ITM_finalizeProcess)); /* TinySTM initialization */ stm_init(); mod_mem_init(0); mod_alloc_cpp(); mod_log_init(); mod_cb_init(); ATOMIC_STORE(&global_abi.status, ABI_INITIALIZED); /* Also initialize thread as specify in the specification */ abi_init_thread(); return; } else { goto reload; } } else if (ATOMIC_LOAD_ACQ(&global_abi.status) != ABI_INITIALIZED) { /* Wait the end of the initialization */ goto reload; } return; }
size_t RingFIFOWrite(struct RingFIFO* buffer, const void* value, size_t length) { void* data = buffer->writePtr; void* end; ATOMIC_LOAD(end, buffer->readPtr); // Wrap around if we can't fit enough in here if ((intptr_t) data - (intptr_t) buffer->data + length >= buffer->capacity) { if (end == buffer->data) { // Oops! If we wrap now, it'll appear empty return 0; } data = buffer->data; } size_t remaining; if (data >= end) { uintptr_t bufferEnd = (uintptr_t) buffer->data + buffer->capacity; remaining = bufferEnd - (uintptr_t) data; } else { remaining = (uintptr_t) end - (uintptr_t) data; } // Note that we can't hit the end pointer if (remaining <= length) { return 0; } if (value) { memcpy(data, value, length); } ATOMIC_STORE(buffer->writePtr, (void*) ((intptr_t) data + length)); return length; }
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat value) { ALCcontext *context; ALeffectslot *slot; context = GetContextRef(); if(!context) return; if((slot=LookupEffectSlot(context, effectslot)) == NULL) SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); switch(param) { case AL_EFFECTSLOT_GAIN: if(!(value >= 0.0f && value <= 1.0f)) SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); slot->Gain = value; ATOMIC_STORE(&slot->NeedsUpdate, AL_TRUE); break; default: SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); } done: ALCcontext_DecRef(context); }
void FreeThunkEntry(ALuint index) { ReadLock(&ThunkLock); if(index > 0 && index <= ThunkArraySize) ATOMIC_STORE(&ThunkArray[index-1], AL_FALSE); ReadUnlock(&ThunkLock); }
size_t RingFIFORead(struct RingFIFO* buffer, void* output, size_t length) { void* data = buffer->readPtr; void* end; ATOMIC_LOAD(end, buffer->writePtr); // Wrap around if we can't fit enough in here if ((intptr_t) data - (intptr_t) buffer->data + length >= buffer->capacity) { if (end == data) { // Oops! If we wrap now, it'll appear full return 0; } data = buffer->data; } size_t remaining; if (data > end) { uintptr_t bufferEnd = (uintptr_t) buffer->data + buffer->capacity; remaining = bufferEnd - (uintptr_t) data; } else { remaining = (intptr_t) end - (intptr_t) data; } // If the pointers touch, it's empty if (remaining < length) { return 0; } if (output) { memcpy(output, data, length); } ATOMIC_STORE(buffer->readPtr, (void*) ((intptr_t) data + length)); return length; }
static ALCboolean ALCnullBackend_start(ALCnullBackend *self) { ATOMIC_STORE(&self->killNow, AL_FALSE, almemory_order_release); if(althrd_create(&self->thread, ALCnullBackend_mixerProc, self) != althrd_success) return ALC_FALSE; return ALC_TRUE; }
static void AddEffectSlotList(ALCcontext *context, ALeffectslot *start, ALeffectslot *last) { ALeffectslot *root = ATOMIC_LOAD(&context->ActiveAuxSlotList); do { ATOMIC_STORE(&last->next, root, almemory_order_relaxed); } while(!ATOMIC_COMPARE_EXCHANGE_WEAK(ALeffectslot*, &context->ActiveAuxSlotList, &root, start)); }
static INLINE void abi_exit(void) { TX_GET; char * statistics; abi_exit_thread(tx); /* Ensure thread safety */ reload: if (ATOMIC_LOAD_ACQ(&global_abi.status) == ABI_INITIALIZED) { if (ATOMIC_CAS_FULL(&global_abi.status, ABI_INITIALIZED, ABI_FINALIZING) == 0) goto reload; } else { return; } if ((statistics = getenv("ITM_STATISTICS")) != NULL) { FILE * f; int i = 0; stats_t * ts; if (statistics[0] == '-') f = stdout; else if ((f = fopen("itm.log", "w")) == NULL) { fprintf(stderr, "can't open itm.log for writing\n"); goto finishing; } fprintf(f, "STATS REPORT\n"); fprintf(f, "THREAD TOTALS\n"); while (1) { do { ts = (stats_t *)ATOMIC_LOAD(&thread_stats); if (ts == NULL) goto no_more_stat; } while(ATOMIC_CAS_FULL(&thread_stats, ts, ts->next) == 0); /* Skip stats if not a transactional thread */ if (ts->nb_commits == 0) continue; fprintf(f, "Thread %-4i : %12s %12s %12s %12s\n", i, "Min", "Mean", "Max", "Total"); fprintf(f, " Transactions : %12lu\n", ts->nb_commits); fprintf(f, " %-25s: %12lu %12.2f %12lu %12lu\n", "Retries", ts->nb_retries_min, ts->nb_retries_avg, ts->nb_retries_max, ts->nb_aborts); fprintf(f,"\n"); /* Free the thread stats structure */ free(ts); i++; } no_more_stat: if (f != stdout) { fclose(f); } } finishing: stm_exit(); ATOMIC_STORE(&global_abi.status, ABI_NOT_INITIALIZED); }
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint value) { ALCdevice *device; ALCcontext *context; ALeffectslot *slot; ALeffect *effect = NULL; ALenum err; context = GetContextRef(); if(!context) return; device = context->Device; if((slot=LookupEffectSlot(context, effectslot)) == NULL) SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); switch(param) { case AL_EFFECTSLOT_EFFECT: effect = (value ? LookupEffect(device, value) : NULL); if(!(value == 0 || effect != NULL)) SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); err = InitializeEffect(device, slot, effect); if(err != AL_NO_ERROR) SET_ERROR_AND_GOTO(context, err, done); ATOMIC_STORE(&context->UpdateSources, AL_TRUE); break; case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO: if(!(value == AL_TRUE || value == AL_FALSE)) SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); slot->AuxSendAuto = value; ATOMIC_STORE(&context->UpdateSources, AL_TRUE); break; default: SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); } done: ALCcontext_DecRef(context); }
AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots) { ALCcontext *context; ALeffectslot *first, *last; ALsizei cur; ALenum err; context = GetContextRef(); if(!context) return; if(!(n >= 0)) SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); first = last = NULL; for(cur = 0;cur < n;cur++) { ALeffectslot *slot = al_calloc(16, sizeof(ALeffectslot)); err = AL_OUT_OF_MEMORY; if(!slot || (err=InitEffectSlot(slot)) != AL_NO_ERROR) { al_free(slot); alDeleteAuxiliaryEffectSlots(cur, effectslots); SET_ERROR_AND_GOTO(context, err, done); } err = NewThunkEntry(&slot->id); if(err == AL_NO_ERROR) err = InsertUIntMapEntry(&context->EffectSlotMap, slot->id, slot); if(err != AL_NO_ERROR) { FreeThunkEntry(slot->id); DELETE_OBJ(slot->Params.EffectState); al_free(slot); alDeleteAuxiliaryEffectSlots(cur, effectslots); SET_ERROR_AND_GOTO(context, err, done); } aluInitEffectPanning(slot); if(!first) first = slot; if(last) ATOMIC_STORE(&last->next, slot); last = slot; effectslots[cur] = slot->id; } AddEffectSlotList(context, first, last); done: ALCcontext_DecRef(context); }
/* * Store a word-sized value in a unit transaction. */ static INLINE int stm_unit_write(volatile stm_word_t *addr, stm_word_t value, stm_word_t mask, stm_word_t *timestamp) { #ifdef UNIT_TX volatile stm_word_t *lock; stm_word_t l; PRINT_DEBUG2("==> stm_unit_write(a=%p,d=%p-%lu,m=0x%lx)\n", addr, (void *)value, (unsigned long)value, (unsigned long)mask); /* Get reference to lock */ lock = GET_LOCK(addr); /* Try to acquire lock */ restart: l = ATOMIC_LOAD_ACQ(lock); if (LOCK_GET_OWNED(l)) { /* Locked: wait until lock is free */ #ifdef WAIT_YIELD sched_yield(); #endif /* WAIT_YIELD */ goto restart; } /* Not locked */ if (timestamp != NULL && LOCK_GET_TIMESTAMP(l) > *timestamp) { /* Return current timestamp */ *timestamp = LOCK_GET_TIMESTAMP(l); return 0; } /* TODO: would need to store thread ID to be able to kill it (for wait freedom) */ if (ATOMIC_CAS_FULL(lock, l, LOCK_UNIT) == 0) goto restart; ATOMIC_STORE(addr, value); /* Update timestamp with newer value (may exceed VERSION_MAX by up to MAX_THREADS) */ l = FETCH_INC_CLOCK + 1; if (timestamp != NULL) *timestamp = l; /* Make sure that lock release becomes visible */ ATOMIC_STORE_REL(lock, LOCK_SET_TIMESTAMP(l)); if (unlikely(l >= VERSION_MAX)) { /* Block all transactions and reset clock (current thread is not in active transaction) */ stm_quiesce_barrier(NULL, rollover_clock, NULL); } return 1; #else /* ! UNIT_TX */ fprintf(stderr, "Unit transaction is not enabled\n"); exit(-1); return 1; #endif /* ! UNIT_TX */ }
AL_API ALvoid AL_APIENTRY alSpeedOfSound(ALfloat value) { ALCcontext *context; context = GetContextRef(); if(!context) return; if(!(value > 0.0f && isfinite(value))) SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); context->SpeedOfSound = value; ATOMIC_STORE(&context->UpdateSources, AL_TRUE); done: ALCcontext_DecRef(context); }
AL_API ALvoid AL_APIENTRY alDistanceModel(ALenum value) { ALCcontext *context; context = GetContextRef(); if(!context) return; if(!(value == AL_INVERSE_DISTANCE || value == AL_INVERSE_DISTANCE_CLAMPED || value == AL_LINEAR_DISTANCE || value == AL_LINEAR_DISTANCE_CLAMPED || value == AL_EXPONENT_DISTANCE || value == AL_EXPONENT_DISTANCE_CLAMPED || value == AL_NONE)) SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); context->DistanceModel = value; if(!context->SourceDistanceModel) ATOMIC_STORE(&context->UpdateSources, AL_TRUE); done: ALCcontext_DecRef(context); }
AL_API ALvoid AL_APIENTRY alDisable(ALenum capability) { ALCcontext *context; context = GetContextRef(); if(!context) return; switch(capability) { case AL_SOURCE_DISTANCE_MODEL: context->SourceDistanceModel = AL_FALSE; ATOMIC_STORE(&context->UpdateSources, AL_TRUE); break; default: SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); } done: ALCcontext_DecRef(context); }
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; }
ALenum NewThunkEntry(ALuint *index) { void *NewList; ALuint i; ReadLock(&ThunkLock); for(i = 0;i < ThunkArraySize;i++) { if(ATOMIC_EXCHANGE(ALenum, &ThunkArray[i], AL_TRUE) == AL_FALSE) { ReadUnlock(&ThunkLock); *index = i+1; return AL_NO_ERROR; } } ReadUnlock(&ThunkLock); WriteLock(&ThunkLock); NewList = al_calloc(16, ThunkArraySize*2 * sizeof(*ThunkArray)); if(!NewList) { WriteUnlock(&ThunkLock); ERR("Realloc failed to increase to %u entries!\n", ThunkArraySize*2); return AL_OUT_OF_MEMORY; } memcpy(NewList, ThunkArray, ThunkArraySize*sizeof(*ThunkArray)); al_free(ThunkArray); ThunkArray = NewList; ThunkArraySize *= 2; ATOMIC_STORE(&ThunkArray[i], AL_TRUE); WriteUnlock(&ThunkLock); *index = i+1; return AL_NO_ERROR; }
static int32_t _masterUpdate(struct GBSIOLockstepNode* node) { bool needsToWait = false; int i; switch (node->p->d.transferActive) { case TRANSFER_IDLE: // If the master hasn't initiated a transfer, it can keep going. node->nextEvent += LOCKSTEP_INCREMENT; break; case TRANSFER_STARTING: // Start the transfer, but wait for the other GBs to catch up node->transferFinished = false; needsToWait = true; ATOMIC_STORE(node->p->d.transferActive, TRANSFER_STARTED); node->nextEvent += 4; break; case TRANSFER_STARTED: // All the other GBs have caught up and are sleeping, we can all continue now node->nextEvent += 4; ATOMIC_STORE(node->p->d.transferActive, TRANSFER_FINISHING); break; case TRANSFER_FINISHING: // Finish the transfer // We need to make sure the other GBs catch up so they don't get behind node->nextEvent += node->d.p->period - 8; // Split the cycles to avoid waiting too long #ifndef NDEBUG ATOMIC_ADD(node->p->d.transferId, 1); #endif needsToWait = true; ATOMIC_STORE(node->p->d.transferActive, TRANSFER_FINISHED); break; case TRANSFER_FINISHED: // Everything's settled. We're done. _finishTransfer(node); ATOMIC_STORE(node->p->masterClaimed, false); node->nextEvent += LOCKSTEP_INCREMENT; ATOMIC_STORE(node->p->d.transferActive, TRANSFER_IDLE); break; } int mask = 0; for (i = 1; i < node->p->d.attached; ++i) { mask |= 1 << i; } if (mask) { if (needsToWait) { if (!node->p->d.wait(&node->p->d, mask)) { abort(); } } else { node->p->d.signal(&node->p->d, mask); } } // Tell the other GBs they can continue up to where we were node->p->d.addCycles(&node->p->d, 0, node->eventDiff); #ifndef NDEBUG node->phase = node->p->d.transferActive; #endif if (needsToWait) { return 0; } return node->nextEvent; }
// we know that this "node" is a node that has either no neighbors on // one side -or- connects to a chain of nodes that leads to a single node. static bool check_for_tip_removal(SeqGraph *graph, SeqNode *node, bool moving_right, bool singlecopy_tip, unsigned length) { // XXX: performance optimization not correctness, right? #ifdef VELOUR_TBB if (atomic_isNodeDead<SeqNode>(node)) { return false; } #else if (isNodeDead<SeqNode>(node)) { return false; } #endif length += node->sequence.get_length() - g__FULLKMER_LENGTH + 1; singlecopy_tip &= (isNodeWeight_None(node) || isNodeWeight_AllSingleCopy(node)); if (length >= TIP_REMOVAL_LENGTH && !singlecopy_tip) { // FIXME? singlecopy_tip might be incorrect as didn't consider forward arc??? return false; // can't remove a tip that is too long } // find out if this tip can be extended. This has two conditions: // CONDITION 1: there is a single neighbor in the extension direction #ifdef VELOUR_TBB union { counter_t count[4]; four_counter_t side; } local_counters; local_counters.side = moving_right ? ATOMIC_LOAD(node->right_side) : ATOMIC_LOAD(node->left_side); counter_t *counters = local_counters.count; #else counter_t *counters = moving_right ? node->right_count : node->left_count; #endif int valid_dir = valid_single_successor(counters); if (valid_dir == MULTIPLE_SUCCESSORS) { return false; // can't remove a tip with two outgrowths (the base of a Y) } if (valid_dir == NO_SUCCESSORS) { #ifdef VELOUR_TBB atomic_setNodeDead<SeqNode>(node); ATOMIC_STORE(node->connections) = 0; ATOMIC_STORE(node->left_side_colors) = 0; ATOMIC_STORE(node->right_side_colors) = 0; ATOMIZE(DISCONNECTED_CHUNKS).fetch_and_increment(); #else setNodeDead<SeqNode>(node); node->connections = 0; node->left_side_colors = 0; node->right_side_colors = 0; ++ DISCONNECTED_CHUNKS; #endif // printf("a disconnected chunk of length %d\n", length); return true; } // a single successor // CONDITION 2: the node in the extension direction has a single // neighbor in the direction facing this node assert((valid_dir >= 0) && (valid_dir < 4)); bool sense_changed; #ifdef VELOUR_TBB union { color_t color[4]; four_color_t side; } local_colors; local_colors.side = moving_right ? ATOMIC_LOAD(node->right_side_colors) : ATOMIC_LOAD(node->left_side_colors); color_t *colors = local_colors.color; #else color_t *colors = moving_right ? node->right_color : node->left_color; #endif SeqNode *next = NULL; if (colors[valid_dir] == 0) { next = graph->findNextNode(node, valid_dir, moving_right, &sense_changed); } else { return false; } assert( next != NULL ); bool next_moving_right = moving_right ^ sense_changed; #ifdef VELOUR_TBB union { counter_t count[4]; four_counter_t side; } local_back_counters; local_back_counters.side = next_moving_right ? ATOMIC_LOAD(next->left_side) : ATOMIC_LOAD(next->right_side); counter_t *next_back_counters = local_back_counters.count; #else counter_t *next_back_counters = next_moving_right ? next->left_count : next->right_count; #endif int next_back_valid = valid_single_successor(next_back_counters); if (next_back_valid != MULTIPLE_SUCCESSORS) { bool forceclip = (abs(next_back_counters[next_back_valid]) == CLIP_SINGLECOPY_COUNTER_VALUE); singlecopy_tip &= cnorm(counters[valid_dir]) == 1; bool remove = check_for_tip_removal(graph, next, next_moving_right, singlecopy_tip, length); if (remove || singlecopy_tip || forceclip) { #ifdef VELOUR_TBB atomic_setNodeDead<SeqNode>(node); ATOMIC_STORE(node->connections) = 0; ATOMIC_STORE(node->left_side_colors) = 0; ATOMIC_STORE(node->right_side_colors) = 0; #else setNodeDead<SeqNode>(node); node->connections = 0; node->left_side_colors = 0; node->right_side_colors = 0; #endif } if (!remove && (singlecopy_tip || forceclip)) { #ifdef VELOUR_TBB ATOMIC_STORE( (next_moving_right ? next->left_count : next->right_count)[next_back_valid] ) = 0; ATOMIC_STORE( (next_moving_right?next->left_color:next->right_color)[next_back_valid] ) = 0; #else next_back_counters[next_back_valid] = 0; (next_moving_right?next->left_color:next->right_color)[next_back_valid] = 0; #endif } return remove || singlecopy_tip || forceclip; } // can't extend. Need to determine if we should trim. counter_t max_value = get_counter_max(next_back_counters); counter_t value = abs(counters[valid_dir]); if (value == CLIP_SINGLECOPY_COUNTER_VALUE) value = 1; if ((value >= g_minimum_edge_weight) && (value == max_value)) { // printf("dominant connection: length %d, weight %d\n", length, abs(counters[valid_dir])); return false; // can't remove the dominant connection } // check for multiple single-copy predecessors in next node; mark those arcs as potential clips if (value == 1 && value == max_value) { for (int i = 0 ; i < 4 ; ++ i) { if (next_back_counters[i] == 1) { #ifdef VELOUR_TBB ATOMIC_STORE( (next_moving_right ? next->left_count : next->right_count)[i] ) = CLIP_SINGLECOPY_COUNTER_VALUE; #else next_back_counters[i] = CLIP_SINGLECOPY_COUNTER_VALUE; #endif } else if (next_back_counters[i] == -1) { #ifdef VELOUR_TBB ATOMIC_STORE( (next_moving_right ? next->left_count : next->right_count)[i] ) = - CLIP_SINGLECOPY_COUNTER_VALUE; #else next_back_counters[i] = - CLIP_SINGLECOPY_COUNTER_VALUE; #endif } } } // if we are clipping the tip, then mark the current "node" for // removal and disconnect the "next" node from the tip. /* #ifdef VERIFY verify_node(node, HASHTABLE, g__FULLKMER_LENGTH); // FINE, BEFORE WE LET IT GET INCONSISTENT. verify_node(next, HASHTABLE, g__FULLKMER_LENGTH); #endif */ // Note: we remove the link from "next", but not from "node". The // reason why is that we don't want code to start on the other side // thinking that it is a tip that might need removal. This means // that from "node's" perspective, the graph looks inconsistent, but // that is okay, since we're going to remove "node" shortly. #ifdef VELOUR_TBB atomic_setNodeDead<SeqNode>(node); ATOMIC_STORE(node->connections) = 0; ATOMIC_STORE(node->left_side_colors) = 0; ATOMIC_STORE(node->right_side_colors) = 0; #else setNodeDead<SeqNode>(node); node->connections = 0; node->left_side_colors = 0; node->right_side_colors = 0; #endif // printf("removal candidate: length %d, weight %d\n", length, abs(counters[valid_dir])); Nucleotide head_rightmost_base = node->sequence.GetHeadKmerRightmostBase(g__FULLKMER_LENGTH); Nucleotide tail_leftmost_base = node->sequence.GetTailKmerLeftmostBase(g__FULLKMER_LENGTH); next_back_valid = moving_right ? tail_leftmost_base : head_rightmost_base; if (sense_changed) { next_back_valid ^= 0x3; } // FIXME: i.e. complement?? #ifdef VELOUR_TBB ATOMIC_STORE( (next_moving_right?next->left_color:next->right_color)[next_back_valid] ) = 0; #else (next_moving_right?next->left_color:next->right_color)[next_back_valid] = 0; #endif #ifdef VELOUR_TBB ATOMIC_STORE( (next_moving_right ? next->left_count : next->right_count)[next_back_valid] ) = 0; #else next_back_counters[next_back_valid] = 0; #endif #ifdef VELOUR_TBB ATOMIZE(TIP_DETACHED).fetch_and_increment(); #else ++ TIP_DETACHED; #endif /* #ifdef VERIFY // verify_node(node, g__FULLKMER_LENGTH); // THIS VALIDATION WOULD FAIL, SINCE WE DON'T MODIFY NODE verify_node(next, HASHTABLE, g__FULLKMER_LENGTH); #endif */ return true; }
/* * 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); }
static ALCenum ALCwinmmCapture_open(ALCwinmmCapture *self, const ALCchar *name) { ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; const al_string *iter; ALbyte *BufferData = NULL; DWORD CapturedDataSize; ALint BufferSize; UINT DeviceID; MMRESULT res; ALuint i; if(VECTOR_SIZE(CaptureDevices) == 0) ProbeCaptureDevices(); // Find the Device ID matching the deviceName if valid #define MATCH_DEVNAME(iter) (!alstr_empty(*(iter)) && (!name || alstr_cmp_cstr(*iter, name) == 0)) VECTOR_FIND_IF(iter, const al_string, CaptureDevices, MATCH_DEVNAME); if(iter == VECTOR_END(CaptureDevices)) return ALC_INVALID_VALUE; #undef MATCH_DEVNAME DeviceID = (UINT)(iter - VECTOR_BEGIN(CaptureDevices)); switch(device->FmtChans) { case DevFmtMono: case DevFmtStereo: break; case DevFmtQuad: case DevFmtX51: case DevFmtX51Rear: case DevFmtX61: case DevFmtX71: case DevFmtAmbi3D: return ALC_INVALID_ENUM; } switch(device->FmtType) { case DevFmtUByte: case DevFmtShort: case DevFmtInt: case DevFmtFloat: break; case DevFmtByte: case DevFmtUShort: case DevFmtUInt: return ALC_INVALID_ENUM; } memset(&self->Format, 0, sizeof(WAVEFORMATEX)); self->Format.wFormatTag = ((device->FmtType == DevFmtFloat) ? WAVE_FORMAT_IEEE_FLOAT : WAVE_FORMAT_PCM); self->Format.nChannels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder); self->Format.wBitsPerSample = BytesFromDevFmt(device->FmtType) * 8; self->Format.nBlockAlign = self->Format.wBitsPerSample * self->Format.nChannels / 8; self->Format.nSamplesPerSec = device->Frequency; self->Format.nAvgBytesPerSec = self->Format.nSamplesPerSec * self->Format.nBlockAlign; self->Format.cbSize = 0; if((res=waveInOpen(&self->InHdl, DeviceID, &self->Format, (DWORD_PTR)&ALCwinmmCapture_waveInProc, (DWORD_PTR)self, CALLBACK_FUNCTION)) != MMSYSERR_NOERROR) { ERR("waveInOpen failed: %u\n", res); goto failure; } // Allocate circular memory buffer for the captured audio CapturedDataSize = device->UpdateSize*device->NumUpdates; // Make sure circular buffer is at least 100ms in size if(CapturedDataSize < (self->Format.nSamplesPerSec / 10)) CapturedDataSize = self->Format.nSamplesPerSec / 10; self->Ring = ll_ringbuffer_create(CapturedDataSize, self->Format.nBlockAlign, false); if(!self->Ring) goto failure; InitRef(&self->WaveBuffersCommitted, 0); // Create 4 Buffers of 50ms each BufferSize = self->Format.nAvgBytesPerSec / 20; BufferSize -= (BufferSize % self->Format.nBlockAlign); BufferData = calloc(4, BufferSize); if(!BufferData) goto failure; for(i = 0;i < 4;i++) { memset(&self->WaveBuffer[i], 0, sizeof(WAVEHDR)); self->WaveBuffer[i].dwBufferLength = BufferSize; self->WaveBuffer[i].lpData = ((i==0) ? (CHAR*)BufferData : (self->WaveBuffer[i-1].lpData + self->WaveBuffer[i-1].dwBufferLength)); self->WaveBuffer[i].dwFlags = 0; self->WaveBuffer[i].dwLoops = 0; waveInPrepareHeader(self->InHdl, &self->WaveBuffer[i], sizeof(WAVEHDR)); waveInAddBuffer(self->InHdl, &self->WaveBuffer[i], sizeof(WAVEHDR)); IncrementRef(&self->WaveBuffersCommitted); } ATOMIC_STORE(&self->killNow, AL_FALSE, almemory_order_release); if(althrd_create(&self->thread, ALCwinmmCapture_captureProc, self) != althrd_success) goto failure; alstr_copy(&device->DeviceName, VECTOR_ELEM(CaptureDevices, DeviceID)); return ALC_NO_ERROR; failure: if(BufferData) { for(i = 0;i < 4;i++) waveInUnprepareHeader(self->InHdl, &self->WaveBuffer[i], sizeof(WAVEHDR)); free(BufferData); } ll_ringbuffer_free(self->Ring); self->Ring = NULL; if(self->InHdl) waveInClose(self->InHdl); self->InHdl = NULL; return ALC_INVALID_VALUE; }
ALenum InitializeEffect(ALCdevice *Device, ALeffectslot *EffectSlot, ALeffect *effect) { ALenum newtype = (effect ? effect->type : AL_EFFECT_NULL); ALeffectStateFactory *factory; if(newtype != EffectSlot->EffectType) { ALeffectState *State; FPUCtl oldMode; factory = getFactoryByType(newtype); if(!factory) { ERR("Failed to find factory for effect type 0x%04x\n", newtype); return AL_INVALID_ENUM; } State = V0(factory,create)(); if(!State) return AL_OUT_OF_MEMORY; SetMixerFPUMode(&oldMode); ALCdevice_Lock(Device); if(V(State,deviceUpdate)(Device) == AL_FALSE) { ALCdevice_Unlock(Device); RestoreFPUMode(&oldMode); DELETE_OBJ(State); return AL_OUT_OF_MEMORY; } State = ExchangePtr((XchgPtr*)&EffectSlot->EffectState, State); if(!effect) { memset(&EffectSlot->EffectProps, 0, sizeof(EffectSlot->EffectProps)); EffectSlot->EffectType = AL_EFFECT_NULL; } else { memcpy(&EffectSlot->EffectProps, &effect->Props, sizeof(effect->Props)); EffectSlot->EffectType = effect->type; } /* FIXME: This should be done asynchronously, but since the EffectState * object was changed, it needs an update before its Process method can * be called. */ ATOMIC_STORE(&EffectSlot->NeedsUpdate, AL_FALSE); V(EffectSlot->EffectState,update)(Device, EffectSlot); ALCdevice_Unlock(Device); RestoreFPUMode(&oldMode); DELETE_OBJ(State); State = NULL; } else { if(effect) { ALCdevice_Lock(Device); memcpy(&EffectSlot->EffectProps, &effect->Props, sizeof(effect->Props)); ALCdevice_Unlock(Device); ATOMIC_STORE(&EffectSlot->NeedsUpdate, AL_TRUE); } } return AL_NO_ERROR; }
void RingFIFOClear(struct RingFIFO* buffer) { ATOMIC_STORE(buffer->readPtr, buffer->data); ATOMIC_STORE(buffer->writePtr, buffer->data); }
void UpdateListenerProps(ALCcontext *context) { ALlistener *listener = context->Listener; struct ALlistenerProps *props; /* Get an unused proprty container, or allocate a new one as needed. */ props = ATOMIC_LOAD(&listener->FreeList, almemory_order_acquire); if(!props) props = al_calloc(16, sizeof(*props)); else { struct ALlistenerProps *next; do { next = ATOMIC_LOAD(&props->next, almemory_order_relaxed); } while(ATOMIC_COMPARE_EXCHANGE_WEAK(struct ALlistenerProps*, &listener->FreeList, &props, next, almemory_order_seq_cst, almemory_order_acquire) == 0); } /* Copy in current property values. */ ATOMIC_STORE(&props->Position[0], listener->Position[0], almemory_order_relaxed); ATOMIC_STORE(&props->Position[1], listener->Position[1], almemory_order_relaxed); ATOMIC_STORE(&props->Position[2], listener->Position[2], almemory_order_relaxed); ATOMIC_STORE(&props->Velocity[0], listener->Velocity[0], almemory_order_relaxed); ATOMIC_STORE(&props->Velocity[1], listener->Velocity[1], almemory_order_relaxed); ATOMIC_STORE(&props->Velocity[2], listener->Velocity[2], almemory_order_relaxed); ATOMIC_STORE(&props->Forward[0], listener->Forward[0], almemory_order_relaxed); ATOMIC_STORE(&props->Forward[1], listener->Forward[1], almemory_order_relaxed); ATOMIC_STORE(&props->Forward[2], listener->Forward[2], almemory_order_relaxed); ATOMIC_STORE(&props->Up[0], listener->Up[0], almemory_order_relaxed); ATOMIC_STORE(&props->Up[1], listener->Up[1], almemory_order_relaxed); ATOMIC_STORE(&props->Up[2], listener->Up[2], almemory_order_relaxed); ATOMIC_STORE(&props->Gain, listener->Gain, almemory_order_relaxed); ATOMIC_STORE(&props->MetersPerUnit, listener->MetersPerUnit, almemory_order_relaxed); ATOMIC_STORE(&props->DopplerFactor, context->DopplerFactor, almemory_order_relaxed); ATOMIC_STORE(&props->DopplerVelocity, context->DopplerVelocity, almemory_order_relaxed); ATOMIC_STORE(&props->SpeedOfSound, context->SpeedOfSound, almemory_order_relaxed); ATOMIC_STORE(&props->SourceDistanceModel, context->SourceDistanceModel, almemory_order_relaxed); ATOMIC_STORE(&props->DistanceModel, context->DistanceModel, almemory_order_relaxed); /* Set the new container for updating internal parameters. */ props = ATOMIC_EXCHANGE(struct ALlistenerProps*, &listener->Update, props, almemory_order_acq_rel); if(props) { /* If there was an unused update container, put it back in the * freelist. */ ATOMIC_REPLACE_HEAD(struct ALlistenerProps*, &listener->FreeList, props); } }
/* * 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; }