github.com/dshulyak/uring@v0.0.0-20210209113719-1b2ec51f1542/setup.go (about) 1 package uring 2 3 import ( 4 "fmt" 5 "syscall" 6 "unsafe" 7 ) 8 9 const ( 10 MinSize = 2 11 MaxSize = 4096 12 ) 13 14 func Setup(size uint, params *IOUringParams) (*Ring, error) { 15 var ring Ring 16 if params != nil { 17 ring.params = *params 18 } 19 if err := setup(&ring, size, &ring.params); err != nil { 20 return nil, err 21 } 22 return &ring, nil 23 } 24 25 func setup(ring *Ring, size uint, p *IOUringParams) error { 26 fd, _, errno := syscall.Syscall(IO_URING_SETUP, uintptr(size), uintptr(unsafe.Pointer(p)), 0) 27 if errno != 0 { 28 return fmt.Errorf("IO_URING_SETUP %w", error(errno)) 29 } 30 ring.fd = int(fd) 31 32 sqsize := p.SQOff.Array + p.SQEntries*uint32(4) 33 cqsize := p.CQOff.CQEs + p.CQEntries*uint32(cqeSize) 34 isSingleMap := p.Features&IORING_FEAT_SINGLE_MMAP > 0 35 if isSingleMap { 36 if cqsize > sqsize { 37 sqsize = cqsize 38 } 39 } 40 41 data, err := syscall.Mmap(int(fd), IORING_OFF_SQ_RING, int(sqsize), 42 syscall.PROT_READ|syscall.PROT_WRITE, 43 syscall.MAP_SHARED|syscall.MAP_POPULATE) 44 if err != nil { 45 return err 46 } 47 ring.sqData = data 48 pointer := unsafe.Pointer(&data[0]) 49 50 ring.sq.head = (*uint32)(unsafe.Pointer(uintptr(pointer) + uintptr(p.SQOff.Head))) 51 ring.sq.tail = (*uint32)(unsafe.Pointer(uintptr(pointer) + uintptr(p.SQOff.Tail))) 52 ring.sq.ringMask = (*uint32)(unsafe.Pointer(uintptr(pointer) + uintptr(p.SQOff.RingMask))) 53 ring.sq.ringEntries = (*uint32)(unsafe.Pointer(uintptr(pointer) + uintptr(p.SQOff.RingEntries))) 54 ring.sq.flags = (*uint32)(unsafe.Pointer(uintptr(pointer) + uintptr(p.SQOff.Flags))) 55 ring.sq.dropped = (*uint32)(unsafe.Pointer(uintptr(pointer) + uintptr(p.SQOff.Dropped))) 56 ring.sq.array = uint32Array(unsafe.Pointer(uintptr(pointer) + uintptr(p.SQOff.Array))) 57 58 if !isSingleMap { 59 data, err = syscall.Mmap(int(fd), IORING_OFF_CQ_RING, int(cqsize), 60 syscall.PROT_READ|syscall.PROT_WRITE, 61 syscall.MAP_SHARED|syscall.MAP_POPULATE) 62 if err != nil { 63 return err 64 } 65 ring.cqData = data 66 pointer = unsafe.Pointer(&data[0]) 67 } 68 69 ring.cq.head = (*uint32)(unsafe.Pointer(uintptr(pointer) + uintptr(p.CQOff.Head))) 70 ring.cq.tail = (*uint32)(unsafe.Pointer(uintptr(pointer) + uintptr(p.CQOff.Tail))) 71 ring.cq.ringmask = (*uint32)(unsafe.Pointer(uintptr(pointer) + uintptr(p.CQOff.RingMask))) 72 ring.cq.ringEntries = (*uint32)(unsafe.Pointer(uintptr(pointer) + uintptr(p.CQOff.RingEntries))) 73 ring.cq.overflow = (*uint32)(unsafe.Pointer(uintptr(pointer) + uintptr(p.CQOff.Overflow))) 74 ring.cq.cqes = cqeArray(unsafe.Pointer(uintptr(pointer) + uintptr(p.CQOff.CQEs))) 75 if p.CQOff.Flags != 0 { 76 ring.cq.flags = (*uint32)(unsafe.Pointer(uintptr(pointer) + uintptr(p.CQOff.Flags))) 77 } 78 79 entries, err := syscall.Mmap(int(fd), IORING_OFF_SQES, 80 int(p.SQEntries)*int(sqeSize), 81 syscall.PROT_READ|syscall.PROT_WRITE, 82 syscall.MAP_SHARED|syscall.MAP_POPULATE) 83 84 if err != nil { 85 return err 86 } 87 ring.sqArrayData = entries 88 ring.sq.sqes = sqeArray(unsafe.Pointer(&entries[0])) 89 return nil 90 } 91 92 func (r *Ring) Close() (err error) { 93 if r.cqData != nil { 94 ret := syscall.Munmap(r.cqData) 95 if err == nil { 96 err = ret 97 } 98 if ret == nil { 99 r.cqData = nil 100 } 101 } 102 if r.sqData != nil { 103 ret := syscall.Munmap(r.sqData) 104 if err == nil { 105 err = ret 106 } 107 if ret == nil { 108 r.sqData = nil 109 } 110 } 111 if r.sqArrayData != nil { 112 ret := syscall.Munmap(r.sqArrayData) 113 if err == nil { 114 err = ret 115 } 116 if ret == nil { 117 r.sqArrayData = nil 118 } 119 } 120 if r.fd != 0 { 121 ret := syscall.Close(r.fd) 122 if err == nil { 123 err = ret 124 } 125 if ret == nil { 126 r.fd = 0 127 } 128 } 129 return 130 }