Merge pull request #1071 from martinling/concurrency-cleanup
Simplify logic for tracking finished transfers
This commit is contained in:
@ -134,8 +134,7 @@ struct hackrf_device {
|
|||||||
unsigned char buffer[TRANSFER_COUNT * TRANSFER_BUFFER_SIZE];
|
unsigned char buffer[TRANSFER_COUNT * TRANSFER_BUFFER_SIZE];
|
||||||
bool transfers_setup; /* true if the USB transfers have been setup */
|
bool transfers_setup; /* true if the USB transfers have been setup */
|
||||||
pthread_mutex_t transfer_lock; /* must be held to cancel or restart transfers */
|
pthread_mutex_t transfer_lock; /* must be held to cancel or restart transfers */
|
||||||
bool transfer_finished[TRANSFER_COUNT]; /* which transfers have finished */
|
volatile int active_transfers; /* number of active transfers */
|
||||||
volatile bool all_finished; /* whether all transfers have finished */
|
|
||||||
pthread_cond_t all_finished_cv; /* signalled when all transfers have finished */
|
pthread_cond_t all_finished_cv; /* signalled when all transfers have finished */
|
||||||
pthread_mutex_t all_finished_lock; /* used to protect all_finished */
|
pthread_mutex_t all_finished_lock; /* used to protect all_finished */
|
||||||
};
|
};
|
||||||
@ -211,7 +210,6 @@ static int transfers_check_setup(hackrf_device* device)
|
|||||||
static int cancel_transfers(hackrf_device* device)
|
static int cancel_transfers(hackrf_device* device)
|
||||||
{
|
{
|
||||||
uint32_t transfer_index;
|
uint32_t transfer_index;
|
||||||
int i;
|
|
||||||
|
|
||||||
// If we're cancelling transfers for any reason, we're shutting down.
|
// If we're cancelling transfers for any reason, we're shutting down.
|
||||||
device->streaming = false;
|
device->streaming = false;
|
||||||
@ -243,17 +241,11 @@ static int cancel_transfers(hackrf_device* device)
|
|||||||
// Now wait for the transfer thread to signal that all transfers
|
// Now wait for the transfer thread to signal that all transfers
|
||||||
// have finished, either by completing or being fully cancelled.
|
// have finished, either by completing or being fully cancelled.
|
||||||
pthread_mutex_lock(&device->all_finished_lock);
|
pthread_mutex_lock(&device->all_finished_lock);
|
||||||
while (!device->all_finished) {
|
while (device->active_transfers > 0) {
|
||||||
pthread_cond_wait(&device->all_finished_cv, &device->all_finished_lock);
|
pthread_cond_wait(&device->all_finished_cv, &device->all_finished_lock);
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&device->all_finished_lock);
|
pthread_mutex_unlock(&device->all_finished_lock);
|
||||||
|
|
||||||
// Now that all waiting and handling is completed, it's safe to
|
|
||||||
// reset these flags ready for the next time.
|
|
||||||
for (i = 0; i < TRANSFER_COUNT; i++)
|
|
||||||
device->transfer_finished[i] = false;
|
|
||||||
device->all_finished = false;
|
|
||||||
|
|
||||||
return HACKRF_SUCCESS;
|
return HACKRF_SUCCESS;
|
||||||
} else {
|
} else {
|
||||||
return HACKRF_ERROR_OTHER;
|
return HACKRF_ERROR_OTHER;
|
||||||
@ -344,6 +336,7 @@ static int prepare_transfers(
|
|||||||
last_libusb_error = error;
|
last_libusb_error = error;
|
||||||
return HACKRF_ERROR_LIBUSB;
|
return HACKRF_ERROR_LIBUSB;
|
||||||
}
|
}
|
||||||
|
device->active_transfers++;
|
||||||
}
|
}
|
||||||
device->transfers_setup = true;
|
device->transfers_setup = true;
|
||||||
device->streaming = true;
|
device->streaming = true;
|
||||||
@ -617,7 +610,7 @@ libusb_device_handle* hackrf_open_usb(const char* const desired_serial_number)
|
|||||||
|
|
||||||
static int hackrf_open_setup(libusb_device_handle* usb_device, hackrf_device** device)
|
static int hackrf_open_setup(libusb_device_handle* usb_device, hackrf_device** device)
|
||||||
{
|
{
|
||||||
int result, i;
|
int result;
|
||||||
hackrf_device* lib_device;
|
hackrf_device* lib_device;
|
||||||
|
|
||||||
//int speed = libusb_get_device_speed(usb_device);
|
//int speed = libusb_get_device_speed(usb_device);
|
||||||
@ -653,9 +646,7 @@ static int hackrf_open_setup(libusb_device_handle* usb_device, hackrf_device** d
|
|||||||
lib_device->transfer_thread_started = false;
|
lib_device->transfer_thread_started = false;
|
||||||
lib_device->streaming = false;
|
lib_device->streaming = false;
|
||||||
lib_device->do_exit = false;
|
lib_device->do_exit = false;
|
||||||
for (i = 0; i < TRANSFER_COUNT; i++)
|
lib_device->active_transfers = 0;
|
||||||
lib_device->transfer_finished[i] = false;
|
|
||||||
lib_device->all_finished = false;
|
|
||||||
|
|
||||||
result = pthread_mutex_init(&lib_device->transfer_lock, NULL);
|
result = pthread_mutex_init(&lib_device->transfer_lock, NULL);
|
||||||
if( result != 0 )
|
if( result != 0 )
|
||||||
@ -1700,26 +1691,18 @@ static void* transfer_threadproc(void* arg)
|
|||||||
|
|
||||||
static void transfer_finished(struct hackrf_device* device, struct libusb_transfer* finished_transfer)
|
static void transfer_finished(struct hackrf_device* device, struct libusb_transfer* finished_transfer)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
bool all_finished = true;
|
|
||||||
|
|
||||||
// If a transfer finished for any reason, we're shutting down.
|
// If a transfer finished for any reason, we're shutting down.
|
||||||
device->streaming = false;
|
device->streaming = false;
|
||||||
|
|
||||||
for (i = 0; i < TRANSFER_COUNT; i++) {
|
// If this is the last transfer, signal that all are now finished.
|
||||||
if (device->transfers[i] == finished_transfer) {
|
pthread_mutex_lock(&device->all_finished_lock);
|
||||||
device->transfer_finished[i] = true;
|
if (device->active_transfers == 1) {
|
||||||
} else {
|
device->active_transfers = 0;
|
||||||
all_finished &= device->transfer_finished[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (all_finished) {
|
|
||||||
pthread_mutex_lock(&device->all_finished_lock);
|
|
||||||
device->all_finished = true;
|
|
||||||
pthread_cond_signal(&device->all_finished_cv);
|
pthread_cond_signal(&device->all_finished_cv);
|
||||||
pthread_mutex_unlock(&device->all_finished_lock);
|
} else {
|
||||||
|
device->active_transfers--;
|
||||||
}
|
}
|
||||||
|
pthread_mutex_unlock(&device->all_finished_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void LIBUSB_CALL hackrf_libusb_transfer_callback(struct libusb_transfer* usb_transfer)
|
static void LIBUSB_CALL hackrf_libusb_transfer_callback(struct libusb_transfer* usb_transfer)
|
||||||
@ -1823,15 +1806,12 @@ static int prepare_setup_transfers(hackrf_device* device,
|
|||||||
|
|
||||||
static int create_transfer_thread(hackrf_device* device)
|
static int create_transfer_thread(hackrf_device* device)
|
||||||
{
|
{
|
||||||
int result, i;
|
int result;
|
||||||
|
|
||||||
if( device->transfer_thread_started == false )
|
if( device->transfer_thread_started == false )
|
||||||
{
|
{
|
||||||
device->streaming = false;
|
device->streaming = false;
|
||||||
device->do_exit = false;
|
device->do_exit = false;
|
||||||
for (i = 0; i < TRANSFER_COUNT; i++)
|
|
||||||
device->transfer_finished[i] = false;
|
|
||||||
device->all_finished = false;
|
|
||||||
result = pthread_create(&device->transfer_thread, 0, transfer_threadproc, device);
|
result = pthread_create(&device->transfer_thread, 0, transfer_threadproc, device);
|
||||||
if( result == 0 )
|
if( result == 0 )
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user