summaryrefslogtreecommitdiffstats
path: root/cpukit/libdl/rtl-allocator.c
diff options
context:
space:
mode:
Diffstat (limited to 'cpukit/libdl/rtl-allocator.c')
-rw-r--r--cpukit/libdl/rtl-allocator.c167
1 files changed, 140 insertions, 27 deletions
diff --git a/cpukit/libdl/rtl-allocator.c b/cpukit/libdl/rtl-allocator.c
index 647c0c89a4..7503183367 100644
--- a/cpukit/libdl/rtl-allocator.c
+++ b/cpukit/libdl/rtl-allocator.c
@@ -1,10 +1,5 @@
-/*
- * COPYRIGHT (c) 2012, 2018 Chris Johns <chrisj@rtems.org>
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
- */
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/**
* @file
*
@@ -13,6 +8,31 @@
* @brief RTEMS Run-Time Linker Allocator
*/
+/*
+ * COPYRIGHT (c) 2012, 2018, 2023 Chris Johns <chrisj@rtems.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
#include <stdio.h>
#include <string.h>
@@ -90,6 +110,39 @@ rtems_rtl_alloc_del (rtems_rtl_alloc_tag tag, void* address)
rtems_rtl_unlock ();
}
+void* rtems_rtl_alloc_resize (rtems_rtl_alloc_tag tag,
+ void* address,
+ size_t size,
+ bool zero)
+{
+ rtems_rtl_data* rtl = rtems_rtl_lock ();
+ const void* prev_address = address;
+
+ /*
+ * Resize memory of an existing allocation. The address field is set
+ * by the allocator and may change.
+ */
+ if (rtl != NULL)
+ rtl->allocator.allocator (RTEMS_RTL_ALLOC_RESIZE, tag, &address, size);
+
+ rtems_rtl_unlock ();
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_ALLOCATOR))
+ printf ("rtl: alloc: resize: %s%s prev-addr=%p addr=%p size=%zu\n",
+ rtems_rtl_trace_tag_label (tag), prev_address == address ? "" : " MOVED",
+ prev_address, address, size);
+
+ /*
+ * Only zero the memory if asked to and the resize was successful. We
+ * cannot clear the resized area if bigger than the previouis allocation
+ * because we do not have the original size.
+ */
+ if (address != NULL && zero)
+ memset (address, 0, size);
+
+ return address;
+}
+
void
rtems_rtl_alloc_wr_enable (rtems_rtl_alloc_tag tag, void* address)
{
@@ -257,21 +310,23 @@ rtems_rtl_alloc_module_new (void** text_base, size_t text_size,
{
*text_base = *const_base = *data_base = *bss_base = NULL;
- if (text_size)
+ if (data_size != 0)
{
- *text_base = rtems_rtl_alloc_new (rtems_rtl_alloc_text_tag (),
- text_size, false);
- if (!*text_base)
+ *data_base = rtems_rtl_alloc_new (rtems_rtl_alloc_data_tag (),
+ data_size, false);
+ if (*data_base == NULL)
{
+ rtems_rtl_alloc_module_del (text_base, const_base, eh_base,
+ data_base, bss_base);
return false;
}
}
- if (const_size)
+ if (bss_size != 0)
{
- *const_base = rtems_rtl_alloc_new (rtems_rtl_alloc_const_tag (),
- const_size, false);
- if (!*const_base)
+ *bss_base = rtems_rtl_alloc_new (rtems_rtl_alloc_bss_tag (),
+ bss_size, false);
+ if (*bss_base == NULL)
{
rtems_rtl_alloc_module_del (text_base, const_base, eh_base,
data_base, bss_base);
@@ -279,11 +334,11 @@ rtems_rtl_alloc_module_new (void** text_base, size_t text_size,
}
}
- if (eh_size)
+ if (eh_size != 0)
{
*eh_base = rtems_rtl_alloc_new (rtems_rtl_alloc_eh_tag (),
eh_size, false);
- if (!*eh_base)
+ if (*eh_base == NULL)
{
rtems_rtl_alloc_module_del (text_base, const_base, eh_base,
data_base, bss_base);
@@ -291,11 +346,11 @@ rtems_rtl_alloc_module_new (void** text_base, size_t text_size,
}
}
- if (data_size)
+ if (const_size != 0)
{
- *data_base = rtems_rtl_alloc_new (rtems_rtl_alloc_data_tag (),
- data_size, false);
- if (!*data_base)
+ *const_base = rtems_rtl_alloc_new (rtems_rtl_alloc_const_tag (),
+ const_size, false);
+ if (*const_base == NULL)
{
rtems_rtl_alloc_module_del (text_base, const_base, eh_base,
data_base, bss_base);
@@ -303,14 +358,72 @@ rtems_rtl_alloc_module_new (void** text_base, size_t text_size,
}
}
- if (bss_size)
+ if (text_size != 0)
{
- *bss_base = rtems_rtl_alloc_new (rtems_rtl_alloc_bss_tag (),
- bss_size, false);
- if (!*bss_base)
+ *text_base = rtems_rtl_alloc_new (rtems_rtl_alloc_text_tag (),
+ text_size, false);
+ if (*text_base == NULL)
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool
+rtems_rtl_alloc_module_resize (void** text_base, size_t text_size,
+ void** const_base, size_t const_size,
+ void** eh_base, size_t eh_size,
+ void** data_base, size_t data_size,
+ void** bss_base, size_t bss_size)
+{
+ if (data_size != 0)
+ {
+ *data_base = rtems_rtl_alloc_resize (rtems_rtl_alloc_data_tag (),
+ *data_base, data_size, false);
+ if (*data_base == NULL)
+ {
+ return false;
+ }
+ }
+
+ if (bss_size != 0)
+ {
+ *bss_base = rtems_rtl_alloc_resize (rtems_rtl_alloc_bss_tag (),
+ *bss_base, bss_size, false);
+ if (*bss_base == NULL)
+ {
+ return false;
+ }
+ }
+
+ if (eh_size != 0)
+ {
+ *eh_base = rtems_rtl_alloc_resize (rtems_rtl_alloc_eh_tag (),
+ *eh_base, eh_size, false);
+ if (*eh_base == NULL)
+ {
+ return false;
+ }
+ }
+
+ if (const_size != 0)
+ {
+ *const_base = rtems_rtl_alloc_resize (rtems_rtl_alloc_const_tag (),
+ *const_base, const_size, false);
+ if (*const_base == NULL)
+ {
+ return false;
+ }
+ }
+
+ if (text_size != 0)
+ {
+ *text_base = rtems_rtl_alloc_resize (rtems_rtl_alloc_text_tag (),
+ *text_base, text_size, false);
+ if (*text_base == NULL)
{
- rtems_rtl_alloc_module_del (text_base, const_base, eh_base,
- data_base, bss_base);
return false;
}
}