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 <jwerner@chromium.org>
Signed-off-by: Raul E Rangel <rrangel@chromium.org>
Change-Id: I325ab6181b17c5c084ca1e2c181b4df235020557
Reviewed-on: https://review.coreboot.org/c/coreboot/+/56350
Reviewed-by: Karthik Ramasubramanian <kramasub@google.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
Raul E Rangel 2021-07-15 13:52:03 -06:00 committed by Raul Rangel
parent b95369c914
commit be60a0ddb0
2 changed files with 18 additions and 7 deletions

View File

@ -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);

View File

@ -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--;
}