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

4.115
Last change on this file since 25f5730f was 884a6c59, checked in by Sebastian Huber <sebastian.huber@…>, on 05/21/14 at 07:18:29

score: Add comment regarding TLS workspace size

  • Property mode set to 100644
File size: 4.9 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>
[e6f7f81]22#include <rtems/score/heapimpl.h>
[5e9b32b]23#include <rtems/score/interr.h>
[022851a]24#include <rtems/score/threadimpl.h>
25#include <rtems/score/tls.h>
[e6f7f81]26#include <rtems/config.h>
[976162a6]27
28#include <string.h>  /* for memset */
[ac7d5ef0]29
[e63b79d]30/* #define DEBUG_WORKSPACE */
31#if defined(DEBUG_WORKSPACE)
32  #include <rtems/bspIo.h>
33#endif
34
[022851a]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
[47a3cd8]54void _Workspace_Handler_initialization(
55  Heap_Area *areas,
56  size_t area_count,
57  Heap_Initialization_or_extend_handler extend
58)
[8faca06]59{
[47a3cd8]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 );
[bee71f8e]66  uintptr_t tls_size = _TLS_Get_size();
[47a3cd8]67  size_t i;
68
[884a6c59]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   */
[022851a]77  if ( tls_size > 0 ) {
[6cf45cb]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 );
[022851a]87
88    remaining += _Get_maximum_thread_count()
[6cf45cb]89      * _Heap_Size_with_overhead( page_size, tls_alloc, tls_align );
[022851a]90  }
91
[47a3cd8]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;
[05279b84]123
[47a3cd8]124      if ( space_available < remaining ) {
125        remaining -= space_available;
126      } else {
127        remaining = 0;
128      }
[05279b84]129
[47a3cd8]130      init_or_extend = extend;
131    }
132  }
[05279b84]133
[47a3cd8]134  if ( remaining > 0 ) {
[83bf105]135    _Terminate(
[8faca06]136      INTERNAL_ERROR_CORE,
[aae7f1a1]137      true,
[8faca06]138      INTERNAL_ERROR_TOO_LITTLE_WORKSPACE
139    );
[47a3cd8]140  }
[2a713e3]141
142  _Heap_Protection_set_delayed_free_fraction( &_Workspace_Area, 1 );
[8faca06]143}
144
[5b33dc80]145void *_Workspace_Allocate(
[7ff6115]146  size_t   size
[5b33dc80]147)
148{
[a2fa532d]149  void *memory;
[e63b79d]150
[a2fa532d]151  memory = _Heap_Allocate( &_Workspace_Area, size );
[e63b79d]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 ),
[a2fa532d]158      memory
[e63b79d]159    );
160  #endif
[a2fa532d]161  return memory;
[5b33dc80]162}
[ac7d5ef0]163
[a850d04]164void *_Workspace_Allocate_aligned( size_t size, size_t alignment )
165{
166  return _Heap_Allocate_aligned( &_Workspace_Area, size, alignment );
167}
168
[5b33dc80]169/*
[9d4fa67]170 *  _Workspace_Free
[5b33dc80]171 */
[a0323a9f]172void _Workspace_Free(
[5b33dc80]173  void *block
174)
175{
[e63b79d]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
[8249054]184  _Heap_Free( &_Workspace_Area, block );
[5b33dc80]185}
186
[ac7d5ef0]187void *_Workspace_Allocate_or_fatal_error(
[7ff6115]188  size_t      size
[ac7d5ef0]189)
190{
[a2fa532d]191  void *memory;
[ac7d5ef0]192
[a2fa532d]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
[ac7d5ef0]203
204  if ( memory == NULL )
[83bf105]205    _Terminate(
[3a4ae6c]206      INTERNAL_ERROR_CORE,
[aae7f1a1]207      true,
[3a4ae6c]208      INTERNAL_ERROR_WORKSPACE_ALLOCATION
209    );
[ac7d5ef0]210
211  return memory;
212}
Note: See TracBrowser for help on using the repository browser.