LCOV - code coverage report
Current view: top level - util/io_uring - fd_io_uring.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 25 41 61.0 %
Date: 2026-09-17 04:28:31 Functions: 6 32 18.8 %

          Line data    Source code
       1             : #ifndef HEADER_fd_src_util_io_uring_fd_io_uring_h
       2             : #define HEADER_fd_src_util_io_uring_fd_io_uring_h
       3             : 
       4             : /* fd_io_uring.h provides APIs for job submission and completion polling
       5             :    against io_uring instances.
       6             : 
       7             :    These APIs are suitable for cooperative or interrupt-driven I/O only
       8             :    (completions delivered on the thread that submitted requests). These
       9             :    APIs do not support busy polling with kernel worker threads  */
      10             : 
      11             : #include "fd_io_uring_sys.h"
      12             : #include <stdatomic.h>
      13             : 
      14             : struct fd_io_uring_sq {
      15             : 
      16             :   /* State bits shared with the kernel.
      17             : 
      18             :      The kernel might set these in an interrupt context, therefore we
      19             :      accesses to be explicit.  We assume no concurrent operation
      20             :      (although io_uring supports such operation), so accesses to these
      21             :      do not need stronger consistency than C11 relaxed. */
      22             : 
      23             :   atomic_uint * khead;
      24             :   atomic_uint * ktail;
      25             :   atomic_uint * kflags;
      26             :   atomic_uint * kdropped;
      27             : 
      28             :   uint *              array;
      29             :   fd_io_uring_sqe_t * sqes;
      30             : 
      31             :   uint sqe_head;
      32             :   uint sqe_tail;
      33             :   uint depth;
      34             : };
      35             : 
      36             : typedef struct fd_io_uring_sq fd_io_uring_sq_t;
      37             : 
      38             : struct fd_io_uring_cq {
      39             :   uint depth;
      40             : 
      41             :   atomic_uint * khead;
      42             :   atomic_uint * ktail;
      43             :   atomic_uint * koverflow;
      44             : 
      45             :   fd_io_uring_cqe_t * cqes;
      46             : };
      47             : 
      48             : typedef struct fd_io_uring_cq fd_io_uring_cq_t;
      49             : 
      50             : struct fd_io_uring {
      51             :   int ioring_fd;
      52             : 
      53             :   fd_io_uring_sq_t sq[1];
      54             :   fd_io_uring_cq_t cq[1];
      55             : 
      56             :   /* Kernel-allocated memory */
      57             : 
      58             :   void * kern_sq_mem;
      59             :   ulong  kern_sq_sz;
      60             :   void * kern_cq_mem;
      61             :   ulong  kern_cq_sz;
      62             :   void * kern_sqe_mem;
      63             :   ulong  kern_sqe_sz;
      64             : };
      65             : 
      66             : typedef struct fd_io_uring fd_io_uring_t;
      67             : 
      68             : FD_PROTOTYPES_BEGIN
      69             : 
      70             : /* fd_io_uring_submit flushes the submission queue and waits for
      71             :    wait_cnt completions to arrive.  Returns the number of submitted
      72             :    entries on success, or a negative errno value on error. */
      73             : 
      74             : FD_FN_UNUSED static int
      75             : fd_io_uring_submit( fd_io_uring_sq_t * sq,
      76             :                     int                ring_fd,
      77             :                     uint               wait_cnt,
      78           0 :                     uint               flags ) {
      79           0 :   uint tail = sq->sqe_tail;
      80           0 :   atomic_store_explicit( sq->ktail, tail, memory_order_release );
      81           0 :   uint head = atomic_load_explicit( sq->khead, memory_order_relaxed );
      82           0 :   sq->sqe_head = head;
      83           0 :   uint to_submit = tail - head;
      84           0 :   return fd_io_uring_enter( ring_fd, to_submit, wait_cnt, flags, NULL, 0 );
      85           0 : }
      86             : 
      87             : static inline uint
      88         786 : fd_io_uring_sq_dropped( fd_io_uring_sq_t const * sq ) {
      89         786 :   return atomic_load_explicit( sq->kdropped, memory_order_relaxed );
      90         786 : }
      91             : 
      92             : static inline uint
      93         786 : fd_io_uring_cq_overflow( fd_io_uring_cq_t const * cq ) {
      94         786 :   return atomic_load_explicit( cq->koverflow, memory_order_relaxed );
      95         786 : }
      96             : 
      97             : static inline fd_io_uring_sqe_t *
      98         999 : fd_io_uring_get_sqe( fd_io_uring_sq_t * sq ) {
      99         999 :   uint tail  = sq->sqe_tail;
     100         999 :   uint depth = sq->depth;
     101         999 :   if( tail+1U - sq->sqe_head > depth ) {
     102           0 :     return NULL;
     103           0 :   }
     104         999 :   sq->sqe_tail = tail+1U;
     105         999 :   return &sq->sqes[ tail & (depth-1U) ];
     106         999 : }
     107             : 
     108             : /* fd_io_uring_sq_space_left returns the lower bound on the number of
     109             :    free SQEs. */
     110             : 
     111             : static inline uint
     112           0 : fd_io_uring_sq_space_left( fd_io_uring_sq_t * sq ) {
     113           0 :   uint head    = atomic_load_explicit( sq->khead, memory_order_acquire );
     114           0 :   uint pending = sq->sqe_tail - head;
     115           0 :   sq->sqe_head = head;
     116           0 :   return (uint)sq->depth - pending;
     117           0 : }
     118             : 
     119             : /* fd_io_uring_cq_ready returns the lower bound on the number of CQEs
     120             :    not yet received. */
     121             : 
     122             : static inline uint
     123        1578 : fd_io_uring_cq_ready( fd_io_uring_cq_t const * cq ) {
     124        1578 :   uint tail = atomic_load_explicit( cq->ktail, memory_order_acquire );
     125        1578 :   uint head = atomic_load_explicit( cq->khead, memory_order_relaxed );
     126        1578 :   return tail - head;
     127        1578 : }
     128             : 
     129             : static inline void
     130             : fd_io_uring_cq_advance( fd_io_uring_cq_t * cq,
     131         972 :                         uint               cnt ) {
     132         972 :   uint head = atomic_load_explicit( cq->khead, memory_order_relaxed );
     133         972 :   atomic_store_explicit( cq->khead, head + cnt, memory_order_release );
     134         972 : }
     135             : 
     136             : static inline fd_io_uring_cqe_t *
     137         972 : fd_io_uring_cq_head( fd_io_uring_cq_t const * cq ) {
     138             :   uint head = atomic_load_explicit( cq->khead, memory_order_relaxed );
     139         972 :   return &cq->cqes[ head & (cq->depth - 1U) ];
     140         972 : }
     141             : 
     142             : FD_PROTOTYPES_END
     143             : 
     144             : #endif /* HEADER_fd_src_util_io_uring_fd_io_uring_h */

Generated by: LCOV version 1.14