0 | module IO.Async.Loop.Epoll
2 | import public Data.Nat
3 | import Control.Monad.Elin
4 | import Data.Array.Core as AC
5 | import Data.Array.Mutable
8 | import Data.Linear.Traverse1
12 | import IO.Async.Internal.Ref
13 | import IO.Async.Loop.Poller
14 | import IO.Async.Loop.Queue
15 | import IO.Async.Loop.SignalST
16 | import IO.Async.Loop.TimerST
17 | import IO.Async.Signal
19 | import public IO.Async
20 | import public IO.Async.Loop
21 | import public IO.Async.Loop.PollH
22 | import public IO.Async.Loop.Posix
23 | import public IO.Async.Loop.SignalH
24 | import public IO.Async.Loop.TimerH
28 | import System.Linux.Epoll.Prim
29 | import System.Posix.File.Prim
30 | import System.Posix.Limits
52 | handles : IOArray maxFiles FileHandle
55 | events : CArrayIO maxFiles SEpollEvent
62 | let maxfiles := cast {to = Nat} (sysconf SC_OPEN_MAX)
63 | waiting # t := ref1 Z t
64 | handles # t := marray1 maxfiles hdummy t
65 | events # t := malloc1 SEpollEvent maxfiles t
66 | epoll # t := dieOnErr (epollCreate EPOLL_CLOEXEC) t
67 | in P waiting maxfiles handles events epoll # t
73 | parameters (p : Epoll)
76 | getHandle : Fd -> IO1 FileHandle
78 | case tryNatToFin (cast f.fd) of
79 | Just v => AC.get p.handles v t
80 | Nothing => hdummy # t
82 | handleEvs : List PollPair -> IO1 ()
83 | handleEvs [] t = () # t
84 | handleEvs (PP fd ev::es) t =
85 | let h # t := getHandle fd t
94 | pollWaitImpl : (timeout : Clock Duration) -> IO1 ()
96 | let vs # t := dieOnErr (epollPwait2Vals p.epoll p.events to []) t
101 | let S _ # t := read1 p.waiting t | _ # t => () # t
102 | in pollWaitImpl (makeDuration 0 0) t
106 | let _ # t := free1 p.events t
107 | in toF1 (close' p.epoll) t
113 | parameters (p : Epoll)
117 | (cb : Either Errno PollEvent -> IO1 ())
121 | ctl : EpollOp -> E1 World [Errno] ()
122 | ctl op = epollCtl p.epoll op fd ev
128 | closefd = when1 autoClose (toF1 $
close' fd)
132 | cleanup : Fin p.maxFiles -> IO1 ()
134 | let _ # t := Queue.dec p.waiting t
135 | _ # t := AC.set p.handles v hdummy t
136 | in e1ToF1 (ctl Del) t
141 | act : Fin p.maxFiles -> FileHandle
143 | let _ # t := Epoll.cleanup v t
144 | _ # t := cb (Right e) t
151 | abrt : Either Errno PollEvent -> IO1 (IO1 ())
153 | let _ # t := cb res t
159 | cncl : Fin p.maxFiles -> FileHandle
161 | let _ # t := Epoll.cleanup v t
164 | pollFileImpl : IO1 (IO1 ())
168 | case tryNatToFin (cast fd.fd) of
170 | Just v => case ctl Add t of
172 | E (Here x) t => case x == EPERM of
177 | True => abrt (Right ev) t
180 | False => abrt (Left x) t
195 | r # t := ref1 True t
196 | _ # t := AC.set p.handles v (\e => once r (act v e)) t
197 | _ # t := Queue.inc p.waiting t
198 | in once r (cleanup v) # t
199 | Nothing => abrt (Left EINVAL) t
203 | epollPoller : IO1 Poller
205 | let ep # t := mkEpoll t
206 | in MkPoller (pollImpl ep) (pollWaitImpl ep) (release ep) (pollFileImpl ep) # t
220 | : {default [SIGINT] sigs : List Signal}
222 | => Async Poll [] ()
224 | epollApp {sigs} prog = do
226 | app n sigs epollPoller cprog
229 | cprog : Async Poll [] ()
233 | , dropErrs {es = [Errno]} $
onSignal SIGINT (pure ())