MCPcopy Create free account
hub / github.com/apache/brpc / fd_wait

Function fd_wait

src/bthread/fd.cpp:206–276  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

204 }
205
206 int fd_wait(int fd, unsigned events, const timespec* abstime) {
207 butil::atomic<EpollButex*>* p = fd_butexes.get_or_new(fd);
208 if (NULL == p) {
209 errno = ENOMEM;
210 return -1;
211 }
212
213 EpollButex* butex = p->load(butil::memory_order_consume);
214 if (NULL == butex) {
215 // It is rare to wait on one file descriptor from multiple threads
216 // simultaneously. Creating singleton by optimistic locking here
217 // saves mutexes for each butex.
218 butex = butex_create_checked<EpollButex>();
219 butex->store(0, butil::memory_order_relaxed);
220 EpollButex* expected = NULL;
221 if (!p->compare_exchange_strong(expected, butex,
222 butil::memory_order_release,
223 butil::memory_order_consume)) {
224 butex_destroy(butex);
225 butex = expected;
226 }
227 }
228
229 while (butex == CLOSING_GUARD) { // bthread_close() is running.
230 if (sched_yield() < 0) {
231 return -1;
232 }
233 butex = p->load(butil::memory_order_consume);
234 }
235 // Save value of butex before adding to epoll because the butex may
236 // be changed before butex_wait. No memory fence because EPOLL_CTL_MOD
237 // and EPOLL_CTL_ADD shall have release fence.
238 const int expected_val = butex->load(butil::memory_order_relaxed);
239
240#if defined(OS_LINUX)
241# ifdef BAIDU_KERNEL_FIXED_EPOLLONESHOT_BUG
242 epoll_event evt = { events | EPOLLONESHOT, { butex } };
243 if (epoll_ctl(_epfd, EPOLL_CTL_MOD, fd, &evt) < 0) {
244 if (epoll_ctl(_epfd, EPOLL_CTL_ADD, fd, &evt) < 0 &&
245 errno != EEXIST) {
246 PLOG(FATAL) << "Fail to add fd=" << fd << " into epfd=" << _epfd;
247 return -1;
248 }
249 }
250# else
251 epoll_event evt;
252 evt.events = events;
253 evt.data.fd = fd;
254 if (epoll_ctl(_epfd, EPOLL_CTL_ADD, fd, &evt) < 0 &&
255 errno != EEXIST) {
256 PLOG(FATAL) << "Fail to add fd=" << fd << " into epfd=" << _epfd;
257 return -1;
258 }
259# endif
260#elif defined(OS_MACOSX)
261 struct kevent kqueue_event;
262 EV_SET(&kqueue_event, fd, events, EV_ADD | EV_ENABLE | EV_ONESHOT,
263 0, 0, butex);

Callers

nothing calls this directly

Calls 7

butex_destroyFunction · 0.85
butex_waitFunction · 0.85
get_or_newMethod · 0.80
keventClass · 0.70
loadMethod · 0.45
storeMethod · 0.45

Tested by

no test coverage detected