sandbox: Add os_realloc()
authorSimon Glass <sjg@chromium.org>
Sat, 6 Feb 2021 16:57:32 +0000 (09:57 -0700)
committerTom Rini <trini@konsulko.com>
Tue, 2 Mar 2021 20:53:37 +0000 (15:53 -0500)
We provide os_malloc() and os_free() but not os_realloc(). Add this,
following the usual semantics. Also update os_malloc() to behave correctly
when passed a zero size.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
arch/sandbox/cpu/os.c
include/os.h

index 3d8af0a52bbc51c874efb1acfff9f9df15a2cd4b..d23aad318bea61feb038f1aa49206885dbeda670 100644 (file)
@@ -267,11 +267,18 @@ void os_tty_raw(int fd, bool allow_sigs)
        signal(SIGINT, os_sigint_handler);
 }
 
+/*
+ * Provide our own malloc so we don't use space in the sandbox ram_buf for
+ * allocations that are internal to sandbox, or need to be done before U-Boot's
+ * malloc() is ready.
+ */
 void *os_malloc(size_t length)
 {
        int page_size = getpagesize();
        struct os_mem_hdr *hdr;
 
+       if (!length)
+               return NULL;
        /*
         * Use an address that is hopefully available to us so that pointers
         * to this memory are fairly obvious. If we end up with a different
@@ -298,6 +305,47 @@ void os_free(void *ptr)
        }
 }
 
+/* These macros are from kernel.h but not accessible in this file */
+#define ALIGN(x, a)            __ALIGN_MASK((x), (typeof(x))(a) - 1)
+#define __ALIGN_MASK(x, mask)  (((x) + (mask)) & ~(mask))
+
+/*
+ * Provide our own malloc so we don't use space in the sandbox ram_buf for
+ * allocations that are internal to sandbox, or need to be done before U-Boot's
+ * malloc() is ready.
+ */
+void *os_realloc(void *ptr, size_t length)
+{
+       int page_size = getpagesize();
+       struct os_mem_hdr *hdr;
+       void *new_ptr;
+
+       /* Reallocating a NULL pointer is just an alloc */
+       if (!ptr)
+               return os_malloc(length);
+
+       /* Changing a length to 0 is just a free */
+       if (length) {
+               os_free(ptr);
+               return NULL;
+       }
+
+       /*
+        * If the new size is the same number of pages as the old, nothing to
+        * do. There isn't much point in shrinking things
+        */
+       hdr = ptr - page_size;
+       if (ALIGN(length, page_size) <= ALIGN(hdr->length, page_size))
+               return ptr;
+
+       /* We have to grow it, so allocate something new */
+       new_ptr = os_malloc(length);
+       memcpy(new_ptr, ptr, hdr->length);
+       os_free(ptr);
+
+       return new_ptr;
+}
+
 void os_usleep(unsigned long usec)
 {
        usleep(usec);
index 65bcb232caba4974eec2f3bcafa326f10c1f2c92..fd010cfee8388fcff004da6e0411a341eff41eb2 100644 (file)
@@ -114,7 +114,7 @@ void os_fd_restore(void);
  * os_malloc() - aquires some memory from the underlying os.
  *
  * @length:    Number of bytes to be allocated
- * Return:     Pointer to length bytes or NULL on error
+ * Return:     Pointer to length bytes or NULL if @length is 0 or on error
  */
 void *os_malloc(size_t length);
 
@@ -127,6 +127,16 @@ void *os_malloc(size_t length);
  */
 void os_free(void *ptr);
 
+/**
+ * os_realloc() - reallocate memory
+ *
+ * This follows the semantics of realloc(), so can perform an os_malloc() or
+ * os_free() depending on @ptr and @length.
+ *
+ * Return:     Pointer to reallocated memory or NULL if @length is 0
+ */
+void *os_realloc(void *ptr, size_t length);
+
 /**
  * os_usleep() - access to the usleep function of the os
  *