diff options
author | Vadim Yanitskiy <axilirator@gmail.com> | 2017-09-01 16:19:40 +0700 |
---|---|---|
committer | Vadim Yanitskiy <axilirator@gmail.com> | 2017-12-31 12:20:59 +0100 |
commit | 539af39e29726fc196e874b5d9cd6ec619dc5f3c (patch) | |
tree | 0a72fa47938ab09bff7cd1464a54bde5e52fbc70 | |
parent | 1cf7f34444b3d8b44122a57d2bed7542b8c3b7f2 (diff) |
procqueue: use linuxlist to store queue items
The usage of linuxlist is more flexible than having a limited
array of pointers. This approach allows to have as much items
in a processing queue as required.
-rw-r--r-- | include/osmocom/gapk/procqueue.h | 8 | ||||
-rw-r--r-- | src/procqueue.c | 104 |
2 files changed, 65 insertions, 47 deletions
diff --git a/include/osmocom/gapk/procqueue.h b/include/osmocom/gapk/procqueue.h index 6921b51..a72fd61 100644 --- a/include/osmocom/gapk/procqueue.h +++ b/include/osmocom/gapk/procqueue.h @@ -22,6 +22,8 @@ #include <stdint.h> #include <stdio.h> /* for FILE */ +#include <osmocom/core/linuxlist.h> + struct osmo_gapk_pq_item { /*! input frame size (in bytes). '0' in case of variable frames */ unsigned int len_in; @@ -39,14 +41,16 @@ struct osmo_gapk_pq_item { * \returns number of output bytes written to \a out; negative on error */ int (*proc)(void *state, uint8_t *out, const uint8_t *in, unsigned int in_len); void (*exit)(void *state); + + /*! \brief link to a processing queue */ + struct llist_head list; }; #define VAR_BUF_SIZE 320 -#define MAX_PQ_ITEMS 8 struct osmo_gapk_pq { + struct llist_head items; unsigned n_items; - struct osmo_gapk_pq_item *items[MAX_PQ_ITEMS]; }; /* Processing queue management */ diff --git a/src/procqueue.c b/src/procqueue.c index 1586f97..00472d3 100644 --- a/src/procqueue.c +++ b/src/procqueue.c @@ -21,13 +21,23 @@ #include <stdint.h> #include <stdlib.h> +#include <osmocom/core/linuxlist.h> + #include <osmocom/gapk/procqueue.h> /* crate a new (empty) processing queue */ struct osmo_gapk_pq * osmo_gapk_pq_create(void) { - return (struct osmo_gapk_pq *) calloc(1, sizeof(struct osmo_gapk_pq)); + struct osmo_gapk_pq *pq; + + /* Allocate memory for a new processing queue */ + pq = (struct osmo_gapk_pq *) calloc(1, sizeof(struct osmo_gapk_pq)); + + /* Init its list of items */ + INIT_LLIST_HEAD(&pq->items); + + return pq; } /*! destroy a processing queue, calls exit() callback of each item @@ -35,19 +45,23 @@ osmo_gapk_pq_create(void) void osmo_gapk_pq_destroy(struct osmo_gapk_pq *pq) { - int i; + struct osmo_gapk_pq_item *item, *item_next; if (!pq) return; - for (i=0; i<pq->n_items; i++) { - if (!pq->items[i]) - continue; - if (pq->items[i]->exit) - pq->items[i]->exit(pq->items[i]->state); + /* Iterate over all items in queue */ + llist_for_each_entry_safe(item, item_next, &pq->items, list) { + /* Free output buffer memory */ + free(item->buf); + + /* Call exit handler if preset */ + if (item->exit) + item->exit(item->state); - free(pq->items[i]->buf); - free(pq->items[i]); + /* Delete an item from list */ + llist_del(&item->list); + free(item); } free(pq); @@ -61,17 +75,16 @@ osmo_gapk_pq_add_item(struct osmo_gapk_pq *pq) { struct osmo_gapk_pq_item *item; - if (pq->n_items == MAX_PQ_ITEMS) { - fprintf(stderr, "[!] Processing Queue cannot handle more than %u items\n", - MAX_PQ_ITEMS); - return NULL; - } - + /* Allocate memory for a new item */ item = calloc(1, sizeof(struct osmo_gapk_pq_item)); if (!item) return NULL; - pq->items[pq->n_items++] = item; + /* Add one to the end of a queue */ + llist_add_tail(&item->list, &pq->items); + + /* Increase the items count */ + pq->n_items++; return item; } @@ -82,35 +95,40 @@ osmo_gapk_pq_add_item(struct osmo_gapk_pq *pq) int osmo_gapk_pq_prepare(struct osmo_gapk_pq *pq) { - int i; - unsigned int len_prev; - - len_prev = 0; - - for (i=0; i<pq->n_items; i++) { - struct osmo_gapk_pq_item *item = pq->items[i]; + struct osmo_gapk_pq_item *item; + unsigned int len_prev = 0; + /* Iterate over all items in queue */ + llist_for_each_entry(item, &pq->items, list) { + /* Make sure I/O data lengths are equal */ if (item->len_in && item->len_in != len_prev) { - fprintf(stderr, "[!] PQ item requires input size %u, but previous output is %u\n", - item->len_in, len_prev); + fprintf(stderr, "[!] PQ item requires input size %u, " + "but previous output is %u\n", item->len_in, len_prev); return -EINVAL; } - if (i < (pq->n_items-1)) { + /* The sink item doesn't require an output buffer */ + if (item->list.next != &pq->items) { unsigned int buf_size = item->len_out; - /* variable-length codec output, use maximum - * known buffer size */ + + /** + * Use maximum known buffer size + * for variable-length codec output + */ if (!buf_size) buf_size = VAR_BUF_SIZE; + /* Allocate memory for an output buffer */ item->buf = malloc(buf_size); if (!item->buf) return -ENOMEM; - } else{ + } else { + /* Make sure the last item is a sink */ if (item->len_out) return -EINVAL; } + /* Store output length for further comparation */ len_prev = item->len_out; } @@ -123,26 +141,22 @@ osmo_gapk_pq_prepare(struct osmo_gapk_pq *pq) int osmo_gapk_pq_execute(struct osmo_gapk_pq *pq) { - int i; - uint8_t *buf_prev, *buf; - unsigned int len_prev; - - buf_prev = NULL; - len_prev = 0; - - for (i=0; i<pq->n_items; i++) { - int rv; - struct osmo_gapk_pq_item *item = pq->items[i]; - - buf = i < (pq->n_items-1) ? item->buf : NULL; - - rv = item->proc(item->state, buf, buf_prev, len_prev); + struct osmo_gapk_pq_item *item; + unsigned int len_prev = 0; + uint8_t *buf_prev = NULL; + int rv; + + /* Iterate over all items in queue */ + llist_for_each_entry(item, &pq->items, list) { + /* Call item's processing handler */ + rv = item->proc(item->state, item->buf, buf_prev, len_prev); if (rv < 0) { - fprintf(stderr, "[!] osmo_gapk_pq_execute(): abort, item returned %d\n", rv); + fprintf(stderr, "[!] osmo_gapk_pq_execute(): " + "abort, item returned %d\n", rv); return rv; } - buf_prev = buf; + buf_prev = item->buf; len_prev = rv; } |