Skip to content

Commit 91d3064

Browse files
author
Andrew Boie
committed
libc: set up memory partitions
* Newlib now defines a special z_newlib_partition containing all globals relevant to newlib. Most of these are in libc.a with a heap tracking variable in newlib's hooks. * Both C libraries now expose a k_mem_partition containing the bounds of the malloc heap arena. Threads that want to use libc malloc() will need to add this to their memory domain. * z_newlib_get_heap_bounds has been removed, in favor of the memory partition for the heap arena * ztest now includes the C library partitions in its memory domain. * The mem_alloc test now runs in user mode to prove that this all works for both C libraries. Signed-off-by: Andrew Boie <[email protected]>
1 parent 308f078 commit 91d3064

File tree

9 files changed

+90
-50
lines changed

9 files changed

+90
-50
lines changed

CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1228,12 +1228,16 @@ if(CONFIG_APP_SHARED_MEM AND CONFIG_USERSPACE)
12281228
kernel ${ZEPHYR_LIBS_PROPERTY}
12291229
)
12301230

1231+
if(CONFIG_NEWLIB_LIBC)
1232+
set(NEWLIB_PART -l libc.a z_newlib_partition)
1233+
endif()
12311234
add_custom_command(
12321235
TARGET ${APP_SMEM_DEP}
12331236
COMMAND ${PYTHON_EXECUTABLE}
12341237
${ZEPHYR_BASE}/scripts/gen_app_partitions.py
12351238
-d ${OBJ_FILE_DIR}
12361239
-o ${APP_SMEM_LD}
1240+
${NEWLIB_PART}
12371241
$<$<BOOL:${CMAKE_VERBOSE_MAKEFILE}>:--verbose>
12381242
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/
12391243
COMMENT "Generating app_smem linker section"

include/misc/libc-hooks.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,27 @@ __syscall int _zephyr_read(char *buf, int nbytes);
2727

2828
__syscall int _zephyr_write(const void *buf, int nbytes);
2929

30+
#ifdef CONFIG_APP_SHARED_MEM
31+
/* Memory partition containing newlib's globals. This includes all the globals
32+
* within libc.a and the supporting zephyr hooks, but not the malloc arena.
33+
*/
34+
extern struct k_mem_partition z_newlib_partition;
35+
#endif /* CONFIG_APP_SHARED_MEM */
36+
3037
#else
3138
/* Minimal libc */
3239

3340
__syscall int _zephyr_fputc(int c, FILE *stream);
3441

3542
__syscall size_t _zephyr_fwrite(const void *_MLIBC_RESTRICT ptr, size_t size,
3643
size_t nitems, FILE *_MLIBC_RESTRICT stream);
37-
3844
#endif /* CONFIG_NEWLIB_LIBC */
3945

46+
#ifdef CONFIG_APP_SHARED_MEM
47+
/* Memory partition containing the libc malloc arena */
48+
extern struct k_mem_partition z_malloc_partition;
49+
#endif
50+
4051
#include <syscalls/libc-hooks.h>
4152

4253
#endif /* ZEPHYR_INCLUDE_MISC_LIBC_HOOKS_H_ */

kernel/include/kernel_internal.h

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -206,21 +206,6 @@ extern void smp_init(void);
206206

207207
extern void smp_timer_init(void);
208208

209-
#ifdef CONFIG_NEWLIB_LIBC
210-
/**
211-
* @brief Fetch dimentions of newlib heap area for _sbrk()
212-
*
213-
* This memory region is used for heap allocations by the newlib C library.
214-
* If user threads need to have access to this, the results returned can be
215-
* used to program memory protection hardware appropriately.
216-
*
217-
* @param base Pointer to void pointer, filled in with the heap starting
218-
* address
219-
* @param size Pointer to a size_y, filled in with the maximum heap size
220-
*/
221-
extern void z_newlib_get_heap_bounds(void **base, size_t *size);
222-
#endif
223-
224209
extern u32_t z_early_boot_rand32_get(void);
225210

226211
#if CONFIG_STACK_POINTER_RANDOM

lib/libc/minimal/source/stdlib/malloc.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,26 @@
1010
#include <errno.h>
1111
#include <misc/mempool.h>
1212
#include <string.h>
13+
#include <app_memory/app_memdomain.h>
1314

1415
#define LOG_LEVEL CONFIG_KERNEL_LOG_LEVEL
1516
#include <logging/log.h>
1617
LOG_MODULE_DECLARE(os);
1718

19+
#ifdef CONFIG_APP_SHARED_MEM
20+
K_APPMEM_PARTITION_DEFINE(z_malloc_partition);
21+
#endif
22+
1823
#if (CONFIG_MINIMAL_LIBC_MALLOC_ARENA_SIZE > 0)
24+
#ifdef CONFIG_APP_SHARED_MEM
25+
#define POOL_SECTION K_APP_DMEM_SECTION(z_malloc_partition)
26+
#else
27+
#define POOL_SECTION .data
28+
#endif /* CONFIG_APP_SHARED_MEM */
29+
1930
K_MUTEX_DEFINE(malloc_mutex);
2031
SYS_MEM_POOL_DEFINE(z_malloc_mem_pool, &malloc_mutex, 16,
21-
CONFIG_MINIMAL_LIBC_MALLOC_ARENA_SIZE, 1, 4, .data);
32+
CONFIG_MINIMAL_LIBC_MALLOC_ARENA_SIZE, 1, 4, POOL_SECTION);
2233

2334
void *malloc(size_t size)
2435
{

lib/libc/newlib/libc-hooks.c

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,30 @@
1414
#include <misc/errno_private.h>
1515
#include <misc/libc-hooks.h>
1616
#include <syscall_handler.h>
17+
#include <app_memory/app_memdomain.h>
18+
#include <init.h>
19+
20+
#ifdef CONFIG_APP_SHARED_MEM
21+
K_APPMEM_PARTITION_DEFINE(z_newlib_partition);
22+
#define LIBC_BSS K_APP_BMEM(z_newlib_partition)
23+
#define LIBC_DATA K_APP_DMEM(z_newlib_partition)
24+
25+
#if CONFIG_NEWLIB_LIBC_ALIGNED_HEAP_SIZE
26+
K_APPMEM_PARTITION_DEFINE(z_malloc_partition);
27+
#define MALLOC_BSS K_APP_BMEM(z_malloc_partition)
28+
#endif /* CONFIG_NEWLIB_LIBC_ALIGNED_HEAP_SIZE */
29+
30+
#else
31+
#define LIBC_BSS
32+
#define LIBC_DATA
33+
#define MALLOC_BSS
34+
#endif /* CONFIG_APP_SHARED_MEM */
1735

1836
#define USED_RAM_END_ADDR POINTER_TO_UINT(&_end)
1937

2038
#if CONFIG_NEWLIB_LIBC_ALIGNED_HEAP_SIZE
2139
/* Compiler will throw an error if the provided value isn't a power of two */
22-
static unsigned char __kernel __aligned(CONFIG_NEWLIB_LIBC_ALIGNED_HEAP_SIZE)
40+
MALLOC_BSS static unsigned char __kernel __aligned(CONFIG_NEWLIB_LIBC_ALIGNED_HEAP_SIZE)
2341
heap_base[CONFIG_NEWLIB_LIBC_ALIGNED_HEAP_SIZE];
2442
#define MAX_HEAP_SIZE CONFIG_NEWLIB_LIBC_ALIGNED_HEAP_SIZE
2543
#else
@@ -48,9 +66,25 @@ extern void *_heap_sentry;
4866
#endif
4967

5068
static unsigned char *heap_base = UINT_TO_POINTER(USED_RAM_END_ADDR);
69+
70+
#ifdef CONFIG_APP_SHARED_MEM
71+
struct k_mem_partition z_malloc_partition;
72+
73+
static int malloc_prepare(struct device *unused)
74+
{
75+
ARG_UNUSED(unused);
76+
77+
z_malloc_partition.start = (u32_t)heap_base;
78+
z_malloc_partition.size = MAX_HEAP_SIZE;
79+
z_malloc_partition.attr = K_MEM_PARTITION_P_RW_U_RW;
80+
return 0;
81+
}
82+
83+
SYS_INIT(malloc_prepare, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
84+
#endif
5185
#endif /* CONFIG_NEWLIB_LIBC_ALIGNED_HEAP_SIZE */
5286

53-
static unsigned int heap_sz;
87+
LIBC_BSS static unsigned int heap_sz;
5488

5589
static int _stdout_hook_default(int c)
5690
{
@@ -207,12 +241,6 @@ void *_sbrk(int count)
207241
}
208242
FUNC_ALIAS(_sbrk, sbrk, void *);
209243

210-
void z_newlib_get_heap_bounds(void **base, size_t *size)
211-
{
212-
*base = heap_base;
213-
*size = MAX_HEAP_SIZE;
214-
}
215-
216244
int *__errno(void)
217245
{
218246
return z_errno();

tests/lib/mem_alloc/prj_newlib.conf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
CONFIG_ZTEST=y
22
CONFIG_NEWLIB_LIBC=y
33
CONFIG_MAIN_STACK_SIZE=1024
4+
CONFIG_NEWLIB_LIBC_ALIGNED_HEAP_SIZE=512

tests/lib/mem_alloc/src/main.c

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,6 @@
2424

2525
#define BUF_LEN 10
2626

27-
#ifdef CONFIG_MINIMAL_LIBC_MALLOC_ARENA_SIZE
28-
#define MAX_HEAP_SIZE CONFIG_MINIMAL_LIBC_MALLOC_ARENA_SIZE
29-
#endif
30-
3127
/**
3228
* @brief Test dynamic memory allocation using malloc
3329
*
@@ -40,6 +36,7 @@ void test_malloc(void)
4036

4137
iptr = malloc(BUF_LEN * sizeof(int));
4238
zassert_not_null((iptr), "malloc failed, errno: %d", errno);
39+
memset(iptr, 'p', BUF_LEN * sizeof(int));
4340
free(iptr);
4441
iptr = NULL;
4542
}
@@ -64,7 +61,7 @@ void test_free(void)
6461
* @see calloc(), free()
6562
*/
6663
#define CALLOC_BUFLEN (200)
67-
static unsigned char zerobuf[CALLOC_BUFLEN];
64+
ZTEST_BMEM static unsigned char zerobuf[CALLOC_BUFLEN];
6865

6966
void test_calloc(void)
7067
{
@@ -74,6 +71,7 @@ void test_calloc(void)
7471
zassert_not_null((cptr), "calloc failed, errno: %d", errno);
7572
zassert_true(((memcmp(cptr, zerobuf, CALLOC_BUFLEN)) == 0),
7673
"calloc failed to set zero value, errno: %d", errno);
74+
memset(cptr, 'p', CALLOC_BUFLEN);
7775
free(cptr);
7876
cptr = NULL;
7977
}
@@ -83,7 +81,7 @@ void test_calloc(void)
8381
*
8482
* @see malloc(), realloc(), free()
8583
*/
86-
unsigned char filled_buf[BUF_LEN];
84+
ZTEST_BMEM unsigned char filled_buf[BUF_LEN];
8785

8886
void test_realloc(void)
8987
{
@@ -191,17 +189,9 @@ void test_memalloc_all(void)
191189

192190
void test_memalloc_max(void)
193191
{
194-
size_t max_heap_size = 0;
195192
char *ptr = NULL;
196193

197-
#ifdef CONFIG_NEWLIB_LIBC
198-
void *heap_base = NULL;
199-
200-
z_newlib_get_heap_bounds(&heap_base, &max_heap_size);
201-
#else
202-
max_heap_size = MAX_HEAP_SIZE;
203-
#endif
204-
ptr = malloc(max_heap_size + 1);
194+
ptr = malloc(0xF0000000);
205195
zassert_is_null(ptr, "malloc passed unexpectedly");
206196
free(ptr);
207197
ptr = NULL;
@@ -210,13 +200,13 @@ void test_memalloc_max(void)
210200
void test_main(void)
211201
{
212202
ztest_test_suite(test_c_lib_dynamic_memalloc,
213-
ztest_unit_test(test_malloc),
214-
ztest_unit_test(test_free),
215-
ztest_unit_test(test_calloc),
216-
ztest_unit_test(test_realloc),
217-
ztest_unit_test(test_reallocarray),
218-
ztest_unit_test(test_memalloc_all),
219-
ztest_unit_test(test_memalloc_max)
203+
ztest_user_unit_test(test_malloc),
204+
ztest_user_unit_test(test_free),
205+
ztest_user_unit_test(test_calloc),
206+
ztest_user_unit_test(test_realloc),
207+
ztest_user_unit_test(test_reallocarray),
208+
ztest_user_unit_test(test_memalloc_all),
209+
ztest_user_unit_test(test_memalloc_max)
220210
);
221211
ztest_run_test_suite(test_c_lib_dynamic_memalloc);
222212
}

tests/lib/mem_alloc/testcase.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ tests:
22
libraries.libc.minimal:
33
extra_args: CONF_FILE=prj.conf
44
arch_exclude: posix
5-
tags: clib minimal_libc
5+
tags: clib minimal_libc userspace
66
libraries.libc.newlib:
77
extra_args: CONF_FILE=prj_newlib.conf
88
arch_exclude: posix
99
filter: TOOLCHAIN_HAS_NEWLIB == 1
10-
tags: clib newlib
10+
tags: clib newlib userspace

tests/ztest/src/ztest.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77
#include <ztest.h>
88
#include <stdio.h>
99
#include <app_memory/app_memdomain.h>
10+
#ifdef CONFIG_APP_SHARED_MEM
11+
#include <misc/libc-hooks.h>
12+
#endif
13+
1014
#ifdef KERNEL
1115
__kernel static struct k_thread ztest_thread;
1216
#endif
@@ -297,7 +301,13 @@ void main(void)
297301
{
298302
#ifdef CONFIG_APP_SHARED_MEM
299303
struct k_mem_partition *parts[] = {
300-
&ztest_mem_partition
304+
&ztest_mem_partition,
305+
#ifdef CONFIG_NEWLIB_LIBC
306+
/* Newlib libc.a library and hooks globals */
307+
&z_newlib_partition,
308+
#endif
309+
/* Both minimal and newlib libc expose this for malloc arena */
310+
&z_malloc_partition
301311
};
302312

303313
/* Ztests just have one memory domain with one partition.

0 commit comments

Comments
 (0)