github.com/iceber/iouring-go@v0.0.0-20230403020409-002cfd2e2a90/poller.go (about) 1 // +build linux 2 3 package iouring 4 5 import ( 6 "os" 7 "sync" 8 9 "golang.org/x/sys/unix" 10 ) 11 12 const initEpollEvents = 1 13 14 type iourPoller struct { 15 sync.Mutex 16 17 fd int 18 iours map[int]*IOURing 19 events []unix.EpollEvent 20 } 21 22 var ( 23 poller *iourPoller 24 initpollerLock sync.Mutex 25 ) 26 27 func initpoller() error { 28 // fast path 29 if poller != nil { 30 return nil 31 } 32 33 initpollerLock.Lock() 34 defer initpollerLock.Unlock() 35 if poller != nil { 36 return nil 37 } 38 39 epfd, err := unix.EpollCreate1(unix.EPOLL_CLOEXEC) 40 if err != nil { 41 return os.NewSyscallError("epoll_create1", err) 42 } 43 44 poller = &iourPoller{ 45 fd: epfd, 46 iours: make(map[int]*IOURing), 47 events: make([]unix.EpollEvent, initEpollEvents), 48 } 49 50 go poller.run() 51 return nil 52 } 53 54 func registerIOURing(iour *IOURing) error { 55 if err := initpoller(); err != nil { 56 return err 57 } 58 59 if err := unix.EpollCtl(poller.fd, unix.EPOLL_CTL_ADD, iour.eventfd, 60 &unix.EpollEvent{Fd: int32(iour.eventfd), Events: unix.EPOLLIN | unix.EPOLLET}, 61 ); err != nil { 62 return os.NewSyscallError("epoll_ctl_add", err) 63 } 64 65 poller.Lock() 66 poller.iours[iour.eventfd] = iour 67 poller.Unlock() 68 return nil 69 } 70 71 func removeIOURing(iour *IOURing) error { 72 poller.Lock() 73 delete(poller.iours, iour.eventfd) 74 poller.Unlock() 75 76 return os.NewSyscallError("epoll_ctl_del", 77 unix.EpollCtl(poller.fd, unix.EPOLL_CTL_DEL, iour.eventfd, nil)) 78 } 79 80 func (poller *iourPoller) run() { 81 for { 82 n, err := unix.EpollWait(poller.fd, poller.events, -1) 83 if err != nil { 84 continue 85 } 86 87 for i := 0; i < n; i++ { 88 fd := int(poller.events[i].Fd) 89 poller.Lock() 90 iour, ok := poller.iours[fd] 91 poller.Unlock() 92 if !ok { 93 continue 94 } 95 96 select { 97 case iour.cqeSign <- struct{}{}: 98 default: 99 } 100 } 101 102 poller.adjust() 103 } 104 } 105 106 func (poller *iourPoller) adjust() { 107 poller.Lock() 108 l := len(poller.iours) - len(poller.events) 109 poller.Unlock() 110 111 if l <= 0 { 112 return 113 } 114 115 events := make([]unix.EpollEvent, l*2) 116 poller.events = append(poller.events, events...) 117 }