… | |
… | |
83 | return; |
83 | return; |
84 | |
84 | |
85 | oldmask = anfds [fd].emask; |
85 | oldmask = anfds [fd].emask; |
86 | anfds [fd].emask = nev; |
86 | anfds [fd].emask = nev; |
87 | |
87 | |
88 | ev.data.u64 = fd; /* use u64 to fully initialise the struct, for nicer strace etc. */ |
88 | /* store the generation counter in the upper 32 bits */ |
|
|
89 | ev.data.u64 = fd | ((uint64_t)++anfds [fd].egen << 32); |
89 | ev.events = (nev & EV_READ ? EPOLLIN : 0) |
90 | ev.events = (nev & EV_READ ? EPOLLIN : 0) |
90 | | (nev & EV_WRITE ? EPOLLOUT : 0); |
91 | | (nev & EV_WRITE ? EPOLLOUT : 0); |
91 | |
92 | |
92 | if (expect_true (!epoll_ctl (backend_fd, oev ? EPOLL_CTL_MOD : EPOLL_CTL_ADD, fd, &ev))) |
93 | if (expect_true (!epoll_ctl (backend_fd, oev ? EPOLL_CTL_MOD : EPOLL_CTL_ADD, fd, &ev))) |
93 | return; |
94 | return; |
94 | |
95 | |
95 | if (expect_true (errno == ENOENT)) |
96 | if (expect_true (errno == ENOENT)) |
96 | { |
97 | { |
97 | /* if ENOENT then the fd went away, so try to do the right thing */ |
98 | /* if ENOENT then the fd went away, so try to do the right thing */ |
98 | if (!nev) |
99 | if (!nev) |
99 | return; |
100 | goto dec_egen; |
100 | |
101 | |
101 | if (!epoll_ctl (backend_fd, EPOLL_CTL_ADD, fd, &ev)) |
102 | if (!epoll_ctl (backend_fd, EPOLL_CTL_ADD, fd, &ev)) |
102 | return; |
103 | return; |
103 | } |
104 | } |
104 | else if (expect_true (errno == EEXIST)) |
105 | else if (expect_true (errno == EEXIST)) |
105 | { |
106 | { |
106 | /* EEXIST means we ignored a previous DEL, but the fd is still active */ |
107 | /* EEXIST means we ignored a previous DEL, but the fd is still active */ |
107 | /* if the kernel mask is the same as the new mask, we assume it hasn't changed */ |
108 | /* if the kernel mask is the same as the new mask, we assume it hasn't changed */ |
|
|
109 | if (oldmask == nev) |
|
|
110 | goto dec_egen; |
|
|
111 | |
108 | if (oldmask == nev || !epoll_ctl (backend_fd, EPOLL_CTL_MOD, fd, &ev)) |
112 | if (!epoll_ctl (backend_fd, EPOLL_CTL_MOD, fd, &ev)) |
109 | return; |
113 | return; |
110 | } |
114 | } |
111 | |
115 | |
112 | fd_kill (EV_A_ fd); |
116 | fd_kill (EV_A_ fd); |
|
|
117 | |
|
|
118 | dec_egen: |
|
|
119 | /* we didn't successfully call epoll_ctl, so decrement the generation counter again */ |
|
|
120 | --anfds [fd].egen; |
113 | } |
121 | } |
114 | |
122 | |
115 | static void |
123 | static void |
116 | epoll_poll (EV_P_ ev_tstamp timeout) |
124 | epoll_poll (EV_P_ ev_tstamp timeout) |
117 | { |
125 | { |
… | |
… | |
128 | |
136 | |
129 | for (i = 0; i < eventcnt; ++i) |
137 | for (i = 0; i < eventcnt; ++i) |
130 | { |
138 | { |
131 | struct epoll_event *ev = epoll_events + i; |
139 | struct epoll_event *ev = epoll_events + i; |
132 | |
140 | |
133 | int fd = ev->data.u64; |
141 | int fd = (uint32_t)ev->data.u64; /* mask out the lower 32 bits */ |
134 | int got = (ev->events & (EPOLLOUT | EPOLLERR | EPOLLHUP) ? EV_WRITE : 0) |
142 | int got = (ev->events & (EPOLLOUT | EPOLLERR | EPOLLHUP) ? EV_WRITE : 0) |
135 | | (ev->events & (EPOLLIN | EPOLLERR | EPOLLHUP) ? EV_READ : 0); |
143 | | (ev->events & (EPOLLIN | EPOLLERR | EPOLLHUP) ? EV_READ : 0); |
136 | int want = anfds [fd].events; |
144 | int want = anfds [fd].events; |
|
|
145 | |
|
|
146 | if (anfds [fd].egen != (unsigned char)(ev->data.u64 >> 32)) |
|
|
147 | /*fprintf (stderr, "spurious notification fd %d, %d vs %d\n", fd, (int)(ev->data.u64 >> 32), anfds [fd].egen);*/ |
|
|
148 | continue; |
137 | |
149 | |
138 | if (expect_false (got & ~want)) |
150 | if (expect_false (got & ~want)) |
139 | { |
151 | { |
140 | anfds [fd].emask = want; |
152 | anfds [fd].emask = want; |
141 | |
153 | |