forked from ARMmbed/mbed-os
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCThunkBase.cpp
145 lines (126 loc) · 4.37 KB
/
CThunkBase.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/* mbed Microcontroller Library
* Copyright (c) 2018-2019 ARM Limited
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "platform/platform.h"
#include "platform/mbed_critical.h"
#include "platform/mbed_assert.h"
#include "platform/mbed_error.h"
#include "platform/internal/CThunkBase.h"
static_assert(MBED_CONF_PLATFORM_CTHUNK_COUNT_MAX < 256, "MBED_CONF_PLATFORM_CTHUNK_COUNT_MAX must be less than 256");
static_assert(MBED_CONF_PLATFORM_CTHUNK_COUNT_MAX > 0, "MBED_CONF_PLATFORM_CTHUNK_COUNT_MAX must be greater than 0");
#define ENABLE_N(N) ((MBED_CONF_PLATFORM_CTHUNK_COUNT_MAX & N) ? 1 : 0)
#define START_128 0
#define START_64 (START_128 + ENABLE_N(128) * 128)
#define START_32 (START_64 + ENABLE_N(64) * 64)
#define START_16 (START_32 + ENABLE_N(32) * 32)
#define START_8 (START_16 + ENABLE_N(16) * 16)
#define START_4 (START_8 + ENABLE_N(8) * 8)
#define START_2 (START_4 + ENABLE_N(4) * 4)
#define START_1 (START_2 + ENABLE_N(2) * 2)
#define DECLARE_THUNK128(start) \
DECLARE_THUNK64(start), \
DECLARE_THUNK64(start + 64)
#define DECLARE_THUNK64(start) \
DECLARE_THUNK32(start), \
DECLARE_THUNK32(start + 32)
#define DECLARE_THUNK32(start) \
DECLARE_THUNK16(start), \
DECLARE_THUNK16(start + 16)
#define DECLARE_THUNK16(start) \
DECLARE_THUNK8(start), \
DECLARE_THUNK8(start + 8)
#define DECLARE_THUNK8(start) \
DECLARE_THUNK4(start), \
DECLARE_THUNK4(start + 4)
#define DECLARE_THUNK4(start) \
DECLARE_THUNK2(start), \
DECLARE_THUNK2(start + 2)
#define DECLARE_THUNK2(start) \
DECLARE_THUNK1(start), \
DECLARE_THUNK1(start + 1)
#define DECLARE_THUNK1(index) &CThunkBase::thunk_entry<index>
const CThunkEntry CThunkBase::_thunk_table[MBED_CONF_PLATFORM_CTHUNK_COUNT_MAX] = {
#if ENABLE_N(128)
DECLARE_THUNK128(START_128),
#endif
#if ENABLE_N(64)
DECLARE_THUNK64(START_64),
#endif
#if ENABLE_N(32)
DECLARE_THUNK32(START_32),
#endif
#if ENABLE_N(16)
DECLARE_THUNK16(START_16),
#endif
#if ENABLE_N(8)
DECLARE_THUNK8(START_8),
#endif
#if ENABLE_N(4)
DECLARE_THUNK4(START_4),
#endif
#if ENABLE_N(2)
DECLARE_THUNK2(START_2),
#endif
#if ENABLE_N(1)
DECLARE_THUNK1(START_1)
#endif
};
CThunkBase *CThunkBase::_thunk_storage[MBED_CONF_PLATFORM_CTHUNK_COUNT_MAX];
CThunkBase::CthunkFree CThunkBase::_cthunk_free_real = NULL;
CThunkEntry CThunkBase::cthunk_alloc(CThunkBase *cthunk)
{
// Atomically allocate one entry
core_util_critical_section_enter();
CThunkEntry entry = NULL;
for (int i = 0; i < MBED_CONF_PLATFORM_CTHUNK_COUNT_MAX; i++) {
if (_thunk_storage[i] == NULL) {
_thunk_storage[i] = cthunk;
entry = _thunk_table[i];
break;
}
}
core_util_critical_section_exit();
if (entry == NULL) {
MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_OUT_OF_RESOURCES), "Ran out of CThunk entries. Increase MBED_CONF_PLATFORM_CTHUNK_COUNT_MAX to fix this error");
}
// Set function pointer on first use. This allows _thunk_table
// and _thunk_storage to get removed by the linker if
// cthunk_alloc is never used.
_cthunk_free_real = &cthunk_free_real;
return entry;
}
void CThunkBase::cthunk_free(CThunkEntry item)
{
if (_cthunk_free_real) {
_cthunk_free_real(item);
}
}
void CThunkBase::cthunk_free_real(CThunkEntry item)
{
bool found = false;
core_util_critical_section_enter();
for (int i = 0; i < MBED_CONF_PLATFORM_CTHUNK_COUNT_MAX; i++) {
if (_thunk_table[i] == item) {
_thunk_storage[i] = NULL;
found = true;
break;
}
}
core_util_critical_section_exit();
if (!found) {
MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_INVALID_ARGUMENT), "Tried to free invalid CThunkEntry");
}
}