epoll_reactor.ipp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846
  1. //
  2. // detail/impl/epoll_reactor.ipp
  3. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2025 Christopher M. Kohlhoff (chris at kohlhoff dot com)
  6. //
  7. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. #ifndef BOOST_ASIO_DETAIL_IMPL_EPOLL_REACTOR_IPP
  11. #define BOOST_ASIO_DETAIL_IMPL_EPOLL_REACTOR_IPP
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include <boost/asio/detail/config.hpp>
  16. #if defined(BOOST_ASIO_HAS_EPOLL)
  17. #include <cstddef>
  18. #include <sys/epoll.h>
  19. #include <boost/asio/config.hpp>
  20. #include <boost/asio/detail/epoll_reactor.hpp>
  21. #include <boost/asio/detail/scheduler.hpp>
  22. #include <boost/asio/detail/throw_error.hpp>
  23. #include <boost/asio/error.hpp>
  24. #if defined(BOOST_ASIO_HAS_TIMERFD)
  25. # include <sys/timerfd.h>
  26. #endif // defined(BOOST_ASIO_HAS_TIMERFD)
  27. #include <boost/asio/detail/push_options.hpp>
  28. namespace boost {
  29. namespace asio {
  30. namespace detail {
  31. epoll_reactor::epoll_reactor(boost::asio::execution_context& ctx)
  32. : execution_context_service_base<epoll_reactor>(ctx),
  33. scheduler_(use_service<scheduler>(ctx)),
  34. mutex_(config(ctx).get("reactor", "registration_locking", true),
  35. config(ctx).get("reactor", "registration_locking_spin_count", 0)),
  36. interrupter_(config(ctx).get("reactor", "use_eventfd", true)),
  37. epoll_fd_(do_epoll_create()),
  38. timer_fd_(config(ctx).get("reactor", "use_timerfd", true)
  39. ? do_timerfd_create() : -1),
  40. shutdown_(false),
  41. io_locking_(config(ctx).get("reactor", "io_locking", true)),
  42. io_locking_spin_count_(
  43. config(ctx).get("reactor", "io_locking_spin_count", 0)),
  44. registered_descriptors_mutex_(mutex_.enabled(), mutex_.spin_count()),
  45. registered_descriptors_(execution_context::allocator<void>(ctx),
  46. config(ctx).get("reactor", "preallocated_io_objects", 0U),
  47. io_locking_, io_locking_spin_count_)
  48. {
  49. // Add the interrupter's descriptor to epoll.
  50. epoll_event ev = { 0, { 0 } };
  51. ev.events = EPOLLIN | EPOLLERR | EPOLLET;
  52. ev.data.ptr = &interrupter_;
  53. epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, interrupter_.read_descriptor(), &ev);
  54. interrupter_.interrupt();
  55. // Add the timer descriptor to epoll.
  56. if (timer_fd_ != -1)
  57. {
  58. ev.events = EPOLLIN | EPOLLERR;
  59. ev.data.ptr = &timer_fd_;
  60. epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, timer_fd_, &ev);
  61. }
  62. }
  63. epoll_reactor::~epoll_reactor()
  64. {
  65. if (epoll_fd_ != -1)
  66. close(epoll_fd_);
  67. if (timer_fd_ != -1)
  68. close(timer_fd_);
  69. }
  70. void epoll_reactor::shutdown()
  71. {
  72. mutex::scoped_lock lock(mutex_);
  73. shutdown_ = true;
  74. lock.unlock();
  75. op_queue<operation> ops;
  76. while (descriptor_state* state = registered_descriptors_.first())
  77. {
  78. for (int i = 0; i < max_ops; ++i)
  79. ops.push(state->op_queue_[i]);
  80. state->shutdown_ = true;
  81. registered_descriptors_.free(state);
  82. }
  83. timer_queues_.get_all_timers(ops);
  84. scheduler_.abandon_operations(ops);
  85. }
  86. void epoll_reactor::notify_fork(
  87. boost::asio::execution_context::fork_event fork_ev)
  88. {
  89. if (fork_ev == boost::asio::execution_context::fork_child)
  90. {
  91. if (epoll_fd_ != -1)
  92. ::close(epoll_fd_);
  93. epoll_fd_ = -1;
  94. epoll_fd_ = do_epoll_create();
  95. if (timer_fd_ != -1)
  96. {
  97. ::close(timer_fd_);
  98. timer_fd_ = -1;
  99. timer_fd_ = do_timerfd_create();
  100. }
  101. interrupter_.recreate();
  102. // Add the interrupter's descriptor to epoll.
  103. epoll_event ev = { 0, { 0 } };
  104. ev.events = EPOLLIN | EPOLLERR | EPOLLET;
  105. ev.data.ptr = &interrupter_;
  106. epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, interrupter_.read_descriptor(), &ev);
  107. interrupter_.interrupt();
  108. // Add the timer descriptor to epoll.
  109. if (timer_fd_ != -1)
  110. {
  111. ev.events = EPOLLIN | EPOLLERR;
  112. ev.data.ptr = &timer_fd_;
  113. epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, timer_fd_, &ev);
  114. }
  115. update_timeout();
  116. // Re-register all descriptors with epoll.
  117. mutex::scoped_lock descriptors_lock(registered_descriptors_mutex_);
  118. for (descriptor_state* state = registered_descriptors_.first();
  119. state != 0; state = state->next_)
  120. {
  121. if (state->registered_events_ != 0)
  122. {
  123. ev.events = state->registered_events_;
  124. ev.data.ptr = state;
  125. int result = epoll_ctl(epoll_fd_,
  126. EPOLL_CTL_ADD, state->descriptor_, &ev);
  127. if (result != 0)
  128. {
  129. boost::system::error_code ec(errno,
  130. boost::asio::error::get_system_category());
  131. boost::asio::detail::throw_error(ec, "epoll re-registration");
  132. }
  133. }
  134. }
  135. }
  136. }
  137. void epoll_reactor::init_task()
  138. {
  139. scheduler_.init_task();
  140. }
  141. int epoll_reactor::register_descriptor(socket_type descriptor,
  142. epoll_reactor::per_descriptor_data& descriptor_data)
  143. {
  144. descriptor_data = allocate_descriptor_state();
  145. BOOST_ASIO_HANDLER_REACTOR_REGISTRATION((
  146. context(), static_cast<uintmax_t>(descriptor),
  147. reinterpret_cast<uintmax_t>(descriptor_data)));
  148. {
  149. mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
  150. descriptor_data->reactor_ = this;
  151. descriptor_data->descriptor_ = descriptor;
  152. descriptor_data->shutdown_ = false;
  153. for (int i = 0; i < max_ops; ++i)
  154. descriptor_data->try_speculative_[i] = true;
  155. }
  156. epoll_event ev = { 0, { 0 } };
  157. ev.events = EPOLLIN | EPOLLERR | EPOLLHUP | EPOLLPRI | EPOLLET;
  158. descriptor_data->registered_events_ = ev.events;
  159. ev.data.ptr = descriptor_data;
  160. int result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev);
  161. if (result != 0)
  162. {
  163. if (errno == EPERM)
  164. {
  165. // This file descriptor type is not supported by epoll. However, if it is
  166. // a regular file then operations on it will not block. We will allow
  167. // this descriptor to be used and fail later if an operation on it would
  168. // otherwise require a trip through the reactor.
  169. descriptor_data->registered_events_ = 0;
  170. return 0;
  171. }
  172. return errno;
  173. }
  174. return 0;
  175. }
  176. int epoll_reactor::register_internal_descriptor(
  177. int op_type, socket_type descriptor,
  178. epoll_reactor::per_descriptor_data& descriptor_data, reactor_op* op)
  179. {
  180. descriptor_data = allocate_descriptor_state();
  181. BOOST_ASIO_HANDLER_REACTOR_REGISTRATION((
  182. context(), static_cast<uintmax_t>(descriptor),
  183. reinterpret_cast<uintmax_t>(descriptor_data)));
  184. {
  185. mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
  186. descriptor_data->reactor_ = this;
  187. descriptor_data->descriptor_ = descriptor;
  188. descriptor_data->shutdown_ = false;
  189. descriptor_data->op_queue_[op_type].push(op);
  190. for (int i = 0; i < max_ops; ++i)
  191. descriptor_data->try_speculative_[i] = true;
  192. }
  193. epoll_event ev = { 0, { 0 } };
  194. ev.events = EPOLLIN | EPOLLERR | EPOLLHUP | EPOLLPRI | EPOLLET;
  195. descriptor_data->registered_events_ = ev.events;
  196. ev.data.ptr = descriptor_data;
  197. int result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev);
  198. if (result != 0)
  199. {
  200. // Don't try to re-register internal descriptor after fork().
  201. descriptor_data->registered_events_ = 0;
  202. return errno;
  203. }
  204. return 0;
  205. }
  206. void epoll_reactor::move_descriptor(socket_type,
  207. epoll_reactor::per_descriptor_data& target_descriptor_data,
  208. epoll_reactor::per_descriptor_data& source_descriptor_data)
  209. {
  210. target_descriptor_data = source_descriptor_data;
  211. source_descriptor_data = 0;
  212. }
  213. void epoll_reactor::call_post_immediate_completion(
  214. operation* op, bool is_continuation, const void* self)
  215. {
  216. static_cast<const epoll_reactor*>(self)->post_immediate_completion(
  217. op, is_continuation);
  218. }
  219. void epoll_reactor::start_op(int op_type, socket_type descriptor,
  220. epoll_reactor::per_descriptor_data& descriptor_data, reactor_op* op,
  221. bool is_continuation, bool allow_speculative,
  222. void (*on_immediate)(operation*, bool, const void*),
  223. const void* immediate_arg)
  224. {
  225. if (!descriptor_data)
  226. {
  227. op->ec_ = boost::asio::error::bad_descriptor;
  228. on_immediate(op, is_continuation, immediate_arg);
  229. return;
  230. }
  231. mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
  232. if (descriptor_data->shutdown_)
  233. {
  234. on_immediate(op, is_continuation, immediate_arg);
  235. return;
  236. }
  237. if (descriptor_data->op_queue_[op_type].empty())
  238. {
  239. if (allow_speculative
  240. && (op_type != read_op
  241. || descriptor_data->op_queue_[except_op].empty()))
  242. {
  243. if (descriptor_data->try_speculative_[op_type])
  244. {
  245. if (reactor_op::status status = op->perform())
  246. {
  247. if (status == reactor_op::done_and_exhausted)
  248. if (descriptor_data->registered_events_ != 0)
  249. descriptor_data->try_speculative_[op_type] = false;
  250. descriptor_lock.unlock();
  251. on_immediate(op, is_continuation, immediate_arg);
  252. return;
  253. }
  254. }
  255. if (descriptor_data->registered_events_ == 0)
  256. {
  257. op->ec_ = boost::asio::error::operation_not_supported;
  258. on_immediate(op, is_continuation, immediate_arg);
  259. return;
  260. }
  261. if (op_type == write_op)
  262. {
  263. if ((descriptor_data->registered_events_ & EPOLLOUT) == 0)
  264. {
  265. epoll_event ev = { 0, { 0 } };
  266. ev.events = descriptor_data->registered_events_ | EPOLLOUT;
  267. ev.data.ptr = descriptor_data;
  268. if (epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev) == 0)
  269. {
  270. descriptor_data->registered_events_ |= ev.events;
  271. }
  272. else
  273. {
  274. op->ec_ = boost::system::error_code(errno,
  275. boost::asio::error::get_system_category());
  276. on_immediate(op, is_continuation, immediate_arg);
  277. return;
  278. }
  279. }
  280. }
  281. }
  282. else if (descriptor_data->registered_events_ == 0)
  283. {
  284. op->ec_ = boost::asio::error::operation_not_supported;
  285. on_immediate(op, is_continuation, immediate_arg);
  286. return;
  287. }
  288. else
  289. {
  290. if (op_type == write_op)
  291. {
  292. descriptor_data->registered_events_ |= EPOLLOUT;
  293. }
  294. epoll_event ev = { 0, { 0 } };
  295. ev.events = descriptor_data->registered_events_;
  296. ev.data.ptr = descriptor_data;
  297. epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev);
  298. }
  299. }
  300. descriptor_data->op_queue_[op_type].push(op);
  301. scheduler_.work_started();
  302. }
  303. void epoll_reactor::cancel_ops(socket_type,
  304. epoll_reactor::per_descriptor_data& descriptor_data)
  305. {
  306. if (!descriptor_data)
  307. return;
  308. mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
  309. op_queue<operation> ops;
  310. for (int i = 0; i < max_ops; ++i)
  311. {
  312. while (reactor_op* op = descriptor_data->op_queue_[i].front())
  313. {
  314. op->ec_ = boost::asio::error::operation_aborted;
  315. descriptor_data->op_queue_[i].pop();
  316. ops.push(op);
  317. }
  318. }
  319. descriptor_lock.unlock();
  320. scheduler_.post_deferred_completions(ops);
  321. }
  322. void epoll_reactor::cancel_ops_by_key(socket_type,
  323. epoll_reactor::per_descriptor_data& descriptor_data,
  324. int op_type, void* cancellation_key)
  325. {
  326. if (!descriptor_data)
  327. return;
  328. mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
  329. op_queue<operation> ops;
  330. op_queue<reactor_op> other_ops;
  331. while (reactor_op* op = descriptor_data->op_queue_[op_type].front())
  332. {
  333. descriptor_data->op_queue_[op_type].pop();
  334. if (op->cancellation_key_ == cancellation_key)
  335. {
  336. op->ec_ = boost::asio::error::operation_aborted;
  337. ops.push(op);
  338. }
  339. else
  340. other_ops.push(op);
  341. }
  342. descriptor_data->op_queue_[op_type].push(other_ops);
  343. descriptor_lock.unlock();
  344. scheduler_.post_deferred_completions(ops);
  345. }
  346. void epoll_reactor::deregister_descriptor(socket_type descriptor,
  347. epoll_reactor::per_descriptor_data& descriptor_data, bool closing)
  348. {
  349. if (!descriptor_data)
  350. return;
  351. mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
  352. if (!descriptor_data->shutdown_)
  353. {
  354. if (closing)
  355. {
  356. // The descriptor will be automatically removed from the epoll set when
  357. // it is closed.
  358. }
  359. else if (descriptor_data->registered_events_ != 0)
  360. {
  361. epoll_event ev = { 0, { 0 } };
  362. epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, descriptor, &ev);
  363. }
  364. op_queue<operation> ops;
  365. for (int i = 0; i < max_ops; ++i)
  366. {
  367. while (reactor_op* op = descriptor_data->op_queue_[i].front())
  368. {
  369. op->ec_ = boost::asio::error::operation_aborted;
  370. descriptor_data->op_queue_[i].pop();
  371. ops.push(op);
  372. }
  373. }
  374. descriptor_data->descriptor_ = -1;
  375. descriptor_data->shutdown_ = true;
  376. descriptor_lock.unlock();
  377. BOOST_ASIO_HANDLER_REACTOR_DEREGISTRATION((
  378. context(), static_cast<uintmax_t>(descriptor),
  379. reinterpret_cast<uintmax_t>(descriptor_data)));
  380. scheduler_.post_deferred_completions(ops);
  381. // Leave descriptor_data set so that it will be freed by the subsequent
  382. // call to cleanup_descriptor_data.
  383. }
  384. else
  385. {
  386. // We are shutting down, so prevent cleanup_descriptor_data from freeing
  387. // the descriptor_data object and let the destructor free it instead.
  388. descriptor_data = 0;
  389. }
  390. }
  391. void epoll_reactor::deregister_internal_descriptor(socket_type descriptor,
  392. epoll_reactor::per_descriptor_data& descriptor_data)
  393. {
  394. if (!descriptor_data)
  395. return;
  396. mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
  397. if (!descriptor_data->shutdown_)
  398. {
  399. epoll_event ev = { 0, { 0 } };
  400. epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, descriptor, &ev);
  401. op_queue<operation> ops;
  402. for (int i = 0; i < max_ops; ++i)
  403. ops.push(descriptor_data->op_queue_[i]);
  404. descriptor_data->descriptor_ = -1;
  405. descriptor_data->shutdown_ = true;
  406. descriptor_lock.unlock();
  407. BOOST_ASIO_HANDLER_REACTOR_DEREGISTRATION((
  408. context(), static_cast<uintmax_t>(descriptor),
  409. reinterpret_cast<uintmax_t>(descriptor_data)));
  410. // Leave descriptor_data set so that it will be freed by the subsequent
  411. // call to cleanup_descriptor_data.
  412. }
  413. else
  414. {
  415. // We are shutting down, so prevent cleanup_descriptor_data from freeing
  416. // the descriptor_data object and let the destructor free it instead.
  417. descriptor_data = 0;
  418. }
  419. }
  420. void epoll_reactor::cleanup_descriptor_data(
  421. per_descriptor_data& descriptor_data)
  422. {
  423. if (descriptor_data)
  424. {
  425. free_descriptor_state(descriptor_data);
  426. descriptor_data = 0;
  427. }
  428. }
  429. void epoll_reactor::run(long usec, op_queue<operation>& ops)
  430. {
  431. // This code relies on the fact that the scheduler queues the reactor task
  432. // behind all descriptor operations generated by this function. This means,
  433. // that by the time we reach this point, any previously returned descriptor
  434. // operations have already been dequeued. Therefore it is now safe for us to
  435. // reuse and return them for the scheduler to queue again.
  436. // Calculate timeout. Check the timer queues only if timerfd is not in use.
  437. int timeout;
  438. if (usec == 0)
  439. timeout = 0;
  440. else
  441. {
  442. timeout = (usec < 0) ? -1 : ((usec - 1) / 1000 + 1);
  443. if (timer_fd_ == -1)
  444. {
  445. mutex::scoped_lock lock(mutex_);
  446. timeout = get_timeout(timeout);
  447. }
  448. }
  449. // Block on the epoll descriptor.
  450. epoll_event events[128];
  451. int num_events = epoll_wait(epoll_fd_, events, 128, timeout);
  452. #if defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
  453. // Trace the waiting events.
  454. for (int i = 0; i < num_events; ++i)
  455. {
  456. void* ptr = events[i].data.ptr;
  457. if (ptr == &interrupter_)
  458. {
  459. // Ignore.
  460. }
  461. # if defined(BOOST_ASIO_HAS_TIMERFD)
  462. else if (ptr == &timer_fd_)
  463. {
  464. // Ignore.
  465. }
  466. # endif // defined(BOOST_ASIO_HAS_TIMERFD)
  467. else
  468. {
  469. unsigned event_mask = 0;
  470. if ((events[i].events & EPOLLIN) != 0)
  471. event_mask |= BOOST_ASIO_HANDLER_REACTOR_READ_EVENT;
  472. if ((events[i].events & EPOLLOUT))
  473. event_mask |= BOOST_ASIO_HANDLER_REACTOR_WRITE_EVENT;
  474. if ((events[i].events & (EPOLLERR | EPOLLHUP)) != 0)
  475. event_mask |= BOOST_ASIO_HANDLER_REACTOR_ERROR_EVENT;
  476. BOOST_ASIO_HANDLER_REACTOR_EVENTS((context(),
  477. reinterpret_cast<uintmax_t>(ptr), event_mask));
  478. }
  479. }
  480. #endif // defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
  481. #if defined(BOOST_ASIO_HAS_TIMERFD)
  482. bool check_timers = (timer_fd_ == -1);
  483. #else // defined(BOOST_ASIO_HAS_TIMERFD)
  484. bool check_timers = true;
  485. #endif // defined(BOOST_ASIO_HAS_TIMERFD)
  486. // Dispatch the waiting events.
  487. for (int i = 0; i < num_events; ++i)
  488. {
  489. void* ptr = events[i].data.ptr;
  490. if (ptr == &interrupter_)
  491. {
  492. // No need to reset the interrupter since we're leaving the descriptor
  493. // in a ready-to-read state and relying on edge-triggered notifications
  494. // to make it so that we only get woken up when the descriptor's epoll
  495. // registration is updated.
  496. #if defined(BOOST_ASIO_HAS_TIMERFD)
  497. if (timer_fd_ == -1)
  498. check_timers = true;
  499. #else // defined(BOOST_ASIO_HAS_TIMERFD)
  500. check_timers = true;
  501. #endif // defined(BOOST_ASIO_HAS_TIMERFD)
  502. }
  503. #if defined(BOOST_ASIO_HAS_TIMERFD)
  504. else if (ptr == &timer_fd_)
  505. {
  506. check_timers = true;
  507. }
  508. #endif // defined(BOOST_ASIO_HAS_TIMERFD)
  509. else
  510. {
  511. // The descriptor operation doesn't count as work in and of itself, so we
  512. // don't call work_started() here. This still allows the scheduler to
  513. // stop if the only remaining operations are descriptor operations.
  514. descriptor_state* descriptor_data = static_cast<descriptor_state*>(ptr);
  515. if (!ops.is_enqueued(descriptor_data))
  516. {
  517. descriptor_data->set_ready_events(events[i].events);
  518. ops.push(descriptor_data);
  519. }
  520. else
  521. {
  522. descriptor_data->add_ready_events(events[i].events);
  523. }
  524. }
  525. }
  526. if (check_timers)
  527. {
  528. mutex::scoped_lock common_lock(mutex_);
  529. timer_queues_.get_ready_timers(ops);
  530. #if defined(BOOST_ASIO_HAS_TIMERFD)
  531. if (timer_fd_ != -1)
  532. {
  533. itimerspec new_timeout;
  534. itimerspec old_timeout;
  535. int flags = get_timeout(new_timeout);
  536. timerfd_settime(timer_fd_, flags, &new_timeout, &old_timeout);
  537. }
  538. #endif // defined(BOOST_ASIO_HAS_TIMERFD)
  539. }
  540. }
  541. void epoll_reactor::interrupt()
  542. {
  543. epoll_event ev = { 0, { 0 } };
  544. ev.events = EPOLLIN | EPOLLERR | EPOLLET;
  545. ev.data.ptr = &interrupter_;
  546. epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, interrupter_.read_descriptor(), &ev);
  547. }
  548. int epoll_reactor::do_epoll_create()
  549. {
  550. #if defined(EPOLL_CLOEXEC)
  551. int fd = epoll_create1(EPOLL_CLOEXEC);
  552. #else // defined(EPOLL_CLOEXEC)
  553. int fd = -1;
  554. errno = EINVAL;
  555. #endif // defined(EPOLL_CLOEXEC)
  556. if (fd == -1 && (errno == EINVAL || errno == ENOSYS))
  557. {
  558. fd = epoll_create(epoll_size);
  559. if (fd != -1)
  560. ::fcntl(fd, F_SETFD, FD_CLOEXEC);
  561. }
  562. if (fd == -1)
  563. {
  564. boost::system::error_code ec(errno,
  565. boost::asio::error::get_system_category());
  566. boost::asio::detail::throw_error(ec, "epoll");
  567. }
  568. return fd;
  569. }
  570. int epoll_reactor::do_timerfd_create()
  571. {
  572. #if defined(BOOST_ASIO_HAS_TIMERFD)
  573. # if defined(TFD_CLOEXEC)
  574. int fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
  575. # else // defined(TFD_CLOEXEC)
  576. int fd = -1;
  577. errno = EINVAL;
  578. # endif // defined(TFD_CLOEXEC)
  579. if (fd == -1 && errno == EINVAL)
  580. {
  581. fd = timerfd_create(CLOCK_MONOTONIC, 0);
  582. if (fd != -1)
  583. ::fcntl(fd, F_SETFD, FD_CLOEXEC);
  584. }
  585. return fd;
  586. #else // defined(BOOST_ASIO_HAS_TIMERFD)
  587. return -1;
  588. #endif // defined(BOOST_ASIO_HAS_TIMERFD)
  589. }
  590. epoll_reactor::descriptor_state* epoll_reactor::allocate_descriptor_state()
  591. {
  592. mutex::scoped_lock descriptors_lock(registered_descriptors_mutex_);
  593. return registered_descriptors_.alloc(io_locking_, io_locking_spin_count_);
  594. }
  595. void epoll_reactor::free_descriptor_state(epoll_reactor::descriptor_state* s)
  596. {
  597. mutex::scoped_lock descriptors_lock(registered_descriptors_mutex_);
  598. registered_descriptors_.free(s);
  599. }
  600. void epoll_reactor::do_add_timer_queue(timer_queue_base& queue)
  601. {
  602. mutex::scoped_lock lock(mutex_);
  603. timer_queues_.insert(&queue);
  604. }
  605. void epoll_reactor::do_remove_timer_queue(timer_queue_base& queue)
  606. {
  607. mutex::scoped_lock lock(mutex_);
  608. timer_queues_.erase(&queue);
  609. }
  610. void epoll_reactor::update_timeout()
  611. {
  612. #if defined(BOOST_ASIO_HAS_TIMERFD)
  613. if (timer_fd_ != -1)
  614. {
  615. itimerspec new_timeout;
  616. itimerspec old_timeout;
  617. int flags = get_timeout(new_timeout);
  618. timerfd_settime(timer_fd_, flags, &new_timeout, &old_timeout);
  619. return;
  620. }
  621. #endif // defined(BOOST_ASIO_HAS_TIMERFD)
  622. interrupt();
  623. }
  624. int epoll_reactor::get_timeout(int msec)
  625. {
  626. // By default we will wait no longer than 5 minutes. This will ensure that
  627. // any changes to the system clock are detected after no longer than this.
  628. const int max_msec = 5 * 60 * 1000;
  629. return timer_queues_.wait_duration_msec(
  630. (msec < 0 || max_msec < msec) ? max_msec : msec);
  631. }
  632. #if defined(BOOST_ASIO_HAS_TIMERFD)
  633. int epoll_reactor::get_timeout(itimerspec& ts)
  634. {
  635. ts.it_interval.tv_sec = 0;
  636. ts.it_interval.tv_nsec = 0;
  637. long usec = timer_queues_.wait_duration_usec(5 * 60 * 1000 * 1000);
  638. ts.it_value.tv_sec = usec / 1000000;
  639. ts.it_value.tv_nsec = usec ? (usec % 1000000) * 1000 : 1;
  640. return usec ? 0 : TFD_TIMER_ABSTIME;
  641. }
  642. #endif // defined(BOOST_ASIO_HAS_TIMERFD)
  643. struct epoll_reactor::perform_io_cleanup_on_block_exit
  644. {
  645. explicit perform_io_cleanup_on_block_exit(epoll_reactor* r)
  646. : reactor_(r), first_op_(0)
  647. {
  648. }
  649. ~perform_io_cleanup_on_block_exit()
  650. {
  651. if (first_op_)
  652. {
  653. // Post the remaining completed operations for invocation.
  654. if (!ops_.empty())
  655. reactor_->scheduler_.post_deferred_completions(ops_);
  656. // A user-initiated operation has completed, but there's no need to
  657. // explicitly call work_finished() here. Instead, we'll take advantage of
  658. // the fact that the scheduler will call work_finished() once we return.
  659. }
  660. else
  661. {
  662. // No user-initiated operations have completed, so we need to compensate
  663. // for the work_finished() call that the scheduler will make once this
  664. // operation returns.
  665. reactor_->scheduler_.compensating_work_started();
  666. }
  667. }
  668. epoll_reactor* reactor_;
  669. op_queue<operation> ops_;
  670. operation* first_op_;
  671. };
  672. epoll_reactor::descriptor_state::descriptor_state(bool locking, int spin_count)
  673. : operation(&epoll_reactor::descriptor_state::do_complete),
  674. mutex_(locking, spin_count)
  675. {
  676. }
  677. operation* epoll_reactor::descriptor_state::perform_io(uint32_t events)
  678. {
  679. mutex_.lock();
  680. perform_io_cleanup_on_block_exit io_cleanup(reactor_);
  681. mutex::scoped_lock descriptor_lock(mutex_, mutex::scoped_lock::adopt_lock);
  682. // Exception operations must be processed first to ensure that any
  683. // out-of-band data is read before normal data.
  684. static const int flag[max_ops] = { EPOLLIN, EPOLLOUT, EPOLLPRI };
  685. for (int j = max_ops - 1; j >= 0; --j)
  686. {
  687. if (events & (flag[j] | EPOLLERR | EPOLLHUP))
  688. {
  689. try_speculative_[j] = true;
  690. while (reactor_op* op = op_queue_[j].front())
  691. {
  692. if (reactor_op::status status = op->perform())
  693. {
  694. op_queue_[j].pop();
  695. io_cleanup.ops_.push(op);
  696. if (status == reactor_op::done_and_exhausted)
  697. {
  698. try_speculative_[j] = false;
  699. break;
  700. }
  701. }
  702. else
  703. break;
  704. }
  705. }
  706. }
  707. // The first operation will be returned for completion now. The others will
  708. // be posted for later by the io_cleanup object's destructor.
  709. io_cleanup.first_op_ = io_cleanup.ops_.front();
  710. io_cleanup.ops_.pop();
  711. return io_cleanup.first_op_;
  712. }
  713. void epoll_reactor::descriptor_state::do_complete(
  714. void* owner, operation* base,
  715. const boost::system::error_code& ec, std::size_t bytes_transferred)
  716. {
  717. if (owner)
  718. {
  719. descriptor_state* descriptor_data = static_cast<descriptor_state*>(base);
  720. uint32_t events = static_cast<uint32_t>(bytes_transferred);
  721. if (operation* op = descriptor_data->perform_io(events))
  722. {
  723. op->complete(owner, ec, 0);
  724. }
  725. }
  726. }
  727. } // namespace detail
  728. } // namespace asio
  729. } // namespace boost
  730. #include <boost/asio/detail/pop_options.hpp>
  731. #endif // defined(BOOST_ASIO_HAS_EPOLL)
  732. #endif // BOOST_ASIO_DETAIL_IMPL_EPOLL_REACTOR_IPP