github.com/dshulyak/uring@v0.0.0-20210209113719-1b2ec51f1542/core.go (about)

     1  package uring
     2  
     3  import (
     4  	"unsafe"
     5  )
     6  
     7  // syscalls
     8  const (
     9  	IO_URING_SETUP uintptr = 425 + iota
    10  	IO_URING_ENTER
    11  	IO_URING_REGISTER
    12  )
    13  
    14  // operations
    15  const (
    16  	IORING_OP_NOP uint8 = iota
    17  	IORING_OP_READV
    18  	IORING_OP_WRITEV
    19  	IORING_OP_FSYNC
    20  	IORING_OP_READ_FIXED
    21  	IORING_OP_WRITE_FIXED
    22  	IORING_OP_POLL_ADD
    23  	IORING_OP_POLL_REMOVE
    24  	IORING_OP_SYNC_FILE_RANGE
    25  	IORING_OP_SENDMSG
    26  	IORING_OP_RECVMSG
    27  	IORING_OP_TIMEOUT
    28  	IORING_OP_TIMEOUT_REMOVE
    29  	IORING_OP_ACCEPT
    30  	IORING_OP_ASYNC_CANCEL
    31  	IORING_OP_LINK_TIMEOUT
    32  	IORING_OP_CONNECT
    33  	IORING_OP_FALLOCATE
    34  	IORING_OP_OPENAT
    35  	IORING_OP_CLOSE
    36  	IORING_OP_FILES_UPDATE
    37  	IORING_OP_STATX
    38  	IORING_OP_READ
    39  	IORING_OP_WRITE
    40  	IORING_OP_FADVISE
    41  	IORING_OP_MADVISE
    42  	IORING_OP_SEND
    43  	IORING_OP_RECV
    44  	IORING_OP_OPENAT2
    45  	IORING_OP_EPOLL_CTL
    46  	IORING_OP_SPLICE
    47  	IORING_OP_PROVIDE_BUFFERS
    48  	IORING_OP_REMOVE_BUFFERS
    49  	IORING_OP_TEE
    50  	IORING_OP_LAST
    51  )
    52  
    53  // submission queue entry flags
    54  const (
    55  	IOSQE_FIXED_FILE uint8 = 1 << iota
    56  	IOSQE_IO_DRAIN
    57  	IOSQE_IO_LINK
    58  	IOSQE_IO_HARDLINK
    59  	IOSQE_ASYNC
    60  	IOSQE_BUFFER_SELECT
    61  )
    62  
    63  // sqe fsync flags
    64  const IORING_FSYNC_DATASYNC uint32 = 1 << 0
    65  
    66  // sqe timeout flags
    67  const IORING_TIMEOUT_ABS uint32 = 1 << 0
    68  
    69  // sqe splice flags
    70  const SPLICE_F_FD_IN_FIXED uint32 = 1 << 31
    71  
    72  // cqe flags
    73  const IORING_CQE_F_BUFFER uint32 = 1 << 0
    74  
    75  const IORING_CQE_BUFFER_SHIFT uint32 = 16
    76  
    77  // cqe ring flags
    78  const IORING_CQ_EVENTFD_DISABLED uint32 = 1 << 0
    79  
    80  // setup flags
    81  const (
    82  	IORING_SETUP_IOPOLL uint32 = 1 << iota
    83  	IORING_SETUP_SQPOLL
    84  	IORING_SETUP_SQ_AFF
    85  	IORING_SETUP_CQSIZE
    86  	IORING_SETUP_CLAMP
    87  	IORING_SETUP_ATTACH_WQ
    88  )
    89  
    90  // offsets for mmap
    91  const (
    92  	IORING_OFF_SQ_RING int64 = 0
    93  	IORING_OFF_CQ_RING int64 = 0x8000000
    94  	IORING_OFF_SQES    int64 = 0x10000000
    95  )
    96  
    97  // sq ring flags
    98  const (
    99  	IORING_SQ_NEED_WAKEUP uint32 = 1 << iota
   100  	IORING_SQ_CQ_OVERFLOW
   101  )
   102  
   103  // enter flags
   104  const (
   105  	IORING_ENTER_GETEVENTS uint32 = 1 << iota
   106  	IORING_ENTER_SQ_WAKEUP
   107  )
   108  
   109  // params feature flags
   110  const (
   111  	IORING_FEAT_SINGLE_MMAP uint32 = 1 << iota
   112  	IORING_FEAT_NODROP
   113  	IORING_FEAT_SUBMIT_STABLE
   114  	IORING_FEAT_RW_CUR_POS
   115  	IORING_FEAT_CUR_PERSONALITY
   116  	IORING_FEAT_FAST_POLL
   117  	IORING_FEAT_POLL_32BITS
   118  )
   119  
   120  const (
   121  	sqeSize uintptr = 64
   122  	cqeSize uintptr = 16
   123  )
   124  
   125  var (
   126  	empty [sqeSize]byte
   127  )
   128  
   129  // IOUringParams can be used to control io_uring instance behavior.
   130  // For more details see manpages for IO_URING_SETUP(2).
   131  //
   132  // IORING_SETUP_* can be passed to Flags to enable specific behaviour.
   133  //
   134  // Specifying CQEntries will be ignored unlless IORING_SETUP_CQSIZE provided.
   135  //
   136  // SQThreadIdle is in milliseconds and controls amount of time SQ thread can be idle
   137  // before it will be put to sleep by kernel.
   138  //
   139  // SQThreadCPU if specified together with IORING_SETUP_SQ_AFF to bound SQ thread to
   140  // specific CPU.
   141  //
   142  // WQFd can be used to share kernel thread worker pool between multiple io_uring
   143  // instances.
   144  // Ignored unless specified with IORING_SETUP_ATTACH_WQ.
   145  // For an example see queue.ShardedQueue and relevant tests.
   146  //
   147  // Other fields should be ignored, as they are filled in by the kernel.
   148  // TODO those fields can be private, SQOff and CQOff should be definitely private
   149  type IOUringParams struct {
   150  	SQEntries    uint32
   151  	CQEntries    uint32
   152  	Flags        uint32
   153  	SQThreadCPU  uint32
   154  	SQThreadIdle uint32
   155  	Features     uint32
   156  	WQFd         uint32
   157  	// reserved 12 bytes
   158  	resv  [3]uint32
   159  	SQOff SQRingOffsets
   160  	CQOff CQRingOffsets
   161  }
   162  
   163  // SQRingOffsets ...
   164  type SQRingOffsets struct {
   165  	Head        uint32
   166  	Tail        uint32
   167  	RingMask    uint32
   168  	RingEntries uint32
   169  	Flags       uint32
   170  	Dropped     uint32
   171  	Array       uint32
   172  	Resv1       uint32
   173  	Resv2       uint64
   174  }
   175  
   176  // CQRingOffsets ...
   177  type CQRingOffsets struct {
   178  	Head        uint32
   179  	Tail        uint32
   180  	RingMask    uint32
   181  	RingEntries uint32
   182  	Overflow    uint32
   183  	CQEs        uint32
   184  	Flags       uint32
   185  	Resv1       uint32
   186  	Resv2       uint64
   187  }
   188  
   189  // SQEntry is a submission queue entry.
   190  // In C some of the fields are unions. Golang doesn't support union declaration,
   191  // instead SQEntry provided setters with descriptive names.
   192  type SQEntry struct {
   193  	opcode      uint8
   194  	flags       uint8
   195  	ioprio      uint16
   196  	fd          int32
   197  	offset      uint64 // union {off,addr2}
   198  	addr        uint64 // union {addr,splice_off_in}
   199  	len         uint32
   200  	opcodeFlags uint32 // union for opcode specific flags
   201  	userData    uint64
   202  
   203  	bufIG       uint16 // union {buf_index,buf_group}
   204  	personality uint16
   205  	spliceFdIn  int32
   206  	pad2        [2]uint64
   207  }
   208  
   209  func (e *SQEntry) UserData() uint64 {
   210  	return e.userData
   211  }
   212  
   213  // SetOpcode ...
   214  func (e *SQEntry) SetOpcode(opcode uint8) {
   215  	e.opcode = opcode
   216  }
   217  
   218  // SetFlags ...
   219  func (e *SQEntry) SetFlags(flags uint8) {
   220  	e.flags = flags
   221  }
   222  
   223  // SetIOPrio ...
   224  func (e *SQEntry) SetIOPrio(ioprio uint16) {
   225  	e.ioprio = ioprio
   226  }
   227  
   228  // SetFD ...
   229  func (e *SQEntry) SetFD(fd int32) {
   230  	e.fd = fd
   231  }
   232  
   233  // SetUserData ...
   234  func (e *SQEntry) SetUserData(ud uint64) {
   235  	e.userData = ud
   236  }
   237  
   238  // SetOffset ...
   239  func (e *SQEntry) SetOffset(off uint64) {
   240  	e.offset = off
   241  }
   242  
   243  // SetAddr ...
   244  func (e *SQEntry) SetAddr(addr uint64) {
   245  	e.addr = addr
   246  }
   247  
   248  // SetLen ....
   249  func (e *SQEntry) SetLen(len uint32) {
   250  	e.len = len
   251  }
   252  
   253  // SetOpcodeFlags ...
   254  func (e *SQEntry) SetOpcodeFlags(flags uint32) {
   255  	e.opcodeFlags = flags
   256  }
   257  
   258  // SetBufIndex ...
   259  func (e *SQEntry) SetBufIndex(index uint16) {
   260  	e.bufIG = index
   261  }
   262  
   263  // SetBufGroup ...
   264  func (e *SQEntry) SetBufGroup(group uint16) {
   265  	e.bufIG = group
   266  }
   267  
   268  // SetPersonality ...
   269  func (e *SQEntry) SetPersonality(personality uint16) {
   270  	e.personality = personality
   271  }
   272  
   273  // SetSpliceOffIn ...
   274  func (e *SQEntry) SetSpliceOffIn(val uint64) {
   275  	e.addr = val
   276  }
   277  
   278  // SetSpliceFdIn ...
   279  func (e *SQEntry) SetSpliceFdIn(val int32) {
   280  	e.spliceFdIn = val
   281  }
   282  
   283  // SetAddr2 ...
   284  func (e *SQEntry) SetAddr2(addr2 uint64) {
   285  	e.offset = addr2
   286  }
   287  
   288  // Reset will reset all fields to zeros.
   289  func (e *SQEntry) Reset() {
   290  	// this is by far the fastest way to reset sqe memory to zeros
   291  	// on my machine 2ns vs 60ns for zeroing each byte
   292  	buf := (*[sqeSize]byte)(unsafe.Pointer(e))
   293  	copy(buf[:], empty[:])
   294  }
   295  
   296  // CQEntry is a submission queue entry.
   297  // Filled in by kernel, applications should not modify it.
   298  type CQEntry struct {
   299  	userData uint64
   300  	res      int32
   301  	flags    uint32
   302  }
   303  
   304  // Result ...
   305  func (e CQEntry) Result() int32 {
   306  	return e.res
   307  }
   308  
   309  // Flags ...
   310  func (e CQEntry) Flags() uint32 {
   311  	return e.flags
   312  }
   313  
   314  // UserData is a copy of user data from SQEntry.
   315  func (e CQEntry) UserData() uint64 {
   316  	return e.userData
   317  }
   318  
   319  type Sigset_t struct {
   320  	Val [16]uint64
   321  }
   322  
   323  type IOUringFilesUpdate struct {
   324  	Offset uint32
   325  	resv   uint32
   326  	Fds    *int32
   327  }