1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com> 4f08c3bdfSopenharmony_ci */ 5f08c3bdfSopenharmony_ci 6f08c3bdfSopenharmony_ci/*\ 7f08c3bdfSopenharmony_ci * [Description] 8f08c3bdfSopenharmony_ci * 9f08c3bdfSopenharmony_ci * Verify that edge triggering is correctly handled by epoll, for both EPOLLIN 10f08c3bdfSopenharmony_ci * and EPOLLOUT. 11f08c3bdfSopenharmony_ci * 12f08c3bdfSopenharmony_ci * [Algorithm] 13f08c3bdfSopenharmony_ci * 14f08c3bdfSopenharmony_ci * - The file descriptors for non-blocking pipe are registered on an epoll 15f08c3bdfSopenharmony_ci * instance. 16f08c3bdfSopenharmony_ci * - A pipe writer writes data on the write side of the pipe. 17f08c3bdfSopenharmony_ci * - A call to epoll_wait() is done that will return a EPOLLIN event. 18f08c3bdfSopenharmony_ci * - The pipe reader reads half of data from rfd. 19f08c3bdfSopenharmony_ci * - A call to epoll_wait() should hang because there's data left to read. 20f08c3bdfSopenharmony_ci * - The pipe reader reads remaining data from rfd. 21f08c3bdfSopenharmony_ci * - A call to epoll_wait() should return a EPOLLOUT event. 22f08c3bdfSopenharmony_ci */ 23f08c3bdfSopenharmony_ci 24f08c3bdfSopenharmony_ci#define _GNU_SOURCE 25f08c3bdfSopenharmony_ci 26f08c3bdfSopenharmony_ci#include <fcntl.h> 27f08c3bdfSopenharmony_ci#include "tst_test.h" 28f08c3bdfSopenharmony_ci#include "tst_epoll.h" 29f08c3bdfSopenharmony_ci 30f08c3bdfSopenharmony_cistatic size_t write_size; 31f08c3bdfSopenharmony_cistatic size_t read_size; 32f08c3bdfSopenharmony_cistatic int fds[2]; 33f08c3bdfSopenharmony_cistatic int epfd; 34f08c3bdfSopenharmony_ci 35f08c3bdfSopenharmony_cistatic void setup(void) 36f08c3bdfSopenharmony_ci{ 37f08c3bdfSopenharmony_ci write_size = getpagesize(); 38f08c3bdfSopenharmony_ci read_size = write_size / 2; 39f08c3bdfSopenharmony_ci 40f08c3bdfSopenharmony_ci SAFE_PIPE2(fds, O_NONBLOCK); 41f08c3bdfSopenharmony_ci 42f08c3bdfSopenharmony_ci /* EPOLLOUT will be raised when buffer became empty after becoming full */ 43f08c3bdfSopenharmony_ci SAFE_FCNTL(fds[1], F_SETPIPE_SZ, write_size); 44f08c3bdfSopenharmony_ci} 45f08c3bdfSopenharmony_ci 46f08c3bdfSopenharmony_cistatic void cleanup(void) 47f08c3bdfSopenharmony_ci{ 48f08c3bdfSopenharmony_ci if (epfd > 0) 49f08c3bdfSopenharmony_ci SAFE_CLOSE(epfd); 50f08c3bdfSopenharmony_ci 51f08c3bdfSopenharmony_ci if (fds[0] > 0) 52f08c3bdfSopenharmony_ci SAFE_CLOSE(fds[0]); 53f08c3bdfSopenharmony_ci 54f08c3bdfSopenharmony_ci if (fds[1] > 0) 55f08c3bdfSopenharmony_ci SAFE_CLOSE(fds[1]); 56f08c3bdfSopenharmony_ci} 57f08c3bdfSopenharmony_ci 58f08c3bdfSopenharmony_cistatic void run(void) 59f08c3bdfSopenharmony_ci{ 60f08c3bdfSopenharmony_ci char buff[write_size]; 61f08c3bdfSopenharmony_ci struct epoll_event evt_receive; 62f08c3bdfSopenharmony_ci 63f08c3bdfSopenharmony_ci tst_res(TINFO, "Polling on channel with EPOLLET"); 64f08c3bdfSopenharmony_ci 65f08c3bdfSopenharmony_ci epfd = SAFE_EPOLL_CREATE1(0); 66f08c3bdfSopenharmony_ci 67f08c3bdfSopenharmony_ci SAFE_EPOLL_CTL(epfd, EPOLL_CTL_ADD, fds[0], &((struct epoll_event) { 68f08c3bdfSopenharmony_ci .events = EPOLLIN | EPOLLET, 69f08c3bdfSopenharmony_ci .data.fd = fds[0], 70f08c3bdfSopenharmony_ci })); 71f08c3bdfSopenharmony_ci SAFE_EPOLL_CTL(epfd, EPOLL_CTL_ADD, fds[1], &((struct epoll_event) { 72f08c3bdfSopenharmony_ci .events = EPOLLOUT | EPOLLET, 73f08c3bdfSopenharmony_ci .data.fd = fds[1], 74f08c3bdfSopenharmony_ci })); 75f08c3bdfSopenharmony_ci 76f08c3bdfSopenharmony_ci tst_res(TINFO, "Write bytes on channel: %zu bytes", write_size); 77f08c3bdfSopenharmony_ci 78f08c3bdfSopenharmony_ci memset(buff, 'a', write_size); 79f08c3bdfSopenharmony_ci SAFE_WRITE(SAFE_WRITE_ANY, fds[1], buff, write_size); 80f08c3bdfSopenharmony_ci TST_EXP_FAIL(write(fds[1], buff, write_size), EAGAIN, "write() failed"); 81f08c3bdfSopenharmony_ci 82f08c3bdfSopenharmony_ci TST_EXP_EQ_LI(SAFE_EPOLL_WAIT(epfd, &evt_receive, 1, 0), 1); 83f08c3bdfSopenharmony_ci TST_EXP_EQ_LI(evt_receive.data.fd, fds[0]); 84f08c3bdfSopenharmony_ci TST_EXP_EQ_LI(evt_receive.events & EPOLLIN, EPOLLIN); 85f08c3bdfSopenharmony_ci 86f08c3bdfSopenharmony_ci tst_res(TINFO, "Read half bytes from channel: %zu bytes", read_size); 87f08c3bdfSopenharmony_ci 88f08c3bdfSopenharmony_ci memset(buff, 0, write_size); 89f08c3bdfSopenharmony_ci SAFE_READ(1, fds[0], buff, read_size); 90f08c3bdfSopenharmony_ci 91f08c3bdfSopenharmony_ci TST_EXP_EQ_LI(SAFE_EPOLL_WAIT(epfd, &evt_receive, 1, 0), 0); 92f08c3bdfSopenharmony_ci 93f08c3bdfSopenharmony_ci tst_res(TINFO, "Read remaining bytes from channel: %zu bytes", read_size); 94f08c3bdfSopenharmony_ci 95f08c3bdfSopenharmony_ci SAFE_READ(1, fds[0], buff + read_size, read_size); 96f08c3bdfSopenharmony_ci TST_EXP_FAIL(read(fds[0], buff, read_size), EAGAIN, "read() failed"); 97f08c3bdfSopenharmony_ci 98f08c3bdfSopenharmony_ci TST_EXP_EQ_LI(SAFE_EPOLL_WAIT(epfd, &evt_receive, 1, 0), 1); 99f08c3bdfSopenharmony_ci TST_EXP_EQ_LI(evt_receive.data.fd, fds[1]); 100f08c3bdfSopenharmony_ci TST_EXP_EQ_LI(evt_receive.events & EPOLLOUT, EPOLLOUT); 101f08c3bdfSopenharmony_ci} 102f08c3bdfSopenharmony_ci 103f08c3bdfSopenharmony_cistatic struct tst_test test = { 104f08c3bdfSopenharmony_ci .setup = setup, 105f08c3bdfSopenharmony_ci .cleanup = cleanup, 106f08c3bdfSopenharmony_ci .test_all = run, 107f08c3bdfSopenharmony_ci}; 108