Skip to content

Commit a8f0121

Browse files
committed
---
yaml --- r: 14658 b: refs/heads/try c: 0a5603c h: refs/heads/master v: v3
1 parent 8aef53b commit a8f0121

File tree

6 files changed

+59
-32
lines changed

6 files changed

+59
-32
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
refs/heads/master: 61b1875c16de39c166b0f4d54bba19f9c6777d1a
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
44
refs/heads/snap-stage3: 4a81779abd786ff22d71434c6d9a5917ea4cdfff
5-
refs/heads/try: cc276fe3c96965ba39b9fba3b588a1eaa3941d86
5+
refs/heads/try: 0a5603cb58bdc66ad6b6a030e4e98ebeb3c13721
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105

branches/try/src/rt/rust_port.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,11 @@ void rust_port::receive(void *dptr, uintptr_t *yield) {
8888
task->rendezvous_ptr = (uintptr_t*) dptr;
8989
task->block(this, "waiting for rendezvous data");
9090

91+
// Blocking the task might fail if the task has already been killed, but
92+
// in the event of both failure and success the task needs to yield. On
93+
// success, it yields and waits to be unblocked. On failure it yields and
94+
// is then fails the task.
95+
9196
*yield = true;
9297
}
9398

branches/try/src/rt/rust_port_selector.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,14 @@ rust_port_selector::select(rust_task *task, rust_port **dptr,
4848
this->n_ports = n_ports;
4949
I(task->thread, task->rendezvous_ptr == NULL);
5050
task->rendezvous_ptr = (uintptr_t*)dptr;
51-
*yield = true;
5251
task->block(this, "waiting for select rendezvous");
52+
53+
// Blocking the task might fail if the task has already been
54+
// killed, but in the event of both failure and success the
55+
// task needs to yield. On success, it yields and waits to be
56+
// unblocked. On failure it yields and is then fails the task.
57+
58+
*yield = true;
5359
}
5460

5561
for (size_t i = 0; i < locks_taken; i++) {

branches/try/src/rt/rust_task.cpp

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -246,13 +246,20 @@ void rust_task::start()
246246
bool
247247
rust_task::must_fail_from_being_killed() {
248248
scoped_lock with(kill_lock);
249+
return must_fail_from_being_killed_unlocked();
250+
}
251+
252+
bool
253+
rust_task::must_fail_from_being_killed_unlocked() {
254+
I(thread, kill_lock.lock_held_by_current_thread());
249255
return killed && !reentered_rust_stack;
250256
}
251257

252258
// Only run this on the rust stack
253259
void
254260
rust_task::yield(bool *killed) {
255261
if (must_fail_from_being_killed()) {
262+
I(thread, !blocked());
256263
*killed = true;
257264
}
258265

@@ -266,26 +273,26 @@ rust_task::yield(bool *killed) {
266273

267274
void
268275
rust_task::kill() {
276+
scoped_lock with(kill_lock);
277+
269278
if (dead()) {
270279
// Task is already dead, can't kill what's already dead.
271280
fail_parent();
272-
return;
273281
}
274282

275283
// Note the distinction here: kill() is when you're in an upcall
276284
// from task A and want to force-fail task B, you do B->kill().
277285
// If you want to fail yourself you do self->fail().
278286
LOG(this, task, "killing task %s @0x%" PRIxPTR, name, this);
279287
// When the task next goes to yield or resume it will fail
280-
{
281-
scoped_lock with(kill_lock);
282-
killed = true;
283-
}
288+
killed = true;
284289
// Unblock the task so it can unwind.
285-
unblock();
290+
291+
if (blocked()) {
292+
wakeup(cond);
293+
}
286294

287295
LOG(this, task, "preparing to unwind task: 0x%" PRIxPTR, this);
288-
// run_on_resume(rust_unwind_glue);
289296
}
290297

291298
extern "C" CDECL
@@ -324,7 +331,6 @@ rust_task::fail_parent() {
324331
name, this, supervisor->name, supervisor);
325332
supervisor->kill();
326333
}
327-
// FIXME: implement unwinding again.
328334
if (NULL == supervisor && propagate_failure)
329335
thread->fail();
330336
}
@@ -411,14 +417,23 @@ rust_task::set_state(rust_task_list *state,
411417
this->cond_name = cond_name;
412418
}
413419

414-
void
420+
bool
415421
rust_task::block(rust_cond *on, const char* name) {
422+
scoped_lock with(kill_lock);
423+
424+
if (must_fail_from_being_killed_unlocked()) {
425+
// We're already going to die. Don't block. Tell the task to fail
426+
return false;
427+
}
428+
416429
LOG(this, task, "Blocking on 0x%" PRIxPTR ", cond: 0x%" PRIxPTR,
417430
(uintptr_t) on, (uintptr_t) cond);
418431
A(thread, cond == NULL, "Cannot block an already blocked task.");
419432
A(thread, on != NULL, "Cannot block on a NULL object.");
420433

421434
transition(&thread->running_tasks, &thread->blocked_tasks, on, name);
435+
436+
return true;
422437
}
423438

424439
void
@@ -436,15 +451,6 @@ rust_task::die() {
436451
transition(&thread->running_tasks, &thread->dead_tasks, NULL, "none");
437452
}
438453

439-
void
440-
rust_task::unblock() {
441-
if (blocked()) {
442-
// FIXME: What if another thread unblocks the task between when
443-
// we checked and here?
444-
wakeup(cond);
445-
}
446-
}
447-
448454
rust_crate_cache *
449455
rust_task::get_crate_cache()
450456
{

branches/try/src/rt/rust_task.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,8 @@ rust_task : public kernel_owned<rust_task>, rust_cond
140140
void transition(rust_task_list *src, rust_task_list *dst,
141141
rust_cond *cond, const char* cond_name);
142142

143+
bool must_fail_from_being_killed_unlocked();
144+
143145
friend void task_start_wrapper(spawn_args *a);
144146
friend void cleanup_task(cleanup_args *a);
145147
friend void reset_stack_limit_on_c_stack(reset_args *a);
@@ -169,10 +171,9 @@ rust_task : public kernel_owned<rust_task>, rust_cond
169171
void set_state(rust_task_list *state,
170172
rust_cond *cond, const char* cond_name);
171173

172-
void block(rust_cond *on, const char* name);
174+
bool block(rust_cond *on, const char* name);
173175
void wakeup(rust_cond *from);
174176
void die();
175-
void unblock();
176177

177178
// Print a backtrace, if the "bt" logging option is on.
178179
void backtrace();

branches/try/src/rt/rust_task_thread.cpp

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include <stdarg.h>
33
#include <cassert>
44
#include <pthread.h>
5+
#include <vector>
56
#include "rust_internal.h"
67
#include "rust_util.h"
78
#include "globals.h"
@@ -95,19 +96,27 @@ rust_task_thread::fail() {
9596

9697
void
9798
rust_task_thread::kill_all_tasks() {
98-
I(this, !lock.lock_held_by_current_thread());
99-
scoped_lock with(lock);
99+
std::vector<rust_task*> all_tasks;
100100

101-
for (size_t i = 0; i < running_tasks.length(); i++) {
102-
// We don't want the failure of these tasks to propagate back
103-
// to the kernel again since we're already failing everything
104-
running_tasks[i]->unsupervise();
105-
running_tasks[i]->kill();
101+
{
102+
scoped_lock with(lock);
103+
104+
for (size_t i = 0; i < running_tasks.length(); i++) {
105+
all_tasks.push_back(running_tasks[i]);
106+
}
107+
108+
for (size_t i = 0; i < blocked_tasks.length(); i++) {
109+
all_tasks.push_back(blocked_tasks[i]);
110+
}
106111
}
107112

108-
for (size_t i = 0; i < blocked_tasks.length(); i++) {
109-
blocked_tasks[i]->unsupervise();
110-
blocked_tasks[i]->kill();
113+
while (!all_tasks.empty()) {
114+
rust_task *task = all_tasks.back();
115+
all_tasks.pop_back();
116+
// We don't want the failure of these tasks to propagate back
117+
// to the kernel again since we're already failing everything
118+
task->unsupervise();
119+
task->kill();
111120
}
112121
}
113122

0 commit comments

Comments
 (0)