[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] | 35 | static 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] | 54 | void _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] | 145 | void *_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] | 164 | void *_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] | 172 | void _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] | 187 | void *_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 | } |
---|