suspended thread itself, on the return path from
thread_suspend_check(). A consequence is that return from
thread_single_end(SINGLE_BOUNDARY) may leave p_boundary_count
non-zero, it might be even equal to the threads count.
Now, assume that we have two threads in the process, both calling
execve(2). Suppose that the first thread won the race to be the
suspension thread, and that afterward its exec failed for any reason.
After the first thread did thread_single_end(SINGLE_BOUNDARY), second
thread becomes the process suspension thread and checks
p_boundary_count. The non-zero value of the count allows the
suspension loop to finish without actually suspending some threads.
In other words, we enter exec code with some threads not suspended.
Fix this by decrementing p_boundary_count in the
thread_single_end()->thread_unsuspend_one() during marking the thread
as runnable. This way, a return from thread_single_end() guarantees
that the counter is cleared. We do not care whether the unsuspended
thread has a chance to run.
Add some asserts to ensure the state of the process when single
boundary suspension is lifted. Also make thread_unuspend_one()
static.
In collaboration with: pho
Sponsored by: The FreeBSD Foundation
MFC after: 1 week