Skip to content

Instantly share code, notes, and snippets.

@jamorton
Created April 1, 2012 07:33
Show Gist options
  • Save jamorton/2272730 to your computer and use it in GitHub Desktop.
Save jamorton/2272730 to your computer and use it in GitHub Desktop.
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