Commit f2728fe8 authored by Heiher's avatar Heiher Committed by Linus Torvalds

selftests: add epoll selftests

This adds the promised selftest for epoll.  It will verify the wakeups
of epoll.  Including leaf and nested mode, epoll_wait() and poll() and
multi-threads.

Link: http://lkml.kernel.org/r/20191009121518.4027-1-r@hev.ccSigned-off-by: default avatarhev <r@hev.cc>
Reviewed-by: default avatarRoman Penyaev <rpenyaev@suse.de>
Cc: Jason Baron <jbaron@akamai.com>
Cc: Shuah Khan <shuah@kernel.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 339ddb53
...@@ -13,6 +13,7 @@ TARGETS += efivarfs ...@@ -13,6 +13,7 @@ TARGETS += efivarfs
TARGETS += exec TARGETS += exec
TARGETS += filesystems TARGETS += filesystems
TARGETS += filesystems/binderfs TARGETS += filesystems/binderfs
TARGETS += filesystems/epoll
TARGETS += firmware TARGETS += firmware
TARGETS += ftrace TARGETS += ftrace
TARGETS += futex TARGETS += futex
......
# SPDX-License-Identifier: GPL-2.0
CFLAGS += -I../../../../../usr/include/
LDFLAGS += -lpthread
TEST_GEN_PROGS := epoll_wakeup_test
include ../../lib.mk
// SPDX-License-Identifier: GPL-2.0
#define _GNU_SOURCE
#include <poll.h>
#include <unistd.h>
#include <signal.h>
#include <pthread.h>
#include <sys/epoll.h>
#include <sys/socket.h>
#include "../../kselftest_harness.h"
struct epoll_mtcontext
{
int efd[3];
int sfd[4];
int count;
pthread_t main;
pthread_t waiter;
};
static void signal_handler(int signum)
{
}
static void kill_timeout(struct epoll_mtcontext *ctx)
{
usleep(1000000);
pthread_kill(ctx->main, SIGUSR1);
pthread_kill(ctx->waiter, SIGUSR1);
}
static void *waiter_entry1a(void *data)
{
struct epoll_event e;
struct epoll_mtcontext *ctx = data;
if (epoll_wait(ctx->efd[0], &e, 1, -1) > 0)
__sync_fetch_and_add(&ctx->count, 1);
return NULL;
}
static void *waiter_entry1ap(void *data)
{
struct pollfd pfd;
struct epoll_event e;
struct epoll_mtcontext *ctx = data;
pfd.fd = ctx->efd[0];
pfd.events = POLLIN;
if (poll(&pfd, 1, -1) > 0) {
if (epoll_wait(ctx->efd[0], &e, 1, 0) > 0)
__sync_fetch_and_add(&ctx->count, 1);
}
return NULL;
}
static void *waiter_entry1o(void *data)
{
struct epoll_event e;
struct epoll_mtcontext *ctx = data;
if (epoll_wait(ctx->efd[0], &e, 1, -1) > 0)
__sync_fetch_and_or(&ctx->count, 1);
return NULL;
}
static void *waiter_entry1op(void *data)
{
struct pollfd pfd;
struct epoll_event e;
struct epoll_mtcontext *ctx = data;
pfd.fd = ctx->efd[0];
pfd.events = POLLIN;
if (poll(&pfd, 1, -1) > 0) {
if (epoll_wait(ctx->efd[0], &e, 1, 0) > 0)
__sync_fetch_and_or(&ctx->count, 1);
}
return NULL;
}
static void *waiter_entry2a(void *data)
{
struct epoll_event events[2];
struct epoll_mtcontext *ctx = data;
if (epoll_wait(ctx->efd[0], events, 2, -1) > 0)
__sync_fetch_and_add(&ctx->count, 1);
return NULL;
}
static void *waiter_entry2ap(void *data)
{
struct pollfd pfd;
struct epoll_event events[2];
struct epoll_mtcontext *ctx = data;
pfd.fd = ctx->efd[0];
pfd.events = POLLIN;
if (poll(&pfd, 1, -1) > 0) {
if (epoll_wait(ctx->efd[0], events, 2, 0) > 0)
__sync_fetch_and_add(&ctx->count, 1);
}
return NULL;
}
static void *emitter_entry1(void *data)
{
struct epoll_mtcontext *ctx = data;
usleep(100000);
write(ctx->sfd[1], "w", 1);
kill_timeout(ctx);
return NULL;
}
static void *emitter_entry2(void *data)
{
struct epoll_mtcontext *ctx = data;
usleep(100000);
write(ctx->sfd[1], "w", 1);
write(ctx->sfd[3], "w", 1);
kill_timeout(ctx);
return NULL;
}
/*
* t0
* | (ew)
* e0
* | (lt)
* s0
*/
TEST(epoll1)
{
int efd;
int sfd[2];
struct epoll_event e;
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, sfd), 0);
efd = epoll_create(1);
ASSERT_GE(efd, 0);
e.events = EPOLLIN;
ASSERT_EQ(epoll_ctl(efd, EPOLL_CTL_ADD, sfd[0], &e), 0);
ASSERT_EQ(write(sfd[1], "w", 1), 1);
EXPECT_EQ(epoll_wait(efd, &e, 1, 0), 1);
EXPECT_EQ(epoll_wait(efd, &e, 1, 0), 1);
close(efd);
close(sfd[0]);
close(sfd[1]);
}
/*
* t0
* | (ew)
* e0
* | (et)
* s0
*/
TEST(epoll2)
{
int efd;
int sfd[2];
struct epoll_event e;
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, sfd), 0);
efd = epoll_create(1);
ASSERT_GE(efd, 0);
e.events = EPOLLIN | EPOLLET;
ASSERT_EQ(epoll_ctl(efd, EPOLL_CTL_ADD, sfd[0], &e), 0);
ASSERT_EQ(write(sfd[1], "w", 1), 1);
EXPECT_EQ(epoll_wait(efd, &e, 1, 0), 1);
EXPECT_EQ(epoll_wait(efd, &e, 1, 0), 0);
close(efd);
close(sfd[0]);
close(sfd[1]);
}
/*
* t0
* | (ew)
* e0
* (lt) / \ (lt)
* s0 s2
*/
TEST(epoll3)
{
int efd;
int sfd[4];
struct epoll_event events[2];
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &sfd[0]), 0);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &sfd[2]), 0);
efd = epoll_create(1);
ASSERT_GE(efd, 0);
events[0].events = EPOLLIN;
ASSERT_EQ(epoll_ctl(efd, EPOLL_CTL_ADD, sfd[0], events), 0);
events[0].events = EPOLLIN;
ASSERT_EQ(epoll_ctl(efd, EPOLL_CTL_ADD, sfd[2], events), 0);
ASSERT_EQ(write(sfd[1], "w", 1), 1);
ASSERT_EQ(write(sfd[3], "w", 1), 1);
EXPECT_EQ(epoll_wait(efd, events, 2, 0), 2);
EXPECT_EQ(epoll_wait(efd, events, 2, 0), 2);
close(efd);
close(sfd[0]);
close(sfd[1]);
close(sfd[2]);
close(sfd[3]);
}
/*
* t0
* | (ew)
* e0
* (et) / \ (et)
* s0 s2
*/
TEST(epoll4)
{
int efd;
int sfd[4];
struct epoll_event events[2];
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &sfd[0]), 0);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &sfd[2]), 0);
efd = epoll_create(1);
ASSERT_GE(efd, 0);
events[0].events = EPOLLIN | EPOLLET;
ASSERT_EQ(epoll_ctl(efd, EPOLL_CTL_ADD, sfd[0], events), 0);
events[0].events = EPOLLIN | EPOLLET;
ASSERT_EQ(epoll_ctl(efd, EPOLL_CTL_ADD, sfd[2], events), 0);
ASSERT_EQ(write(sfd[1], "w", 1), 1);
ASSERT_EQ(write(sfd[3], "w", 1), 1);
EXPECT_EQ(epoll_wait(efd, events, 2, 0), 2);
EXPECT_EQ(epoll_wait(efd, events, 2, 0), 0);
close(efd);
close(sfd[0]);
close(sfd[1]);
close(sfd[2]);
close(sfd[3]);
}
/*
* t0
* | (p)
* e0
* | (lt)
* s0
*/
TEST(epoll5)
{
int efd;
int sfd[2];
struct pollfd pfd;
struct epoll_event e;
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &sfd[0]), 0);
efd = epoll_create(1);
ASSERT_GE(efd, 0);
e.events = EPOLLIN;
ASSERT_EQ(epoll_ctl(efd, EPOLL_CTL_ADD, sfd[0], &e), 0);
ASSERT_EQ(write(sfd[1], "w", 1), 1);
pfd.fd = efd;
pfd.events = POLLIN;
ASSERT_EQ(poll(&pfd, 1, 0), 1);
ASSERT_EQ(epoll_wait(efd, &e, 1, 0), 1);
pfd.fd = efd;
pfd.events = POLLIN;
ASSERT_EQ(poll(&pfd, 1, 0), 1);
ASSERT_EQ(epoll_wait(efd, &e, 1, 0), 1);
close(efd);
close(sfd[0]);
close(sfd[1]);
}
/*
* t0
* | (p)
* e0
* | (et)
* s0
*/
TEST(epoll6)
{
int efd;
int sfd[2];
struct pollfd pfd;
struct epoll_event e;
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &sfd[0]), 0);
efd = epoll_create(1);
ASSERT_GE(efd, 0);
e.events = EPOLLIN | EPOLLET;
ASSERT_EQ(epoll_ctl(efd, EPOLL_CTL_ADD, sfd[0], &e), 0);
ASSERT_EQ(write(sfd[1], "w", 1), 1);
pfd.fd = efd;
pfd.events = POLLIN;
ASSERT_EQ(poll(&pfd, 1, 0), 1);
ASSERT_EQ(epoll_wait(efd, &e, 1, 0), 1);
pfd.fd = efd;
pfd.events = POLLIN;
ASSERT_EQ(poll(&pfd, 1, 0), 0);
ASSERT_EQ(epoll_wait(efd, &e, 1, 0), 0);
close(efd);
close(sfd[0]);
close(sfd[1]);
}
/*
* t0
* | (p)
* e0
* (lt) / \ (lt)
* s0 s2
*/
TEST(epoll7)
{
int efd;
int sfd[4];
struct pollfd pfd;
struct epoll_event events[2];
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &sfd[0]), 0);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &sfd[2]), 0);
efd = epoll_create(1);
ASSERT_GE(efd, 0);
events[0].events = EPOLLIN;
ASSERT_EQ(epoll_ctl(efd, EPOLL_CTL_ADD, sfd[0], events), 0);
events[0].events = EPOLLIN;
ASSERT_EQ(epoll_ctl(efd, EPOLL_CTL_ADD, sfd[2], events), 0);
ASSERT_EQ(write(sfd[1], "w", 1), 1);
ASSERT_EQ(write(sfd[3], "w", 1), 1);
pfd.fd = efd;
pfd.events = POLLIN;
EXPECT_EQ(poll(&pfd, 1, 0), 1);
EXPECT_EQ(epoll_wait(efd, events, 2, 0), 2);
pfd.fd = efd;
pfd.events = POLLIN;
EXPECT_EQ(poll(&pfd, 1, 0), 1);
EXPECT_EQ(epoll_wait(efd, events, 2, 0), 2);
close(efd);
close(sfd[0]);
close(sfd[1]);
close(sfd[2]);
close(sfd[3]);
}
/*
* t0
* | (p)
* e0
* (et) / \ (et)
* s0 s2
*/
TEST(epoll8)
{
int efd;
int sfd[4];
struct pollfd pfd;
struct epoll_event events[2];
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &sfd[0]), 0);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &sfd[2]), 0);
efd = epoll_create(1);
ASSERT_GE(efd, 0);
events[0].events = EPOLLIN | EPOLLET;
ASSERT_EQ(epoll_ctl(efd, EPOLL_CTL_ADD, sfd[0], events), 0);
events[0].events = EPOLLIN | EPOLLET;
ASSERT_EQ(epoll_ctl(efd, EPOLL_CTL_ADD, sfd[2], events), 0);
ASSERT_EQ(write(sfd[1], "w", 1), 1);
ASSERT_EQ(write(sfd[3], "w", 1), 1);
pfd.fd = efd;
pfd.events = POLLIN;
EXPECT_EQ(poll(&pfd, 1, 0), 1);
EXPECT_EQ(epoll_wait(efd, events, 2, 0), 2);
pfd.fd = efd;
pfd.events = POLLIN;
EXPECT_EQ(poll(&pfd, 1, 0), 0);
EXPECT_EQ(epoll_wait(efd, events, 2, 0), 0);
close(efd);
close(sfd[0]);
close(sfd[1]);
close(sfd[2]);
close(sfd[3]);
}
/*
* t0 t1
* (ew) \ / (ew)
* e0
* | (lt)
* s0
*/
TEST(epoll9)
{
pthread_t emitter;
struct epoll_event e;
struct epoll_mtcontext ctx = { 0 };
signal(SIGUSR1, signal_handler);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0);
ctx.efd[0] = epoll_create(1);
ASSERT_GE(ctx.efd[0], 0);
e.events = EPOLLIN;
ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0);
ctx.main = pthread_self();
ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1a, &ctx), 0);
ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0);
if (epoll_wait(ctx.efd[0], &e, 1, -1) > 0)
__sync_fetch_and_add(&ctx.count, 1);
ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0);
EXPECT_EQ(ctx.count, 2);
if (pthread_tryjoin_np(emitter, NULL) < 0) {
pthread_kill(emitter, SIGUSR1);
pthread_join(emitter, NULL);
}
close(ctx.efd[0]);
close(ctx.sfd[0]);
close(ctx.sfd[1]);
}
/*
* t0 t1
* (ew) \ / (ew)
* e0
* | (et)
* s0
*/
TEST(epoll10)
{
pthread_t emitter;
struct epoll_event e;
struct epoll_mtcontext ctx = { 0 };
signal(SIGUSR1, signal_handler);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0);
ctx.efd[0] = epoll_create(1);
ASSERT_GE(ctx.efd[0], 0);
e.events = EPOLLIN | EPOLLET;
ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0);
ctx.main = pthread_self();
ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1a, &ctx), 0);
ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0);
if (epoll_wait(ctx.efd[0], &e, 1, -1) > 0)
__sync_fetch_and_add(&ctx.count, 1);
ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0);
EXPECT_EQ(ctx.count, 1);
if (pthread_tryjoin_np(emitter, NULL) < 0) {
pthread_kill(emitter, SIGUSR1);
pthread_join(emitter, NULL);
}
close(ctx.efd[0]);
close(ctx.sfd[0]);
close(ctx.sfd[1]);
}
/*
* t0 t1
* (ew) \ / (ew)
* e0
* (lt) / \ (lt)
* s0 s2
*/
TEST(epoll11)
{
pthread_t emitter;
struct epoll_event events[2];
struct epoll_mtcontext ctx = { 0 };
signal(SIGUSR1, signal_handler);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &ctx.sfd[0]), 0);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &ctx.sfd[2]), 0);
ctx.efd[0] = epoll_create(1);
ASSERT_GE(ctx.efd[0], 0);
events[0].events = EPOLLIN;
ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.sfd[0], events), 0);
events[0].events = EPOLLIN;
ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.sfd[2], events), 0);
ctx.main = pthread_self();
ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry2a, &ctx), 0);
ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry2, &ctx), 0);
if (epoll_wait(ctx.efd[0], events, 2, -1) > 0)
__sync_fetch_and_add(&ctx.count, 1);
ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0);
EXPECT_EQ(ctx.count, 2);
if (pthread_tryjoin_np(emitter, NULL) < 0) {
pthread_kill(emitter, SIGUSR1);
pthread_join(emitter, NULL);
}
close(ctx.efd[0]);
close(ctx.sfd[0]);
close(ctx.sfd[1]);
close(ctx.sfd[2]);
close(ctx.sfd[3]);
}
/*
* t0 t1
* (ew) \ / (ew)
* e0
* (et) / \ (et)
* s0 s2
*/
TEST(epoll12)
{
pthread_t emitter;
struct epoll_event events[2];
struct epoll_mtcontext ctx = { 0 };
signal(SIGUSR1, signal_handler);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &ctx.sfd[0]), 0);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &ctx.sfd[2]), 0);
ctx.efd[0] = epoll_create(1);
ASSERT_GE(ctx.efd[0], 0);
events[0].events = EPOLLIN | EPOLLET;
ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.sfd[0], events), 0);
events[0].events = EPOLLIN | EPOLLET;
ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.sfd[2], events), 0);
ctx.main = pthread_self();
ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1a, &ctx), 0);
ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry2, &ctx), 0);
if (epoll_wait(ctx.efd[0], events, 1, -1) > 0)
__sync_fetch_and_add(&ctx.count, 1);
ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0);
EXPECT_EQ(ctx.count, 2);
if (pthread_tryjoin_np(emitter, NULL) < 0) {
pthread_kill(emitter, SIGUSR1);
pthread_join(emitter, NULL);
}
close(ctx.efd[0]);
close(ctx.sfd[0]);
close(ctx.sfd[1]);
close(ctx.sfd[2]);
close(ctx.sfd[3]);
}
/*
* t0 t1
* (ew) \ / (p)
* e0
* | (lt)
* s0
*/
TEST(epoll13)
{
pthread_t emitter;
struct epoll_event e;
struct epoll_mtcontext ctx = { 0 };
signal(SIGUSR1, signal_handler);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0);
ctx.efd[0] = epoll_create(1);
ASSERT_GE(ctx.efd[0], 0);
e.events = EPOLLIN;
ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0);
ctx.main = pthread_self();
ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1ap, &ctx), 0);
ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0);
if (epoll_wait(ctx.efd[0], &e, 1, -1) > 0)
__sync_fetch_and_add(&ctx.count, 1);
ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0);
EXPECT_EQ(ctx.count, 2);
if (pthread_tryjoin_np(emitter, NULL) < 0) {
pthread_kill(emitter, SIGUSR1);
pthread_join(emitter, NULL);
}
close(ctx.efd[0]);
close(ctx.sfd[0]);
close(ctx.sfd[1]);
}
/*
* t0 t1
* (ew) \ / (p)
* e0
* | (et)
* s0
*/
TEST(epoll14)
{
pthread_t emitter;
struct epoll_event e;
struct epoll_mtcontext ctx = { 0 };
signal(SIGUSR1, signal_handler);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0);
ctx.efd[0] = epoll_create(1);
ASSERT_GE(ctx.efd[0], 0);
e.events = EPOLLIN | EPOLLET;
ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0);
ctx.main = pthread_self();
ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1ap, &ctx), 0);
ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0);
if (epoll_wait(ctx.efd[0], &e, 1, -1) > 0)
__sync_fetch_and_add(&ctx.count, 1);
ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0);
EXPECT_EQ(ctx.count, 1);
if (pthread_tryjoin_np(emitter, NULL) < 0) {
pthread_kill(emitter, SIGUSR1);
pthread_join(emitter, NULL);
}
close(ctx.efd[0]);
close(ctx.sfd[0]);
close(ctx.sfd[1]);
}
/*
* t0 t1
* (ew) \ / (p)
* e0
* (lt) / \ (lt)
* s0 s2
*/
TEST(epoll15)
{
pthread_t emitter;
struct epoll_event events[2];
struct epoll_mtcontext ctx = { 0 };
signal(SIGUSR1, signal_handler);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &ctx.sfd[0]), 0);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &ctx.sfd[2]), 0);
ctx.efd[0] = epoll_create(1);
ASSERT_GE(ctx.efd[0], 0);
events[0].events = EPOLLIN;
ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.sfd[0], events), 0);
events[0].events = EPOLLIN;
ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.sfd[2], events), 0);
ctx.main = pthread_self();
ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry2ap, &ctx), 0);
ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry2, &ctx), 0);
if (epoll_wait(ctx.efd[0], events, 2, -1) > 0)
__sync_fetch_and_add(&ctx.count, 1);
ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0);
EXPECT_EQ(ctx.count, 2);
if (pthread_tryjoin_np(emitter, NULL) < 0) {
pthread_kill(emitter, SIGUSR1);
pthread_join(emitter, NULL);
}
close(ctx.efd[0]);
close(ctx.sfd[0]);
close(ctx.sfd[1]);
close(ctx.sfd[2]);
close(ctx.sfd[3]);
}
/*
* t0 t1
* (ew) \ / (p)
* e0
* (et) / \ (et)
* s0 s2
*/
TEST(epoll16)
{
pthread_t emitter;
struct epoll_event events[2];
struct epoll_mtcontext ctx = { 0 };
signal(SIGUSR1, signal_handler);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &ctx.sfd[0]), 0);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &ctx.sfd[2]), 0);
ctx.efd[0] = epoll_create(1);
ASSERT_GE(ctx.efd[0], 0);
events[0].events = EPOLLIN | EPOLLET;
ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.sfd[0], events), 0);
events[0].events = EPOLLIN | EPOLLET;
ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.sfd[2], events), 0);
ctx.main = pthread_self();
ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1ap, &ctx), 0);
ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry2, &ctx), 0);
if (epoll_wait(ctx.efd[0], events, 1, -1) > 0)
__sync_fetch_and_add(&ctx.count, 1);
ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0);
EXPECT_EQ(ctx.count, 2);
if (pthread_tryjoin_np(emitter, NULL) < 0) {
pthread_kill(emitter, SIGUSR1);
pthread_join(emitter, NULL);
}
close(ctx.efd[0]);
close(ctx.sfd[0]);
close(ctx.sfd[1]);
close(ctx.sfd[2]);
close(ctx.sfd[3]);
}
/*
* t0
* | (ew)
* e0
* | (lt)
* e1
* | (lt)
* s0
*/
TEST(epoll17)
{
int efd[2];
int sfd[2];
struct epoll_event e;
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, sfd), 0);
efd[0] = epoll_create(1);
ASSERT_GE(efd[0], 0);
efd[1] = epoll_create(1);
ASSERT_GE(efd[1], 0);
e.events = EPOLLIN;
ASSERT_EQ(epoll_ctl(efd[1], EPOLL_CTL_ADD, sfd[0], &e), 0);
e.events = EPOLLIN;
ASSERT_EQ(epoll_ctl(efd[0], EPOLL_CTL_ADD, efd[1], &e), 0);
ASSERT_EQ(write(sfd[1], "w", 1), 1);
EXPECT_EQ(epoll_wait(efd[0], &e, 1, 0), 1);
EXPECT_EQ(epoll_wait(efd[0], &e, 1, 0), 1);
close(efd[0]);
close(efd[1]);
close(sfd[0]);
close(sfd[1]);
}
/*
* t0
* | (ew)
* e0
* | (lt)
* e1
* | (et)
* s0
*/
TEST(epoll18)
{
int efd[2];
int sfd[2];
struct epoll_event e;
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, sfd), 0);
efd[0] = epoll_create(1);
ASSERT_GE(efd[0], 0);
efd[1] = epoll_create(1);
ASSERT_GE(efd[1], 0);
e.events = EPOLLIN | EPOLLET;
ASSERT_EQ(epoll_ctl(efd[1], EPOLL_CTL_ADD, sfd[0], &e), 0);
e.events = EPOLLIN;
ASSERT_EQ(epoll_ctl(efd[0], EPOLL_CTL_ADD, efd[1], &e), 0);
ASSERT_EQ(write(sfd[1], "w", 1), 1);
EXPECT_EQ(epoll_wait(efd[0], &e, 1, 0), 1);
EXPECT_EQ(epoll_wait(efd[0], &e, 1, 0), 1);
close(efd[0]);
close(efd[1]);
close(sfd[0]);
close(sfd[1]);
}
/*
* t0
* | (ew)
* e0
* | (et)
* e1
* | (lt)
* s0
*/
TEST(epoll19)
{
int efd[2];
int sfd[2];
struct epoll_event e;
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, sfd), 0);
efd[0] = epoll_create(1);
ASSERT_GE(efd[0], 0);
efd[1] = epoll_create(1);
ASSERT_GE(efd[1], 0);
e.events = EPOLLIN;
ASSERT_EQ(epoll_ctl(efd[1], EPOLL_CTL_ADD, sfd[0], &e), 0);
e.events = EPOLLIN | EPOLLET;
ASSERT_EQ(epoll_ctl(efd[0], EPOLL_CTL_ADD, efd[1], &e), 0);
ASSERT_EQ(write(sfd[1], "w", 1), 1);
EXPECT_EQ(epoll_wait(efd[0], &e, 1, 0), 1);
EXPECT_EQ(epoll_wait(efd[0], &e, 1, 0), 0);
close(efd[0]);
close(efd[1]);
close(sfd[0]);
close(sfd[1]);
}
/*
* t0
* | (ew)
* e0
* | (et)
* e1
* | (et)
* s0
*/
TEST(epoll20)
{
int efd[2];
int sfd[2];
struct epoll_event e;
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, sfd), 0);
efd[0] = epoll_create(1);
ASSERT_GE(efd[0], 0);
efd[1] = epoll_create(1);
ASSERT_GE(efd[1], 0);
e.events = EPOLLIN | EPOLLET;
ASSERT_EQ(epoll_ctl(efd[1], EPOLL_CTL_ADD, sfd[0], &e), 0);
e.events = EPOLLIN | EPOLLET;
ASSERT_EQ(epoll_ctl(efd[0], EPOLL_CTL_ADD, efd[1], &e), 0);
ASSERT_EQ(write(sfd[1], "w", 1), 1);
EXPECT_EQ(epoll_wait(efd[0], &e, 1, 0), 1);
EXPECT_EQ(epoll_wait(efd[0], &e, 1, 0), 0);
close(efd[0]);
close(efd[1]);
close(sfd[0]);
close(sfd[1]);
}
/*
* t0
* | (p)
* e0
* | (lt)
* e1
* | (lt)
* s0
*/
TEST(epoll21)
{
int efd[2];
int sfd[2];
struct pollfd pfd;
struct epoll_event e;
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, sfd), 0);
efd[0] = epoll_create(1);
ASSERT_GE(efd[0], 0);
efd[1] = epoll_create(1);
ASSERT_GE(efd[1], 0);
e.events = EPOLLIN;
ASSERT_EQ(epoll_ctl(efd[1], EPOLL_CTL_ADD, sfd[0], &e), 0);
e.events = EPOLLIN;
ASSERT_EQ(epoll_ctl(efd[0], EPOLL_CTL_ADD, efd[1], &e), 0);
ASSERT_EQ(write(sfd[1], "w", 1), 1);
pfd.fd = efd[0];
pfd.events = POLLIN;
EXPECT_EQ(poll(&pfd, 1, 0), 1);
EXPECT_EQ(epoll_wait(efd[0], &e, 1, 0), 1);
pfd.fd = efd[0];
pfd.events = POLLIN;
EXPECT_EQ(poll(&pfd, 1, 0), 1);
EXPECT_EQ(epoll_wait(efd[0], &e, 1, 0), 1);
close(efd[0]);
close(efd[1]);
close(sfd[0]);
close(sfd[1]);
}
/*
* t0
* | (p)
* e0
* | (lt)
* e1
* | (et)
* s0
*/
TEST(epoll22)
{
int efd[2];
int sfd[2];
struct pollfd pfd;
struct epoll_event e;
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, sfd), 0);
efd[0] = epoll_create(1);
ASSERT_GE(efd[0], 0);
efd[1] = epoll_create(1);
ASSERT_GE(efd[1], 0);
e.events = EPOLLIN | EPOLLET;
ASSERT_EQ(epoll_ctl(efd[1], EPOLL_CTL_ADD, sfd[0], &e), 0);
e.events = EPOLLIN;
ASSERT_EQ(epoll_ctl(efd[0], EPOLL_CTL_ADD, efd[1], &e), 0);
ASSERT_EQ(write(sfd[1], "w", 1), 1);
pfd.fd = efd[0];
pfd.events = POLLIN;
EXPECT_EQ(poll(&pfd, 1, 0), 1);
EXPECT_EQ(epoll_wait(efd[0], &e, 1, 0), 1);
pfd.fd = efd[0];
pfd.events = POLLIN;
EXPECT_EQ(poll(&pfd, 1, 0), 1);
EXPECT_EQ(epoll_wait(efd[0], &e, 1, 0), 1);
close(efd[0]);
close(efd[1]);
close(sfd[0]);
close(sfd[1]);
}
/*
* t0
* | (p)
* e0
* | (et)
* e1
* | (lt)
* s0
*/
TEST(epoll23)
{
int efd[2];
int sfd[2];
struct pollfd pfd;
struct epoll_event e;
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, sfd), 0);
efd[0] = epoll_create(1);
ASSERT_GE(efd[0], 0);
efd[1] = epoll_create(1);
ASSERT_GE(efd[1], 0);
e.events = EPOLLIN;
ASSERT_EQ(epoll_ctl(efd[1], EPOLL_CTL_ADD, sfd[0], &e), 0);
e.events = EPOLLIN | EPOLLET;
ASSERT_EQ(epoll_ctl(efd[0], EPOLL_CTL_ADD, efd[1], &e), 0);
ASSERT_EQ(write(sfd[1], "w", 1), 1);
pfd.fd = efd[0];
pfd.events = POLLIN;
EXPECT_EQ(poll(&pfd, 1, 0), 1);
EXPECT_EQ(epoll_wait(efd[0], &e, 1, 0), 1);
pfd.fd = efd[0];
pfd.events = POLLIN;
EXPECT_EQ(poll(&pfd, 1, 0), 0);
EXPECT_EQ(epoll_wait(efd[0], &e, 1, 0), 0);
close(efd[0]);
close(efd[1]);
close(sfd[0]);
close(sfd[1]);
}
/*
* t0
* | (p)
* e0
* | (et)
* e1
* | (et)
* s0
*/
TEST(epoll24)
{
int efd[2];
int sfd[2];
struct pollfd pfd;
struct epoll_event e;
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, sfd), 0);
efd[0] = epoll_create(1);
ASSERT_GE(efd[0], 0);
efd[1] = epoll_create(1);
ASSERT_GE(efd[1], 0);
e.events = EPOLLIN | EPOLLET;
ASSERT_EQ(epoll_ctl(efd[1], EPOLL_CTL_ADD, sfd[0], &e), 0);
e.events = EPOLLIN | EPOLLET;
ASSERT_EQ(epoll_ctl(efd[0], EPOLL_CTL_ADD, efd[1], &e), 0);
ASSERT_EQ(write(sfd[1], "w", 1), 1);
pfd.fd = efd[0];
pfd.events = POLLIN;
EXPECT_EQ(poll(&pfd, 1, 0), 1);
EXPECT_EQ(epoll_wait(efd[0], &e, 1, 0), 1);
pfd.fd = efd[0];
pfd.events = POLLIN;
EXPECT_EQ(poll(&pfd, 1, 0), 0);
EXPECT_EQ(epoll_wait(efd[0], &e, 1, 0), 0);
close(efd[0]);
close(efd[1]);
close(sfd[0]);
close(sfd[1]);
}
/*
* t0 t1
* (ew) \ / (ew)
* e0
* | (lt)
* e1
* | (lt)
* s0
*/
TEST(epoll25)
{
pthread_t emitter;
struct epoll_event e;
struct epoll_mtcontext ctx = { 0 };
signal(SIGUSR1, signal_handler);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0);
ctx.efd[0] = epoll_create(1);
ASSERT_GE(ctx.efd[0], 0);
ctx.efd[1] = epoll_create(1);
ASSERT_GE(ctx.efd[1], 0);
e.events = EPOLLIN;
ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0);
e.events = EPOLLIN;
ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0);
ctx.main = pthread_self();
ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1a, &ctx), 0);
ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0);
if (epoll_wait(ctx.efd[0], &e, 1, -1) > 0)
__sync_fetch_and_add(&ctx.count, 1);
ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0);
EXPECT_EQ(ctx.count, 2);
if (pthread_tryjoin_np(emitter, NULL) < 0) {
pthread_kill(emitter, SIGUSR1);
pthread_join(emitter, NULL);
}
close(ctx.efd[0]);
close(ctx.efd[1]);
close(ctx.sfd[0]);
close(ctx.sfd[1]);
}
/*
* t0 t1
* (ew) \ / (ew)
* e0
* | (lt)
* e1
* | (et)
* s0
*/
TEST(epoll26)
{
pthread_t emitter;
struct epoll_event e;
struct epoll_mtcontext ctx = { 0 };
signal(SIGUSR1, signal_handler);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0);
ctx.efd[0] = epoll_create(1);
ASSERT_GE(ctx.efd[0], 0);
ctx.efd[1] = epoll_create(1);
ASSERT_GE(ctx.efd[1], 0);
e.events = EPOLLIN | EPOLLET;
ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0);
e.events = EPOLLIN;
ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0);
ctx.main = pthread_self();
ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1a, &ctx), 0);
ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0);
if (epoll_wait(ctx.efd[0], &e, 1, -1) > 0)
__sync_fetch_and_add(&ctx.count, 1);
ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0);
EXPECT_EQ(ctx.count, 2);
if (pthread_tryjoin_np(emitter, NULL) < 0) {
pthread_kill(emitter, SIGUSR1);
pthread_join(emitter, NULL);
}
close(ctx.efd[0]);
close(ctx.efd[1]);
close(ctx.sfd[0]);
close(ctx.sfd[1]);
}
/*
* t0 t1
* (ew) \ / (ew)
* e0
* | (et)
* e1
* | (lt)
* s0
*/
TEST(epoll27)
{
pthread_t emitter;
struct epoll_event e;
struct epoll_mtcontext ctx = { 0 };
signal(SIGUSR1, signal_handler);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0);
ctx.efd[0] = epoll_create(1);
ASSERT_GE(ctx.efd[0], 0);
ctx.efd[1] = epoll_create(1);
ASSERT_GE(ctx.efd[1], 0);
e.events = EPOLLIN;
ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0);
e.events = EPOLLIN | EPOLLET;
ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0);
ctx.main = pthread_self();
ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1a, &ctx), 0);
ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0);
if (epoll_wait(ctx.efd[0], &e, 1, -1) > 0)
__sync_fetch_and_add(&ctx.count, 1);
ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0);
EXPECT_EQ(ctx.count, 1);
if (pthread_tryjoin_np(emitter, NULL) < 0) {
pthread_kill(emitter, SIGUSR1);
pthread_join(emitter, NULL);
}
close(ctx.efd[0]);
close(ctx.efd[1]);
close(ctx.sfd[0]);
close(ctx.sfd[1]);
}
/*
* t0 t1
* (ew) \ / (ew)
* e0
* | (et)
* e1
* | (et)
* s0
*/
TEST(epoll28)
{
pthread_t emitter;
struct epoll_event e;
struct epoll_mtcontext ctx = { 0 };
signal(SIGUSR1, signal_handler);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0);
ctx.efd[0] = epoll_create(1);
ASSERT_GE(ctx.efd[0], 0);
ctx.efd[1] = epoll_create(1);
ASSERT_GE(ctx.efd[1], 0);
e.events = EPOLLIN | EPOLLET;
ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0);
e.events = EPOLLIN | EPOLLET;
ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0);
ctx.main = pthread_self();
ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1a, &ctx), 0);
ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0);
if (epoll_wait(ctx.efd[0], &e, 1, -1) > 0)
__sync_fetch_and_add(&ctx.count, 1);
ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0);
EXPECT_EQ(ctx.count, 1);
if (pthread_tryjoin_np(emitter, NULL) < 0) {
pthread_kill(emitter, SIGUSR1);
pthread_join(emitter, NULL);
}
close(ctx.efd[0]);
close(ctx.efd[1]);
close(ctx.sfd[0]);
close(ctx.sfd[1]);
}
/*
* t0 t1
* (ew) \ / (p)
* e0
* | (lt)
* e1
* | (lt)
* s0
*/
TEST(epoll29)
{
pthread_t emitter;
struct epoll_event e;
struct epoll_mtcontext ctx = { 0 };
signal(SIGUSR1, signal_handler);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0);
ctx.efd[0] = epoll_create(1);
ASSERT_GE(ctx.efd[0], 0);
ctx.efd[1] = epoll_create(1);
ASSERT_GE(ctx.efd[1], 0);
e.events = EPOLLIN;
ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0);
e.events = EPOLLIN;
ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0);
ctx.main = pthread_self();
ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1ap, &ctx), 0);
ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0);
if (epoll_wait(ctx.efd[0], &e, 1, -1) > 0)
__sync_fetch_and_add(&ctx.count, 1);
ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0);
EXPECT_EQ(ctx.count, 2);
if (pthread_tryjoin_np(emitter, NULL) < 0) {
pthread_kill(emitter, SIGUSR1);
pthread_join(emitter, NULL);
}
close(ctx.efd[0]);
close(ctx.sfd[0]);
close(ctx.sfd[1]);
}
/*
* t0 t1
* (ew) \ / (p)
* e0
* | (lt)
* e1
* | (et)
* s0
*/
TEST(epoll30)
{
pthread_t emitter;
struct epoll_event e;
struct epoll_mtcontext ctx = { 0 };
signal(SIGUSR1, signal_handler);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0);
ctx.efd[0] = epoll_create(1);
ASSERT_GE(ctx.efd[0], 0);
ctx.efd[1] = epoll_create(1);
ASSERT_GE(ctx.efd[1], 0);
e.events = EPOLLIN | EPOLLET;
ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0);
e.events = EPOLLIN;
ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0);
ctx.main = pthread_self();
ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1ap, &ctx), 0);
ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0);
if (epoll_wait(ctx.efd[0], &e, 1, -1) > 0)
__sync_fetch_and_add(&ctx.count, 1);
ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0);
EXPECT_EQ(ctx.count, 2);
if (pthread_tryjoin_np(emitter, NULL) < 0) {
pthread_kill(emitter, SIGUSR1);
pthread_join(emitter, NULL);
}
close(ctx.efd[0]);
close(ctx.sfd[0]);
close(ctx.sfd[1]);
}
/*
* t0 t1
* (ew) \ / (p)
* e0
* | (et)
* e1
* | (lt)
* s0
*/
TEST(epoll31)
{
pthread_t emitter;
struct epoll_event e;
struct epoll_mtcontext ctx = { 0 };
signal(SIGUSR1, signal_handler);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0);
ctx.efd[0] = epoll_create(1);
ASSERT_GE(ctx.efd[0], 0);
ctx.efd[1] = epoll_create(1);
ASSERT_GE(ctx.efd[1], 0);
e.events = EPOLLIN;
ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0);
e.events = EPOLLIN | EPOLLET;
ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0);
ctx.main = pthread_self();
ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1ap, &ctx), 0);
ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0);
if (epoll_wait(ctx.efd[0], &e, 1, -1) > 0)
__sync_fetch_and_add(&ctx.count, 1);
ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0);
EXPECT_EQ(ctx.count, 1);
if (pthread_tryjoin_np(emitter, NULL) < 0) {
pthread_kill(emitter, SIGUSR1);
pthread_join(emitter, NULL);
}
close(ctx.efd[0]);
close(ctx.sfd[0]);
close(ctx.sfd[1]);
}
/*
* t0 t1
* (ew) \ / (p)
* e0
* | (et)
* e1
* | (et)
* s0
*/
TEST(epoll32)
{
pthread_t emitter;
struct epoll_event e;
struct epoll_mtcontext ctx = { 0 };
signal(SIGUSR1, signal_handler);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0);
ctx.efd[0] = epoll_create(1);
ASSERT_GE(ctx.efd[0], 0);
ctx.efd[1] = epoll_create(1);
ASSERT_GE(ctx.efd[1], 0);
e.events = EPOLLIN | EPOLLET;
ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0);
e.events = EPOLLIN | EPOLLET;
ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0);
ctx.main = pthread_self();
ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1ap, &ctx), 0);
ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0);
if (epoll_wait(ctx.efd[0], &e, 1, -1) > 0)
__sync_fetch_and_add(&ctx.count, 1);
ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0);
EXPECT_EQ(ctx.count, 1);
if (pthread_tryjoin_np(emitter, NULL) < 0) {
pthread_kill(emitter, SIGUSR1);
pthread_join(emitter, NULL);
}
close(ctx.efd[0]);
close(ctx.sfd[0]);
close(ctx.sfd[1]);
}
/*
* t0 t1
* (ew) | | (ew)
* | e0
* \ / (lt)
* e1
* | (lt)
* s0
*/
TEST(epoll33)
{
pthread_t emitter;
struct epoll_event e;
struct epoll_mtcontext ctx = { 0 };
signal(SIGUSR1, signal_handler);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0);
ctx.efd[0] = epoll_create(1);
ASSERT_GE(ctx.efd[0], 0);
ctx.efd[1] = epoll_create(1);
ASSERT_GE(ctx.efd[1], 0);
e.events = EPOLLIN;
ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0);
e.events = EPOLLIN;
ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0);
ctx.main = pthread_self();
ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1a, &ctx), 0);
ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0);
if (epoll_wait(ctx.efd[1], &e, 1, -1) > 0)
__sync_fetch_and_add(&ctx.count, 1);
ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0);
EXPECT_EQ(ctx.count, 2);
if (pthread_tryjoin_np(emitter, NULL) < 0) {
pthread_kill(emitter, SIGUSR1);
pthread_join(emitter, NULL);
}
close(ctx.efd[0]);
close(ctx.efd[1]);
close(ctx.sfd[0]);
close(ctx.sfd[1]);
}
/*
* t0 t1
* (ew) | | (ew)
* | e0
* \ / (lt)
* e1
* | (et)
* s0
*/
TEST(epoll34)
{
pthread_t emitter;
struct epoll_event e;
struct epoll_mtcontext ctx = { 0 };
signal(SIGUSR1, signal_handler);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0);
ctx.efd[0] = epoll_create(1);
ASSERT_GE(ctx.efd[0], 0);
ctx.efd[1] = epoll_create(1);
ASSERT_GE(ctx.efd[1], 0);
e.events = EPOLLIN | EPOLLET;
ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0);
e.events = EPOLLIN;
ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0);
ctx.main = pthread_self();
ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1o, &ctx), 0);
ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0);
if (epoll_wait(ctx.efd[1], &e, 1, -1) > 0)
__sync_fetch_and_or(&ctx.count, 2);
ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0);
EXPECT_TRUE((ctx.count == 2) || (ctx.count == 3));
if (pthread_tryjoin_np(emitter, NULL) < 0) {
pthread_kill(emitter, SIGUSR1);
pthread_join(emitter, NULL);
}
close(ctx.efd[0]);
close(ctx.efd[1]);
close(ctx.sfd[0]);
close(ctx.sfd[1]);
}
/*
* t0 t1
* (ew) | | (ew)
* | e0
* \ / (et)
* e1
* | (lt)
* s0
*/
TEST(epoll35)
{
pthread_t emitter;
struct epoll_event e;
struct epoll_mtcontext ctx = { 0 };
signal(SIGUSR1, signal_handler);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0);
ctx.efd[0] = epoll_create(1);
ASSERT_GE(ctx.efd[0], 0);
ctx.efd[1] = epoll_create(1);
ASSERT_GE(ctx.efd[1], 0);
e.events = EPOLLIN;
ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0);
e.events = EPOLLIN | EPOLLET;
ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0);
ctx.main = pthread_self();
ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1a, &ctx), 0);
ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0);
if (epoll_wait(ctx.efd[1], &e, 1, -1) > 0)
__sync_fetch_and_add(&ctx.count, 1);
ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0);
EXPECT_EQ(ctx.count, 2);
if (pthread_tryjoin_np(emitter, NULL) < 0) {
pthread_kill(emitter, SIGUSR1);
pthread_join(emitter, NULL);
}
close(ctx.efd[0]);
close(ctx.efd[1]);
close(ctx.sfd[0]);
close(ctx.sfd[1]);
}
/*
* t0 t1
* (ew) | | (ew)
* | e0
* \ / (et)
* e1
* | (et)
* s0
*/
TEST(epoll36)
{
pthread_t emitter;
struct epoll_event e;
struct epoll_mtcontext ctx = { 0 };
signal(SIGUSR1, signal_handler);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0);
ctx.efd[0] = epoll_create(1);
ASSERT_GE(ctx.efd[0], 0);
ctx.efd[1] = epoll_create(1);
ASSERT_GE(ctx.efd[1], 0);
e.events = EPOLLIN | EPOLLET;
ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0);
e.events = EPOLLIN | EPOLLET;
ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0);
ctx.main = pthread_self();
ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1o, &ctx), 0);
ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0);
if (epoll_wait(ctx.efd[1], &e, 1, -1) > 0)
__sync_fetch_and_or(&ctx.count, 2);
ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0);
EXPECT_TRUE((ctx.count == 2) || (ctx.count == 3));
if (pthread_tryjoin_np(emitter, NULL) < 0) {
pthread_kill(emitter, SIGUSR1);
pthread_join(emitter, NULL);
}
close(ctx.efd[0]);
close(ctx.efd[1]);
close(ctx.sfd[0]);
close(ctx.sfd[1]);
}
/*
* t0 t1
* (p) | | (ew)
* | e0
* \ / (lt)
* e1
* | (lt)
* s0
*/
TEST(epoll37)
{
pthread_t emitter;
struct pollfd pfd;
struct epoll_event e;
struct epoll_mtcontext ctx = { 0 };
signal(SIGUSR1, signal_handler);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0);
ctx.efd[0] = epoll_create(1);
ASSERT_GE(ctx.efd[0], 0);
ctx.efd[1] = epoll_create(1);
ASSERT_GE(ctx.efd[1], 0);
e.events = EPOLLIN;
ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0);
e.events = EPOLLIN;
ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0);
ctx.main = pthread_self();
ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1a, &ctx), 0);
ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0);
pfd.fd = ctx.efd[1];
pfd.events = POLLIN;
if (poll(&pfd, 1, -1) > 0) {
if (epoll_wait(ctx.efd[1], &e, 1, 0) > 0)
__sync_fetch_and_add(&ctx.count, 1);
}
ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0);
EXPECT_EQ(ctx.count, 2);
if (pthread_tryjoin_np(emitter, NULL) < 0) {
pthread_kill(emitter, SIGUSR1);
pthread_join(emitter, NULL);
}
close(ctx.efd[0]);
close(ctx.efd[1]);
close(ctx.sfd[0]);
close(ctx.sfd[1]);
}
/*
* t0 t1
* (p) | | (ew)
* | e0
* \ / (lt)
* e1
* | (et)
* s0
*/
TEST(epoll38)
{
pthread_t emitter;
struct pollfd pfd;
struct epoll_event e;
struct epoll_mtcontext ctx = { 0 };
signal(SIGUSR1, signal_handler);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0);
ctx.efd[0] = epoll_create(1);
ASSERT_GE(ctx.efd[0], 0);
ctx.efd[1] = epoll_create(1);
ASSERT_GE(ctx.efd[1], 0);
e.events = EPOLLIN | EPOLLET;
ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0);
e.events = EPOLLIN;
ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0);
ctx.main = pthread_self();
ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1o, &ctx), 0);
ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0);
pfd.fd = ctx.efd[1];
pfd.events = POLLIN;
if (poll(&pfd, 1, -1) > 0) {
if (epoll_wait(ctx.efd[1], &e, 1, 0) > 0)
__sync_fetch_and_or(&ctx.count, 2);
}
ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0);
EXPECT_TRUE((ctx.count == 2) || (ctx.count == 3));
if (pthread_tryjoin_np(emitter, NULL) < 0) {
pthread_kill(emitter, SIGUSR1);
pthread_join(emitter, NULL);
}
close(ctx.efd[0]);
close(ctx.efd[1]);
close(ctx.sfd[0]);
close(ctx.sfd[1]);
}
/*
* t0 t1
* (p) | | (ew)
* | e0
* \ / (et)
* e1
* | (lt)
* s0
*/
TEST(epoll39)
{
pthread_t emitter;
struct pollfd pfd;
struct epoll_event e;
struct epoll_mtcontext ctx = { 0 };
signal(SIGUSR1, signal_handler);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0);
ctx.efd[0] = epoll_create(1);
ASSERT_GE(ctx.efd[0], 0);
ctx.efd[1] = epoll_create(1);
ASSERT_GE(ctx.efd[1], 0);
e.events = EPOLLIN;
ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0);
e.events = EPOLLIN | EPOLLET;
ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0);
ctx.main = pthread_self();
ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1a, &ctx), 0);
ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0);
pfd.fd = ctx.efd[1];
pfd.events = POLLIN;
if (poll(&pfd, 1, -1) > 0) {
if (epoll_wait(ctx.efd[1], &e, 1, 0) > 0)
__sync_fetch_and_add(&ctx.count, 1);
}
ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0);
EXPECT_EQ(ctx.count, 2);
if (pthread_tryjoin_np(emitter, NULL) < 0) {
pthread_kill(emitter, SIGUSR1);
pthread_join(emitter, NULL);
}
close(ctx.efd[0]);
close(ctx.efd[1]);
close(ctx.sfd[0]);
close(ctx.sfd[1]);
}
/*
* t0 t1
* (p) | | (ew)
* | e0
* \ / (et)
* e1
* | (et)
* s0
*/
TEST(epoll40)
{
pthread_t emitter;
struct pollfd pfd;
struct epoll_event e;
struct epoll_mtcontext ctx = { 0 };
signal(SIGUSR1, signal_handler);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0);
ctx.efd[0] = epoll_create(1);
ASSERT_GE(ctx.efd[0], 0);
ctx.efd[1] = epoll_create(1);
ASSERT_GE(ctx.efd[1], 0);
e.events = EPOLLIN | EPOLLET;
ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0);
e.events = EPOLLIN | EPOLLET;
ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0);
ctx.main = pthread_self();
ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1o, &ctx), 0);
ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0);
pfd.fd = ctx.efd[1];
pfd.events = POLLIN;
if (poll(&pfd, 1, -1) > 0) {
if (epoll_wait(ctx.efd[1], &e, 1, 0) > 0)
__sync_fetch_and_or(&ctx.count, 2);
}
ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0);
EXPECT_TRUE((ctx.count == 2) || (ctx.count == 3));
if (pthread_tryjoin_np(emitter, NULL) < 0) {
pthread_kill(emitter, SIGUSR1);
pthread_join(emitter, NULL);
}
close(ctx.efd[0]);
close(ctx.efd[1]);
close(ctx.sfd[0]);
close(ctx.sfd[1]);
}
/*
* t0 t1
* (ew) | | (p)
* | e0
* \ / (lt)
* e1
* | (lt)
* s0
*/
TEST(epoll41)
{
pthread_t emitter;
struct epoll_event e;
struct epoll_mtcontext ctx = { 0 };
signal(SIGUSR1, signal_handler);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0);
ctx.efd[0] = epoll_create(1);
ASSERT_GE(ctx.efd[0], 0);
ctx.efd[1] = epoll_create(1);
ASSERT_GE(ctx.efd[1], 0);
e.events = EPOLLIN;
ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0);
e.events = EPOLLIN;
ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0);
ctx.main = pthread_self();
ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1ap, &ctx), 0);
ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0);
if (epoll_wait(ctx.efd[1], &e, 1, -1) > 0)
__sync_fetch_and_add(&ctx.count, 1);
ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0);
EXPECT_EQ(ctx.count, 2);
if (pthread_tryjoin_np(emitter, NULL) < 0) {
pthread_kill(emitter, SIGUSR1);
pthread_join(emitter, NULL);
}
close(ctx.efd[0]);
close(ctx.efd[1]);
close(ctx.sfd[0]);
close(ctx.sfd[1]);
}
/*
* t0 t1
* (ew) | | (p)
* | e0
* \ / (lt)
* e1
* | (et)
* s0
*/
TEST(epoll42)
{
pthread_t emitter;
struct epoll_event e;
struct epoll_mtcontext ctx = { 0 };
signal(SIGUSR1, signal_handler);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0);
ctx.efd[0] = epoll_create(1);
ASSERT_GE(ctx.efd[0], 0);
ctx.efd[1] = epoll_create(1);
ASSERT_GE(ctx.efd[1], 0);
e.events = EPOLLIN | EPOLLET;
ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0);
e.events = EPOLLIN;
ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0);
ctx.main = pthread_self();
ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1op, &ctx), 0);
ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0);
if (epoll_wait(ctx.efd[1], &e, 1, -1) > 0)
__sync_fetch_and_or(&ctx.count, 2);
ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0);
EXPECT_TRUE((ctx.count == 2) || (ctx.count == 3));
if (pthread_tryjoin_np(emitter, NULL) < 0) {
pthread_kill(emitter, SIGUSR1);
pthread_join(emitter, NULL);
}
close(ctx.efd[0]);
close(ctx.efd[1]);
close(ctx.sfd[0]);
close(ctx.sfd[1]);
}
/*
* t0 t1
* (ew) | | (p)
* | e0
* \ / (et)
* e1
* | (lt)
* s0
*/
TEST(epoll43)
{
pthread_t emitter;
struct epoll_event e;
struct epoll_mtcontext ctx = { 0 };
signal(SIGUSR1, signal_handler);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0);
ctx.efd[0] = epoll_create(1);
ASSERT_GE(ctx.efd[0], 0);
ctx.efd[1] = epoll_create(1);
ASSERT_GE(ctx.efd[1], 0);
e.events = EPOLLIN;
ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0);
e.events = EPOLLIN | EPOLLET;
ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0);
ctx.main = pthread_self();
ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1ap, &ctx), 0);
ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0);
if (epoll_wait(ctx.efd[1], &e, 1, -1) > 0)
__sync_fetch_and_add(&ctx.count, 1);
ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0);
EXPECT_EQ(ctx.count, 2);
if (pthread_tryjoin_np(emitter, NULL) < 0) {
pthread_kill(emitter, SIGUSR1);
pthread_join(emitter, NULL);
}
close(ctx.efd[0]);
close(ctx.efd[1]);
close(ctx.sfd[0]);
close(ctx.sfd[1]);
}
/*
* t0 t1
* (ew) | | (p)
* | e0
* \ / (et)
* e1
* | (et)
* s0
*/
TEST(epoll44)
{
pthread_t emitter;
struct epoll_event e;
struct epoll_mtcontext ctx = { 0 };
signal(SIGUSR1, signal_handler);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0);
ctx.efd[0] = epoll_create(1);
ASSERT_GE(ctx.efd[0], 0);
ctx.efd[1] = epoll_create(1);
ASSERT_GE(ctx.efd[1], 0);
e.events = EPOLLIN | EPOLLET;
ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0);
e.events = EPOLLIN | EPOLLET;
ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0);
ctx.main = pthread_self();
ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1op, &ctx), 0);
ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0);
if (epoll_wait(ctx.efd[1], &e, 1, -1) > 0)
__sync_fetch_and_or(&ctx.count, 2);
ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0);
EXPECT_TRUE((ctx.count == 2) || (ctx.count == 3));
if (pthread_tryjoin_np(emitter, NULL) < 0) {
pthread_kill(emitter, SIGUSR1);
pthread_join(emitter, NULL);
}
close(ctx.efd[0]);
close(ctx.efd[1]);
close(ctx.sfd[0]);
close(ctx.sfd[1]);
}
/*
* t0 t1
* (p) | | (p)
* | e0
* \ / (lt)
* e1
* | (lt)
* s0
*/
TEST(epoll45)
{
pthread_t emitter;
struct pollfd pfd;
struct epoll_event e;
struct epoll_mtcontext ctx = { 0 };
signal(SIGUSR1, signal_handler);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0);
ctx.efd[0] = epoll_create(1);
ASSERT_GE(ctx.efd[0], 0);
ctx.efd[1] = epoll_create(1);
ASSERT_GE(ctx.efd[1], 0);
e.events = EPOLLIN;
ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0);
e.events = EPOLLIN;
ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0);
ctx.main = pthread_self();
ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1ap, &ctx), 0);
ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0);
pfd.fd = ctx.efd[1];
pfd.events = POLLIN;
if (poll(&pfd, 1, -1) > 0) {
if (epoll_wait(ctx.efd[1], &e, 1, 0) > 0)
__sync_fetch_and_add(&ctx.count, 1);
}
ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0);
EXPECT_EQ(ctx.count, 2);
if (pthread_tryjoin_np(emitter, NULL) < 0) {
pthread_kill(emitter, SIGUSR1);
pthread_join(emitter, NULL);
}
close(ctx.efd[0]);
close(ctx.efd[1]);
close(ctx.sfd[0]);
close(ctx.sfd[1]);
}
/*
* t0 t1
* (p) | | (p)
* | e0
* \ / (lt)
* e1
* | (et)
* s0
*/
TEST(epoll46)
{
pthread_t emitter;
struct epoll_event e;
struct epoll_mtcontext ctx = { 0 };
signal(SIGUSR1, signal_handler);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0);
ctx.efd[0] = epoll_create(1);
ASSERT_GE(ctx.efd[0], 0);
ctx.efd[1] = epoll_create(1);
ASSERT_GE(ctx.efd[1], 0);
e.events = EPOLLIN | EPOLLET;
ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0);
e.events = EPOLLIN;
ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0);
ctx.main = pthread_self();
ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1op, &ctx), 0);
ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0);
if (epoll_wait(ctx.efd[1], &e, 1, -1) > 0)
__sync_fetch_and_or(&ctx.count, 2);
ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0);
EXPECT_TRUE((ctx.count == 2) || (ctx.count == 3));
if (pthread_tryjoin_np(emitter, NULL) < 0) {
pthread_kill(emitter, SIGUSR1);
pthread_join(emitter, NULL);
}
close(ctx.efd[0]);
close(ctx.efd[1]);
close(ctx.sfd[0]);
close(ctx.sfd[1]);
}
/*
* t0 t1
* (p) | | (p)
* | e0
* \ / (et)
* e1
* | (lt)
* s0
*/
TEST(epoll47)
{
pthread_t emitter;
struct pollfd pfd;
struct epoll_event e;
struct epoll_mtcontext ctx = { 0 };
signal(SIGUSR1, signal_handler);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0);
ctx.efd[0] = epoll_create(1);
ASSERT_GE(ctx.efd[0], 0);
ctx.efd[1] = epoll_create(1);
ASSERT_GE(ctx.efd[1], 0);
e.events = EPOLLIN;
ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0);
e.events = EPOLLIN | EPOLLET;
ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0);
ctx.main = pthread_self();
ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1ap, &ctx), 0);
ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0);
pfd.fd = ctx.efd[1];
pfd.events = POLLIN;
if (poll(&pfd, 1, -1) > 0) {
if (epoll_wait(ctx.efd[1], &e, 1, 0) > 0)
__sync_fetch_and_add(&ctx.count, 1);
}
ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0);
EXPECT_EQ(ctx.count, 2);
if (pthread_tryjoin_np(emitter, NULL) < 0) {
pthread_kill(emitter, SIGUSR1);
pthread_join(emitter, NULL);
}
close(ctx.efd[0]);
close(ctx.efd[1]);
close(ctx.sfd[0]);
close(ctx.sfd[1]);
}
/*
* t0 t1
* (p) | | (p)
* | e0
* \ / (et)
* e1
* | (et)
* s0
*/
TEST(epoll48)
{
pthread_t emitter;
struct epoll_event e;
struct epoll_mtcontext ctx = { 0 };
signal(SIGUSR1, signal_handler);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0);
ctx.efd[0] = epoll_create(1);
ASSERT_GE(ctx.efd[0], 0);
ctx.efd[1] = epoll_create(1);
ASSERT_GE(ctx.efd[1], 0);
e.events = EPOLLIN | EPOLLET;
ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0);
e.events = EPOLLIN | EPOLLET;
ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0);
ctx.main = pthread_self();
ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1op, &ctx), 0);
ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0);
if (epoll_wait(ctx.efd[1], &e, 1, -1) > 0)
__sync_fetch_and_or(&ctx.count, 2);
ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0);
EXPECT_TRUE((ctx.count == 2) || (ctx.count == 3));
if (pthread_tryjoin_np(emitter, NULL) < 0) {
pthread_kill(emitter, SIGUSR1);
pthread_join(emitter, NULL);
}
close(ctx.efd[0]);
close(ctx.efd[1]);
close(ctx.sfd[0]);
close(ctx.sfd[1]);
}
/*
* t0
* | (ew)
* e0
* (lt) / \ (lt)
* e1 e2
* (lt) | | (lt)
* s0 s2
*/
TEST(epoll49)
{
int efd[3];
int sfd[4];
struct epoll_event events[2];
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &sfd[0]), 0);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &sfd[2]), 0);
efd[0] = epoll_create(1);
ASSERT_GE(efd[0], 0);
efd[1] = epoll_create(1);
ASSERT_GE(efd[1], 0);
efd[2] = epoll_create(1);
ASSERT_GE(efd[2], 0);
events[0].events = EPOLLIN;
ASSERT_EQ(epoll_ctl(efd[1], EPOLL_CTL_ADD, sfd[0], events), 0);
events[0].events = EPOLLIN;
ASSERT_EQ(epoll_ctl(efd[2], EPOLL_CTL_ADD, sfd[2], events), 0);
events[0].events = EPOLLIN;
ASSERT_EQ(epoll_ctl(efd[0], EPOLL_CTL_ADD, efd[1], events), 0);
events[0].events = EPOLLIN;
ASSERT_EQ(epoll_ctl(efd[0], EPOLL_CTL_ADD, efd[2], events), 0);
ASSERT_EQ(write(sfd[1], "w", 1), 1);
ASSERT_EQ(write(sfd[3], "w", 1), 1);
EXPECT_EQ(epoll_wait(efd[0], events, 2, 0), 2);
EXPECT_EQ(epoll_wait(efd[0], events, 2, 0), 2);
close(efd[0]);
close(efd[1]);
close(efd[2]);
close(sfd[0]);
close(sfd[1]);
close(sfd[2]);
close(sfd[3]);
}
/*
* t0
* | (ew)
* e0
* (et) / \ (et)
* e1 e2
* (lt) | | (lt)
* s0 s2
*/
TEST(epoll50)
{
int efd[3];
int sfd[4];
struct epoll_event events[2];
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &sfd[0]), 0);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &sfd[2]), 0);
efd[0] = epoll_create(1);
ASSERT_GE(efd[0], 0);
efd[1] = epoll_create(1);
ASSERT_GE(efd[1], 0);
efd[2] = epoll_create(1);
ASSERT_GE(efd[2], 0);
events[0].events = EPOLLIN;
ASSERT_EQ(epoll_ctl(efd[1], EPOLL_CTL_ADD, sfd[0], events), 0);
events[0].events = EPOLLIN;
ASSERT_EQ(epoll_ctl(efd[2], EPOLL_CTL_ADD, sfd[2], events), 0);
events[0].events = EPOLLIN | EPOLLET;
ASSERT_EQ(epoll_ctl(efd[0], EPOLL_CTL_ADD, efd[1], events), 0);
events[0].events = EPOLLIN | EPOLLET;
ASSERT_EQ(epoll_ctl(efd[0], EPOLL_CTL_ADD, efd[2], events), 0);
ASSERT_EQ(write(sfd[1], "w", 1), 1);
ASSERT_EQ(write(sfd[3], "w", 1), 1);
EXPECT_EQ(epoll_wait(efd[0], events, 2, 0), 2);
EXPECT_EQ(epoll_wait(efd[0], events, 2, 0), 0);
close(efd[0]);
close(efd[1]);
close(efd[2]);
close(sfd[0]);
close(sfd[1]);
close(sfd[2]);
close(sfd[3]);
}
/*
* t0
* | (p)
* e0
* (lt) / \ (lt)
* e1 e2
* (lt) | | (lt)
* s0 s2
*/
TEST(epoll51)
{
int efd[3];
int sfd[4];
struct pollfd pfd;
struct epoll_event events[2];
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &sfd[0]), 0);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &sfd[2]), 0);
efd[0] = epoll_create(1);
ASSERT_GE(efd[0], 0);
efd[1] = epoll_create(1);
ASSERT_GE(efd[1], 0);
efd[2] = epoll_create(1);
ASSERT_GE(efd[2], 0);
events[0].events = EPOLLIN;
ASSERT_EQ(epoll_ctl(efd[1], EPOLL_CTL_ADD, sfd[0], events), 0);
events[0].events = EPOLLIN;
ASSERT_EQ(epoll_ctl(efd[2], EPOLL_CTL_ADD, sfd[2], events), 0);
events[0].events = EPOLLIN;
ASSERT_EQ(epoll_ctl(efd[0], EPOLL_CTL_ADD, efd[1], events), 0);
events[0].events = EPOLLIN;
ASSERT_EQ(epoll_ctl(efd[0], EPOLL_CTL_ADD, efd[2], events), 0);
ASSERT_EQ(write(sfd[1], "w", 1), 1);
ASSERT_EQ(write(sfd[3], "w", 1), 1);
pfd.fd = efd[0];
pfd.events = POLLIN;
EXPECT_EQ(poll(&pfd, 1, 0), 1);
EXPECT_EQ(epoll_wait(efd[0], events, 2, 0), 2);
pfd.fd = efd[0];
pfd.events = POLLIN;
EXPECT_EQ(poll(&pfd, 1, 0), 1);
EXPECT_EQ(epoll_wait(efd[0], events, 2, 0), 2);
close(efd[0]);
close(efd[1]);
close(efd[2]);
close(sfd[0]);
close(sfd[1]);
close(sfd[2]);
close(sfd[3]);
}
/*
* t0
* | (p)
* e0
* (et) / \ (et)
* e1 e2
* (lt) | | (lt)
* s0 s2
*/
TEST(epoll52)
{
int efd[3];
int sfd[4];
struct pollfd pfd;
struct epoll_event events[2];
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &sfd[0]), 0);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &sfd[2]), 0);
efd[0] = epoll_create(1);
ASSERT_GE(efd[0], 0);
efd[1] = epoll_create(1);
ASSERT_GE(efd[1], 0);
efd[2] = epoll_create(1);
ASSERT_GE(efd[2], 0);
events[0].events = EPOLLIN;
ASSERT_EQ(epoll_ctl(efd[1], EPOLL_CTL_ADD, sfd[0], events), 0);
events[0].events = EPOLLIN;
ASSERT_EQ(epoll_ctl(efd[2], EPOLL_CTL_ADD, sfd[2], events), 0);
events[0].events = EPOLLIN | EPOLLET;
ASSERT_EQ(epoll_ctl(efd[0], EPOLL_CTL_ADD, efd[1], events), 0);
events[0].events = EPOLLIN | EPOLLET;
ASSERT_EQ(epoll_ctl(efd[0], EPOLL_CTL_ADD, efd[2], events), 0);
ASSERT_EQ(write(sfd[1], "w", 1), 1);
ASSERT_EQ(write(sfd[3], "w", 1), 1);
pfd.fd = efd[0];
pfd.events = POLLIN;
EXPECT_EQ(poll(&pfd, 1, 0), 1);
EXPECT_EQ(epoll_wait(efd[0], events, 2, 0), 2);
pfd.fd = efd[0];
pfd.events = POLLIN;
EXPECT_EQ(poll(&pfd, 1, 0), 0);
EXPECT_EQ(epoll_wait(efd[0], events, 2, 0), 0);
close(efd[0]);
close(efd[1]);
close(efd[2]);
close(sfd[0]);
close(sfd[1]);
close(sfd[2]);
close(sfd[3]);
}
/*
* t0 t1
* (ew) \ / (ew)
* e0
* (lt) / \ (lt)
* e1 e2
* (lt) | | (lt)
* s0 s2
*/
TEST(epoll53)
{
pthread_t emitter;
struct epoll_event e;
struct epoll_mtcontext ctx = { 0 };
signal(SIGUSR1, signal_handler);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &ctx.sfd[0]), 0);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &ctx.sfd[2]), 0);
ctx.efd[0] = epoll_create(1);
ASSERT_GE(ctx.efd[0], 0);
ctx.efd[1] = epoll_create(1);
ASSERT_GE(ctx.efd[1], 0);
ctx.efd[2] = epoll_create(1);
ASSERT_GE(ctx.efd[2], 0);
e.events = EPOLLIN;
ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0);
e.events = EPOLLIN;
ASSERT_EQ(epoll_ctl(ctx.efd[2], EPOLL_CTL_ADD, ctx.sfd[2], &e), 0);
e.events = EPOLLIN;
ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0);
e.events = EPOLLIN;
ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[2], &e), 0);
ctx.main = pthread_self();
ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1a, &ctx), 0);
ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry2, &ctx), 0);
if (epoll_wait(ctx.efd[0], &e, 1, -1) > 0)
__sync_fetch_and_add(&ctx.count, 1);
ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0);
EXPECT_EQ(ctx.count, 2);
if (pthread_tryjoin_np(emitter, NULL) < 0) {
pthread_kill(emitter, SIGUSR1);
pthread_join(emitter, NULL);
}
close(ctx.efd[0]);
close(ctx.efd[1]);
close(ctx.efd[2]);
close(ctx.sfd[0]);
close(ctx.sfd[1]);
close(ctx.sfd[2]);
close(ctx.sfd[3]);
}
/*
* t0 t1
* (ew) \ / (ew)
* e0
* (et) / \ (et)
* e1 e2
* (lt) | | (lt)
* s0 s2
*/
TEST(epoll54)
{
pthread_t emitter;
struct epoll_event e;
struct epoll_mtcontext ctx = { 0 };
signal(SIGUSR1, signal_handler);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &ctx.sfd[0]), 0);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &ctx.sfd[2]), 0);
ctx.efd[0] = epoll_create(1);
ASSERT_GE(ctx.efd[0], 0);
ctx.efd[1] = epoll_create(1);
ASSERT_GE(ctx.efd[1], 0);
ctx.efd[2] = epoll_create(1);
ASSERT_GE(ctx.efd[2], 0);
e.events = EPOLLIN;
ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0);
e.events = EPOLLIN;
ASSERT_EQ(epoll_ctl(ctx.efd[2], EPOLL_CTL_ADD, ctx.sfd[2], &e), 0);
e.events = EPOLLIN | EPOLLET;
ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0);
e.events = EPOLLIN | EPOLLET;
ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[2], &e), 0);
ctx.main = pthread_self();
ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1a, &ctx), 0);
ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry2, &ctx), 0);
if (epoll_wait(ctx.efd[0], &e, 1, -1) > 0)
__sync_fetch_and_add(&ctx.count, 1);
ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0);
EXPECT_EQ(ctx.count, 2);
if (pthread_tryjoin_np(emitter, NULL) < 0) {
pthread_kill(emitter, SIGUSR1);
pthread_join(emitter, NULL);
}
close(ctx.efd[0]);
close(ctx.efd[1]);
close(ctx.efd[2]);
close(ctx.sfd[0]);
close(ctx.sfd[1]);
close(ctx.sfd[2]);
close(ctx.sfd[3]);
}
/*
* t0 t1
* (ew) \ / (p)
* e0
* (lt) / \ (lt)
* e1 e2
* (lt) | | (lt)
* s0 s2
*/
TEST(epoll55)
{
pthread_t emitter;
struct epoll_event e;
struct epoll_mtcontext ctx = { 0 };
signal(SIGUSR1, signal_handler);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &ctx.sfd[0]), 0);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &ctx.sfd[2]), 0);
ctx.efd[0] = epoll_create(1);
ASSERT_GE(ctx.efd[0], 0);
ctx.efd[1] = epoll_create(1);
ASSERT_GE(ctx.efd[1], 0);
ctx.efd[2] = epoll_create(1);
ASSERT_GE(ctx.efd[2], 0);
e.events = EPOLLIN;
ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0);
e.events = EPOLLIN;
ASSERT_EQ(epoll_ctl(ctx.efd[2], EPOLL_CTL_ADD, ctx.sfd[2], &e), 0);
e.events = EPOLLIN;
ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0);
e.events = EPOLLIN;
ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[2], &e), 0);
ctx.main = pthread_self();
ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1ap, &ctx), 0);
ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry2, &ctx), 0);
if (epoll_wait(ctx.efd[0], &e, 1, -1) > 0)
__sync_fetch_and_add(&ctx.count, 1);
ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0);
EXPECT_EQ(ctx.count, 2);
if (pthread_tryjoin_np(emitter, NULL) < 0) {
pthread_kill(emitter, SIGUSR1);
pthread_join(emitter, NULL);
}
close(ctx.efd[0]);
close(ctx.efd[1]);
close(ctx.efd[2]);
close(ctx.sfd[0]);
close(ctx.sfd[1]);
close(ctx.sfd[2]);
close(ctx.sfd[3]);
}
/*
* t0 t1
* (ew) \ / (p)
* e0
* (et) / \ (et)
* e1 e2
* (lt) | | (lt)
* s0 s2
*/
TEST(epoll56)
{
pthread_t emitter;
struct epoll_event e;
struct epoll_mtcontext ctx = { 0 };
signal(SIGUSR1, signal_handler);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &ctx.sfd[0]), 0);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &ctx.sfd[2]), 0);
ctx.efd[0] = epoll_create(1);
ASSERT_GE(ctx.efd[0], 0);
ctx.efd[1] = epoll_create(1);
ASSERT_GE(ctx.efd[1], 0);
ctx.efd[2] = epoll_create(1);
ASSERT_GE(ctx.efd[2], 0);
e.events = EPOLLIN;
ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0);
e.events = EPOLLIN;
ASSERT_EQ(epoll_ctl(ctx.efd[2], EPOLL_CTL_ADD, ctx.sfd[2], &e), 0);
e.events = EPOLLIN | EPOLLET;
ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0);
e.events = EPOLLIN | EPOLLET;
ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[2], &e), 0);
ctx.main = pthread_self();
ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1ap, &ctx), 0);
ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry2, &ctx), 0);
if (epoll_wait(ctx.efd[0], &e, 1, -1) > 0)
__sync_fetch_and_add(&ctx.count, 1);
ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0);
EXPECT_EQ(ctx.count, 2);
if (pthread_tryjoin_np(emitter, NULL) < 0) {
pthread_kill(emitter, SIGUSR1);
pthread_join(emitter, NULL);
}
close(ctx.efd[0]);
close(ctx.efd[1]);
close(ctx.efd[2]);
close(ctx.sfd[0]);
close(ctx.sfd[1]);
close(ctx.sfd[2]);
close(ctx.sfd[3]);
}
/*
* t0 t1
* (p) \ / (p)
* e0
* (lt) / \ (lt)
* e1 e2
* (lt) | | (lt)
* s0 s2
*/
TEST(epoll57)
{
pthread_t emitter;
struct pollfd pfd;
struct epoll_event e;
struct epoll_mtcontext ctx = { 0 };
signal(SIGUSR1, signal_handler);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &ctx.sfd[0]), 0);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &ctx.sfd[2]), 0);
ctx.efd[0] = epoll_create(1);
ASSERT_GE(ctx.efd[0], 0);
ctx.efd[1] = epoll_create(1);
ASSERT_GE(ctx.efd[1], 0);
ctx.efd[2] = epoll_create(1);
ASSERT_GE(ctx.efd[2], 0);
e.events = EPOLLIN;
ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0);
e.events = EPOLLIN;
ASSERT_EQ(epoll_ctl(ctx.efd[2], EPOLL_CTL_ADD, ctx.sfd[2], &e), 0);
e.events = EPOLLIN;
ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0);
e.events = EPOLLIN;
ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[2], &e), 0);
ctx.main = pthread_self();
ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1ap, &ctx), 0);
ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry2, &ctx), 0);
pfd.fd = ctx.efd[0];
pfd.events = POLLIN;
if (poll(&pfd, 1, -1) > 0) {
if (epoll_wait(ctx.efd[0], &e, 1, 0) > 0)
__sync_fetch_and_add(&ctx.count, 1);
}
ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0);
EXPECT_EQ(ctx.count, 2);
if (pthread_tryjoin_np(emitter, NULL) < 0) {
pthread_kill(emitter, SIGUSR1);
pthread_join(emitter, NULL);
}
close(ctx.efd[0]);
close(ctx.efd[1]);
close(ctx.efd[2]);
close(ctx.sfd[0]);
close(ctx.sfd[1]);
close(ctx.sfd[2]);
close(ctx.sfd[3]);
}
/*
* t0 t1
* (p) \ / (p)
* e0
* (et) / \ (et)
* e1 e2
* (lt) | | (lt)
* s0 s2
*/
TEST(epoll58)
{
pthread_t emitter;
struct pollfd pfd;
struct epoll_event e;
struct epoll_mtcontext ctx = { 0 };
signal(SIGUSR1, signal_handler);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &ctx.sfd[0]), 0);
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &ctx.sfd[2]), 0);
ctx.efd[0] = epoll_create(1);
ASSERT_GE(ctx.efd[0], 0);
ctx.efd[1] = epoll_create(1);
ASSERT_GE(ctx.efd[1], 0);
ctx.efd[2] = epoll_create(1);
ASSERT_GE(ctx.efd[2], 0);
e.events = EPOLLIN;
ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0);
e.events = EPOLLIN;
ASSERT_EQ(epoll_ctl(ctx.efd[2], EPOLL_CTL_ADD, ctx.sfd[2], &e), 0);
e.events = EPOLLIN | EPOLLET;
ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0);
e.events = EPOLLIN | EPOLLET;
ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[2], &e), 0);
ctx.main = pthread_self();
ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1ap, &ctx), 0);
ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry2, &ctx), 0);
pfd.fd = ctx.efd[0];
pfd.events = POLLIN;
if (poll(&pfd, 1, -1) > 0) {
if (epoll_wait(ctx.efd[0], &e, 1, 0) > 0)
__sync_fetch_and_add(&ctx.count, 1);
}
ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0);
EXPECT_EQ(ctx.count, 2);
if (pthread_tryjoin_np(emitter, NULL) < 0) {
pthread_kill(emitter, SIGUSR1);
pthread_join(emitter, NULL);
}
close(ctx.efd[0]);
close(ctx.efd[1]);
close(ctx.efd[2]);
close(ctx.sfd[0]);
close(ctx.sfd[1]);
close(ctx.sfd[2]);
close(ctx.sfd[3]);
}
TEST_HARNESS_MAIN
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment