pw_thread_freertos: Fix extra wakeups when detaching threads

vTaskResume() is known to cause premature return from blocking APIs,
since it will indiscriminately call prvAddTaskToReadyList().

Instead, use vTaskSuspendAll() / xTaskResumeAll(), which will not wake
up any tasks which weren't already running (and weren't signalled during
scheduler suspension).

This also fixes a latent bug where, in the existing fallback case of
using vTaskSuspendAll(), the new task scheduler state will be
taskSCHEDULER_SUSPENDED, causing the subsequent xTaskResumeAll() to be
skipped.

Bug: b/303885539
Change-Id: I4d09400e133b4d44353d601d07e13917e096a3eb
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/175310
Reviewed-by: Ewout van Bekkum <ewout@google.com>
Reviewed-by: Christoph Klee <chklee@google.com>
Commit-Queue: Auto-Submit <auto-submit@pigweed-service-accounts.iam.gserviceaccount.com>
Pigweed-Auto-Submit: Austin Foxley <afoxley@google.com>
Reviewed-by: Jonathon Reinhart <jrreinhart@google.com>
diff --git a/pw_thread_freertos/thread.cc b/pw_thread_freertos/thread.cc
index a7e3681..de9f004 100644
--- a/pw_thread_freertos/thread.cc
+++ b/pw_thread_freertos/thread.cc
@@ -193,22 +193,20 @@
 void Thread::detach() {
   PW_CHECK(joinable());
 
-  if (xTaskGetSchedulerState() == taskSCHEDULER_RUNNING) {
-#if (INCLUDE_vTaskSuspend == 1)
-    // No need to suspend extra tasks.
-    vTaskSuspend(native_type_->task_handle());
-#else
+  // xTaskResumeAll() can only be used after the scheduler has been started.
+  const bool scheduler_initialized =
+      xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED;
+
+  if (scheduler_initialized) {
+    // We don't want to individually suspend and resume this task using
+    // vTaskResume() as that can cause tasks to prematurely wake up and return
+    // from blocking APIs (b/303885539).
     vTaskSuspendAll();
-#endif  // INCLUDE_vTaskSuspend == 1
   }
   native_type_->set_detached();
   const bool thread_done = native_type_->thread_done();
-  if (xTaskGetSchedulerState() == taskSCHEDULER_RUNNING) {
-#if (INCLUDE_vTaskSuspend == 1)
-    vTaskResume(native_type_->task_handle());
-#else
+  if (scheduler_initialized) {
     xTaskResumeAll();
-#endif  // INCLUDE_vTaskSuspend == 1
   }
 
   if (thread_done) {