source: rtems/cpukit/score/src/wkspace.c @ 6cf45cb

4.115
Last change on this file since 6cf45cb was 6cf45cb, checked in by Sebastian Huber <sebastian.huber@…>, on 04/07/14 at 14:50:13

score: Fix workspace size estimate for TLS

  • Property mode set to 100644
File size: 4.5 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 = (uintptr_t) _TLS_Size;
67  size_t i;
68
69  if ( tls_size > 0 ) {
70    uintptr_t tls_align = _TLS_Heap_align_up( (uintptr_t) _TLS_Alignment );
71    uintptr_t tls_alloc = _TLS_Get_allocation_size( tls_size, tls_align );
72
73    /*
74     * Memory allocated with an alignment constraint is allocated from the end
75     * of a free block.  The last allocation may need one free block of minimum
76     * size.
77     */
78    remaining += _Heap_Min_block_size( page_size );
79
80    remaining += _Get_maximum_thread_count()
81      * _Heap_Size_with_overhead( page_size, tls_alloc, tls_align );
82  }
83
84  for (i = 0; i < area_count; ++i) {
85    Heap_Area *area = &areas [i];
86
87    if ( do_zero ) {
88      memset( area->begin, 0, area->size );
89    }
90
91    if ( area->size > overhead ) {
92      uintptr_t space_available;
93      uintptr_t size;
94
95      if ( unified ) {
96        size = area->size;
97      } else {
98        if ( remaining > 0 ) {
99          size = remaining < area->size - overhead ?
100            remaining + overhead : area->size;
101        } else {
102          size = 0;
103        }
104      }
105
106      space_available = (*init_or_extend)(
107        &_Workspace_Area,
108        area->begin,
109        size,
110        page_size
111      );
112
113      area->begin = (char *) area->begin + size;
114      area->size -= size;
115
116      if ( space_available < remaining ) {
117        remaining -= space_available;
118      } else {
119        remaining = 0;
120      }
121
122      init_or_extend = extend;
123    }
124  }
125
126  if ( remaining > 0 ) {
127    _Terminate(
128      INTERNAL_ERROR_CORE,
129      true,
130      INTERNAL_ERROR_TOO_LITTLE_WORKSPACE
131    );
132  }
133
134  _Heap_Protection_set_delayed_free_fraction( &_Workspace_Area, 1 );
135}
136
137void *_Workspace_Allocate(
138  size_t   size
139)
140{
141  void *memory;
142
143  memory = _Heap_Allocate( &_Workspace_Area, size );
144  #if defined(DEBUG_WORKSPACE)
145    printk(
146      "Workspace_Allocate(%d) from %p/%p -> %p\n",
147      size,
148      __builtin_return_address( 0 ),
149      __builtin_return_address( 1 ),
150      memory
151    );
152  #endif
153  return memory;
154}
155
156void *_Workspace_Allocate_aligned( size_t size, size_t alignment )
157{
158  return _Heap_Allocate_aligned( &_Workspace_Area, size, alignment );
159}
160
161/*
162 *  _Workspace_Free
163 */
164void _Workspace_Free(
165  void *block
166)
167{
168  #if defined(DEBUG_WORKSPACE)
169    printk(
170      "Workspace_Free(%p) from %p/%p\n",
171      block,
172      __builtin_return_address( 0 ),
173      __builtin_return_address( 1 )
174    );
175  #endif
176  _Heap_Free( &_Workspace_Area, block );
177}
178
179void *_Workspace_Allocate_or_fatal_error(
180  size_t      size
181)
182{
183  void *memory;
184
185  memory = _Heap_Allocate( &_Workspace_Area, size );
186  #if defined(DEBUG_WORKSPACE)
187    printk(
188      "Workspace_Allocate_or_fatal_error(%d) from %p/%p -> %p\n",
189      size,
190      __builtin_return_address( 0 ),
191      __builtin_return_address( 1 ),
192      memory
193    );
194  #endif
195
196  if ( memory == NULL )
197    _Terminate(
198      INTERNAL_ERROR_CORE,
199      true,
200      INTERNAL_ERROR_WORKSPACE_ALLOCATION
201    );
202
203  return memory;
204}
Note: See TracBrowser for help on using the repository browser.