From: Emil Velikov <[email protected]> Inlining the implementation does not cause additional overhead in terms of build time while the binary is increased only marginally (~1k)
At the same time the compiler should be able to optimise better, although this is not a path where we'll notice much difference. Use a local u_is_power_of_two to avoid pulling u_math.h. Latter of which would require updating 5+ locations to have an extra -I directive. Doing this will allow us to address a unrelated issue, as mentioned in the report below. Cc: "17.2" <[email protected]> Cc: Daniel Stone <[email protected]> Cc: Jason Ekstrand <[email protected]> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=101851 Signed-off-by: Emil Velikov <[email protected]> --- FTR I'm not a huge fan of this change, but it's like the least invasive one. --- src/util/Makefile.sources | 1 - src/util/u_vector.c | 110 ---------------------------------------------- src/util/u_vector.h | 93 ++++++++++++++++++++++++++++++++++++--- 3 files changed, 88 insertions(+), 116 deletions(-) delete mode 100644 src/util/u_vector.c diff --git a/src/util/Makefile.sources b/src/util/Makefile.sources index 3315285f05e..08c7a7ea6a8 100644 --- a/src/util/Makefile.sources +++ b/src/util/Makefile.sources @@ -51,7 +51,6 @@ MESA_UTIL_FILES := \ u_queue.h \ u_string.h \ u_thread.h \ - u_vector.c \ u_vector.h MESA_UTIL_GENERATED_FILES = \ diff --git a/src/util/u_vector.c b/src/util/u_vector.c deleted file mode 100644 index 0de492ccf9a..00000000000 --- a/src/util/u_vector.c +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright © 2015 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include <string.h> -#include "util/u_math.h" -#include "util/u_vector.h" - -/** @file u_vector.c - * - * A dynamically growable, circular buffer. Elements are added at head and - * removed from tail. head and tail are free-running uint32_t indices and we - * only compute the modulo with size when accessing the array. This way, - * number of bytes in the queue is always head - tail, even in case of - * wraparound. - */ - -int -u_vector_init(struct u_vector *vector, uint32_t element_size, uint32_t size) -{ - assert(util_is_power_of_two(size)); - assert(element_size < size && util_is_power_of_two(element_size)); - - vector->head = 0; - vector->tail = 0; - vector->element_size = element_size; - vector->size = size; - vector->data = malloc(size); - - return vector->data != NULL; -} - -void * -u_vector_add(struct u_vector *vector) -{ - uint32_t offset, size, split, src_tail, dst_tail; - void *data; - - if (vector->head - vector->tail == vector->size) { - size = vector->size * 2; - data = malloc(size); - if (data == NULL) - return NULL; - src_tail = vector->tail & (vector->size - 1); - dst_tail = vector->tail & (size - 1); - if (src_tail == 0) { - /* Since we know that the vector is full, this means that it's - * linear from start to end so we can do one copy. - */ - memcpy((char *)data + dst_tail, vector->data, vector->size); - } else { - /* In this case, the vector is split into two pieces and we have - * to do two copies. We have to be careful to make sure each - * piece goes to the right locations. Thanks to the change in - * size, it may or may not still wrap around. - */ - split = u_align_u32(vector->tail, vector->size); - assert(vector->tail <= split && split < vector->head); - memcpy((char *)data + dst_tail, (char *)vector->data + src_tail, - split - vector->tail); - memcpy((char *)data + (split & (size - 1)), vector->data, - vector->head - split); - } - free(vector->data); - vector->data = data; - vector->size = size; - } - - assert(vector->head - vector->tail < vector->size); - - offset = vector->head & (vector->size - 1); - vector->head += vector->element_size; - - return (char *)vector->data + offset; -} - -void * -u_vector_remove(struct u_vector *vector) -{ - uint32_t offset; - - if (vector->head == vector->tail) - return NULL; - - assert(vector->head - vector->tail <= vector->size); - - offset = vector->tail & (vector->size - 1); - vector->tail += vector->element_size; - - return (char *)vector->data + offset; -} diff --git a/src/util/u_vector.h b/src/util/u_vector.h index cd8a95dcbe3..40d52d91207 100644 --- a/src/util/u_vector.h +++ b/src/util/u_vector.h @@ -22,15 +22,20 @@ */ /* - * u_vector is a vector based queue for storing arbitrary - * sized arrays of objects without using a linked list. + * A dynamically growable, circular buffer. Elements are added at head and + * removed from tail. head and tail are free-running uint32_t indices and we + * only compute the modulo with size when accessing the array. This way, + * number of bytes in the queue is always head - tail, even in case of + * wraparound. */ #ifndef U_VECTOR_H #define U_VECTOR_H +#include <stdbool.h> #include <stdint.h> #include <stdlib.h> +#include <string.h> #include "util/macros.h" /* TODO - move to u_math.h - name it better etc */ @@ -41,6 +46,13 @@ u_align_u32(uint32_t v, uint32_t a) return (v + a - 1) & ~(a - 1); } +/* XXX - copies from u_math.h since it requires adding gallium include in 5+ places */ +static inline bool +u_is_power_of_two(uint32_t v) +{ + return (v & (v-1)) == 0; +} + struct u_vector { uint32_t head; uint32_t tail; @@ -49,9 +61,80 @@ struct u_vector { void *data; }; -int u_vector_init(struct u_vector *queue, uint32_t element_size, uint32_t size); -void *u_vector_add(struct u_vector *queue); -void *u_vector_remove(struct u_vector *queue); +MAYBE_UNUSED static int +u_vector_init(struct u_vector *vector, uint32_t element_size, uint32_t size) +{ + assert(u_is_power_of_two(size)); + assert(element_size < size && u_is_power_of_two(element_size)); + + vector->head = 0; + vector->tail = 0; + vector->element_size = element_size; + vector->size = size; + vector->data = malloc(size); + + return vector->data != NULL; +} + +MAYBE_UNUSED static void * +u_vector_add(struct u_vector *vector) +{ + uint32_t offset, size, split, src_tail, dst_tail; + void *data; + + if (vector->head - vector->tail == vector->size) { + size = vector->size * 2; + data = malloc(size); + if (data == NULL) + return NULL; + src_tail = vector->tail & (vector->size - 1); + dst_tail = vector->tail & (size - 1); + if (src_tail == 0) { + /* Since we know that the vector is full, this means that it's + * linear from start to end so we can do one copy. + */ + memcpy((char *)data + dst_tail, vector->data, vector->size); + } else { + /* In this case, the vector is split into two pieces and we have + * to do two copies. We have to be careful to make sure each + * piece goes to the right locations. Thanks to the change in + * size, it may or may not still wrap around. + */ + split = u_align_u32(vector->tail, vector->size); + assert(vector->tail <= split && split < vector->head); + memcpy((char *)data + dst_tail, (char *)vector->data + src_tail, + split - vector->tail); + memcpy((char *)data + (split & (size - 1)), vector->data, + vector->head - split); + } + free(vector->data); + vector->data = data; + vector->size = size; + } + + assert(vector->head - vector->tail < vector->size); + + offset = vector->head & (vector->size - 1); + vector->head += vector->element_size; + + return (char *)vector->data + offset; +} + +MAYBE_UNUSED static void * +u_vector_remove(struct u_vector *vector) +{ + uint32_t offset; + + if (vector->head == vector->tail) + return NULL; + + assert(vector->head - vector->tail <= vector->size); + + offset = vector->tail & (vector->size - 1); + vector->tail += vector->element_size; + + return (char *)vector->data + offset; +} static inline int u_vector_length(struct u_vector *queue) -- 2.13.3 _______________________________________________ mesa-dev mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/mesa-dev
