Some synchronization built into `close-output-port` seems unnecessary
on modern Windows (NT and up). An extra manager thread is needed for a
anonymous pipe for "write ready?" purposes, but not to buffer output.
The Windows documentation is not entirely clear on this point, but
experiments suggest that modern anonymous pipes behave in the obvious
way.
Meanwhile, adjust the io layer used by Racket CS with the
synchronization that would be needed for Windows 95. This adjustment
is questionable, because it doesn't seem likely that we'll ever go
back that far with Racket CS. But the rktio interface to support
flushing synchronization might somehow be needed in a future setting,
or mabe it will turn out that I'm wrong about pipe buffers.
Avoid a continuation frame and layer of thunks that was in place for
checking for breaks just after applying a continuation. Instead, we
install just the continuation marks and check for breaks before
actually jumping; the break checker can't tell the difference, since
marks are the only way for it to check the continuation. This
improvement cust about 40% of the time for simple continuation capture
and application.
The ctak benchmark had lost a `(lambda (k) ...)`, which made it a
slightly different benchamrk than it was supposed to be. There's not a
good option here; changing it is a break with past Racket
benchmarking, but leaving it broken is misleading. Since the repaired
benchmark runs about the same in traditional Racket, it seems the
lesser evil to repair the benchmark. But also increase the number of
iterations, which makes the benchmark better for Racket CS (which runs
10 titmes as fast) and will help highlight the adjustment if someone
is trying to compare.
A misplaced `wrap-evt` could allow the result from `sync` on
a log receiver to be an opaque event, instead of a vector.
In other cases, a differently misplaced `wrap-evt` could also cause an
internal instance of `control-state-evt` to not be unregistered
correctly.
The solution to both problems is to add a wrapper procedure to
`control-state-evt`.
Closes#2664
Repair problems with asynchronous callbacks for futures and for
foreign callbacks. Asynchronous callbacks are used for future "sync"
operations, like `hash-set!`, that run must in a place's main thread
(as of commit f574583907).
Separately, synchronization to clean up future threads used a `ping?`
flag in a backwards sense, and it also treated a record as a box.
These problems could cause place termination to hang.
Related to #2725
The `math` library relies on this working right, since MPFR is
normally not compiled as thread-safe.
Also, fix some locking/interrupt/atomicity problems with async
callbacks generally.
When `sync` or `place-channel-get` is used on a place channel whose
other end has been GCed, then the blocking thread should also be
GCable. The `sync` case didn't work because the implementation uses
`replace-evt`. Change `sync` so that it can recognize asynchronous
`replace-evt`s in the same way as semaphores and channels (which is
more than traditional Racket offers).
When a place terminates, it was directly accessing its parent's
custodian. Prior support for cross-place uses of a hash table
probably helped hide this problem previously.
At least for now. Chez Scheme can fasl some things that traditional
Racket would refuse. This seems like a problem, but it's not a new
one, and it's not immediately obvious how to fix it. One test started
failing because the representation of scopes changed just enough to
become faslable.
Although extremely unlikely, it was possible for multiple Racket
threads operating on the same scopes to race on a multi-scope's table
mapping phase levels to scopes.
Also, for some some mutable hash tables that will be shared across
places as read-only in Racket CS, make sure they are definitely set up
for iteration.
An `eq?`-based hash table in the implementation of custodians was
still shared across threads.
Also, taking the global lock at the Rumble level did not disable
interrupts. Since sometimes the lock is taken with interrupts
disabled, threads could potentially deadlock by not having an order.
Fix the problem by disabling interrupts before taking the lock.