Improve pthread_join()

Since we're now on Windows 8, we can have clone() work as advertised on
Windows, where it sends a futex wake to the child tid. It's also likely
we no longer need to work around thread flakes on OpenBSD, in _wait0().
This commit is contained in:
Justine Tunney 2022-09-16 14:02:06 -07:00
parent 3733b43a8f
commit 994e1f4386
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
19 changed files with 154 additions and 74 deletions

View file

@ -16,36 +16,43 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/errno.h"
#include "libc/intrin/atomic.h"
#include "libc/thread/thread.h"
#include "libc/macros.internal.h"
#include "libc/mem/mem.h"
#include "libc/thread/posixthread.internal.h"
#include "libc/thread/spawn.h"
#include "libc/thread/thread.h"
/**
* Asks POSIX thread to free itself automatically on termination.
*
* @return 0 on success, or errno with error
* @raise EINVAL if thread is null or already detached
*/
int pthread_detach(pthread_t thread) {
struct PosixThread *pt;
enum PosixThreadStatus status;
struct PosixThread *pt = (struct PosixThread *)thread;
if (!(pt = (struct PosixThread *)thread)) {
return EINVAL;
}
for (;;) {
status = atomic_load_explicit(&pt->status, memory_order_relaxed);
status = atomic_load_explicit(&pt->status, memory_order_acquire);
if (status == kPosixThreadDetached || status == kPosixThreadZombie) {
// these two states indicate the thread was already detached, in
// which case it's already listed under _pthread_zombies.
break;
return EINVAL;
} else if (status == kPosixThreadTerminated) {
// thread was joinable and finished running. since pthread_join
// won't be called, it's safe to free the thread resources now.
// POSIX says this could be reported as ESRCH but then our test
// code would be less elegant in order for it to avoid flaking.
_pthread_wait(pt);
_pthread_free(pt);
break;
} else if (status == kPosixThreadJoinable) {
if (atomic_compare_exchange_weak_explicit(
&pt->status, &status, kPosixThreadDetached, memory_order_acquire,
&pt->status, &status, kPosixThreadDetached, memory_order_release,
memory_order_relaxed)) {
_pthread_zombies_add(pt);
break;