Hold transfer lock during initial submissions in prepare_transfers.

This commit is contained in:
Martin Ling
2022-09-26 13:42:28 +01:00
parent 559a45bd6b
commit 367ce3d7b3

View File

@ -382,7 +382,11 @@ static int prepare_transfers(
ready_transfers = TRANSFER_COUNT; ready_transfers = TRANSFER_COUNT;
} }
// Now everything is ready, go ahead and submit the ready transfers. // Now everything is ready, go ahead and submit the ready transfers. We must hold
// the transfer lock whilst doing this, so that completion callbacks cannot resubmit
// any transfers until all transfers have been initially submitted.
pthread_mutex_lock(&device->transfer_lock);
for (transfer_index = 0; transfer_index < ready_transfers; transfer_index++) { for (transfer_index = 0; transfer_index < ready_transfers; transfer_index++) {
struct libusb_transfer* transfer = device->transfers[transfer_index]; struct libusb_transfer* transfer = device->transfers[transfer_index];
transfer->endpoint = endpoint_address; transfer->endpoint = endpoint_address;
@ -397,27 +401,35 @@ static int prepare_transfers(
error = libusb_submit_transfer(transfer); error = libusb_submit_transfer(transfer);
if (error != 0) { if (error != 0) {
last_libusb_error = error; last_libusb_error = error;
return HACKRF_ERROR_LIBUSB; break;
} }
device->active_transfers++; device->active_transfers++;
} }
// We should only continue streaming if all transfers were made ready if (error == 0) {
// and submitted above. Otherwise, set streaming to false so that the // We should only continue streaming if all transfers were made ready
// libusb completion callback won't submit further transfers. // and submitted above. Otherwise, set streaming to false so that the
device->streaming = (ready_transfers == TRANSFER_COUNT); // libusb completion callback won't submit further transfers.
device->transfers_setup = true; device->streaming = (ready_transfers == TRANSFER_COUNT);
device->transfers_setup = true;
// If we're not continuing streaming, follow up with a flush if needed. // If we're not continuing streaming, follow up with a flush if needed.
if (!device->streaming && device->flush) { if (!device->streaming && device->flush) {
error = libusb_submit_transfer(device->flush_transfer); error = libusb_submit_transfer(device->flush_transfer);
if (error != 0) { if (error != 0) {
last_libusb_error = error; last_libusb_error = error;
return HACKRF_ERROR_LIBUSB; }
} }
} }
return HACKRF_SUCCESS; // Now we can release the transfer lock.
pthread_mutex_unlock(&device->transfer_lock);
if (error == 0) {
return HACKRF_SUCCESS;
} else {
return HACKRF_ERROR_LIBUSB;
}
} }
static int detach_kernel_drivers(libusb_device_handle* usb_device_handle) static int detach_kernel_drivers(libusb_device_handle* usb_device_handle)