This is a bit of a pickle and I'm unsure what's the best behavior here.
Since notifiers fire asynchronously via the event loop, we may end up
firing a notifier for a socket fd, but then reading/writing that socket
fd before ending up in the notifier callback.
In that situation, the socket is no longer in the same state as it was
when the event loop generated the notifier event.
This patch stops Socket from firing one hook in this situation but this
probably needs a global rethink.
With this change, Browser starts reliably in multi-process mode. :^)
Also move the existing backspace lambda out of the loop.
The do_delete() extraction fixes a minor bug where
InputState::ExpectTerminator wasn't entered if delete was pressed at the
very end of a line. Now that this is fixed, there's no more
"LibLine: Unhandled final: 7e (~)" when hitting delete at the end of the
line.
The fact that JsonValues can contain 64-bit values isn't a JavaScript
compatible behavior in the first place, but as long as we're supporting
this, we should make sure it works correctly.
MemoryManager::quickmap_pd and MemoryManager::quickmap_pt can only
be called by one processor at the time anyway, since anything using
these must have the MM lock held. So, no need to inform the other
CPUs to flush their TLBs, we can just flush our own.
We can now properly initialize all processors without
crashing by sending SMP IPI messages to synchronize memory
between processors.
We now initialize the APs once we have the scheduler running.
This is so that we can process IPI messages from the other
cores.
Also rework interrupt handling a bit so that it's more of a
1:1 mapping. We need to allocate non-sharable interrupts for
IPIs.
This also fixes the occasional hang/crash because all
CPUs now synchronize memory with each other.
Everyone who connects to ProtocolServer now gets his own instance.
This means that different users can no longer talk to the same exact
ProtocolServer process, enhanching security and stability.
This allows the parser to finally parse the entire source into a single
AST.
As a result of allowing comments inside sequences, Sequence is also
marked as would_execute if its left or right node would.
The short-circuit path added for waiting on a queue that already had a
pending wake was able to return with interrupts disabled, which breaks
the API contract of wait_on() always returning with IF=1.
Fix this by adding a way to override the restored IF in ScopedCritical.
If WaitQueue::wake_all, WaitQueue::wake_one, or WaitQueue::wake_n
is called but nobody is currently waiting, we should remember that
fact and prevent someone from waiting after such a request. This
solves a race condition where the Finalizer thread is notified
to finalize a thread, but it is not (yet) waiting on this queue.
Fixes#2693
These changes solve a number of problems with the software
context swithcing:
* The scheduler lock really should be held throughout context switches
* Transitioning from the initial (idle) thread to another needs to
hold the scheduler lock
* Transitioning from a dying thread to another also needs to hold
the scheduler lock
* Dying threads cannot necessarily be finalized if they haven't
switched out of it yet, so flag them as active while a processor
is running it (the Running state may be switched to Dying while
it still is actually running)
We need to be able to prevent a WaitQueue from being
modified by another CPU. So, add a SpinLock to it.
Because this pushes some other class over the 64 byte
limit, we also need to add another 128-byte bucket to
the slab allocator.
The Lock class still permits no reason, but for everything else
require a reason to be passed to Thread::wait_on. This makes it
easier to diagnose why a Thread is in Queued state.
Change: on_link_hover(String) -> on_link_hover(URL)
Also, we now fire the hook when a link is unhovered as well, allowing
the embedder to react to nothing being hovered anymore.