Example #1
0
void sync_deinit(struct bladerf_sync *sync)
{
    if (sync != NULL) {

        if (sync->stream_config.module == BLADERF_MODULE_TX) {
            async_submit_stream_buffer(sync->worker->stream,
                                       BLADERF_STREAM_SHUTDOWN, 0);
        }

        sync_worker_deinit(sync->worker, &sync->buf_mgmt.lock,
                           &sync->buf_mgmt.buf_ready);

         /* De-allocate our buffer management resources */
        free(sync->buf_mgmt.status);
        free(sync);
    }
}
Example #2
0
void sync_deinit(struct bladerf_sync *sync)
{
    if (sync->initialized) {
        if ((sync->stream_config.layout & BLADERF_DIRECTION_MASK) == BLADERF_TX) {
            async_submit_stream_buffer(sync->worker->stream,
                                       BLADERF_STREAM_SHUTDOWN, 0, false);
        }

        sync_worker_deinit(sync->worker, &sync->buf_mgmt.lock,
                           &sync->buf_mgmt.buf_ready);

        /* De-allocate our buffer management resources */
        if (sync->buf_mgmt.status) {
            MUTEX_DESTROY(&sync->buf_mgmt.lock);
            free(sync->buf_mgmt.status);
        }

        MUTEX_DESTROY(&sync->lock);

        sync->initialized = false;
    }
}
Example #3
0
/* Assumes buffer lock is held */
static int advance_tx_buffer(struct bladerf_sync *s, struct buffer_mgmt *b)
{
    int status;

    log_verbose("%s: Marking buf[%u] full\n", __FUNCTION__, b->prod_i);
    b->status[b->prod_i] = SYNC_BUFFER_IN_FLIGHT;

    /* This call may block and it results in a per-stream lock being held, so
     * the buffer lock must be dropped.
     *
     * A callback may occur in the meantime, but this will not touch the status
     * for this this buffer, or the producer index.
     */
    MUTEX_UNLOCK(&b->lock);
    status = async_submit_stream_buffer(s->worker->stream,
                                        b->buffers[b->prod_i],
                                        s->stream_config.timeout_ms);
    MUTEX_LOCK(&b->lock);

    if (status == 0) {
        b->prod_i = (b->prod_i + 1) % b->num_buffers;

        /* Go handle the next buffer, if we have one available.  Otherwise,
         * check up on the worker's state and restart it if needed. */
        if (b->status[b->prod_i] == SYNC_BUFFER_EMPTY) {
            s->state = SYNC_STATE_BUFFER_READY;
        } else {
            s->state = SYNC_STATE_CHECK_WORKER;
        }
    } else {
        log_debug("%s: Failed to advance buffer: %s\n",
                  __FUNCTION__, bladerf_strerror(status));
    }

    return status;
}
Example #4
0
int bladerf_submit_stream_buffer(struct bladerf_stream *stream,
                                 void *buffer,
                                 unsigned int timeout_ms)
{
    return async_submit_stream_buffer(stream, buffer, timeout_ms);
}
Example #5
0
/* Assumes buffer lock is held */
static int advance_tx_buffer(struct bladerf_sync *s, struct buffer_mgmt *b)
{
    int status = 0;
    const unsigned int idx = b->prod_i;

    if (b->submitter == SYNC_TX_SUBMITTER_FN) {
        /* Mark buffer in flight because we're going to send it out.
         * This ensures that if the callback fires before this function
         * completes, its state will be correct. */
        b->status[idx] = SYNC_BUFFER_IN_FLIGHT;

        /* This call may block and it results in a per-stream lock being held,
         * so the buffer lock must be dropped.
         *
         * A callback may occur in the meantime, but this will not touch the
         * status for this this buffer, or the producer index.
         */
        MUTEX_UNLOCK(&b->lock);
        status = async_submit_stream_buffer(s->worker->stream,
                                            b->buffers[idx],
                                            s->stream_config.timeout_ms,
                                            true);
        MUTEX_LOCK(&b->lock);

        if (status == 0) {
            log_verbose("%s: buf[%u] submitted.\n",
                        __FUNCTION__, idx);

        } else if (status == BLADERF_ERR_WOULD_BLOCK) {
            log_verbose("%s: Deferring buf[%u] submission to worker callback.\n",
                        __FUNCTION__, idx);

            /* Mark this buffer as being full of data, but not in flight */
            b->status[idx] = SYNC_BUFFER_FULL;

            /* Assign callback the duty of submitting deferred buffers,
             * and use buffer_mgmt.cons_i to denote which it should submit
             * (i.e., consume). */
            b->submitter = SYNC_TX_SUBMITTER_CALLBACK;
            b->cons_i = idx;

            /* This is expected and we are handling it. Don't propagate this
             * status back up */
            status = 0;
        } else {
            /* Unmark this as being in flight */
            b->status[idx] = SYNC_BUFFER_FULL;

            log_debug("%s: Failed to submit buf[%u].\n", __FUNCTION__, idx);
            return status;
       }
    } else {
        /* We are not submitting this buffer; this is deffered to the worker
         * call back. Just update its state to being full of samples. */
        b->status[idx] = SYNC_BUFFER_FULL;
    }

    /* Advance "producer" insertion index. */
    b->prod_i = (idx + 1) % b->num_buffers;

    /* Determine our next state based upon the state of the next buffer we
     * want to use. */
    if (b->status[b->prod_i] == SYNC_BUFFER_EMPTY) {
        /* Buffer is empty and ready for use */
        s->state = SYNC_STATE_BUFFER_READY;
    } else {
        /* We'll have to wait on this buffer to become ready. First, we'll
         * verify that the worker is running. */
        s->state = SYNC_STATE_CHECK_WORKER;
    }

    return status;
}