From 3af72991f65b9758a93be57f940dc17a5e3b6d73 Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Tue, 5 Dec 2023 11:33:34 +0100 Subject: [PATCH 1/4] utils/iio-common: Use CLOCK_MONOTONIC clock for timeouts The CLOCK_REALTIME clock may jump in time, which can be a huge problem when computing timeouts. Use the CLOCK_MONOTONIC one instead, which does not have this problem. Signed-off-by: Paul Cercueil --- utils/iio_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/iio_common.c b/utils/iio_common.c index bcaae5055..a108a0246 100644 --- a/utils/iio_common.c +++ b/utils/iio_common.c @@ -444,7 +444,7 @@ uint64_t get_time_us(void) #ifdef _MSC_BUILD timespec_get(&tp, TIME_UTC); #else - clock_gettime(CLOCK_REALTIME, &tp); + clock_gettime(CLOCK_MONOTONIC, &tp); #endif return tp.tv_sec * 1000000ull + tp.tv_nsec / 1000; From 2819ff36420c5d2b68d9afdb4f110e8594508b3c Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Mon, 11 Dec 2023 10:29:08 +0100 Subject: [PATCH 2/4] iiod: Fix segmentation fault when buffer creation failed When the buffer creation failed, entry->buf was left to whatever error pointer it had previously, instead of being reset to NULL; cleanup code would subsequently try to destroy the buffer once again with an invalid pointer. Signed-off-by: Paul Cercueil --- iiod/ops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iiod/ops.c b/iiod/ops.c index 0019daf95..473078691 100644 --- a/iiod/ops.c +++ b/iiod/ops.c @@ -398,8 +398,8 @@ static int create_buf_and_blocks(struct DevEntry *entry, size_t samples_count, for (; i; i--) iio_block_destroy(entry->blocks[i - 1]); iio_buffer_destroy(entry->buf); - entry->buf = NULL; err_free_blocks_array: + entry->buf = NULL; free(entry->blocks); entry->blocks = NULL; return err; From 9466de621554ab18798245eeea35376db88669ed Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Mon, 11 Dec 2023 11:39:43 +0100 Subject: [PATCH 3/4] Add "cyclic" parameter to .buffer_enable() backend callback IIOD v0.x supports enqueueing cyclic blocks, but it needs to know about it when the iio_buffer is opened through the "OPEN" command. As iiod-client calls this command when the buffer is to be enabled, pass an extra "cyclic" parameter to .buffer_enable(), always set to "false" for now. Signed-off-by: Paul Cercueil --- buffer.c | 3 ++- iiod-client.c | 4 ++-- include/iio/iio-backend.h | 2 +- include/iio/iiod-client.h | 2 +- local.c | 2 +- network.c | 4 ++-- serial.c | 4 ++-- usb.c | 4 ++-- 8 files changed, 13 insertions(+), 12 deletions(-) diff --git a/buffer.c b/buffer.c index eb759f8b6..e8b35afd7 100644 --- a/buffer.c +++ b/buffer.c @@ -46,6 +46,7 @@ static int iio_buffer_set_enabled(const struct iio_buffer *buf, bool enabled) { const struct iio_backend_ops *ops = buf->dev->ctx->ops; size_t sample_size, nb_samples = 0; + bool cyclic = false; if (buf->block_size) { sample_size = iio_device_get_sample_size(buf->dev, buf->mask); @@ -53,7 +54,7 @@ static int iio_buffer_set_enabled(const struct iio_buffer *buf, bool enabled) } if (ops->enable_buffer) - return ops->enable_buffer(buf->pdata, nb_samples, enabled); + return ops->enable_buffer(buf->pdata, nb_samples, enabled, cyclic); return -ENOSYS; } diff --git a/iiod-client.c b/iiod-client.c index 5039f0ace..92dbfde14 100644 --- a/iiod-client.c +++ b/iiod-client.c @@ -1490,7 +1490,7 @@ void iiod_client_free_buffer(struct iiod_client_buffer_pdata *pdata) } int iiod_client_enable_buffer(struct iiod_client_buffer_pdata *pdata, - size_t nb_samples, bool enable) + size_t nb_samples, bool enable, bool cyclic) { struct iiod_client *client = pdata->client; struct iiod_client_io *client_io; @@ -1511,7 +1511,7 @@ int iiod_client_enable_buffer(struct iiod_client_buffer_pdata *pdata, if (enable) { client_io = iiod_client_open_with_mask(client, pdata->dev, pdata->mask, - nb_samples, false); + nb_samples, cyclic); err = iio_err(client_io); pdata->io = err ? NULL : client_io; } else { diff --git a/include/iio/iio-backend.h b/include/iio/iio-backend.h index 73b5fec6c..ae907ba63 100644 --- a/include/iio/iio-backend.h +++ b/include/iio/iio-backend.h @@ -108,7 +108,7 @@ struct iio_backend_ops { struct iio_channels_mask *mask); void (*free_buffer)(struct iio_buffer_pdata *pdata); int (*enable_buffer)(struct iio_buffer_pdata *pdata, - size_t nb_samples, bool enable); + size_t nb_samples, bool enable, bool cyclic); void (*cancel_buffer)(struct iio_buffer_pdata *pdata); ssize_t (*readbuf)(struct iio_buffer_pdata *pdata, diff --git a/include/iio/iiod-client.h b/include/iio/iiod-client.h index 7582f7c60..1ec23f141 100644 --- a/include/iio/iiod-client.h +++ b/include/iio/iiod-client.h @@ -77,7 +77,7 @@ iiod_client_create_buffer(struct iiod_client *client, struct iio_channels_mask *mask); __api void iiod_client_free_buffer(struct iiod_client_buffer_pdata *pdata); __api int iiod_client_enable_buffer(struct iiod_client_buffer_pdata *pdata, - size_t nb_samples, bool enable); + size_t nb_samples, bool enable, bool cyclic); __api struct iio_block_pdata * iiod_client_create_block(struct iiod_client_buffer_pdata *pdata, diff --git a/local.c b/local.c index 89b337684..c3ee9731d 100644 --- a/local.c +++ b/local.c @@ -313,7 +313,7 @@ static int local_do_enable_buffer(struct iio_buffer_pdata *pdata, bool enable) } static int local_enable_buffer(struct iio_buffer_pdata *pdata, - size_t nb_samples, bool enable) + size_t nb_samples, bool enable, bool cyclic) { int ret; diff --git a/network.c b/network.c index 4e6dcb3d2..699307c79 100644 --- a/network.c +++ b/network.c @@ -485,9 +485,9 @@ void network_free_buffer(struct iio_buffer_pdata *pdata) } int network_enable_buffer(struct iio_buffer_pdata *pdata, - size_t block_size, bool enable) + size_t block_size, bool enable, bool cyclic) { - return iiod_client_enable_buffer(pdata->pdata, block_size, enable); + return iiod_client_enable_buffer(pdata->pdata, block_size, enable, cyclic); } struct iio_block_pdata * network_create_block(struct iio_buffer_pdata *pdata, diff --git a/serial.c b/serial.c index 390b05ae9..6116faae1 100644 --- a/serial.c +++ b/serial.c @@ -257,9 +257,9 @@ static void serial_free_buffer(struct iio_buffer_pdata *buf) } static int serial_enable_buffer(struct iio_buffer_pdata *buf, - size_t nb_samples, bool enable) + size_t nb_samples, bool enable, bool cyclic) { - return iiod_client_enable_buffer(buf->pdata, nb_samples, enable); + return iiod_client_enable_buffer(buf->pdata, nb_samples, enable, cyclic); } static ssize_t diff --git a/usb.c b/usb.c index d8e255909..40406324a 100644 --- a/usb.c +++ b/usb.c @@ -490,9 +490,9 @@ static void usb_free_buffer(struct iio_buffer_pdata *buf) } static int usb_enable_buffer(struct iio_buffer_pdata *pdata, - size_t nb_samples, bool enable) + size_t nb_samples, bool enable, bool cyclic) { - return iiod_client_enable_buffer(pdata->pdata, nb_samples, enable); + return iiod_client_enable_buffer(pdata->pdata, nb_samples, enable, cyclic); } static struct iio_block_pdata * From b8f3ea0be33ee90a7dfc4614752615acb65dc978 Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Mon, 11 Dec 2023 11:50:34 +0100 Subject: [PATCH 4/4] Rework cyclic block enqueue when talking to v0.x IIOD Instead of continuously sending the same block again and again, set the "cyclic" parameter of the .enable_buffer() backend callback to the value of the "cyclic" parameter of the last call to iio_buffer_enqueue(). Signed-off-by: Paul Cercueil --- block.c | 18 +++--------------- buffer.c | 1 + iio-private.h | 3 +++ 3 files changed, 7 insertions(+), 15 deletions(-) diff --git a/block.c b/block.c index 8a263100e..f6b0f9bbc 100644 --- a/block.c +++ b/block.c @@ -19,9 +19,8 @@ struct iio_block { size_t size; void *data; - struct iio_task_token *token, *old_token; + struct iio_task_token *token; size_t bytes_used; - bool cyclic; }; struct iio_block * @@ -83,9 +82,6 @@ void iio_block_destroy(struct iio_block *block) struct iio_buffer *buf = block->buffer; const struct iio_backend_ops *ops = buf->dev->ctx->ops; - /* Stop the cyclic task */ - block->cyclic = false; - if (block->token) { iio_task_cancel(block->token); iio_task_sync(block->token, 0); @@ -132,20 +128,12 @@ int iio_block_io(struct iio_block *block) if (!iio_device_is_tx(block->buffer->dev)) return iio_block_read(block); - if (block->old_token) - iio_task_sync(block->old_token, 0); - - if (block->cyclic) { - block->old_token = block->token; - block->token = iio_task_enqueue(block->buffer->worker, block); - } - return iio_block_write(block); } int iio_block_enqueue(struct iio_block *block, size_t bytes_used, bool cyclic) { - const struct iio_buffer *buffer = block->buffer; + struct iio_buffer *buffer = block->buffer; const struct iio_device *dev = buffer->dev; const struct iio_backend_ops *ops = dev->ctx->ops; @@ -164,7 +152,7 @@ int iio_block_enqueue(struct iio_block *block, size_t bytes_used, bool cyclic) } block->bytes_used = bytes_used; - block->cyclic = cyclic; + buffer->cyclic = cyclic; block->token = iio_task_enqueue(buffer->worker, block); return iio_err(block->token); diff --git a/buffer.c b/buffer.c index e8b35afd7..654fd9490 100644 --- a/buffer.c +++ b/buffer.c @@ -51,6 +51,7 @@ static int iio_buffer_set_enabled(const struct iio_buffer *buf, bool enabled) if (buf->block_size) { sample_size = iio_device_get_sample_size(buf->dev, buf->mask); nb_samples = buf->block_size / sample_size; + cyclic = buf->cyclic; } if (ops->enable_buffer) diff --git a/iio-private.h b/iio-private.h index 5d6ec2951..575b5ac73 100644 --- a/iio-private.h +++ b/iio-private.h @@ -146,7 +146,10 @@ struct iio_buffer { struct iio_task *worker; + /* These two fields are set by the last block created. They are only + * used when communicating with v0.x IIOD. */ size_t block_size; + bool cyclic; struct iio_attr_list attrlist;