[Mesa-dev] [PATCH v2 2/3] u_dynarray: return 0 on realloc failure and ensure no-op
Nicolai Hähnle
nhaehnle at gmail.com
Mon May 13 14:58:07 UTC 2019
From: Nicolai Hähnle <nicolai.haehnle at amd.com>
We're not very good at handling out-of-memory conditions in general, but
this change at least gives the caller the option of handling it gracefully
and without memory leaks.
This happens to fix an error in out-of-memory handling in i965, which has
the following code in brw_bufmgr.c:
node = util_dynarray_grow(vma_list, sizeof(struct vma_bucket_node));
if (unlikely(!node))
return 0ull;
Previously, allocation failure for util_dynarray_grow wouldn't actually
return NULL when the dynarray was previously non-empty.
v2:
- make util_dynarray_ensure_cap a no-op on failure, add MUST_CHECK attribute
- simplify the new capacity calculation: aside from avoiding a useless loop
when newcap is very large, this also avoids an infinite loop when newcap
is larger than 1 << 31
---
src/util/u_dynarray.h | 18 ++++++++++--------
1 file changed, 10 insertions(+), 8 deletions(-)
diff --git a/src/util/u_dynarray.h b/src/util/u_dynarray.h
index b30fd7b1154..769c3820546 100644
--- a/src/util/u_dynarray.h
+++ b/src/util/u_dynarray.h
@@ -70,35 +70,37 @@ util_dynarray_fini(struct util_dynarray *buf)
}
static inline void
util_dynarray_clear(struct util_dynarray *buf)
{
buf->size = 0;
}
#define DYN_ARRAY_INITIAL_SIZE 64
-static inline void *
+MUST_CHECK static inline void *
util_dynarray_ensure_cap(struct util_dynarray *buf, unsigned newcap)
{
if (newcap > buf->capacity) {
- if (buf->capacity == 0)
- buf->capacity = DYN_ARRAY_INITIAL_SIZE;
-
- while (newcap > buf->capacity)
- buf->capacity *= 2;
+ unsigned capacity = MAX3(DYN_ARRAY_INITIAL_SIZE, buf->capacity * 2, newcap);
+ void *data;
if (buf->mem_ctx) {
- buf->data = reralloc_size(buf->mem_ctx, buf->data, buf->capacity);
+ data = reralloc_size(buf->mem_ctx, buf->data, capacity);
} else {
- buf->data = realloc(buf->data, buf->capacity);
+ data = realloc(buf->data, capacity);
}
+ if (!data)
+ return 0;
+
+ buf->data = data;
+ buf->capacity = capacity;
}
return (void *)((char *)buf->data + buf->size);
}
static inline void *
util_dynarray_grow_cap(struct util_dynarray *buf, int diff)
{
return util_dynarray_ensure_cap(buf, buf->size + diff);
}
--
2.20.1
More information about the mesa-dev
mailing list