source: rtems/cpukit/score/src/wkspace.c @ 25f5730f

4.11
Last change on this file since 25f5730f was 884a6c59, checked in by Sebastian Huber <sebastian.huber@…>, on May 21, 2014 at 7:18:29 AM

score: Add comment regarding TLS workspace size

  • Property mode set to 100644
File size: 4.9 KB
Line 
1/**
2 *  @file
3 *
4 *  @brief Workspace Handler Support
5 *  @ingroup ScoreWorkspace
6 */
7
8/*
9 *  COPYRIGHT (c) 1989-2009.
10 *  On-Line Applications Research Corporation (OAR).
11 *
12 *  The license and distribution terms for this file may be
13 *  found in the file LICENSE in this distribution or at
14 *  http://www.rtems.org/license/LICENSE.
15 */
16
17#if HAVE_CONFIG_H
18  #include "config.h"
19#endif
20
21#include <rtems/score/wkspace.h>
22#include <rtems/score/heapimpl.h>
23#include <rtems/score/interr.h>
24#include <rtems/score/threadimpl.h>
25#include <rtems/score/tls.h>
26#include <rtems/config.h>
27
28#include <string.h>  /* for memset */
29
30/* #define DEBUG_WORKSPACE */
31#if defined(DEBUG_WORKSPACE)
32  #include <rtems/bspIo.h>
33#endif
34
35static uint32_t _Get_maximum_thread_count(void)
36{
37  uint32_t thread_count = 0;
38
39  thread_count += _Thread_Get_maximum_internal_threads();
40
41  thread_count += rtems_resource_maximum_per_allocation(
42    Configuration_RTEMS_API.maximum_tasks
43  );
44
45#if defined(RTEMS_POSIX_API)
46  thread_count += rtems_resource_maximum_per_allocation(
47    Configuration_POSIX_API.maximum_threads
48  );
49#endif
50
51  return thread_count;
52}
53
54void _Workspace_Handler_initialization(
55  Heap_Area *areas,
56  size_t area_count,
57  Heap_Initialization_or_extend_handler extend
58)
59{
60  Heap_Initialization_or_extend_handler init_or_extend = _Heap_Initialize;
61  uintptr_t remaining = rtems_configuration_get_work_space_size();
62  bool do_zero = rtems_configuration_get_do_zero_of_workspace();
63  bool unified = rtems_configuration_get_unified_work_area();
64  uintptr_t page_size = CPU_HEAP_ALIGNMENT;
65  uintptr_t overhead = _Heap_Area_overhead( page_size );
66  uintptr_t tls_size = _TLS_Get_size();
67  size_t i;
68
69  /*
70   * In case we have a non-zero TLS size, then we need a TLS area for each
71   * thread.  These areas are allocated from the workspace.  Ensure that the
72   * workspace is large enough to fulfill all requests known at configuration
73   * time (so excluding the unlimited option).  It is not possible to estimate
74   * the TLS size in the configuration at compile-time.  The TLS size is
75   * determined at application link-time.
76   */
77  if ( tls_size > 0 ) {
78    uintptr_t tls_align = _TLS_Heap_align_up( (uintptr_t) _TLS_Alignment );
79    uintptr_t tls_alloc = _TLS_Get_allocation_size( tls_size, tls_align );
80
81    /*
82     * Memory allocated with an alignment constraint is allocated from the end
83     * of a free block.  The last allocation may need one free block of minimum
84     * size.
85     */
86    remaining += _Heap_Min_block_size( page_size );
87
88    remaining += _Get_maximum_thread_count()
89      * _Heap_Size_with_overhead( page_size, tls_alloc, tls_align );
90  }
91
92  for (i = 0; i < area_count; ++i) {
93    Heap_Area *area = &areas [i];
94
95    if ( do_zero ) {
96      memset( area->begin, 0, area->size );
97    }
98
99    if ( area->size > overhead ) {
100      uintptr_t space_available;
101      uintptr_t size;
102
103      if ( unified ) {
104        size = area->size;
105      } else {
106        if ( remaining > 0 ) {
107          size = remaining < area->size - overhead ?
108            remaining + overhead : area->size;
109        } else {
110          size = 0;
111        }
112      }
113
114      space_available = (*init_or_extend)(
115        &_Workspace_Area,
116        area->begin,
117        size,
118        page_size
119      );
120
121      area->begin = (char *) area->begin + size;
122      area->size -= size;
123
124      if ( space_available < remaining ) {
125        remaining -= space_available;
126      } else {
127        remaining = 0;
128      }
129
130      init_or_extend = extend;
131    }
132  }
133
134  if ( remaining > 0 ) {
135    _Terminate(
136      INTERNAL_ERROR_CORE,
137      true,
138      INTERNAL_ERROR_TOO_LITTLE_WORKSPACE
139    );
140  }
141
142  _Heap_Protection_set_delayed_free_fraction( &_Workspace_Area, 1 );
143}
144
145void *_Workspace_Allocate(
146  size_t   size
147)
148{
149  void *memory;
150
151  memory = _Heap_Allocate( &_Workspace_Area, size );
152  #if defined(DEBUG_WORKSPACE)
153    printk(
154      "Workspace_Allocate(%d) from %p/%p -> %p\n",
155      size,
156      __builtin_return_address( 0 ),
157      __builtin_return_address( 1 ),
158      memory
159    );
160  #endif
161  return memory;
162}
163
164void *_Workspace_Allocate_aligned( size_t size, size_t alignment )
165{
166  return _Heap_Allocate_aligned( &_Workspace_Area, size, alignment );
167}
168
169/*
170 *  _Workspace_Free
171 */
172void _Workspace_Free(
173  void *block
174)
175{
176  #if defined(DEBUG_WORKSPACE)
177    printk(
178      "Workspace_Free(%p) from %p/%p\n",
179      block,
180      __builtin_return_address( 0 ),
181      __builtin_return_address( 1 )
182    );
183  #endif
184  _Heap_Free( &_Workspace_Area, block );
185}
186
187void *_Workspace_Allocate_or_fatal_error(
188  size_t      size
189)
190{
191  void *memory;
192
193  memory = _Heap_Allocate( &_Workspace_Area, size );
194  #if defined(DEBUG_WORKSPACE)
195    printk(
196      "Workspace_Allocate_or_fatal_error(%d) from %p/%p -> %p\n",
197      size,
198      __builtin_return_address( 0 ),
199      __builtin_return_address( 1 ),
200      memory
201    );
202  #endif
203
204  if ( memory == NULL )
205    _Terminate(
206      INTERNAL_ERROR_CORE,
207      true,
208      INTERNAL_ERROR_WORKSPACE_ALLOCATION
209    );
210
211  return memory;
212}
Note: See TracBrowser for help on using the repository browser.