Пример #1
0
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);
}
Пример #2
0
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;
    }
}
Пример #3
0
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;
}
Пример #4
0
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;
}
Пример #5
0
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;
}
Пример #6
0
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);
}
Пример #7
0
void FreeThunkEntry(ALuint index)
{
    ReadLock(&ThunkLock);
    if(index > 0 && index <= ThunkArraySize)
        ATOMIC_STORE(&ThunkArray[index-1], AL_FALSE);
    ReadUnlock(&ThunkLock);
}
Пример #8
0
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;
}
Пример #9
0
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;
}
Пример #10
0
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));
}
Пример #11
0
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);
}
Пример #12
0
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);
}
Пример #13
0
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);
}
Пример #14
0
/*
 * 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 */
}
Пример #15
0
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);
}
Пример #16
0
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);
}
Пример #17
0
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);
}
Пример #18
0
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;
}
Пример #19
0
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;
}
Пример #20
0
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;
}
Пример #21
0
// 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;
}
Пример #22
0
/*
 * 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);
}
Пример #23
0
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;
}
Пример #24
0
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;
}
Пример #25
0
void RingFIFOClear(struct RingFIFO* buffer) {
	ATOMIC_STORE(buffer->readPtr, buffer->data);
	ATOMIC_STORE(buffer->writePtr, buffer->data);
}
Пример #26
0
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);
    }
}
Пример #27
0
/*
 * 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;
}