Skip to content

Commit da45ff9

Browse files
committed
---
yaml --- r: 14131 b: refs/heads/try c: 028af5c h: refs/heads/master i: 14129: 6a49a62 14127: 6103c15 v: v3
1 parent edac831 commit da45ff9

File tree

9 files changed

+67
-24
lines changed

9 files changed

+67
-24
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: ebc3646c39e2a24fe6eec778fb7ca5862d95acf7
5+
refs/heads/try: 028af5cb6c588a33b0bf5cbf451236407f5ba110
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105

branches/try/src/rt/rust_internal.h

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -104,15 +104,14 @@ static size_t const BUF_BYTES = 2048;
104104
void ref() { ++ref_count; } \
105105
void deref() { if (--ref_count == 0) { dtor; } }
106106

107-
#define RUST_ATOMIC_REFCOUNT() \
108-
private: \
109-
intptr_t ref_count; \
110-
public: \
111-
void ref() { \
112-
intptr_t old = sync::increment(ref_count); \
113-
assert(old > 0); \
114-
} \
115-
void deref() { if(0 == sync::decrement(ref_count)) { delete this; } }
107+
#define RUST_ATOMIC_REFCOUNT() \
108+
public: \
109+
intptr_t ref_count; \
110+
void ref() { \
111+
intptr_t old = sync::increment(ref_count); \
112+
assert(old > 0); \
113+
} \
114+
void deref() { if(0 == sync::decrement(ref_count)) { delete_this(); } }
116115

117116
template <typename T> struct task_owned {
118117
inline void *operator new(size_t size, rust_task *task, const char *tag);

branches/try/src/rt/rust_kernel.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -129,11 +129,6 @@ rust_kernel::release_task_id(rust_task_id id) {
129129
new_live_tasks = --live_tasks;
130130
}
131131
KLOG_("Total outstanding tasks: %d", new_live_tasks);
132-
if (new_live_tasks == 0) {
133-
// There are no more tasks and there never will be.
134-
// Tell all the schedulers to exit.
135-
sched->exit();
136-
}
137132
}
138133

139134
rust_task *

branches/try/src/rt/rust_scheduler.cpp

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ rust_scheduler::rust_scheduler(rust_kernel *kernel,
99
srv(srv),
1010
env(srv->env),
1111
live_threads(num_threads),
12+
live_tasks(0),
1213
num_threads(num_threads),
1314
id(id)
1415
{
@@ -84,6 +85,7 @@ rust_scheduler::create_task(rust_task *spawner, const char *name,
8485
{
8586
scoped_lock with(lock);
8687
thread_no = isaac_rand(&rctx) % num_threads;
88+
live_tasks++;
8789
}
8890
rust_task_thread *thread = threads[thread_no];
8991
return thread->create_task(spawner, name, init_stack_sz);
@@ -94,9 +96,28 @@ rust_scheduler::create_task(rust_task *spawner, const char *name) {
9496
return create_task(spawner, name, env->min_stack_size);
9597
}
9698

99+
void
100+
rust_scheduler::release_task() {
101+
bool need_exit = false;
102+
{
103+
scoped_lock with(lock);
104+
live_tasks--;
105+
if (live_tasks == 0) {
106+
need_exit = true;
107+
}
108+
}
109+
if (need_exit) {
110+
// There are no more tasks on this scheduler. Time to leave
111+
exit();
112+
}
113+
}
114+
97115
void
98116
rust_scheduler::exit() {
99-
for(size_t i = 0; i < num_threads; ++i) {
117+
// Take a copy of num_threads. After the last thread exits this
118+
// scheduler will get destroyed, and our fields will cease to exist.
119+
size_t current_num_threads = num_threads;
120+
for(size_t i = 0; i < current_num_threads; ++i) {
100121
threads[i]->exit();
101122
}
102123
}

branches/try/src/rt/rust_scheduler.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ class rust_scheduler : public kernel_owned<rust_scheduler> {
1414
lock_and_signal lock;
1515
// When this hits zero we'll tell the kernel to release us
1616
uintptr_t live_threads;
17+
// When this hits zero we'll tell the threads to exit
18+
uintptr_t live_tasks;
1719
randctx rctx;
1820

1921
array_list<rust_task_thread *> threads;
@@ -27,6 +29,8 @@ class rust_scheduler : public kernel_owned<rust_scheduler> {
2729
rust_task_thread *create_task_thread(int id);
2830
void destroy_task_thread(rust_task_thread *thread);
2931

32+
void exit();
33+
3034
public:
3135
rust_scheduler(rust_kernel *kernel, rust_srv *srv, size_t num_threads,
3236
rust_sched_id id);
@@ -39,7 +43,8 @@ class rust_scheduler : public kernel_owned<rust_scheduler> {
3943
size_t init_stack_sz);
4044
rust_task_id create_task(rust_task *spawner, const char *name);
4145

42-
void exit();
46+
void release_task();
47+
4348
size_t number_of_threads();
4449
// Called by each thread when it terminates. When all threads
4550
// terminate the scheduler does as well.

branches/try/src/rt/rust_task.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,8 @@ rust_task::rust_task(rust_task_thread *thread, rust_task_list *state,
268268
}
269269
}
270270

271-
rust_task::~rust_task()
271+
void
272+
rust_task::delete_this()
272273
{
273274
I(thread, !thread->lock.lock_held_by_current_thread());
274275
I(thread, port_table.is_empty());
@@ -291,6 +292,8 @@ rust_task::~rust_task()
291292
while (stk != NULL) {
292293
del_stk(this, stk);
293294
}
295+
296+
thread->release_task(this);
294297
}
295298

296299
struct spawn_args {

branches/try/src/rt/rust_task.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,15 +122,18 @@ rust_task : public kernel_owned<rust_task>, rust_cond
122122
// The amount of stack we're using, excluding red zones
123123
size_t total_stack_sz;
124124

125+
private:
126+
// Called when the atomic refcount reaches zero
127+
void delete_this();
128+
public:
129+
125130
// Only a pointer to 'name' is kept, so it must live as long as this task.
126131
rust_task(rust_task_thread *thread,
127132
rust_task_list *state,
128133
rust_task *spawner,
129134
const char *name,
130135
size_t init_stack_sz);
131136

132-
~rust_task();
133-
134137
void start(spawn_fn spawnee_fn,
135138
rust_opaque_box *env,
136139
void *args);

branches/try/src/rt/rust_task_thread.cpp

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -136,16 +136,30 @@ rust_task_thread::reap_dead_tasks() {
136136

137137
for (size_t i = 0; i < dead_tasks_len; ++i) {
138138
rust_task *task = dead_tasks_copy[i];
139-
if (task) {
140-
kernel->release_task_id(task->user.id);
141-
task->deref();
142-
}
139+
// Release the task from the kernel so nobody else can get at it
140+
kernel->release_task_id(task->user.id);
141+
// Deref the task, which may cause it to request us to release it
142+
task->deref();
143143
}
144144
srv->free(dead_tasks_copy);
145145

146146
lock.lock();
147147
}
148148

149+
void
150+
rust_task_thread::release_task(rust_task *task) {
151+
// Nobody should have a ref to the task at this point
152+
I(this, task->ref_count == 0);
153+
// Kernel should not know about the task any more
154+
I(this, kernel->get_task_by_id(task->user.id) == NULL);
155+
// Now delete the task, which will require using this thread's
156+
// memory region.
157+
delete task;
158+
// Now release the task from the scheduler, which may trigger this
159+
// thread to exit
160+
sched->release_task();
161+
}
162+
149163
/**
150164
* Schedules a running task for execution. Only running tasks can be
151165
* activated. Blocked tasks have to be unblocked before they can be

branches/try/src/rt/rust_task_thread.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,9 @@ struct rust_task_thread : public kernel_owned<rust_task_thread>,
122122

123123
static rust_task *get_task();
124124

125+
// Called by each task when they are ready to be destroyed
126+
void release_task(rust_task *task);
127+
125128
// Tells the scheduler to exit it's scheduling loop and thread
126129
void exit();
127130
};

0 commit comments

Comments
 (0)