#ifndef TESTS_LIB_LIBPTHREAD_CANCELPOINT_H
#define TESTS_LIB_LIBPTHREAD_CANCELPOINT_H
#include <pthread.h>
#include <stdbool.h>
#include <stddef.h>
#include "h_macros.h"
extern pthread_barrier_t bar;
extern bool cleanup_done;
#if 0
atomic_bool cancelpointreadydone;
#endif
static void
cleanup(void *cookie)
{
bool *cleanup_donep = cookie;
*cleanup_donep = true;
}
static void
cancelpointready(void)
{
(void)pthread_barrier_wait(&bar);
RL(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL));
#if 0
atomic_store_release(&cancelpointreadydone, true);
#endif
}
static void *
thread_cancelpoint(void *cookie)
{
void (*cancelpoint)(void) = cookie;
RL(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL));
(void)pthread_barrier_wait(&bar);
pthread_cleanup_push(&cleanup, &cleanup_done);
(*cancelpoint)();
pthread_cleanup_pop(0);
return NULL;
}
static void
test_cancelpoint_before(void (*cancelpoint)(void))
{
pthread_t t;
void *result;
RZ(pthread_barrier_init(&bar, NULL, 2));
RZ(pthread_create(&t, NULL, &thread_cancelpoint, cancelpoint));
(void)pthread_barrier_wait(&bar);
fprintf(stderr, "cancel\n");
RZ(pthread_cancel(t));
(void)pthread_barrier_wait(&bar);
alarm(1);
RZ(pthread_join(t, &result));
ATF_CHECK_MSG(result == PTHREAD_CANCELED,
"result=%p PTHREAD_CANCELED=%p", result, PTHREAD_CANCELED);
ATF_CHECK(cleanup_done);
}
#if 0
static void
test_cancelpoint_wakeup(void (*cancelpoint)(void))
{
pthread_t t;
RZ(pthread_barrier_init(&bar, NULL, 2));
RZ(pthread_create(&t, NULL, &cancelpoint_thread, cancelpoint));
(void)pthread_barrier_wait(&bar);
while (!atomic_load_acquire(&cancelpointreadydone))
continue;
while (!pthread_sleeping(t))
continue;
RZ(pthread_cancel(t));
}
#endif
#define TEST_CANCELPOINT(CANCELPOINT, XFAIL) \
ATF_TC(CANCELPOINT); \
ATF_TC_HEAD(CANCELPOINT, tc) \
{ \
atf_tc_set_md_var(tc, "descr", "Test cancellation point: " \
#CANCELPOINT); \
} \
ATF_TC_BODY(CANCELPOINT, tc) \
{ \
XFAIL; \
test_cancelpoint_before(&CANCELPOINT); \
}
#define ADD_TEST_CANCELPOINT(CANCELPOINT) \
ATF_TP_ADD_TC(tp, CANCELPOINT)
#endif