summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/include/thread.h9
-rw-r--r--src/lib/thread.c16
2 files changed, 18 insertions, 7 deletions
diff --git a/src/include/thread.h b/src/include/thread.h
index 6df9d7edc5..160173e7e7 100644
--- a/src/include/thread.h
+++ b/src/include/thread.h
@@ -43,8 +43,13 @@ int thread_yield_microseconds(unsigned int microsecs);
/* Allow and prevent thread cooperation on current running thread. By default
* all threads are marked to be cooperative. That means a thread can yield
- * to another thread at a pre-determined switch point. Current there is
- * only a single place where switching may occur: a call to udelay(). */
+ * to another thread at a pre-determined switch point. i.e., udelay,
+ * thread_yield, or thread_yield_microseconds.
+ *
+ * These methods should be used to guard critical sections so a dead lock does
+ * not occur. The critical sections can be nested. Just make sure the methods
+ * are used in pairs.
+ */
void thread_cooperate(void);
void thread_prevent_coop(void);
diff --git a/src/lib/thread.c b/src/lib/thread.c
index d44c218094..266ea381fe 100644
--- a/src/lib/thread.c
+++ b/src/lib/thread.c
@@ -31,7 +31,7 @@ static inline struct cpu_info *thread_cpu_info(const struct thread *t)
static inline int thread_can_yield(const struct thread *t)
{
- return (t != NULL && t->can_yield);
+ return (t != NULL && t->can_yield > 0);
}
/* Assumes current CPU info can switch. */
@@ -358,8 +358,12 @@ void thread_cooperate(void)
current = current_thread();
- if (current != NULL)
- current->can_yield = 1;
+ if (current == NULL)
+ return;
+
+ assert(current->can_yield <= 0);
+
+ current->can_yield++;
}
void thread_prevent_coop(void)
@@ -368,6 +372,8 @@ void thread_prevent_coop(void)
current = current_thread();
- if (current != NULL)
- current->can_yield = 0;
+ if (current == NULL)
+ return;
+
+ current->can_yield--;
}