Created
April 1, 2012 07:33
-
-
Save jamorton/2272730 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/src/rt/rust_port_selector.cpp b/src/rt/rust_port_selector.cpp | |
index d958eac..e1d627e 100644 | |
--- a/src/rt/rust_port_selector.cpp | |
+++ b/src/rt/rust_port_selector.cpp | |
@@ -1,8 +1,10 @@ | |
#include "rust_port.h" | |
#include "rust_port_selector.h" | |
+#include "rust_util.h" | |
-rust_port_selector::rust_port_selector() | |
+rust_port_selector::rust_port_selector(rust_kernel * kernel) | |
: ports(NULL), n_ports(0) { | |
+ isaac_init(kernel, &rctx); | |
} | |
void | |
@@ -27,7 +29,7 @@ rust_port_selector::select(rust_task *task, rust_port **dptr, | |
// message. | |
// Start looking for ports from a different index each time. | |
- size_t j = isaac_rand(&task->thread->rctx); | |
+ size_t j = isaac_rand(&rctx); | |
for (size_t i = 0; i < n_ports; i++) { | |
size_t k = (i + j) % n_ports; | |
rust_port *port = ports[k]; | |
diff --git a/src/rt/rust_port_selector.h b/src/rt/rust_port_selector.h | |
index 3bfc454..d0c2890 100644 | |
--- a/src/rt/rust_port_selector.h | |
+++ b/src/rt/rust_port_selector.h | |
@@ -11,9 +11,10 @@ class rust_port_selector : public rust_cond { | |
rust_port **ports; | |
size_t n_ports; | |
lock_and_signal rendezvous_lock; | |
+ randctx rctx; | |
public: | |
- rust_port_selector(); | |
+ rust_port_selector(rust_kernel *kernel); | |
void select(rust_task *task, | |
rust_port **dptr, | |
diff --git a/src/rt/rust_task.cpp b/src/rt/rust_task.cpp | |
index 83a357f..7a3355d 100644 | |
--- a/src/rt/rust_task.cpp | |
+++ b/src/rt/rust_task.cpp | |
@@ -33,6 +33,8 @@ rust_task::rust_task(rust_task_thread *thread, rust_task_state state, | |
propagate_failure(true), | |
cc_counter(0), | |
total_stack_sz(0), | |
+ thread_next(NULL), | |
+ thread_prev(NULL), | |
state(state), | |
cond(NULL), | |
cond_name("none"), | |
@@ -41,6 +43,7 @@ rust_task::rust_task(rust_task_thread *thread, rust_task_state state, | |
c_stack(NULL), | |
next_c_sp(0), | |
next_rust_sp(0), | |
+ port_selector(kernel), | |
supervisor(spawner) | |
{ | |
LOGPTR(thread, "new task", (uintptr_t)this); | |
diff --git a/src/rt/rust_task.h b/src/rt/rust_task.h | |
index 6a192c2..609d16c 100644 | |
--- a/src/rt/rust_task.h | |
+++ b/src/rt/rust_task.h | |
@@ -143,6 +143,10 @@ rust_task : public kernel_owned<rust_task>, rust_cond | |
// The amount of stack we're using, excluding red zones | |
size_t total_stack_sz; | |
+ // for linked lists of tasks in rust_task_thead | |
+ rust_task * thread_next; | |
+ rust_task * thread_prev; | |
+ | |
private: | |
// Protects state, cond, cond_name | |
diff --git a/src/rt/rust_task_thread.cpp b/src/rt/rust_task_thread.cpp | |
index 62644d0..4acf6b6 100644 | |
--- a/src/rt/rust_task_thread.cpp | |
+++ b/src/rt/rust_task_thread.cpp | |
@@ -26,6 +26,11 @@ rust_task_thread::rust_task_thread(rust_scheduler *sched, | |
id(id), | |
should_exit(false), | |
cached_c_stack(NULL), | |
+ extra_c_stack(NULL), | |
+ running_tasks(NULL), | |
+ blocked_tasks(NULL), | |
+ num_running_tasks(0), | |
+ num_blocked_tasks(0), | |
dead_task(NULL), | |
kernel(sched->kernel), | |
sched(sched), | |
@@ -37,7 +42,6 @@ rust_task_thread::rust_task_thread(rust_scheduler *sched, | |
name("main") | |
{ | |
LOGPTR(this, "new dom", (uintptr_t)this); | |
- isaac_init(kernel, &rctx); | |
if (!tls_initialized) | |
init_tls(); | |
@@ -75,33 +79,26 @@ rust_task_thread::fail() { | |
void | |
rust_task_thread::kill_all_tasks() { | |
- std::vector<rust_task*> all_tasks; | |
- | |
- { | |
- scoped_lock with(lock); | |
- | |
- for (size_t i = 0; i < running_tasks.length(); i++) { | |
- all_tasks.push_back(running_tasks[i]); | |
- } | |
- | |
- for (size_t i = 0; i < blocked_tasks.length(); i++) { | |
- all_tasks.push_back(blocked_tasks[i]); | |
- } | |
+ rust_task *task = running_tasks; | |
+ if (task != NULL) { | |
+ do { | |
+ task->unsupervise(); | |
+ task->kill(); | |
+ } while ((task = task->thread_next) != NULL); | |
} | |
- | |
- while (!all_tasks.empty()) { | |
- rust_task *task = all_tasks.back(); | |
- all_tasks.pop_back(); | |
- // We don't want the failure of these tasks to propagate back | |
- // to the kernel again since we're already failing everything | |
- task->unsupervise(); | |
- task->kill(); | |
+ | |
+ task = blocked_tasks; | |
+ if (task != NULL) { | |
+ do { | |
+ task->unsupervise(); | |
+ task->kill(); | |
+ } while ((task = task->thread_next) != NULL); | |
} | |
} | |
size_t | |
rust_task_thread::number_of_live_tasks() { | |
- return running_tasks.length() + blocked_tasks.length(); | |
+ return num_running_tasks + num_blocked_tasks; | |
} | |
/** | |
@@ -149,41 +146,42 @@ rust_task_thread::schedule_task() { | |
I(this, this); | |
// FIXME: in the face of failing tasks, this is not always right. | |
// I(this, n_live_tasks() > 0); | |
- if (running_tasks.length() > 0) { | |
- size_t k = isaac_rand(&rctx); | |
- // Look around for a runnable task, starting at k. | |
- for(size_t j = 0; j < running_tasks.length(); ++j) { | |
- size_t i = (j + k) % running_tasks.length(); | |
- return (rust_task *)running_tasks[i]; | |
- } | |
- } | |
- return NULL; | |
+ if (running_tasks == NULL) | |
+ return NULL; | |
+ | |
+ // move linked list head one over, effectively making it a queue | |
+ rust_task * ret = running_tasks; | |
+ running_tasks = running_tasks->thread_next; | |
+ return ret; | |
} | |
void | |
rust_task_thread::log_state() { | |
if (log_rt_task < log_debug) return; | |
- if (!running_tasks.is_empty()) { | |
+ if (running_tasks != NULL) { | |
log(NULL, log_debug, "running tasks:"); | |
- for (size_t i = 0; i < running_tasks.length(); i++) { | |
+ rust_task *task = running_tasks; | |
+ do { | |
log(NULL, log_debug, "\t task: %s @0x%" PRIxPTR, | |
- running_tasks[i]->name, | |
- running_tasks[i]); | |
- } | |
+ task->name, | |
+ task); | |
+ } while ((task = task->thread_next) != running_tasks); | |
} | |
- if (!blocked_tasks.is_empty()) { | |
+ if (blocked_tasks != NULL) { | |
log(NULL, log_debug, "blocked tasks:"); | |
- for (size_t i = 0; i < blocked_tasks.length(); i++) { | |
- log(NULL, log_debug, "\t task: %s @0x%" PRIxPTR | |
- ", blocked on: 0x%" PRIxPTR " '%s'", | |
- blocked_tasks[i]->name, blocked_tasks[i], | |
- blocked_tasks[i]->get_cond(), | |
- blocked_tasks[i]->get_cond_name()); | |
- } | |
+ rust_task *task = blocked_tasks; | |
+ do { | |
+ log(NULL, log_debug, "\t task: %s @0x%" PRIxPTR ", blocked on: 0x%" | |
+ PRIxPTR " '%s'", | |
+ task->name, task, | |
+ task->get_cond(), | |
+ task->get_cond_name()); | |
+ } while((task = task->thread_next) != blocked_tasks); | |
} | |
} | |
+ | |
/** | |
* Starts the main scheduler loop which performs task scheduling for this | |
* domain. | |
@@ -243,8 +241,8 @@ rust_task_thread::start_main_loop() { | |
reap_dead_tasks(); | |
} | |
- A(this, running_tasks.is_empty(), "Should have no running tasks"); | |
- A(this, blocked_tasks.is_empty(), "Should have no blocked tasks"); | |
+ A(this, running_tasks == NULL, "Should have no running tasks"); | |
+ A(this, blocked_tasks == NULL, "Should have no blocked tasks"); | |
A(this, dead_task == NULL, "Should have no dead tasks"); | |
DLOG(this, dom, "finished main-loop %d", id); | |
@@ -271,18 +269,6 @@ rust_task_thread::create_task(rust_task *spawner, const char *name) { | |
return task; | |
} | |
-rust_task_list * | |
-rust_task_thread::state_list(rust_task_state state) { | |
- switch (state) { | |
- case task_state_running: | |
- return &running_tasks; | |
- case task_state_blocked: | |
- return &blocked_tasks; | |
- default: | |
- return NULL; | |
- } | |
-} | |
- | |
const char * | |
rust_task_thread::state_name(rust_task_state state) { | |
switch (state) { | |
@@ -310,20 +296,37 @@ rust_task_thread::transition(rust_task *task, | |
name, (uintptr_t)this, state_name(src), state_name(dst), | |
state_name(task->get_state())); | |
I(this, task->get_state() == src); | |
- rust_task_list *src_list = state_list(src); | |
- if (src_list) { | |
- src_list->remove(task); | |
- } | |
- rust_task_list *dst_list = state_list(dst); | |
- if (dst_list) { | |
- dst_list->append(task); | |
+ | |
+ if (task->thread_next != NULL) | |
+ { | |
+ task->thread_prev->thread_next = task->thread_next; | |
+ task->thread_next->thread_prev = task->thread_prev; | |
+ task->thread_next = NULL; | |
+ task->thread_prev = NULL; | |
+ if (src == task_state_running) | |
+ num_running_tasks--; | |
+ else if (src == task_state_blocked) | |
+ num_blocked_tasks--; | |
} | |
- if (dst == task_state_dead) { | |
- I(this, dead_task == NULL); | |
- dead_task = task; | |
+ | |
+ if (dst == task_state_running || dst == task_state_blocked) | |
+ { | |
+ rust_task *dst_list; | |
+ if (dst == task_state_running) { | |
+ dst_list = running_tasks; | |
+ num_running_tasks++; | |
+ } else { | |
+ dst_list = blocked_tasks; | |
+ num_blocked_tasks++; | |
+ } | |
+ | |
+ if (dst_list != NULL) { | |
+ dst_list->thread_prev->thread_next = task; | |
+ dst_list->thread_prev = task; | |
+ } else | |
+ dst_list = task; | |
} | |
task->set_state(dst, cond, cond_name); | |
- | |
lock.signal(); | |
} | |
diff --git a/src/rt/rust_task_thread.h b/src/rt/rust_task_thread.h | |
index 6f17843..d72a7ca 100644 | |
--- a/src/rt/rust_task_thread.h | |
+++ b/src/rt/rust_task_thread.h | |
@@ -19,8 +19,6 @@ enum rust_task_state { | |
task_state_dead | |
}; | |
-typedef indexed_list<rust_task> rust_task_list; | |
- | |
struct rust_task_thread : public kernel_owned<rust_task_thread>, | |
rust_thread | |
{ | |
@@ -47,14 +45,16 @@ private: | |
stk_seg *cached_c_stack; | |
stk_seg *extra_c_stack; | |
- rust_task_list running_tasks; | |
- rust_task_list blocked_tasks; | |
+ rust_task *running_tasks; | |
+ rust_task *blocked_tasks; | |
+ size_t num_running_tasks; | |
+ size_t num_blocked_tasks; | |
+ | |
rust_task *dead_task; | |
void prepare_c_stack(rust_task *task); | |
void unprepare_c_stack(); | |
- rust_task_list *state_list(rust_task_state state); | |
const char *state_name(rust_task_state state); | |
public: | |
@@ -73,8 +73,6 @@ public: | |
size_t min_stack_size; | |
rust_env *env; | |
- randctx rctx; | |
- | |
int32_t list_index; | |
const char *const name; | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment