From be60a0ddb0494e5a3becca832d706076820642f7 Mon Sep 17 00:00:00 2001 From: Raul E Rangel Date: Thu, 15 Jul 2021 13:52:03 -0600 Subject: 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. BUG=b:179699789 TEST=Boot guybrush with SPI DMA Suggested-by: Julius Werner Signed-off-by: Raul E Rangel Change-Id: I325ab6181b17c5c084ca1e2c181b4df235020557 Reviewed-on: https://review.coreboot.org/c/coreboot/+/56350 Reviewed-by: Karthik Ramasubramanian Tested-by: build bot (Jenkins) --- src/include/thread.h | 9 +++++++-- src/lib/thread.c | 16 +++++++++++----- 2 files changed, 18 insertions(+), 7 deletions(-) (limited to 'src') 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--; } -- cgit v1.2.3