1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Copyright (c) 2016 Fujitsu Ltd. 4 * Author: Xiao Yang <yangx.jy@cn.fujitsu.com> 5 */ 6 7/*\ 8 * [Description] 9 * 10 * Check the basic functionality of the epoll_ctl: 11 * 12 * - When epoll_ctl succeeds to register fd on the epoll instance and associates 13 * event with fd, epoll_wait will get registered fd and event correctly. 14 * - When epoll_ctl succeeds to change event which is related to fd, epoll_wait 15 * will get changed event correctly. 16 * - When epoll_ctl succeeds to deregister fd from the epoll instance epoll_wait 17 * won't get deregistered fd and event. 18 */ 19 20#include <poll.h> 21#include <sys/epoll.h> 22 23#include "tst_test.h" 24 25static int epfd; 26static int fd[2]; 27 28static struct epoll_event events[3] = { 29 {.events = EPOLLIN}, 30 {.events = EPOLLOUT}, 31 {.events = EPOLLIN} 32}; 33 34static void setup(void) 35{ 36 epfd = epoll_create(2); 37 if (epfd == -1) 38 tst_brk(TBROK | TERRNO, "fail to create epoll instance"); 39 40 SAFE_PIPE(fd); 41 42 events[0].data.fd = fd[0]; 43 events[1].data.fd = fd[1]; 44 events[2].data.fd = fd[1]; 45} 46 47static void cleanup(void) 48{ 49 if (epfd > 0) 50 SAFE_CLOSE(epfd); 51 52 if (fd[0] > 0) 53 SAFE_CLOSE(fd[0]); 54 55 if (fd[1] > 0) 56 SAFE_CLOSE(fd[1]); 57} 58 59static int has_event(struct epoll_event *epvs, int len, 60 int fd, unsigned int events) 61{ 62 int i; 63 64 for (i = 0; i < len; i++) { 65 if ((epvs[i].data.fd == fd) && (epvs[i].events == events)) 66 return 1; 67 } 68 69 return 0; 70} 71 72static void check_epoll_ctl(int opt, int exp_num) 73{ 74 int res; 75 unsigned int events; 76 char write_buf[] = "test"; 77 char read_buf[sizeof(write_buf)]; 78 struct epoll_event res_evs[2]; 79 80 events = EPOLLIN; 81 if (exp_num == 2) 82 events |= EPOLLOUT; 83 84 SAFE_WRITE(SAFE_WRITE_ALL, fd[1], write_buf, sizeof(write_buf)); 85 86 while (events) { 87 int events_matched = 0; 88 89 memset(res_evs, 0, sizeof(res_evs)); 90 res = epoll_wait(epfd, res_evs, 2, -1); 91 92 if (res <= 0) { 93 tst_res(TFAIL | TERRNO, "epoll_wait() returned %i", 94 res); 95 goto end; 96 } 97 98 if ((events & EPOLLIN) && 99 has_event(res_evs, 2, fd[0], EPOLLIN)) { 100 events_matched++; 101 events &= ~EPOLLIN; 102 } 103 104 if ((events & EPOLLOUT) && 105 has_event(res_evs, 2, fd[1], EPOLLOUT)) { 106 events_matched++; 107 events &= ~EPOLLOUT; 108 } 109 110 if (res != events_matched) { 111 tst_res(TFAIL, 112 "epoll_wait() returned unexpected events"); 113 goto end; 114 } 115 } 116 117 tst_res(TPASS, "epoll_ctl() succeeds with op %i", opt); 118 119end: 120 SAFE_READ(1, fd[0], read_buf, sizeof(write_buf)); 121} 122 123static void opera_epoll_ctl(int opt, int fd, struct epoll_event *epvs) 124{ 125 TEST(epoll_ctl(epfd, opt, fd, epvs)); 126 if (TST_RET == -1) 127 tst_brk(TBROK | TTERRNO, "epoll_ctl() fails with op %i", opt); 128} 129 130static void verify_epoll_ctl(void) 131{ 132 opera_epoll_ctl(EPOLL_CTL_ADD, fd[0], &events[0]); 133 opera_epoll_ctl(EPOLL_CTL_ADD, fd[1], &events[2]); 134 check_epoll_ctl(EPOLL_CTL_ADD, 1); 135 opera_epoll_ctl(EPOLL_CTL_MOD, fd[1], &events[1]); 136 check_epoll_ctl(EPOLL_CTL_MOD, 2); 137 opera_epoll_ctl(EPOLL_CTL_DEL, fd[1], &events[1]); 138 check_epoll_ctl(EPOLL_CTL_DEL, 1); 139 opera_epoll_ctl(EPOLL_CTL_DEL, fd[0], &events[0]); 140} 141 142static struct tst_test test = { 143 .setup = setup, 144 .cleanup = cleanup, 145 .test_all = verify_epoll_ctl, 146}; 147