0 | module System.Linux.Timerfd.Prim
 1 |
 2 | import public Data.C.Ptr
 3 | import public System.Linux.Timerfd.Flags
 4 | import public System.Linux.Timerfd.Timerfd
 5 | import public System.Posix.File.Prim
 6 | import public System.Posix.Timer
 7 |
 8 | %default total
 9 |
10 | --------------------------------------------------------------------------------
11 | -- FFI
12 | --------------------------------------------------------------------------------
13 |
14 | %foreign "C:li_timerfd_create, linux-idris"
15 | prim__timerfd_create : Bits8 -> Bits32 -> PrimIO CInt
16 |
17 | %foreign "C:li_timerfd_settime, linux-idris"
18 | prim__timerfd_settime : Bits32 -> Bits32 -> AnyPtr -> AnyPtr -> PrimIO CInt
19 |
20 | %foreign "C:li_timerfd_settime1, linux-idris"
21 | prim__timerfd_settime1 : Bits32 -> Bits32 -> TimeT -> NsecT -> TimeT -> NsecT -> PrimIO CInt
22 |
23 | %foreign "C:li_timerfd_gettime, linux-idris"
24 | prim__timerfd_gettime : Bits32 -> AnyPtr -> PrimIO ()
25 |
26 | %foreign "C:li_timerfd_read, linux-idris"
27 | prim__timerfd_read : Bits32 -> PrimIO Int64
28 |
29 | --------------------------------------------------------------------------------
30 | -- API
31 | --------------------------------------------------------------------------------
32 |
33 | ||| Opens a new `timerfd` file descriptor for observing the given clock.
34 | |||
35 | |||
36 | ||| Notes:
37 | ||| * A `signalfd` should be closed using `close` just like other file
38 | |||   descriptors.
39 | ||| * In general, use `readTimerfd` instead of the `read` functions
40 | |||   from `System.Posix.File` to read from a `timerfd`.
41 | export %inline
42 | timerfd : ClockId -> TimerfdFlags -> EPrim Timerfd
43 | timerfd c (F f) = toVal cast $ prim__timerfd_create (clockCode c) f
44 |
45 | ||| Sets the time of a `timerfd`.
46 | |||
47 | ||| The currently set time will be stored in `old`.
48 | ||| Use the `TFD_TIMER_ABSTIME` flag if the time should be interpreted as
49 | ||| an absolute wall clock time.
50 | export %inline
51 | setitime : Timerfd -> Bits32 -> (new,old : IOTimerspec) -> EPrim ()
52 | setitime t f new old =
53 |   toUnit $ prim__timerfd_settime (fileDesc t) f (unwrap new) (unwrap old)
54 |
55 | ||| Reads the currently set `itimerspec` of a `timerfd` and uses the given
56 | ||| pointer to place the data.
57 | export %inline
58 | getitime : Timerfd -> (old : IOTimerspec) -> PrimIO ()
59 | getitime t old = prim__timerfd_gettime (fileDesc t) (unwrap old)
60 |
61 | ||| Reads data from a `timerfd`.
62 | |||
63 | ||| This will block until the next time the timer expires unless `TFD_NONBLOCK`
64 | ||| was set when creating the timer.
65 | |||
66 | ||| The value returned is the number of times the timer expired since
67 | ||| the last read.
68 | export %inline
69 | readTimerfd : Timerfd -> EPrim Bits64
70 | readTimerfd fd t =
71 |   let r # t := ffi (prim__timerfd_read (fileDesc fd)) t
72 |    in if r < 0 then E (inject $ fromNeg r) t else R (cast r) t
73 |
74 | --------------------------------------------------------------------------------
75 | -- Convenience API
76 | --------------------------------------------------------------------------------
77 |
78 | ||| Like `setitime` but without storing the currently set `itimerspec`.
79 | export %inline
80 | setTime : Timerfd -> Bits32 -> Timerspec -> EPrim ()
81 | setTime t f (TS i v) =
82 |   toUnit $ prim__timerfd_settime1 (fileDesc t) f i.secs i.nsecs v.secs v.nsecs
83 |
84 | ||| Convenience alias for `getitime`.
85 | export %inline
86 | getTime : Timerfd -> EPrim Timerspec
87 | getTime fd =
88 |   withStruct Itimerspec $ \str,t =>
89 |     let _  # t := toF1 (getitime fd str) t
90 |         ts # t := timerspec str t
91 |      in R ts t
92 |