Skip to content

Commit 1ba3028

Browse files
committed
rt: Add task_local_data and related builtin calls (Closes #2680)
1 parent e56ba15 commit 1ba3028

File tree

5 files changed

+45
-16
lines changed

5 files changed

+45
-16
lines changed

src/rt/rust_builtin.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -914,7 +914,19 @@ rust_signal_cond_lock(rust_cond_lock *lock) {
914914
}
915915
}
916916

917-
917+
// set/get/atexit task_local_data can run on the rust stack for speed.
918+
extern "C" void *
919+
rust_get_task_local_data(rust_task *task) {
920+
return task->task_local_data;
921+
}
922+
extern "C" void
923+
rust_set_task_local_data(rust_task *task, void *data) {
924+
task->task_local_data = data;
925+
}
926+
extern "C" void
927+
rust_task_local_data_atexit(rust_task *task, void (*cleanup_fn)(void *data)) {
928+
task->task_local_data_cleanup = cleanup_fn;
929+
}
918930

919931
//
920932
// Local Variables:

src/rt/rust_task.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ rust_task::rust_task(rust_sched_loop *sched_loop, rust_task_state state,
3131
propagate_failure(true),
3232
cc_counter(0),
3333
total_stack_sz(0),
34+
task_local_data(NULL),
35+
task_local_data_cleanup(NULL),
3436
state(state),
3537
cond(NULL),
3638
cond_name("none"),
@@ -115,6 +117,16 @@ cleanup_task(cleanup_args *args) {
115117
}
116118
}
117119

120+
// Clean up TLS. This will only be set if TLS was used to begin with.
121+
// Because this is a crust function, it must be called from the C stack.
122+
if (task->task_local_data_cleanup != NULL) {
123+
// This assert should hold but it's not our job to ensure it (and
124+
// the condition might change). Handled in libcore/task.rs.
125+
// assert(task->task_local_data != NULL);
126+
task->task_local_data_cleanup(task->task_local_data);
127+
task->task_local_data = NULL;
128+
}
129+
118130
// FIXME (#2676): For performance we should do the annihilator
119131
// instead of the cycle collector even under normal termination, but
120132
// since that would hide memory management errors (like not derefing

src/rt/rust_task.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,10 @@ rust_task : public kernel_owned<rust_task>, rust_cond
163163
// The amount of stack we're using, excluding red zones
164164
size_t total_stack_sz;
165165

166+
// Used by rust task management routines in libcore/task.rs.
167+
void *task_local_data;
168+
void (*task_local_data_cleanup)(void *data);
169+
166170
private:
167171

168172
// Protects state, cond, cond_name
@@ -375,6 +379,10 @@ rust_task::call_on_c_stack(void *args, void *fn_ptr) {
375379
// Too expensive to check
376380
// assert(on_rust_stack());
377381

382+
// The shim functions generated by rustc contain the morestack prologue, so
383+
// we need to let them know they have enough stack.
384+
record_sp_limit(0);
385+
378386
uintptr_t prev_rust_sp = next_rust_sp;
379387
next_rust_sp = get_sp();
380388

@@ -398,12 +406,19 @@ rust_task::call_on_c_stack(void *args, void *fn_ptr) {
398406
}
399407

400408
next_rust_sp = prev_rust_sp;
409+
410+
record_stack_limit();
401411
}
402412

403413
inline void
404414
rust_task::call_on_rust_stack(void *args, void *fn_ptr) {
405415
// Too expensive to check
406416
// assert(!on_rust_stack());
417+
418+
// Because of the hack in the other function that disables the stack limit
419+
// when entering the C stack, here we restore the stack limit again.
420+
record_stack_limit();
421+
407422
assert(get_sp_limit() != 0 && "Stack must be configured");
408423
assert(next_rust_sp);
409424

@@ -427,6 +442,8 @@ rust_task::call_on_rust_stack(void *args, void *fn_ptr) {
427442
scoped_lock with(kill_lock);
428443
reentered_rust_stack = had_reentered_rust_stack;
429444
}
445+
446+
record_sp_limit(0);
430447
}
431448

432449
inline void

src/rt/rust_upcall.cpp

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -49,19 +49,12 @@ extern "C" CDECL void
4949
upcall_call_shim_on_c_stack(void *args, void *fn_ptr) {
5050
rust_task *task = rust_get_current_task();
5151

52-
// FIXME (#1226) - The shim functions generated by rustc contain the
53-
// morestack prologue, so we need to let them know they have enough
54-
// stack.
55-
record_sp_limit(0);
56-
5752
try {
5853
task->call_on_c_stack(args, fn_ptr);
5954
} catch (...) {
6055
// Logging here is not reliable
6156
assert(false && "Foreign code threw an exception");
6257
}
63-
64-
task->record_stack_limit();
6558
}
6659

6760
/*
@@ -72,11 +65,6 @@ extern "C" CDECL void
7265
upcall_call_shim_on_rust_stack(void *args, void *fn_ptr) {
7366
rust_task *task = rust_get_current_task();
7467

75-
// FIXME (#2680): Because of the hack in the other function that disables
76-
// the stack limit when entering the C stack, here we restore the stack
77-
// limit again.
78-
task->record_stack_limit();
79-
8068
try {
8169
task->call_on_rust_stack(args, fn_ptr);
8270
} catch (...) {
@@ -85,9 +73,6 @@ upcall_call_shim_on_rust_stack(void *args, void *fn_ptr) {
8573
// Logging here is not reliable
8674
assert(false && "Rust task failed after reentering the Rust stack");
8775
}
88-
89-
// FIXME (#2680): As above
90-
record_sp_limit(0);
9176
}
9277

9378
/**********************************************************************/

src/rt/rustrt.def.in

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,3 +167,6 @@ rust_lock_cond_lock
167167
rust_unlock_cond_lock
168168
rust_wait_cond_lock
169169
rust_signal_cond_lock
170+
rust_get_task_local_data
171+
rust_set_task_local_data
172+
rust_task_local_data_atexit

0 commit comments

Comments
 (0)