mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-28 00:02:28 +00:00
Make futexes cancellable by pthreads
This commit is contained in:
parent
2278327eba
commit
022536cab6
101 changed files with 627 additions and 391 deletions
|
@ -24,8 +24,11 @@
|
|||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "libc/thread/thread.h"
|
||||
#include "libc/thread/thread2.h"
|
||||
|
||||
int pfds[2];
|
||||
pthread_cond_t cv;
|
||||
pthread_mutex_t mu;
|
||||
atomic_bool gotcleanup;
|
||||
char testlib_enable_tmp_setup_teardown;
|
||||
|
||||
|
@ -37,6 +40,49 @@ void OnCleanup(void *arg) {
|
|||
gotcleanup = true;
|
||||
}
|
||||
|
||||
void *CancelSelfWorkerDeferred(void *arg) {
|
||||
char buf[8];
|
||||
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, 0);
|
||||
pthread_cleanup_push(OnCleanup, 0);
|
||||
pthread_cancel(pthread_self());
|
||||
read(pfds[0], buf, sizeof(buf));
|
||||
pthread_cleanup_pop(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
TEST(pthread_cancel, self_deferred_waitsForCancellationPoint) {
|
||||
void *rc;
|
||||
pthread_t th;
|
||||
ASSERT_SYS(0, 0, pipe(pfds));
|
||||
ASSERT_EQ(0, pthread_create(&th, 0, CancelSelfWorkerDeferred, 0));
|
||||
ASSERT_EQ(0, pthread_join(th, &rc));
|
||||
ASSERT_EQ(PTHREAD_CANCELED, rc);
|
||||
ASSERT_TRUE(gotcleanup);
|
||||
ASSERT_SYS(0, 0, close(pfds[1]));
|
||||
ASSERT_SYS(0, 0, close(pfds[0]));
|
||||
}
|
||||
|
||||
void *CancelSelfWorkerAsync(void *arg) {
|
||||
char buf[8];
|
||||
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
|
||||
pthread_cleanup_push(OnCleanup, 0);
|
||||
pthread_cancel(pthread_self());
|
||||
pthread_cleanup_pop(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
TEST(pthread_cancel, self_asynchronous_takesImmediateEffect) {
|
||||
void *rc;
|
||||
pthread_t th;
|
||||
ASSERT_SYS(0, 0, pipe(pfds));
|
||||
ASSERT_EQ(0, pthread_create(&th, 0, CancelSelfWorkerAsync, 0));
|
||||
ASSERT_EQ(0, pthread_join(th, &rc));
|
||||
ASSERT_EQ(PTHREAD_CANCELED, rc);
|
||||
ASSERT_TRUE(gotcleanup);
|
||||
ASSERT_SYS(0, 0, close(pfds[1]));
|
||||
ASSERT_SYS(0, 0, close(pfds[0]));
|
||||
}
|
||||
|
||||
void *Worker(void *arg) {
|
||||
int n;
|
||||
char buf[8];
|
||||
|
@ -74,7 +120,6 @@ TEST(pthread_cancel, synchronous_delayed) {
|
|||
}
|
||||
|
||||
void *DisabledWorker(void *arg) {
|
||||
int n;
|
||||
char buf[8];
|
||||
pthread_setcancelstate(PTHREAD_CANCEL_MASKED, 0);
|
||||
pthread_cleanup_push(OnCleanup, 0);
|
||||
|
@ -109,3 +154,61 @@ TEST(pthread_cancel, masked_delayed) {
|
|||
ASSERT_SYS(0, 0, close(pfds[1]));
|
||||
ASSERT_SYS(0, 0, close(pfds[0]));
|
||||
}
|
||||
|
||||
void *CondWaitMaskedWorker(void *arg) {
|
||||
pthread_setcancelstate(PTHREAD_CANCEL_MASKED, 0);
|
||||
ASSERT_EQ(0, pthread_mutex_lock(&mu));
|
||||
ASSERT_EQ(ECANCELED, pthread_cond_timedwait(&cv, &mu, 0));
|
||||
ASSERT_EQ(0, pthread_mutex_unlock(&mu));
|
||||
return 0;
|
||||
}
|
||||
|
||||
TEST(pthread_cancel, condMaskedWait) {
|
||||
void *rc;
|
||||
pthread_t th;
|
||||
ASSERT_EQ(0, pthread_create(&th, 0, CondWaitMaskedWorker, 0));
|
||||
ASSERT_EQ(0, pthread_cancel(th));
|
||||
ASSERT_EQ(0, pthread_join(th, &rc));
|
||||
ASSERT_EQ(0, rc);
|
||||
}
|
||||
|
||||
TEST(pthread_cancel, condWaitMaskedDelayed) {
|
||||
void *rc;
|
||||
pthread_t th;
|
||||
ASSERT_EQ(0, pthread_create(&th, 0, CondWaitMaskedWorker, 0));
|
||||
usleep(10);
|
||||
ASSERT_EQ(0, pthread_cancel(th));
|
||||
ASSERT_EQ(0, pthread_join(th, &rc));
|
||||
ASSERT_EQ(0, rc);
|
||||
}
|
||||
|
||||
void *CondWaitDeferredWorker(void *arg) {
|
||||
pthread_setcancelstate(PTHREAD_CANCEL_DEFERRED, 0);
|
||||
ASSERT_EQ(0, pthread_mutex_lock(&mu));
|
||||
ASSERT_EQ(ECANCELED, pthread_cond_timedwait(&cv, &mu, 0));
|
||||
ASSERT_EQ(0, pthread_mutex_unlock(&mu));
|
||||
return 0;
|
||||
}
|
||||
|
||||
TEST(pthread_cancel, condDeferredWait) {
|
||||
void *rc;
|
||||
pthread_t th;
|
||||
ASSERT_EQ(0, pthread_create(&th, 0, CondWaitDeferredWorker, 0));
|
||||
ASSERT_EQ(0, pthread_cancel(th));
|
||||
ASSERT_EQ(0, pthread_join(th, &rc));
|
||||
ASSERT_EQ(PTHREAD_CANCELED, rc);
|
||||
ASSERT_EQ(0, pthread_mutex_trylock(&mu));
|
||||
ASSERT_EQ(0, pthread_mutex_unlock(&mu));
|
||||
}
|
||||
|
||||
TEST(pthread_cancel, condDeferredWaitDelayed) {
|
||||
void *rc;
|
||||
pthread_t th;
|
||||
ASSERT_EQ(0, pthread_create(&th, 0, CondWaitDeferredWorker, 0));
|
||||
usleep(10);
|
||||
ASSERT_EQ(0, pthread_cancel(th));
|
||||
ASSERT_EQ(0, pthread_join(th, &rc));
|
||||
ASSERT_EQ(PTHREAD_CANCELED, rc);
|
||||
ASSERT_EQ(0, pthread_mutex_trylock(&mu));
|
||||
ASSERT_EQ(0, pthread_mutex_unlock(&mu));
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue