github.com/ii64/gouring@v0.4.1/setup.go (about) 1 package gouring 2 3 import ( 4 "syscall" 5 "unsafe" 6 ) 7 8 // func io_uring_queue_init(entries uint32, ring *IoUring, flags uint32) error { 9 // p := new(IoUringParams) 10 // p.Flags = flags 11 // return io_uring_queue_init_params(entries, ring, p) 12 // } 13 14 func io_uring_queue_init_params(entries uint32, ring *IoUring, p *IoUringParams) error { 15 fd, err := io_uring_setup(uintptr(entries), p) 16 if err != nil { 17 return err 18 } 19 err = io_uring_queue_mmap(fd, p, ring) 20 if err != nil { 21 return err 22 } 23 ring.Features = p.Features 24 return nil 25 } 26 27 func (ring *IoUring) io_uring_queue_exit() { 28 sq := &ring.Sq 29 cq := &ring.Cq 30 sqeSize := SizeofIoUringSqe 31 if ring.Flags&IORING_SETUP_SQE128 != 0 { 32 sqeSize += 64 33 } 34 munmap(unsafe.Pointer(sq.Sqes), sqeSize*uintptr(*sq._RingEntries())) 35 io_uring_unmap_rings(sq, cq) 36 /* 37 * Not strictly required, but frees up the slot we used now rather 38 * than at process exit time. 39 */ 40 if ring.IntFlags&INT_FLAG_REG_RING != 0 { 41 ring.io_uring_unregister_ring_fd() 42 } 43 syscall.Close(int(ring.RingFd)) 44 } 45 46 func io_uring_queue_mmap(fd int, p *IoUringParams, ring *IoUring) error { 47 err := io_uring_mmap(fd, p, &ring.Sq, &ring.Cq) 48 if err != nil { 49 return err 50 } 51 ring.Flags = p.Flags 52 ring.RingFd, ring.EnterRingFd = fd, fd 53 ring.IntFlags = 0 54 return nil 55 } 56 57 func io_uring_mmap(fd int, p *IoUringParams, sq *IoUringSq, cq *IoUringCq) (err error) { 58 size := SizeofIoUringCqe 59 if p.Flags&IORING_SETUP_CQE32 != 0 { 60 size += SizeofIoUringCqe 61 } 62 63 sq.RingSz = p.SqOff.Array + p.SqEntries*uint32(SizeofUnsigned) 64 cq.RingSz = p.CqOff.Cqes + p.CqEntries*uint32(size) 65 66 if p.Features&IORING_FEAT_SINGLE_MMAP != 0 { 67 if cq.RingSz > sq.RingSz { 68 sq.RingSz = cq.RingSz 69 } 70 // cq.RingSz = sq.RingSz 71 } 72 // alloc sq ring 73 sq.RingPtr, err = mmap(nil, uintptr(sq.RingSz), 74 syscall.PROT_READ|syscall.PROT_WRITE, 75 syscall.MAP_SHARED|syscall.MAP_POPULATE, 76 fd, IORING_OFF_SQ_RING) 77 if err != nil { 78 return 79 } 80 81 if p.Features&IORING_FEAT_SINGLE_MMAP != 0 { 82 cq.RingPtr = sq.RingPtr 83 } else { 84 // alloc cq ring 85 cq.RingPtr, err = mmap(nil, uintptr(cq.RingSz), 86 syscall.PROT_READ|syscall.PROT_WRITE, 87 syscall.MAP_SHARED|syscall.MAP_POPULATE, 88 fd, IORING_OFF_CQ_RING) 89 if err != nil { 90 // goto errLabel 91 io_uring_unmap_rings(sq, cq) 92 return 93 } 94 } 95 96 //sq 97 sq.head = (unsafe.Pointer(uintptr(sq.RingPtr) + uintptr(p.SqOff.Head))) 98 sq.tail = (unsafe.Pointer(uintptr(sq.RingPtr) + uintptr(p.SqOff.Tail))) 99 sq.ringMask = (unsafe.Pointer(uintptr(sq.RingPtr) + uintptr(p.SqOff.RingMask))) 100 sq.ringEntries = (unsafe.Pointer(uintptr(sq.RingPtr) + uintptr(p.SqOff.RingEntries))) 101 sq.flags = (unsafe.Pointer(uintptr(sq.RingPtr) + uintptr(p.SqOff.Flags))) 102 sq.dropped = (unsafe.Pointer(uintptr(sq.RingPtr) + uintptr(p.SqOff.Dropped))) 103 sq.Array = (uint32Array)(unsafe.Pointer(uintptr(sq.RingPtr) + uintptr(p.SqOff.Array))) 104 105 size = SizeofIoUringSqe 106 if p.Flags&IORING_SETUP_SQE128 != 0 { 107 size += 64 108 } 109 var sqeAddr unsafe.Pointer 110 sqeAddr, err = mmap(nil, size*uintptr(p.SqEntries), 111 syscall.PROT_READ|syscall.PROT_WRITE, 112 syscall.MAP_SHARED|syscall.MAP_POPULATE, 113 fd, IORING_OFF_SQES) 114 if err != nil { 115 //errLabel: 116 io_uring_unmap_rings(sq, cq) 117 return 118 } 119 sq.Sqes = (ioUringSqeArray)(sqeAddr) 120 121 //cq 122 cq.head = (unsafe.Pointer(uintptr(cq.RingPtr) + uintptr(p.CqOff.Head))) 123 cq.tail = (unsafe.Pointer(uintptr(cq.RingPtr) + uintptr(p.CqOff.Tail))) 124 cq.ringMask = (unsafe.Pointer(uintptr(cq.RingPtr) + uintptr(p.CqOff.RingMask))) 125 cq.ringEntries = (unsafe.Pointer(uintptr(cq.RingPtr) + uintptr(p.CqOff.RingEntries))) 126 cq.overflow = (unsafe.Pointer(uintptr(cq.RingPtr) + uintptr(p.CqOff.Overflow))) 127 cq.Cqes = (ioUringCqeArray)(unsafe.Pointer(uintptr(cq.RingPtr) + uintptr(p.CqOff.Cqes))) 128 if p.CqOff.Flags != 0 { 129 cq.flags = (unsafe.Pointer(uintptr(cq.RingPtr) + uintptr(p.CqOff.Flags))) 130 } 131 return nil 132 } 133 134 func io_uring_unmap_rings(sq *IoUringSq, cq *IoUringCq) error { 135 munmap(sq.RingPtr, uintptr(sq.RingSz)) 136 if cq.RingPtr != nil && cq.RingPtr != sq.RingPtr { 137 munmap(cq.RingPtr, uintptr(cq.RingSz)) 138 } 139 return nil 140 }