pthread: Implement pthread_timedjoin_np.
This also corrects an oversight in pthread_join() that not all potential error codes of wait_for_thread were accounted for (in particular EDEADLK wasn't.) This is a non-standard extension, but is present on both Linux and FreeBSD, at least. Change-Id: Ie96e7a261e863ab491bee30349360df7ff3d0e80 Reviewed-on: https://review.haiku-os.org/c/haiku/+/5099 Reviewed-by: waddlesplash <[email protected]>
This commit is contained in:
committed by
waddlesplash
parent
69b420563b
commit
9a4c543934
@@ -25,6 +25,8 @@ extern int pthread_getattr_np(pthread_t thread, pthread_attr_t* attr);
|
||||
extern int pthread_getname_np(pthread_t thread, char* buffer, size_t length);
|
||||
extern int pthread_setname_np(pthread_t thread, const char* name);
|
||||
|
||||
extern int pthread_timedjoin_np(pthread_t thread, void** _value, const struct timespec* abstime);
|
||||
|
||||
extern int pthread_setaffinity_np(pthread_t thread, size_t cpusetsize, const cpuset_t* mask);
|
||||
extern int pthread_getaffinity_np(pthread_t thread, size_t cpusetsize, cpuset_t* mask);
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <libroot_private.h>
|
||||
#include <syscalls.h>
|
||||
#include <thread_defs.h>
|
||||
#include <time_private.h>
|
||||
#include <tls.h>
|
||||
|
||||
#include <user_thread.h>
|
||||
@@ -141,6 +142,32 @@ __pthread_set_default_priority(int32 priority)
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
__pthread_join(pthread_t thread, void** _value, int flags = 0, bigtime_t timeout = 0)
|
||||
{
|
||||
status_t status;
|
||||
do {
|
||||
status_t dummy;
|
||||
status = wait_for_thread_etc(thread->id, flags, timeout, &dummy);
|
||||
} while (status == B_INTERRUPTED);
|
||||
|
||||
if (status == B_BAD_THREAD_ID)
|
||||
RETURN_AND_TEST_CANCEL(ESRCH);
|
||||
if (status == B_WOULD_BLOCK || status == B_TIMED_OUT)
|
||||
RETURN_AND_TEST_CANCEL(ETIMEDOUT);
|
||||
if (status < B_OK)
|
||||
RETURN_AND_TEST_CANCEL(status);
|
||||
|
||||
if (_value != NULL)
|
||||
*_value = thread->exit_value;
|
||||
|
||||
if ((atomic_or(&thread->flags, THREAD_DETACHED) & THREAD_DEAD) != 0)
|
||||
free(thread);
|
||||
|
||||
RETURN_AND_TEST_CANCEL(B_OK);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - public API
|
||||
|
||||
|
||||
@@ -199,22 +226,7 @@ pthread_equal(pthread_t t1, pthread_t t2)
|
||||
int
|
||||
pthread_join(pthread_t thread, void** _value)
|
||||
{
|
||||
status_t dummy;
|
||||
status_t error;
|
||||
do {
|
||||
error = wait_for_thread(thread->id, &dummy);
|
||||
} while (error == B_INTERRUPTED);
|
||||
|
||||
if (error == B_BAD_THREAD_ID)
|
||||
RETURN_AND_TEST_CANCEL(ESRCH);
|
||||
|
||||
if (_value != NULL)
|
||||
*_value = thread->exit_value;
|
||||
|
||||
if ((atomic_or(&thread->flags, THREAD_DETACHED) & THREAD_DEAD) != 0)
|
||||
free(thread);
|
||||
|
||||
RETURN_AND_TEST_CANCEL(error);
|
||||
return __pthread_join(thread, _value);
|
||||
}
|
||||
|
||||
|
||||
@@ -346,6 +358,24 @@ pthread_setname_np(pthread_t thread, const char* name)
|
||||
}
|
||||
|
||||
|
||||
extern "C" int
|
||||
pthread_timedjoin_np(pthread_t thread, void** _value, const struct timespec* abstime)
|
||||
{
|
||||
int flags = 0;
|
||||
bigtime_t timeout = 0;
|
||||
if (abstime != NULL) {
|
||||
if (!timespec_to_bigtime(*abstime, timeout))
|
||||
RETURN_AND_TEST_CANCEL(EINVAL);
|
||||
flags |= B_ABSOLUTE_REAL_TIME_TIMEOUT;
|
||||
} else {
|
||||
timeout = 0;
|
||||
flags |= B_RELATIVE_TIMEOUT;
|
||||
}
|
||||
|
||||
return __pthread_join(thread, _value, flags, timeout);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - Haiku thread API bridge
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user