aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias Andrée <maandree@operamail.com>2015-10-16 04:12:06 +0200
committerMattias Andrée <maandree@operamail.com>2015-10-16 04:12:06 +0200
commit8fbc07438e31c171d9333b3221bc12121fe8a2db (patch)
tree6f9a4e539af8fa0a88dfd6981e2b84401e73525b
parentadd custom_realloc (diff)
downloadslibc-8fbc07438e31c171d9333b3221bc12121fe8a2db.tar.gz
slibc-8fbc07438e31c171d9333b3221bc12121fe8a2db.tar.bz2
slibc-8fbc07438e31c171d9333b3221bc12121fe8a2db.tar.xz
fix realloc + add extalloc and naive_extalloc
Signed-off-by: Mattias Andrée <maandree@operamail.com>
-rw-r--r--include/slibc-alloc.h62
-rw-r--r--src/slibc-alloc.c69
2 files changed, 130 insertions, 1 deletions
diff --git a/include/slibc-alloc.h b/include/slibc-alloc.h
index 7bd2e81..70b1b4c 100644
--- a/include/slibc-alloc.h
+++ b/include/slibc-alloc.h
@@ -28,6 +28,26 @@
/**
+ * Configurations for `extalloc`.
+ * There are independent of each other, and
+ * multiple can be selected by using bitwise or
+ * between them.
+ */
+enum extalloc_mode
+ {
+ /**
+ * Clear disowned memory.
+ */
+ EXTALLOC_CLEAR = 1,
+
+ /**
+ * Create new allocation with `malloc` if necessary.
+ */
+ EXTALLOC_MALLOC = 2,
+ };
+
+
+/**
* This function is identical to `free`, except it is guaranteed not to
* override the memory segment with zeroes before freeing the allocation.
*
@@ -134,6 +154,32 @@ void* custom_realloc(void*, size_t, int, int, int)
__GCC_ONLY(__attribute__((warn_unused_result)));
/**
+ * This function is similar to `realloc`, however it
+ * does not copy the data in the memory segment when
+ * a new pointer is created. Additionally, the
+ * behaviour is undefined if `ptr` is `NULL`, `size`
+ * is zero, or `size` equals the old allocation size.
+ * These additional quirks were added to improve
+ * performance; after all, this function was added
+ * to improve performance.
+ *
+ * The behaviour is undefined if `mode` does not
+ * contain a valid flag-combination.
+ *
+ * @param ptr The old allocation, see `realloc` for more details.
+ * @param size The new allocation size, see `realloc` for more details.
+ * @param mode `EXTALLOC_CLEAR` or `EXTALLOC_MALLOC`, or both or neither.
+ * @return The new allocation, see `realloc` for more details.
+ * If `EXTALLOC_MALLOC` is not used, `NULL` is returned
+ * and `errno` set to zero, if a new allocation is required.
+ *
+ * @throws 0 `errno` is set to zero success if `NULL` is returned.
+ * @throws ENOMEM The process cannot allocate more memory.
+ */
+void* extalloc(void*, size_t, enum extalloc_mode)
+ __GCC_ONLY(__attribute__((nonnull, warn_unused_result)));
+
+/**
* This function behaves exactly like `fast_realloc`, except:
* - Its behaviour is undefined if `ptr` is `NULL`.
* - Its behaviour is undefined if `size` equals the old allocation size.
@@ -149,6 +195,22 @@ void* custom_realloc(void*, size_t, int, int, int)
void* naive_realloc(void*, size_t) /* sic! we limit ourself to ASCII */
__GCC_ONLY(__attribute__((nonnull, warn_unused_result)));
+/**
+ * This function behaves exactly like `__attribute__`, except
+ * it will return `NULL` with `errno` set to zero, if it is
+ * not possible to perform the shrink or growth without creating
+ * new pointer.
+ *
+ * @param ptr The old allocation, see `realloc` for more details.
+ * @param size The new allocation size, see `realloc` for more details.
+ * @return `ptr` on success or `NULL` on error or if `malloc` is needed.
+ *
+ * @throws 0 `malloc` is require to perform the action.
+ * @throws ENOMEM The process cannot allocate more memory.
+ */
+void* naive_extalloc(void*, size_t) /* sic! we limit ourself to ASCII */
+ __GCC_ONLY(__attribute__((nonnull, warn_unused_result)));
+
/**
* This macro calls `fast_free` and then sets the pointer to `NULL`,
diff --git a/src/slibc-alloc.c b/src/slibc-alloc.c
index 1b85aad..9380d24 100644
--- a/src/slibc-alloc.c
+++ b/src/slibc-alloc.c
@@ -117,9 +117,11 @@ size_t allocsize(void* segment)
new_ptr = naive_realloc(ptr); \
if (new_ptr != ptr) \
{ \
+ if (new_ptr == NULL) \
+ return NULL; \
if (CLEAR_FREE) \
explicit_bzero(PURE_ALLOC(ptr), PURE_SIZE(ptr)); \
- fast_free(new_ptr); \
+ fast_free(ptr); \
} \
\
if (CLEAR_NEW ? (old_size < size) : 0) \
@@ -207,6 +209,50 @@ void* custom_realloc(void* ptr, size_t size, int clear_old, int clear_new, int c
/**
+ * This function is similar to `realloc`, however it
+ * does not copy the data in the memory segment when
+ * a new pointer is created. Additionally, the
+ * behaviour is undefined if `ptr` is `NULL`, `size`
+ * is zero, or `size` equals the old allocation size.
+ * These additional quirks were added to improve
+ * performance; after all, this function was added
+ * to improve performance.
+ *
+ * The behaviour is undefined if `mode` does not
+ * contain a valid flag-combination.
+ *
+ * @param ptr The old allocation, see `realloc` for more details.
+ * @param size The new allocation size, see `realloc` for more details.
+ * @param mode `EXTALLOC_CLEAR` or `EXTALLOC_MALLOC`, or both or neither.
+ * @return The new allocation, see `realloc` for more details.
+ * If `EXTALLOC_MALLOC` is not used, `NULL` is returned
+ * and `errno` set to zero, if a new allocation is required.
+ *
+ * @throws 0 `errno` is set to zero success if `NULL` is returned.
+ * @throws ENOMEM The process cannot allocate more memory.
+ */
+void* extalloc(void* ptr, size_t size, enum extalloc_mode mode)
+{
+ int clear = mode & EXTALLOC_CLEAR;
+ size_t old_size;
+ void* new_ptr;
+
+ if (clear ? (old_size > size) : 0)
+ explicit_bzero(((char*)ptr) + size, old_size - size);
+
+ new_ptr = ((mode & EXTALLOC_MALLOC) ? naive_realloc : naive_extalloc)(ptr);
+ if ((new_ptr != ptr) && (ptr_new != NULL))
+ {
+ if (clear)
+ explicit_bzero(PURE_ALLOC(ptr), PURE_SIZE(ptr));
+ fast_free(ptr);
+ }
+
+ return new_ptr;
+}
+
+
+/**
* This function behaves exactly like `fast_realloc`, except:
* - Its behaviour is undefined if `ptr` is `NULL`.
* - Its behaviour is undefined if `size` equals the old allocation size.
@@ -226,3 +272,24 @@ void* naive_realloc(void* ptr, size_t size)
(void) ptr;
}
+
+/**
+ * This function behaves exactly like `__attribute__`, except
+ * it will return `NULL` with `errno` set to zero, if it is
+ * not possible to perform the shrink or growth without creating
+ * new pointer.
+ *
+ * @param ptr The old allocation, see `realloc` for more details.
+ * @param size The new allocation size, see `realloc` for more details.
+ * @return `ptr` on success or `NULL` on error or if `malloc` is needed.
+ *
+ * @throws 0 `malloc` is require to perform the action.
+ * @throws ENOMEM The process cannot allocate more memory.
+ */
+void* naive_extalloc(void* ptr, size_t size)
+{
+ /* TODO implement naive_extalloc */
+ return NULL;
+ (void) ptr, (void) size;
+}
+