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 }