Skip to content

Commit 695ab09

Browse files
committed
Change yield() and wait_event() to be MUST_CHECK and return the killed flag. (closes #2875)
1 parent ac9df58 commit 695ab09

File tree

6 files changed

+38
-26
lines changed

6 files changed

+38
-26
lines changed

Diff for: src/libcore/pipes.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ extern mod rustrt {
6969
#[rust_stack]
7070
fn task_clear_event_reject(task: *rust_task);
7171

72-
fn task_wait_event(this: *rust_task, killed: &mut bool) -> *libc::c_void;
72+
fn task_wait_event(this: *rust_task, killed: &mut *libc::c_void) -> bool;
7373
fn task_signal_event(target: *rust_task, event: *libc::c_void);
7474
}
7575

@@ -80,13 +80,13 @@ unsafe fn uniquify<T>(x: *T) -> ~T {
8080
}
8181

8282
fn wait_event(this: *rust_task) -> *libc::c_void {
83-
let mut killed = false;
83+
let mut event = ptr::null();
8484

85-
let res = rustrt::task_wait_event(this, &mut killed);
85+
let killed = rustrt::task_wait_event(this, &mut event);
8686
if killed && !task::failing() {
8787
fail ~"killed"
8888
}
89-
res
89+
event
9090
}
9191

9292
fn swap_state_acq(&dst: state, src: state) -> state {

Diff for: src/libcore/task.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -515,8 +515,7 @@ fn yield() {
515515
//! Yield control to the task scheduler
516516
517517
let task_ = rustrt::rust_get_task();
518-
let mut killed = false;
519-
rustrt::rust_task_yield(task_, killed);
518+
let killed = rustrt::rust_task_yield(task_);
520519
if killed && !failing() {
521520
fail ~"killed";
522521
}
@@ -1104,7 +1103,7 @@ unsafe fn local_data_modify<T: owned>(
11041103

11051104
extern mod rustrt {
11061105
#[rust_stack]
1107-
fn rust_task_yield(task: *rust_task, &killed: bool);
1106+
fn rust_task_yield(task: *rust_task) -> bool;
11081107

11091108
fn rust_get_sched_id() -> sched_id;
11101109
fn rust_new_sched(num_threads: libc::uintptr_t) -> sched_id;

Diff for: src/rt/rust_builtin.cpp

+8-8
Original file line numberDiff line numberDiff line change
@@ -722,9 +722,9 @@ rust_port_id_send(rust_port_id target_port_id, void *sptr) {
722722

723723
// This is called by an intrinsic on the Rust stack and must run
724724
// entirely in the red zone. Do not call on the C stack.
725-
extern "C" CDECL void
725+
extern "C" CDECL MUST_CHECK bool
726726
rust_task_yield(rust_task *task, bool *killed) {
727-
task->yield(killed);
727+
return task->yield();
728728
}
729729

730730
extern "C" CDECL void
@@ -920,8 +920,8 @@ rust_wait_cond_lock(rust_cond_lock *lock) {
920920
lock->waiting = task;
921921
task->block(lock, "waiting for signal");
922922
lock->lock.unlock();
923-
bool killed = false;
924-
task->yield(&killed);
923+
bool killed = task->yield();
924+
assert(!killed && "unimplemented");
925925
lock->lock.lock();
926926
}
927927

@@ -960,12 +960,12 @@ task_clear_event_reject(rust_task *task) {
960960

961961
// Waits on an event, returning the pointer to the event that unblocked this
962962
// task.
963-
extern "C" void *
964-
task_wait_event(rust_task *task, bool *killed) {
965-
// FIXME #2890: we should assert that the passed in task is the currently
963+
extern "C" MUST_CHECK bool
964+
task_wait_event(rust_task *task, void **result) {
965+
// Maybe (if not too slow) assert that the passed in task is the currently
966966
// running task. We wouldn't want to wait some other task.
967967

968-
return task->wait_event(killed);
968+
return task->wait_event(result);
969969
}
970970

971971
extern "C" void

Diff for: src/rt/rust_globals.h

+2
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ extern "C" int check_claims;
8585
} \
8686
}
8787

88+
#define MUST_CHECK __attribute__((warn_unused_result))
89+
8890
#define PTR "0x%" PRIxPTR
8991

9092
// This accounts for logging buffers.

Diff for: src/rt/rust_task.cpp

+18-9
Original file line numberDiff line numberDiff line change
@@ -242,26 +242,30 @@ void rust_task_yield_fail(rust_task *task) {
242242
}
243243

244244
// Only run this on the rust stack
245-
void
246-
rust_task::yield(bool *killed) {
245+
MUST_CHECK bool rust_task::yield() {
246+
bool killed = false;
247+
247248
if (disallow_yield > 0) {
248249
call_on_c_stack(this, (void *)rust_task_yield_fail);
249250
}
250-
// FIXME (#2875): clean this up
251+
252+
// This check is largely superfluous; it's the one after the context swap
253+
// that really matters. This one allows us to assert a useful invariant.
251254
if (must_fail_from_being_killed()) {
252255
{
253256
scoped_lock with(lifecycle_lock);
254257
assert(!(state == task_state_blocked));
255258
}
256-
*killed = true;
259+
killed = true;
257260
}
258261

259262
// Return to the scheduler.
260263
ctx.next->swap(ctx);
261264

262265
if (must_fail_from_being_killed()) {
263-
*killed = true;
266+
killed = true;
264267
}
268+
return killed;
265269
}
266270

267271
void
@@ -687,19 +691,24 @@ void rust_task::allow_yield() {
687691
disallow_yield--;
688692
}
689693

690-
void *
691-
rust_task::wait_event(bool *killed) {
694+
MUST_CHECK bool rust_task::wait_event(void **result) {
695+
bool killed = false;
692696
scoped_lock with(lifecycle_lock);
693697

694698
if(!event_reject) {
695699
block_inner(&event_cond, "waiting on event");
696700
lifecycle_lock.unlock();
697-
yield(killed);
701+
killed = yield();
698702
lifecycle_lock.lock();
703+
} else if (must_fail_from_being_killed_inner()) {
704+
// If the deschedule was rejected, yield won't do our killed check for
705+
// us. For thoroughness, do it here. FIXME (#524)
706+
killed = true;
699707
}
700708

701709
event_reject = false;
702-
return event;
710+
*result = event;
711+
return killed;
703712
}
704713

705714
void

Diff for: src/rt/rust_task.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,8 @@ rust_task : public kernel_owned<rust_task>
259259
void backtrace();
260260

261261
// Yields control to the scheduler. Called from the Rust stack
262-
void yield(bool *killed);
262+
// Returns TRUE if the task was killed and needs to fail.
263+
MUST_CHECK bool yield();
263264

264265
// Fail this task (assuming caller-on-stack is different task).
265266
void kill();
@@ -311,7 +312,8 @@ rust_task : public kernel_owned<rust_task>
311312
this->event_reject = false;
312313
}
313314

314-
void *wait_event(bool *killed);
315+
// Returns TRUE if the task was killed and needs to fail.
316+
MUST_CHECK bool wait_event(void **result);
315317
void signal_event(void *event);
316318

317319
void cleanup_after_turn();

0 commit comments

Comments
 (0)