Raul Rangel has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/56350 )
Change subject: lib/thread: Allow nesting thread_cooperate and thread_prevent_coop ......................................................................
lib/thread: Allow nesting thread_cooperate and thread_prevent_coop
This change allows nesting critical sections, and frees the caller from having to keep track of whether the thread has coop enabled.
I also removed the `thread_cooperate` inside of `idle_thread_init` since it was really setting up the BSP thread and had nothing to do with the idle thread.
BUG=b:179699789 TEST=Boot guybrush with SPI DMA
Suggested-by: Julius Werner jwerner@chromium.org Signed-off-by: Raul E Rangel rrangel@chromium.org Change-Id: I325ab6181b17c5c084ca1e2c181b4df235020557 --- M src/include/thread.h M src/lib/thread.c 2 files changed, 17 insertions(+), 9 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/50/56350/1
diff --git a/src/include/thread.h b/src/include/thread.h index 6df9d7e..8f12343 100644 --- a/src/include/thread.h +++ b/src/include/thread.h @@ -43,8 +43,13 @@
/* 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 method 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 a8c0772c..db70b17 100644 --- a/src/lib/thread.c +++ b/src/lib/thread.c @@ -31,7 +31,7 @@
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. */ @@ -213,8 +213,6 @@ /* Queue idle thread to run once all other threads have yielded. */ prepare_thread(t, idle_thread, NULL, call_wrapper, NULL); push_runnable(t); - /* Mark the currently executing thread to cooperate. */ - thread_cooperate(); }
/* Don't inline this function so the timeout_callback won't have its storage @@ -260,6 +258,7 @@ ci->thread = t; t->stack_orig = (uintptr_t)ci; t->id = 0; + t->can_yield = 1;
stack_top = &thread_stacks[CONFIG_STACK_SIZE] - sizeof(struct cpu_info); for (i = 1; i < TOTAL_NUM_THREADS; i++) { @@ -359,8 +358,10 @@
current = current_thread();
- if (current != NULL) - current->can_yield = 1; + if (current == NULL) + return; + + current->can_yield++; }
void thread_prevent_coop(void) @@ -369,6 +370,8 @@
current = current_thread();
- if (current != NULL) - current->can_yield = 0; + if (current == NULL) + return; + + current->can_yield--; }