[Concurrency] Fix failing concurrency tests on Linux (#90701)
Fixes a use-after-free where a Task could be destroyed while another thread
still held (and was about to release) that Task's status-record lock.
The TaskStatusLock is a hybrid lock: an "is-locked" bit in the
ActiveTaskStatus word plus a real mutex living in the Task's
private storage. On unlock, withStatusRecordLock clears the bit via
CAS *before* it releases the mutex, and it still touches the Task
afterwards (to trace the status change and to unlock). Once the bit
is clear, other threads may make lock-free progress on the Task.
The Task Stealers change (ccaac5299bfd, rdar://160967177, #86082) moved
the swift_task_enqueue for the Task's own Job inside that locked region
(in flagAsAndEnqueueOnExecutor). The enqueue consumes the caller's only
reference to the Task, and the wake/resume callers (completeFuture,
runWaitingTask, resumeTaskAfterContinuation) hold no reference of
their own. So once the Task was published, a worker could dequeue it,
run it to completion, and release the last reference thus destroying
the Task, including the mutex before the enqueuing thread finished
the trace and unlock. That thread then operated on freed memory.
Split "decide what to enqueue" from "enqueue it": rename
swift_task_enqueueSelfOrStealer to swift_task_getSelfOrStealerForEnqueue,
which does the status mutation under the lock and *returns* the Job to
enqueue (the Task itself or a fresh stealer) instead of enqueuing it.
flagAsAndEnqueueOnExecutor now calls swift_task_enqueue on that Job
only after the lock has been released, so the Task is never reachable
by a runner while we still need to touch it. It returns nullptr
when there is nothing to enqueue (the async-let escalation path).
swift_executor_escalate is exempt from the drop-the-lock rule
and enqueues its returned Job while still holding the lock. Its
callers must hold a refcount on the Task for the duration of
the escalate, so the Task cannot be destroyed out from under it.
Also, update the surrounding documentation to describe the new
decide-then-enqueue contract and add a note at the unlock site
in withStatusRecordLock warning that the Task must not have been
published before that point unless the caller holds its own reference.