Skip to content

Commit 5bfbf16

Browse files
committed
Put Rust data/bss in app shared memory domain
Link an object from all of the Rust sources which allows using a linker script to put data/bss from Rust in an app memory region. All the globals used in libstd and any Rust libraries need to be accessible by all Rust threads, so we put them in one memory domain along with a mem pool to serve as a global allocator. Currently still using the mem pool if !usermode. Could use kmalloc instead. Also the pool is created in rust-smem.c but must be set as the global allocator in the top level app crate. Need to somehow tie the creation and use of those together.
1 parent 38b0d9a commit 5bfbf16

File tree

8 files changed

+89
-14
lines changed

8 files changed

+89
-14
lines changed

CMakeLists.txt

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ cmake_minimum_required(VERSION 3.13.1)
55
include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE)
66
project(hello_world)
77

8-
target_sources(app PRIVATE src/main.c)
8+
target_sources(app PRIVATE src/main.c rust_obj.obj)
99

1010
# Use a clang_target known to clang so headers will be processed correctly with
1111
# bindgen. rust_target may point to a custom json target.
@@ -29,11 +29,6 @@ add_custom_command(OUTPUT ${rust_syscall_macros_h}
2929
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/gen_syscall_header.py
3030
)
3131

32-
add_library(syscall_thunk OBJECT syscall_thunk.c)
33-
target_link_libraries(syscall_thunk zephyr_interface)
34-
# High level target that means all headers have been generated
35-
add_dependencies(syscall_thunk offsets_h)
36-
3732
set(rust_src_dir ${CMAKE_CURRENT_SOURCE_DIR}/zephyr-bindgen)
3833
set(rust_build_dir ${CMAKE_CURRENT_BINARY_DIR}/zephyr-bindgen)
3934
set(zephyr_bindgen ${rust_build_dir}/release/zephyr-bindgen)
@@ -81,9 +76,32 @@ ExternalProject_Add(
8176
BUILD_BYPRODUCTS ${rust_staticlib}
8277
)
8378

84-
add_library(rust_lib STATIC IMPORTED)
85-
add_dependencies(rust_lib rust_project)
86-
set_target_properties(rust_lib PROPERTIES IMPORTED_LOCATION ${rust_staticlib})
87-
# This should be a dependency of rust_lib, but adding it as an INTERFACE lib doesn't do anything
88-
target_link_libraries(app PRIVATE syscall_thunk)
89-
target_link_libraries(app PUBLIC rust_lib)
79+
add_library(rust_obj OBJECT syscall-thunk.c rust-smem.c)
80+
target_link_libraries(rust_obj zephyr_interface)
81+
# High level target that means all headers have been generated
82+
add_dependencies(rust_obj offsets_h)
83+
84+
# Relocatable single object library containing all Rust code. This allows using
85+
# a linker script during this link to rename sections, putting data/bss in the
86+
# rust shared memory section. The .obj suffix is significant because
87+
# gen_app_partitions.py searches for specially named sections in all .obj files
88+
# in the build output.
89+
if(CONFIG_USERSPACE)
90+
set(rust_ldscript -Wl,-T ${CMAKE_CURRENT_SOURCE_DIR}/rust-smem.ld)
91+
endif()
92+
set(RUST_OBJ_CFLAGS ${CMAKE_C_FLAGS})
93+
separate_arguments(RUST_OBJ_CFLAGS)
94+
add_custom_command(
95+
OUTPUT rust_obj.obj
96+
COMMAND ${CMAKE_C_COMPILER} ${RUST_OBJ_CFLAGS}
97+
-nostdlib
98+
-static
99+
-no-pie
100+
-Wl,-r
101+
${rust_ldscript}
102+
-Wl,--whole-archive ${rust_staticlib}
103+
-Wl,--no-whole-archive $<TARGET_OBJECTS:rust_obj>
104+
-o rust_obj.obj
105+
DEPENDS ${rust_staticlib} $<TARGET_OBJECTS:rust_obj>
106+
COMMAND_EXPAND_LISTS
107+
)

prj.conf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ CONFIG_CPLUSPLUS=y
44
CONFIG_SERIAL=y
55
CONFIG_UART_NATIVE_POSIX=y
66
CONFIG_NATIVE_UART_0_ON_OWN_PTY=y
7+
CONFIG_USERSPACE=y

rust-app/src/lib.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ use zephyr::mutex::*;
1616
use zephyr::semaphore::*;
1717
use zephyr::thread::ThreadSyscalls;
1818

19+
// Use this mem pool for global allocs instead of kmalloc
20+
zephyr::global_sys_mem_pool!(rust_std_mem_pool);
21+
1922
thread_local!(static TLS: RefCell<u8> = RefCell::new(1));
2023

2124
zephyr_macros::k_mutex_define!(MUTEX);
@@ -33,12 +36,19 @@ fn mutex_test() {
3336
zephyr::any::k_str_out("Unlocking\n");
3437
}
3538

39+
fn thread_join_std_mem_domain(_context: zephyr::context::Kernel) {
40+
use zephyr::context::Kernel as C;
41+
zephyr::static_mem_domain!(rust_std_domain).add_thread::<C>(C::k_current_get());
42+
}
43+
3644
#[no_mangle]
3745
pub extern "C" fn hello_rust_second_thread(
3846
_a: *const c_void,
3947
_b: *const c_void,
4048
_c: *const c_void,
4149
) {
50+
thread_join_std_mem_domain(zephyr::context::Kernel);
51+
4252
println!("Hello from second thread");
4353

4454
TLS.with(|f| {
@@ -104,7 +114,10 @@ pub extern "C" fn hello_rust() {
104114
});
105115
TLS_SEM.give::<Context>();
106116

117+
thread_join_std_mem_domain(Context);
107118
zephyr::kernel::k_thread_user_mode_enter(|| {
119+
use zephyr::context::User as Context;
120+
108121
zephyr::user::k_str_out("Hello from Rust userspace with forced user-mode syscall\n");
109122

110123
mutex_test();

rust-smem.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* Copyright (c) 2012-2014 Wind River Systems, Inc.
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <zephyr.h>
8+
#include <init.h>
9+
#include <misc/mempool.h>
10+
#include <app_memory/app_memdomain.h>
11+
12+
struct k_mem_domain rust_std_domain;
13+
14+
#ifdef CONFIG_USERSPACE
15+
K_APPMEM_PARTITION_DEFINE(rust_std_partition);
16+
#define RUST_STD_SECTION K_APP_DMEM_SECTION(rust_std_partition)
17+
#else
18+
#define RUST_STD_SECTION .data
19+
#endif
20+
21+
#define RUST_STD_MEM_POOL_SIZE 1024
22+
SYS_MEM_POOL_DEFINE(rust_std_mem_pool, NULL, 16,
23+
RUST_STD_MEM_POOL_SIZE, 1, 4, RUST_STD_SECTION);
24+
25+
static int rust_std_init(struct device *arg)
26+
{
27+
ARG_UNUSED(arg);
28+
29+
#ifdef CONFIG_USERSPACE
30+
k_mem_domain_init(&rust_std_domain, 0, NULL);
31+
k_mem_domain_add_partition(&rust_std_domain, &rust_std_partition);
32+
#endif
33+
sys_mem_pool_init(&rust_std_mem_pool);
34+
35+
return 0;
36+
}
37+
38+
SYS_INIT(rust_std_init, PRE_KERNEL_2, CONFIG_APPLICATION_INIT_PRIORITY);

rust-smem.ld

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
SECTIONS
2+
{
3+
data_smem_rust_std_partition_data : { *librust_app.a:*(.data .data.*) }
4+
data_smem_rust_std_partition_bss : { *librust_app.a:*(.bss .bss.* COMMON COMMON.*) }
5+
}

src/main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ extern void hello_rust_user(void);
1212

1313
extern uint8_t hello_rust_second_thread(void *, void *, void *);
1414

15-
#define MY_STACK_SIZE 500
15+
#define MY_STACK_SIZE 1024
1616
#define MY_PRIORITY 5
1717

1818
K_THREAD_DEFINE(my_tid, MY_STACK_SIZE,
File renamed without changes.

0 commit comments

Comments
 (0)