gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/test/util/io_uring_util.cc (about)

     1  // Copyright 2022 The gVisor Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  #include "test/util/io_uring_util.h"
    16  
    17  #include <memory>
    18  
    19  namespace gvisor {
    20  namespace testing {
    21  
    22  PosixErrorOr<std::unique_ptr<IOUring>> IOUring::InitIOUring(
    23      unsigned int entries, IOUringParams &params) {
    24    PosixErrorOr<FileDescriptor> fd = NewIOUringFD(entries, params);
    25    if (!fd.ok()) {
    26      return fd.error();
    27    }
    28  
    29    return std::make_unique<IOUring>(std::move(fd.ValueOrDie()), entries, params);
    30  }
    31  
    32  IOUring::IOUring(FileDescriptor &&fd, unsigned int entries,
    33                   IOUringParams &params)
    34      : iouringfd_(std::move(fd)) {
    35    cring_sz_ = params.cq_off.cqes + params.cq_entries * sizeof(IOUringCqe);
    36    sring_sz_ = params.sq_off.array + params.sq_entries * sizeof(unsigned);
    37    sqes_sz_ = params.sq_entries * sizeof(IOUringSqe);
    38  
    39    cq_ptr_ =
    40        mmap(0, cring_sz_, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE,
    41             iouringfd_.get(), IORING_OFF_SQ_RING);
    42    sq_ptr_ =
    43        mmap(0, sring_sz_, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE,
    44             iouringfd_.get(), IORING_OFF_SQ_RING);
    45    sqe_ptr_ = mmap(0, sqes_sz_, PROT_READ | PROT_WRITE,
    46                    MAP_SHARED | MAP_POPULATE, iouringfd_.get(), IORING_OFF_SQES);
    47  
    48    cqes_ = reinterpret_cast<IOUringCqe *>(reinterpret_cast<char *>(cq_ptr_) +
    49                                           params.cq_off.cqes);
    50  
    51    cq_head_ptr_ = reinterpret_cast<uint32_t *>(
    52        reinterpret_cast<char *>(cq_ptr_) + params.cq_off.head);
    53    cq_tail_ptr_ = reinterpret_cast<uint32_t *>(
    54        reinterpret_cast<char *>(cq_ptr_) + params.cq_off.tail);
    55    sq_head_ptr_ = reinterpret_cast<uint32_t *>(
    56        reinterpret_cast<char *>(sq_ptr_) + params.sq_off.head);
    57    sq_tail_ptr_ = reinterpret_cast<uint32_t *>(
    58        reinterpret_cast<char *>(sq_ptr_) + params.sq_off.tail);
    59    cq_overflow_ptr_ = reinterpret_cast<uint32_t *>(
    60        reinterpret_cast<char *>(cq_ptr_) + params.cq_off.overflow);
    61    sq_dropped_ptr_ = reinterpret_cast<uint32_t *>(
    62        reinterpret_cast<char *>(sq_ptr_) + params.sq_off.dropped);
    63  
    64    sq_mask_ = *(reinterpret_cast<uint32_t *>(reinterpret_cast<char *>(sq_ptr_) +
    65                                              params.sq_off.ring_mask));
    66    sq_array_ = reinterpret_cast<unsigned *>(reinterpret_cast<char *>(sq_ptr_) +
    67                                             params.sq_off.array);
    68  }
    69  
    70  IOUring::~IOUring() {
    71    munmap(cq_ptr_, cring_sz_);
    72    munmap(sq_ptr_, sring_sz_);
    73    munmap(sqe_ptr_, sqes_sz_);
    74  }
    75  
    76  uint32_t IOUring::load_cq_head() { return io_uring_atomic_read(cq_head_ptr_); }
    77  
    78  uint32_t IOUring::load_cq_tail() { return io_uring_atomic_read(cq_tail_ptr_); }
    79  
    80  uint32_t IOUring::load_sq_head() { return io_uring_atomic_read(sq_head_ptr_); }
    81  
    82  uint32_t IOUring::load_sq_tail() { return io_uring_atomic_read(sq_tail_ptr_); }
    83  
    84  uint32_t IOUring::load_cq_overflow() {
    85    return io_uring_atomic_read(cq_overflow_ptr_);
    86  }
    87  
    88  uint32_t IOUring::load_sq_dropped() {
    89    return io_uring_atomic_read(sq_dropped_ptr_);
    90  }
    91  
    92  void IOUring::store_cq_head(uint32_t cq_head_val) {
    93    io_uring_atomic_write(cq_head_ptr_, cq_head_val);
    94  }
    95  
    96  void IOUring::store_sq_tail(uint32_t sq_tail_val) {
    97    io_uring_atomic_write(sq_tail_ptr_, sq_tail_val);
    98  }
    99  
   100  int IOUring::Enter(unsigned int to_submit, unsigned int min_complete,
   101                     unsigned int flags, sigset_t *sig) {
   102    return IOUringEnter(iouringfd_.get(), to_submit, min_complete, flags, sig);
   103  }
   104  
   105  IOUringCqe *IOUring::get_cqes() { return cqes_; }
   106  
   107  IOUringSqe *IOUring::get_sqes() {
   108    return reinterpret_cast<IOUringSqe *>(sqe_ptr_);
   109  }
   110  
   111  uint32_t IOUring::get_sq_mask() { return sq_mask_; }
   112  
   113  unsigned *IOUring::get_sq_array() { return sq_array_; }
   114  
   115  }  // namespace testing
   116  }  // namespace gvisor