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_getname_np(pthread_t thread, char* buffer, size_t length);
|
||||||
extern int pthread_setname_np(pthread_t thread, const char* name);
|
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_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);
|
extern int pthread_getaffinity_np(pthread_t thread, size_t cpusetsize, cpuset_t* mask);
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
#include <libroot_private.h>
|
#include <libroot_private.h>
|
||||||
#include <syscalls.h>
|
#include <syscalls.h>
|
||||||
#include <thread_defs.h>
|
#include <thread_defs.h>
|
||||||
|
#include <time_private.h>
|
||||||
#include <tls.h>
|
#include <tls.h>
|
||||||
|
|
||||||
#include <user_thread.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
|
// #pragma mark - public API
|
||||||
|
|
||||||
|
|
||||||
@@ -199,22 +226,7 @@ pthread_equal(pthread_t t1, pthread_t t2)
|
|||||||
int
|
int
|
||||||
pthread_join(pthread_t thread, void** _value)
|
pthread_join(pthread_t thread, void** _value)
|
||||||
{
|
{
|
||||||
status_t dummy;
|
return __pthread_join(thread, _value);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -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
|
// #pragma mark - Haiku thread API bridge
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user