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  }