aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/rt/rust_dom.cpp27
-rw-r--r--src/rt/rust_dom.h1
2 files changed, 28 insertions, 0 deletions
diff --git a/src/rt/rust_dom.cpp b/src/rt/rust_dom.cpp
index 67a1be36..ce6bebf3 100644
--- a/src/rt/rust_dom.cpp
+++ b/src/rt/rust_dom.cpp
@@ -368,6 +368,31 @@ rust_dom::schedule_task() {
return NULL;
}
+/**
+ * Checks for simple deadlocks.
+ */
+bool
+rust_dom::is_deadlocked() {
+ if (_live_domains.size() != 1) {
+ // We cannot tell if we are deadlocked if other domains exists.
+ return false;
+ }
+
+ if (running_tasks.length() != 0) {
+ // We are making progress and therefore we are not deadlocked.
+ return false;
+ }
+
+ if (_incoming_message_queue.is_empty() && blocked_tasks.length() > 0) {
+ // We have no messages to process, no running tasks to schedule
+ // and some blocked tasks therefore we are likely in a deadlock.
+ log_state();
+ return true;
+ }
+
+ return false;
+}
+
void
rust_dom::log_all_state() {
for (uint32_t i = 0; i < _live_domains.size(); i++) {
@@ -427,6 +452,8 @@ rust_dom::start_main_loop()
logptr("exit-task glue", root_crate->get_exit_task_glue());
while (n_live_tasks() > 0) {
+ A(this, is_deadlocked() == false, "deadlock");
+
drain_incoming_message_queue();
rust_task *scheduled_task = schedule_task();
diff --git a/src/rt/rust_dom.h b/src/rt/rust_dom.h
index d2b6e570..34d8c694 100644
--- a/src/rt/rust_dom.h
+++ b/src/rt/rust_dom.h
@@ -88,6 +88,7 @@ struct rust_dom
void reap_dead_tasks();
rust_task *schedule_task();
+ bool is_deadlocked();
int start_main_loop();
void log_state();