From ae5fe7e6bca2874c5f1ef077204bb63124fb3db3 Mon Sep 17 00:00:00 2001 From: Chris Johns Date: Sun, 26 Oct 2014 18:09:41 -0700 Subject: cpukit: Add libdl with the Runtime Loader (RTL) code. This is a merge of the RTL project. --- cpukit/libdl/rtl-allocator.c | 210 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 210 insertions(+) create mode 100644 cpukit/libdl/rtl-allocator.c (limited to 'cpukit/libdl/rtl-allocator.c') diff --git a/cpukit/libdl/rtl-allocator.c b/cpukit/libdl/rtl-allocator.c new file mode 100644 index 0000000000..b845013fd8 --- /dev/null +++ b/cpukit/libdl/rtl-allocator.c @@ -0,0 +1,210 @@ +/* + * COPYRIGHT (c) 2012 Chris Johns + * + * 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. + */ +/** + * @file + * + * @ingroup rtems_rtl + * + * @brief RTEMS Run-Time Linker Allocator + */ + +#include + +#include +#include "rtl-alloc-heap.h" +#include "rtl-trace.h" + +/** + * Tags as symbols for tracing. + */ +#if RTEMS_RTL_TRACE +static const char* tag_labels[6] = +{ + "OBJECT", + "SYMBOL", + "EXTERNAL", + "READ", + "READ_WRITE", + "READ_EXEC", +}; +#define rtems_rtl_trace_tag_label(_l) tag_labels[_l] +#else +#define rtems_rtl_trace_tag_label(_l) "" +#endif + +void +rtems_rtl_alloc_initialise (rtems_rtl_alloc_data_t* data) +{ + int c; + data->allocator = rtems_rtl_alloc_heap; + for (c = 0; c < RTEMS_RTL_ALLOC_TAGS; ++c) + rtems_chain_initialize_empty (&data->indirects[c]); +} + +void* +rtems_rtl_alloc_new (rtems_rtl_alloc_tag_t tag, size_t size, bool zero) +{ + rtems_rtl_data_t* rtl = rtems_rtl_lock (); + void* address = NULL; + + if (rtl) + rtl->allocator.allocator (true, tag, &address, size); + + rtems_rtl_unlock (); + + if (rtems_rtl_trace (RTEMS_RTL_TRACE_ALLOCATOR)) + printf ("rtl: alloc: new: %s addr=%p size=%zu\n", + rtems_rtl_trace_tag_label (tag), address, size); + + if (zero) + memset (address, 0, size); + + return address; +} + +void +rtems_rtl_alloc_del (rtems_rtl_alloc_tag_t tag, void* address) +{ + rtems_rtl_data_t* rtl = rtems_rtl_lock (); + + if (rtems_rtl_trace (RTEMS_RTL_TRACE_ALLOCATOR)) + printf ("rtl: alloc: del: %s addr=%p\n", + rtems_rtl_trace_tag_label (tag), address); + + if (rtl && address) + rtl->allocator.allocator (false, tag, &address, 0); + + rtems_rtl_unlock (); +} + +rtems_rtl_allocator_t +rtems_rtl_alloc_hook (rtems_rtl_allocator_t handler) +{ + rtems_rtl_data_t* rtl = rtems_rtl_lock (); + rtems_rtl_allocator_t previous = rtl->allocator.allocator; + rtl->allocator.allocator = handler; + rtems_rtl_unlock (); + return previous; +} + +void +rtems_rtl_alloc_indirect_new (rtems_rtl_alloc_tag_t tag, + rtems_rtl_ptr_t* handle, + size_t size) +{ + rtems_rtl_data_t* rtl = rtems_rtl_lock (); + + if (rtems_rtl_trace (RTEMS_RTL_TRACE_ALLOCATOR)) + { + if (!rtems_rtl_ptr_null (handle)) + printf ("rtl: alloc: inew: %s handle=%p: not null\n", + rtems_rtl_trace_tag_label (tag), handle); + printf ("rtl: alloc: inew: %s handle=%p size=%zd\n", + rtems_rtl_trace_tag_label (tag), handle, size); + } + + if (rtl) + { + rtems_rtl_alloc_data_t* allocator = &rtl->allocator; + handle->pointer = rtems_rtl_alloc_new (tag, size, false); + if (!rtems_rtl_ptr_null (handle)) + rtems_chain_append_unprotected (&allocator->indirects[tag], + &handle->node); + } + + rtems_rtl_unlock (); +} + +void +rtems_rtl_alloc_indirect_del (rtems_rtl_alloc_tag_t tag, + rtems_rtl_ptr_t* handle) +{ + rtems_rtl_data_t* rtl = rtems_rtl_lock (); + + if (rtems_rtl_trace (RTEMS_RTL_TRACE_ALLOCATOR)) + { + if (rtems_rtl_ptr_null (handle)) + printf ("rtl: alloc: idel: %s handle=%p: is null\n", + rtems_rtl_trace_tag_label (tag), handle); + printf ("rtl: alloc: idel: %s handle=%p\n", + rtems_rtl_trace_tag_label (tag), handle); + } + + if (rtl && !rtems_rtl_ptr_null (handle)) + { + rtems_chain_extract_unprotected (&handle->node); + rtems_rtl_alloc_del (tag, &handle->pointer); + } +} + +bool +rtems_rtl_alloc_module_new (void** text_base, size_t text_size, + void** const_base, size_t const_size, + void** data_base, size_t data_size, + void** bss_base, size_t bss_size) +{ + *text_base = *const_base = *data_base = *bss_base = NULL; + + if (text_size) + { + *text_base = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_READ_EXEC, + text_size, false); + if (!*text_base) + { + return false; + } + } + + if (const_size) + { + *const_base = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_READ, + const_size, false); + if (!*const_base) + { + rtems_rtl_alloc_module_del (text_base, const_base, data_base, bss_base); + return false; + } + } + + if (data_size) + { + *data_base = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_READ_WRITE, + data_size, false); + if (!*data_base) + { + rtems_rtl_alloc_module_del (text_base, const_base, data_base, bss_base); + return false; + } + } + + if (bss_size) + { + *bss_base = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_READ_WRITE, + bss_size, false); + if (!*bss_base) + { + rtems_rtl_alloc_module_del (text_base, const_base, data_base, bss_base); + return false; + } + } + + return true; +} + +void +rtems_rtl_alloc_module_del (void** text_base, + void** const_base, + void** data_base, + void** bss_base) +{ + rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_READ_WRITE, *bss_base); + rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_READ_WRITE, *data_base); + rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_READ, *const_base); + rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_READ_EXEC, *text_base); + *text_base = *const_base = *data_base = *bss_base = NULL; +} -- cgit v1.2.3