[roll] Roll fuchsia [x86][idle] Fix a race in the idle thread.

Fix a race in the x86 implementation of the idle thread which could
lead to a thread being stuck in the READY state for a period of time
instead of being scheduled to run immediately.

This was a pretty tough one to find, and is a bit complicated.  For
full details, please refer to the analysis posted here

https://bugs.fuchsia.dev/p/fuchsia/issues/detail?id=102058#c58

Here is the short version.
When configured to use MONTOR/MWAIT for putting the CPU into a lower
power state when idle, the idle loop basically looks like the
following.

```
while (true) {
  AutoPreemptDisable apd;
  while (!signaled and !has_pending_preempts) {
    monitor(signaled);
    if (!signaled and !has_pending_preempts) {
      mwait();
    }
  }
}
```

So, preemption is disabled and we sit in mwait until we have a pending
preempt, or until someone writes to our per-cpu signal variable.  The
second check (in the if predicate) exists to handle a case where
another CPU signals us through our global variable after the while
check and just before the monitor check.

There is a window of time, however, after arming the monitor and
performing our second check, but before dropping into the mwait, where
an interrupt can fire.  If this unblocks a thread and assigns it to
the local CPU, it will cause a preempt to become locally.  It cannot
reschedule immediately, however, because the idle thread has disabled
preemption.  When the interrupt unwinds, the idle thread will be past
the second check but not in the mwait yet.  When it drops into the
mwait, it will not immediately wake up as the interrupt fired before
it made it into the wait state.

The fix is to handle this the same way that we handle the HLT version
of this thread.  Disable interrupts before we make our final check,
then re-enable them one instruction before the MWAIT.  This puts the
MWAIT into the interrupt shadow of the STI instruction, and guarantees
that we will have made it into MWAIT before the interrupt fires and
kicks us out again.

Original-Bug: 102058

Original-Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/717178
Original-Revision: bd41e2902a2aaf71c0e16e4a603850c1a7c064b8
GitOrigin-RevId: 0da87dd7a3ab9f27f6e5e00b69fe5ff03d8a911f
Change-Id: I9d33938b5b89822cf3e1f6f07fd99bed35ab437f
1 file changed
tree: b4e952dcf7e70ec6efbda71ba163a999aa7fe0cd
  1. git-hooks/
  2. infra/
  3. third_party/
  4. cts
  5. firmware
  6. flower
  7. jiri.lock
  8. minimal
  9. prebuilts
  10. README.md
  11. stem
  12. test_durations
  13. toolchain
README.md

Integration

This repository contains Fuchsia's Global Integration manifest files.

Making changes

All changes should be made to the internal version of this repository. Our infrastructure automatically updates this version when the internal one changes.

Currently all changes must be made by a Google employee. Non-Google employees wishing to make a change can ask for assistance via the IRC channel #fuchsia on Freenode.

Obtaining the source

First install Jiri.

Next run:

$ jiri init
$ jiri import minimal https://fuchsia.googlesource.com/integration
$ jiri update

Third party

Third party projects should have their own subdirectory in ./third_party.