File indexing completed on 2024-11-15 09:02:48
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_ASIO_DETAIL_IO_URING_SERVICE_HPP
0012 #define BOOST_ASIO_DETAIL_IO_URING_SERVICE_HPP
0013
0014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0015 # pragma once
0016 #endif
0017
0018 #include <boost/asio/detail/config.hpp>
0019
0020 #if defined(BOOST_ASIO_HAS_IO_URING)
0021
0022 #include <liburing.h>
0023 #include <boost/asio/detail/atomic_count.hpp>
0024 #include <boost/asio/detail/buffer_sequence_adapter.hpp>
0025 #include <boost/asio/detail/conditionally_enabled_mutex.hpp>
0026 #include <boost/asio/detail/io_uring_operation.hpp>
0027 #include <boost/asio/detail/limits.hpp>
0028 #include <boost/asio/detail/object_pool.hpp>
0029 #include <boost/asio/detail/op_queue.hpp>
0030 #include <boost/asio/detail/reactor.hpp>
0031 #include <boost/asio/detail/scheduler_task.hpp>
0032 #include <boost/asio/detail/timer_queue_base.hpp>
0033 #include <boost/asio/detail/timer_queue_set.hpp>
0034 #include <boost/asio/detail/wait_op.hpp>
0035 #include <boost/asio/execution_context.hpp>
0036
0037 #include <boost/asio/detail/push_options.hpp>
0038
0039 namespace boost {
0040 namespace asio {
0041 namespace detail {
0042
0043 class io_uring_service
0044 : public execution_context_service_base<io_uring_service>,
0045 public scheduler_task
0046 {
0047 private:
0048
0049 typedef conditionally_enabled_mutex mutex;
0050
0051 public:
0052 enum op_types { read_op = 0, write_op = 1, except_op = 2, max_ops = 3 };
0053
0054 class io_object;
0055
0056
0057 class io_queue : operation
0058 {
0059 friend class io_uring_service;
0060
0061 io_object* io_object_;
0062 op_queue<io_uring_operation> op_queue_;
0063 bool cancel_requested_;
0064
0065 BOOST_ASIO_DECL io_queue();
0066 void set_result(int r) { task_result_ = static_cast<unsigned>(r); }
0067 BOOST_ASIO_DECL operation* perform_io(int result);
0068 BOOST_ASIO_DECL static void do_complete(void* owner, operation* base,
0069 const boost::system::error_code& ec, std::size_t bytes_transferred);
0070 };
0071
0072
0073 class io_object
0074 {
0075 friend class io_uring_service;
0076 friend class object_pool_access;
0077
0078 io_object* next_;
0079 io_object* prev_;
0080
0081 mutex mutex_;
0082 io_uring_service* service_;
0083 io_queue queues_[max_ops];
0084 bool shutdown_;
0085
0086 BOOST_ASIO_DECL io_object(bool locking);
0087 };
0088
0089
0090 typedef io_object* per_io_object_data;
0091
0092
0093 BOOST_ASIO_DECL io_uring_service(boost::asio::execution_context& ctx);
0094
0095
0096 BOOST_ASIO_DECL ~io_uring_service();
0097
0098
0099 BOOST_ASIO_DECL void shutdown();
0100
0101
0102 BOOST_ASIO_DECL void notify_fork(
0103 boost::asio::execution_context::fork_event fork_ev);
0104
0105
0106 BOOST_ASIO_DECL void init_task();
0107
0108
0109 BOOST_ASIO_DECL void register_io_object(io_object*& io_obj);
0110
0111
0112 BOOST_ASIO_DECL void register_internal_io_object(
0113 io_object*& io_obj, int op_type, io_uring_operation* op);
0114
0115
0116 BOOST_ASIO_DECL void register_buffers(const ::iovec* v, unsigned n);
0117
0118
0119 BOOST_ASIO_DECL void unregister_buffers();
0120
0121
0122 void post_immediate_completion(operation* op, bool is_continuation);
0123
0124
0125
0126 BOOST_ASIO_DECL void start_op(int op_type, per_io_object_data& io_obj,
0127 io_uring_operation* op, bool is_continuation);
0128
0129
0130
0131
0132 BOOST_ASIO_DECL void cancel_ops(per_io_object_data& io_obj);
0133
0134
0135
0136
0137 BOOST_ASIO_DECL void cancel_ops_by_key(per_io_object_data& io_obj,
0138 int op_type, void* cancellation_key);
0139
0140
0141
0142
0143 BOOST_ASIO_DECL void deregister_io_object(per_io_object_data& io_obj);
0144
0145
0146
0147 BOOST_ASIO_DECL void cleanup_io_object(per_io_object_data& io_obj);
0148
0149
0150 template <typename Time_Traits>
0151 void add_timer_queue(timer_queue<Time_Traits>& timer_queue);
0152
0153
0154 template <typename Time_Traits>
0155 void remove_timer_queue(timer_queue<Time_Traits>& timer_queue);
0156
0157
0158
0159 template <typename Time_Traits>
0160 void schedule_timer(timer_queue<Time_Traits>& queue,
0161 const typename Time_Traits::time_type& time,
0162 typename timer_queue<Time_Traits>::per_timer_data& timer, wait_op* op);
0163
0164
0165
0166 template <typename Time_Traits>
0167 std::size_t cancel_timer(timer_queue<Time_Traits>& queue,
0168 typename timer_queue<Time_Traits>::per_timer_data& timer,
0169 std::size_t max_cancelled = (std::numeric_limits<std::size_t>::max)());
0170
0171
0172 template <typename Time_Traits>
0173 void cancel_timer_by_key(timer_queue<Time_Traits>& queue,
0174 typename timer_queue<Time_Traits>::per_timer_data* timer,
0175 void* cancellation_key);
0176
0177
0178 template <typename Time_Traits>
0179 void move_timer(timer_queue<Time_Traits>& queue,
0180 typename timer_queue<Time_Traits>::per_timer_data& target,
0181 typename timer_queue<Time_Traits>::per_timer_data& source);
0182
0183
0184
0185 BOOST_ASIO_DECL void run(long usec, op_queue<operation>& ops);
0186
0187
0188 BOOST_ASIO_DECL void interrupt();
0189
0190 private:
0191
0192 enum { ring_size = 16384 };
0193
0194
0195 enum { submit_batch_size = 128 };
0196
0197
0198 enum { complete_batch_size = 128 };
0199
0200
0201 class event_fd_read_op;
0202
0203
0204 BOOST_ASIO_DECL void init_ring();
0205
0206
0207 BOOST_ASIO_DECL void register_with_reactor();
0208
0209
0210 BOOST_ASIO_DECL io_object* allocate_io_object();
0211
0212
0213 BOOST_ASIO_DECL void free_io_object(io_object* s);
0214
0215
0216
0217
0218 BOOST_ASIO_DECL bool do_cancel_ops(
0219 per_io_object_data& io_obj, op_queue<operation>& ops);
0220
0221
0222 BOOST_ASIO_DECL void do_add_timer_queue(timer_queue_base& queue);
0223
0224
0225 BOOST_ASIO_DECL void do_remove_timer_queue(timer_queue_base& queue);
0226
0227
0228 BOOST_ASIO_DECL void update_timeout();
0229
0230
0231 BOOST_ASIO_DECL __kernel_timespec get_timeout() const;
0232
0233
0234 BOOST_ASIO_DECL ::io_uring_sqe* get_sqe();
0235
0236
0237 BOOST_ASIO_DECL void submit_sqes();
0238
0239
0240 BOOST_ASIO_DECL void post_submit_sqes_op(mutex::scoped_lock& lock);
0241
0242
0243 BOOST_ASIO_DECL void push_submit_sqes_op(op_queue<operation>& ops);
0244
0245
0246 class submit_sqes_op : operation
0247 {
0248 friend class io_uring_service;
0249
0250 io_uring_service* service_;
0251
0252 BOOST_ASIO_DECL submit_sqes_op(io_uring_service* s);
0253 BOOST_ASIO_DECL static void do_complete(void* owner, operation* base,
0254 const boost::system::error_code& ec, std::size_t bytes_transferred);
0255 };
0256
0257
0258 scheduler& scheduler_;
0259
0260
0261 mutex mutex_;
0262
0263
0264 ::io_uring ring_;
0265
0266
0267 atomic_count outstanding_work_;
0268
0269
0270 submit_sqes_op submit_sqes_op_;
0271
0272
0273 int pending_sqes_;
0274
0275
0276 bool pending_submit_sqes_op_;
0277
0278
0279 bool shutdown_;
0280
0281
0282 timer_queue_set timer_queues_;
0283
0284
0285
0286 __kernel_timespec timeout_;
0287
0288
0289 mutex registration_mutex_;
0290
0291
0292 object_pool<io_object> registered_io_objects_;
0293
0294
0295 struct perform_io_cleanup_on_block_exit;
0296 friend struct perform_io_cleanup_on_block_exit;
0297
0298
0299 reactor& reactor_;
0300
0301
0302 reactor::per_descriptor_data reactor_data_;
0303
0304
0305 int event_fd_;
0306 };
0307
0308 }
0309 }
0310 }
0311
0312 #include <boost/asio/detail/pop_options.hpp>
0313
0314 #include <boost/asio/detail/impl/io_uring_service.hpp>
0315 #if defined(BOOST_ASIO_HEADER_ONLY)
0316 # include <boost/asio/detail/impl/io_uring_service.ipp>
0317 #endif
0318
0319 #endif
0320
0321 #endif