source: rtems/cpukit/score/src/wkspace.c @ e97806a

5
Last change on this file since e97806a was e97806a, checked in by Sebastian Huber <sebastian.huber@…>, on 10/14/18 at 17:20:05

posix: Split posix_api_configuration_table

Use separate configuration variables to avoid false dependencies.

Update #2514.

  • Property mode set to 100644
File size: 7.0 KB
RevLine 
[f2f63d1]1/**
2 *  @file
[ac7d5ef0]3 *
[f2f63d1]4 *  @brief Workspace Handler Support
5 *  @ingroup ScoreWorkspace
6 */
7
8/*
[e63b79d]9 *  COPYRIGHT (c) 1989-2009.
[ac7d5ef0]10 *  On-Line Applications Research Corporation (OAR).
11 *
[98e4ebf5]12 *  The license and distribution terms for this file may be
13 *  found in the file LICENSE in this distribution or at
[c499856]14 *  http://www.rtems.org/license/LICENSE.
[ac7d5ef0]15 */
16
[a8eed23]17#if HAVE_CONFIG_H
[e6f7f81]18  #include "config.h"
[a8eed23]19#endif
20
[5e9b32b]21#include <rtems/score/wkspace.h>
[cfc4231d]22#include <rtems/score/assert.h>
[e6f7f81]23#include <rtems/score/heapimpl.h>
[5e9b32b]24#include <rtems/score/interr.h>
[cfc4231d]25#include <rtems/score/percpudata.h>
[022851a]26#include <rtems/score/threadimpl.h>
27#include <rtems/score/tls.h>
[e97806a]28#include <rtems/posix/pthread.h>
[e6f7f81]29#include <rtems/config.h>
[976162a6]30
[cfc4231d]31#include <string.h>
[ac7d5ef0]32
[e63b79d]33/* #define DEBUG_WORKSPACE */
34#if defined(DEBUG_WORKSPACE)
35  #include <rtems/bspIo.h>
36#endif
37
[cfc4231d]38RTEMS_LINKER_RWSET(
39  _Per_CPU_Data,
40  RTEMS_ALIGNED( CPU_CACHE_LINE_BYTES ) char
41);
42
[358bd740]43Heap_Control _Workspace_Area;
44
[cfc4231d]45static uint32_t _Workspace_Get_maximum_thread_count( void )
[022851a]46{
[cfc4231d]47  uint32_t thread_count;
[022851a]48
[cfc4231d]49  thread_count = 0;
[022851a]50  thread_count += _Thread_Get_maximum_internal_threads();
51
52  thread_count += rtems_resource_maximum_per_allocation(
53    Configuration_RTEMS_API.maximum_tasks
54  );
55
56#if defined(RTEMS_POSIX_API)
57  thread_count += rtems_resource_maximum_per_allocation(
[e97806a]58    _Configuration_POSIX_Maximum_threads
[022851a]59  );
60#endif
61
62  return thread_count;
63}
64
[cfc4231d]65static uintptr_t _Workspace_Space_for_TLS( uintptr_t page_size )
[8faca06]66{
[cfc4231d]67  uintptr_t tls_size;
68  uintptr_t space;
69
70  tls_size = _TLS_Get_size();
[47a3cd8]71
[884a6c59]72  /*
73   * In case we have a non-zero TLS size, then we need a TLS area for each
74   * thread.  These areas are allocated from the workspace.  Ensure that the
75   * workspace is large enough to fulfill all requests known at configuration
76   * time (so excluding the unlimited option).  It is not possible to estimate
77   * the TLS size in the configuration at compile-time.  The TLS size is
78   * determined at application link-time.
79   */
[022851a]80  if ( tls_size > 0 ) {
[6cf45cb]81    uintptr_t tls_align = _TLS_Heap_align_up( (uintptr_t) _TLS_Alignment );
82    uintptr_t tls_alloc = _TLS_Get_allocation_size( tls_size, tls_align );
83
84    /*
85     * Memory allocated with an alignment constraint is allocated from the end
86     * of a free block.  The last allocation may need one free block of minimum
87     * size.
88     */
[cfc4231d]89    space = _Heap_Min_block_size( page_size );
[022851a]90
[cfc4231d]91    space += _Workspace_Get_maximum_thread_count()
[6cf45cb]92      * _Heap_Size_with_overhead( page_size, tls_alloc, tls_align );
[cfc4231d]93  } else {
94    space = 0;
95  }
96
97  return space;
98}
99
100static uintptr_t _Workspace_Space_for_per_CPU_data( uintptr_t page_size )
101{
102  uintptr_t space;
103
104#ifdef RTEMS_SMP
105  uintptr_t size;
106
107  size = RTEMS_LINKER_SET_SIZE( _Per_CPU_Data );
108  _Assert( size % CPU_CACHE_LINE_BYTES == 0 );
109
110  if ( size > 0 ) {
111    /*
112     * Memory allocated with an alignment constraint is allocated from the end of
113     * a free block.  The last allocation may need one free block of minimum
114     * size.
115     */
116    space = _Heap_Min_block_size( page_size );
117
118    space += ( rtems_configuration_get_maximum_processors() - 1 )
119      * _Heap_Size_with_overhead( page_size, size, CPU_CACHE_LINE_BYTES );
120  } else {
121    space = 0;
[022851a]122  }
[cfc4231d]123#else
124  space = 0;
125#endif
126
127  return space;
128}
129
130static void _Workspace_Allocate_per_CPU_data( void )
131{
132#ifdef RTEMS_SMP
[776464a]133  uintptr_t size;
[cfc4231d]134
135  size = RTEMS_LINKER_SET_SIZE( _Per_CPU_Data );
136
[776464a]137  if ( size > 0 ) {
138    Per_CPU_Control *cpu;
139    uint32_t         cpu_index;
140    uint32_t         cpu_max;
141
142    cpu = _Per_CPU_Get_by_index( 0 );
143    cpu->data = RTEMS_LINKER_SET_BEGIN( _Per_CPU_Data );
144
145    cpu_max = rtems_configuration_get_maximum_processors();
146
147    for ( cpu_index = 1 ; cpu_index < cpu_max ; ++cpu_index ) {
148      cpu = _Per_CPU_Get_by_index( cpu_index );
149      cpu->data = _Workspace_Allocate_aligned( size, CPU_CACHE_LINE_BYTES );
150      _Assert( cpu->data != NULL );
151      memcpy( cpu->data, RTEMS_LINKER_SET_BEGIN( _Per_CPU_Data ), size);
152    }
[cfc4231d]153  }
154#endif
155}
156
157void _Workspace_Handler_initialization(
158  Heap_Area *areas,
159  size_t area_count,
160  Heap_Initialization_or_extend_handler extend
161)
162{
163  Heap_Initialization_or_extend_handler init_or_extend;
164  uintptr_t                             remaining;
165  bool                                  do_zero;
166  bool                                  unified;
167  uintptr_t                             page_size;
168  uintptr_t                             overhead;
169  size_t                                i;
170
171  page_size = CPU_HEAP_ALIGNMENT;
172
173  remaining = rtems_configuration_get_work_space_size();
174  remaining += _Workspace_Space_for_TLS( page_size );
175  remaining += _Workspace_Space_for_per_CPU_data( page_size );
176
177  init_or_extend = _Heap_Initialize;
178  do_zero = rtems_configuration_get_do_zero_of_workspace();
179  unified = rtems_configuration_get_unified_work_area();
180  overhead = _Heap_Area_overhead( page_size );
181
182  for ( i = 0; i < area_count; ++i ) {
183    Heap_Area *area;
[022851a]184
[cfc4231d]185    area = &areas[ i ];
[47a3cd8]186
187    if ( do_zero ) {
188      memset( area->begin, 0, area->size );
189    }
190
191    if ( area->size > overhead ) {
192      uintptr_t space_available;
193      uintptr_t size;
194
195      if ( unified ) {
196        size = area->size;
197      } else {
198        if ( remaining > 0 ) {
199          size = remaining < area->size - overhead ?
200            remaining + overhead : area->size;
201        } else {
202          size = 0;
203        }
204      }
205
[cfc4231d]206      space_available = ( *init_or_extend )(
[47a3cd8]207        &_Workspace_Area,
208        area->begin,
209        size,
210        page_size
211      );
212
213      area->begin = (char *) area->begin + size;
214      area->size -= size;
[05279b84]215
[47a3cd8]216      if ( space_available < remaining ) {
217        remaining -= space_available;
218      } else {
219        remaining = 0;
220      }
[05279b84]221
[47a3cd8]222      init_or_extend = extend;
223    }
224  }
[05279b84]225
[47a3cd8]226  if ( remaining > 0 ) {
[3a659b04]227    _Internal_error( INTERNAL_ERROR_TOO_LITTLE_WORKSPACE );
[47a3cd8]228  }
[2a713e3]229
230  _Heap_Protection_set_delayed_free_fraction( &_Workspace_Area, 1 );
[cfc4231d]231  _Workspace_Allocate_per_CPU_data();
[8faca06]232}
233
[5b33dc80]234void *_Workspace_Allocate(
[7ff6115]235  size_t   size
[5b33dc80]236)
237{
[a2fa532d]238  void *memory;
[e63b79d]239
[a2fa532d]240  memory = _Heap_Allocate( &_Workspace_Area, size );
[e63b79d]241  #if defined(DEBUG_WORKSPACE)
242    printk(
243      "Workspace_Allocate(%d) from %p/%p -> %p\n",
244      size,
245      __builtin_return_address( 0 ),
246      __builtin_return_address( 1 ),
[a2fa532d]247      memory
[e63b79d]248    );
249  #endif
[a2fa532d]250  return memory;
[5b33dc80]251}
[ac7d5ef0]252
[a850d04]253void *_Workspace_Allocate_aligned( size_t size, size_t alignment )
254{
255  return _Heap_Allocate_aligned( &_Workspace_Area, size, alignment );
256}
257
[5b33dc80]258/*
[9d4fa67]259 *  _Workspace_Free
[5b33dc80]260 */
[a0323a9f]261void _Workspace_Free(
[5b33dc80]262  void *block
263)
264{
[e63b79d]265  #if defined(DEBUG_WORKSPACE)
266    printk(
267      "Workspace_Free(%p) from %p/%p\n",
268      block,
269      __builtin_return_address( 0 ),
270      __builtin_return_address( 1 )
271    );
272  #endif
[8249054]273  _Heap_Free( &_Workspace_Area, block );
[5b33dc80]274}
275
[ac7d5ef0]276void *_Workspace_Allocate_or_fatal_error(
[7ff6115]277  size_t      size
[ac7d5ef0]278)
279{
[a2fa532d]280  void *memory;
[ac7d5ef0]281
[a2fa532d]282  memory = _Heap_Allocate( &_Workspace_Area, size );
283  #if defined(DEBUG_WORKSPACE)
284    printk(
285      "Workspace_Allocate_or_fatal_error(%d) from %p/%p -> %p\n",
286      size,
287      __builtin_return_address( 0 ),
288      __builtin_return_address( 1 ),
289      memory
290    );
291  #endif
[ac7d5ef0]292
293  if ( memory == NULL )
[3a659b04]294    _Internal_error( INTERNAL_ERROR_WORKSPACE_ALLOCATION );
[ac7d5ef0]295
296  return memory;
297}
Note: See TracBrowser for help on using the repository browser.