source: rtems/cpukit/libdl/rtl-allocator.c @ 22afb034

5
Last change on this file since 22afb034 was 22afb034, checked in by Chris Johns <chrisj@…>, on 02/18/19 at 00:46:22

libdl/alloc: Add a locking interface to the allocator.

  • Allow an allocator to lock the allocations. This is needed to lock the heap allocator so the text and trampoline table are as close together as possible to allow for the largest possible object file size.
  • Update the default heap allocator to lock the heap allocator.
  • Update ELF loading to lock the allocator.

Updates #3685

  • Property mode set to 100644
File size: 8.3 KB
Line 
1/*
2 *  COPYRIGHT (c) 2012, 2018 Chris Johns <chrisj@rtems.org>
3 *
4 *  The license and distribution terms for this file may be
5 *  found in the file LICENSE in this distribution or at
6 *  http://www.rtems.org/license/LICENSE.
7 */
8/**
9 * @file
10 *
11 * @ingroup rtems_rtl
12 *
13 * @brief RTEMS Run-Time Linker Allocator
14 */
15
16#include <stdio.h>
17#include <string.h>
18
19#include <rtems/rtl/rtl.h>
20#include "rtl-alloc-heap.h"
21#include <rtems/rtl/rtl-trace.h>
22
23/**
24 * Tags as symbols for tracing.
25 */
26#if RTEMS_RTL_TRACE
27static const char* tag_labels[6] =
28{
29  "OBJECT",
30  "SYMBOL",
31  "EXTERNAL",
32  "READ",
33  "READ_WRITE",
34  "READ_EXEC",
35};
36#define rtems_rtl_trace_tag_label(_l) tag_labels[_l]
37#else
38#define rtems_rtl_trace_tag_label(_l) ""
39#endif
40
41void
42rtems_rtl_alloc_initialise (rtems_rtl_alloc_data* data)
43{
44  int c;
45  data->allocator = rtems_rtl_alloc_heap;
46  for (c = 0; c < RTEMS_RTL_ALLOC_TAGS; ++c)
47    rtems_chain_initialize_empty (&data->indirects[c]);
48}
49
50void*
51rtems_rtl_alloc_new (rtems_rtl_alloc_tag tag, size_t size, bool zero)
52{
53  rtems_rtl_data* rtl = rtems_rtl_lock ();
54  void*           address = NULL;
55
56  /*
57   * Obtain memory from the allocator. The address field is set by the
58   * allocator.
59   */
60  if (rtl != NULL)
61    rtl->allocator.allocator (RTEMS_RTL_ALLOC_NEW, tag, &address, size);
62
63  rtems_rtl_unlock ();
64
65  if (rtems_rtl_trace (RTEMS_RTL_TRACE_ALLOCATOR))
66    printf ("rtl: alloc: new: %s addr=%p size=%zu\n",
67            rtems_rtl_trace_tag_label (tag), address, size);
68
69  /*
70   * Only zero the memory if asked to and the allocation was successful.
71   */
72  if (address != NULL && zero)
73    memset (address, 0, size);
74
75  return address;
76}
77
78void
79rtems_rtl_alloc_del (rtems_rtl_alloc_tag tag, void* address)
80{
81  rtems_rtl_data* rtl = rtems_rtl_lock ();
82
83  if (rtems_rtl_trace (RTEMS_RTL_TRACE_ALLOCATOR))
84    printf ("rtl: alloc: del: %s addr=%p\n",
85            rtems_rtl_trace_tag_label (tag), address);
86
87  if (rtl != NULL && address != NULL)
88    rtl->allocator.allocator (RTEMS_RTL_ALLOC_DEL, tag, &address, 0);
89
90  rtems_rtl_unlock ();
91}
92
93void
94rtems_rtl_alloc_wr_enable (rtems_rtl_alloc_tag tag, void* address)
95{
96  rtems_rtl_data* rtl = rtems_rtl_lock ();
97
98  if (rtems_rtl_trace (RTEMS_RTL_TRACE_ALLOCATOR))
99    printf ("rtl: alloc: wr-enable: addr=%p\n", address);
100
101  if (rtl != NULL && address != NULL)
102    rtl->allocator.allocator (RTEMS_RTL_ALLOC_WR_ENABLE,
103                              tag,
104                              address,
105                              0);
106
107  rtems_rtl_unlock ();
108}
109
110void
111rtems_rtl_alloc_lock (void)
112{
113  rtems_rtl_data* rtl = rtems_rtl_lock ();
114
115  if (rtems_rtl_trace (RTEMS_RTL_TRACE_ALLOCATOR))
116    printf ("rtl: alloc: lock\n");
117
118  if (rtl != NULL)
119    rtl->allocator.allocator (RTEMS_RTL_ALLOC_LOCK,
120                              RTEMS_RTL_ALLOC_OBJECT, /* should be ignored */
121                              NULL,
122                              0);
123
124  rtems_rtl_unlock ();
125}
126
127
128void
129rtems_rtl_alloc_unlock (void)
130{
131  rtems_rtl_data* rtl = rtems_rtl_lock ();
132
133  if (rtems_rtl_trace (RTEMS_RTL_TRACE_ALLOCATOR))
134    printf ("rtl: alloc: unlock\n");
135
136  if (rtl != NULL)
137    rtl->allocator.allocator (RTEMS_RTL_ALLOC_UNLOCK,
138                              RTEMS_RTL_ALLOC_OBJECT, /* should be ignored */
139                              NULL,
140                              0);
141
142  rtems_rtl_unlock ();
143}
144void
145rtems_rtl_alloc_wr_disable (rtems_rtl_alloc_tag tag, void* address)
146{
147  rtems_rtl_data* rtl = rtems_rtl_lock ();
148
149  if (rtems_rtl_trace (RTEMS_RTL_TRACE_ALLOCATOR))
150    printf ("rtl: alloc: wr-enable: addr=%p\n", address);
151
152  if (rtl != NULL && address != NULL)
153    rtl->allocator.allocator (RTEMS_RTL_ALLOC_WR_DISABLE,
154                              tag,
155                              address,
156                              0);
157
158  rtems_rtl_unlock ();
159}
160
161rtems_rtl_allocator
162rtems_rtl_alloc_hook (rtems_rtl_allocator handler)
163{
164  rtems_rtl_data*     rtl = rtems_rtl_lock ();
165  rtems_rtl_allocator previous = rtl->allocator.allocator;
166  rtl->allocator.allocator = handler;
167  rtems_rtl_unlock ();
168  return previous;
169}
170
171void
172rtems_rtl_alloc_indirect_new (rtems_rtl_alloc_tag tag,
173                              rtems_rtl_ptr*      handle,
174                              size_t              size)
175{
176  rtems_rtl_data* rtl = rtems_rtl_lock ();
177
178  if (rtems_rtl_trace (RTEMS_RTL_TRACE_ALLOCATOR))
179  {
180    if (!rtems_rtl_ptr_null (handle))
181      printf ("rtl: alloc: inew: %s handle=%p: not null\n",
182              rtems_rtl_trace_tag_label (tag), handle);
183    printf ("rtl: alloc: inew: %s handle=%p size=%zd\n",
184            rtems_rtl_trace_tag_label (tag), handle, size);
185  }
186
187  if (rtl)
188  {
189    rtems_rtl_alloc_data* allocator = &rtl->allocator;
190    handle->pointer = rtems_rtl_alloc_new (tag, size, false);
191    if (!rtems_rtl_ptr_null (handle))
192      rtems_chain_append_unprotected (&allocator->indirects[tag],
193                                      &handle->node);
194  }
195
196  rtems_rtl_unlock ();
197}
198
199void
200rtems_rtl_alloc_indirect_del (rtems_rtl_alloc_tag tag,
201                              rtems_rtl_ptr*      handle)
202{
203  rtems_rtl_data* rtl = rtems_rtl_lock ();
204
205  if (rtems_rtl_trace (RTEMS_RTL_TRACE_ALLOCATOR))
206  {
207    if (rtems_rtl_ptr_null (handle))
208      printf ("rtl: alloc: idel: %s handle=%p: is null\n",
209              rtems_rtl_trace_tag_label (tag), handle);
210    printf ("rtl: alloc: idel: %s handle=%p\n",
211            rtems_rtl_trace_tag_label (tag), handle);
212  }
213
214  if (rtl && !rtems_rtl_ptr_null (handle))
215  {
216    rtems_chain_extract_unprotected (&handle->node);
217    rtems_rtl_alloc_del (tag, &handle->pointer);
218  }
219}
220
221rtems_rtl_alloc_tag
222rtems_rtl_alloc_text_tag (void)
223{
224  return RTEMS_RTL_ALLOC_READ_EXEC;
225}
226
227rtems_rtl_alloc_tag
228rtems_rtl_alloc_const_tag (void)
229{
230  return RTEMS_RTL_ALLOC_READ;
231}
232
233rtems_rtl_alloc_tag
234rtems_rtl_alloc_eh_tag (void)
235{
236  return RTEMS_RTL_ALLOC_READ;
237}
238
239rtems_rtl_alloc_tag
240rtems_rtl_alloc_data_tag (void)
241{
242  return RTEMS_RTL_ALLOC_READ_WRITE;
243}
244
245rtems_rtl_alloc_tag
246rtems_rtl_alloc_bss_tag (void)
247{
248  return RTEMS_RTL_ALLOC_READ_WRITE;
249}
250
251bool
252rtems_rtl_alloc_module_new (void** text_base, size_t text_size,
253                            void** const_base, size_t const_size,
254                            void** eh_base, size_t eh_size,
255                            void** data_base, size_t data_size,
256                            void** bss_base, size_t bss_size)
257{
258  *text_base = *const_base = *data_base = *bss_base = NULL;
259
260  if (text_size)
261  {
262    *text_base = rtems_rtl_alloc_new (rtems_rtl_alloc_text_tag (),
263                                      text_size, false);
264    if (!*text_base)
265    {
266      return false;
267    }
268  }
269
270  if (const_size)
271  {
272    *const_base = rtems_rtl_alloc_new (rtems_rtl_alloc_const_tag (),
273                                       const_size, false);
274    if (!*const_base)
275    {
276      rtems_rtl_alloc_module_del (text_base, const_base, eh_base,
277                                  data_base, bss_base);
278      return false;
279    }
280  }
281
282  if (eh_size)
283  {
284    *eh_base = rtems_rtl_alloc_new (rtems_rtl_alloc_eh_tag (),
285                                    eh_size, false);
286    if (!*eh_base)
287    {
288      rtems_rtl_alloc_module_del (text_base, const_base, eh_base,
289                                  data_base, bss_base);
290      return false;
291    }
292  }
293
294  if (data_size)
295  {
296    *data_base = rtems_rtl_alloc_new (rtems_rtl_alloc_data_tag (),
297                                      data_size, false);
298    if (!*data_base)
299    {
300      rtems_rtl_alloc_module_del (text_base, const_base, eh_base,
301                                  data_base, bss_base);
302      return false;
303    }
304  }
305
306  if (bss_size)
307  {
308    *bss_base = rtems_rtl_alloc_new (rtems_rtl_alloc_bss_tag (),
309                                     bss_size, false);
310    if (!*bss_base)
311    {
312      rtems_rtl_alloc_module_del (text_base, const_base, eh_base,
313                                  data_base, bss_base);
314      return false;
315    }
316  }
317
318  return true;
319}
320
321void
322rtems_rtl_alloc_module_del (void** text_base,
323                            void** const_base,
324                            void** eh_base,
325                            void** data_base,
326                            void** bss_base)
327{
328  rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_READ_WRITE, *bss_base);
329  rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_READ_WRITE, *data_base);
330  rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_READ, *eh_base);
331  rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_READ, *const_base);
332  rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_READ_EXEC, *text_base);
333  *text_base = *const_base = *eh_base = *data_base = *bss_base = NULL;
334}
Note: See TracBrowser for help on using the repository browser.