1 ;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; indent-tabs-mode: nil -*-
3 ;;; --- *NIX-specific routines.
6 (in-package :io.zeta-streams
)
8 (defun compute-poll-flags (type)
10 (:input
(logior pollin pollrdhup pollpri
))
11 (:output
(logior pollout
))
12 (:io
(logior pollin pollrdhup pollpri pollout
))))
14 (defun process-poll-revents (fd event-type revents
)
16 (error 'poll-error
:code ebadfd
:identifier
:ebadfd
17 :event-type event-type
:os-handle fd
18 :message
"invalid OS handle")))
19 (let ((readp nil
) (writep nil
))
21 ((pollin pollrdhup pollpri
)
23 ((pollout pollhup
) (setf writep t
))
24 ((pollerr) (poll-error))
25 ((pollnval) (poll-error)))
26 (values readp writep
))))
28 (defun timeout->milisec
(timeout)
29 (multiple-value-bind (sec usec
)
30 (decode-timeout timeout
)
31 (+ (* sec
1000) (truncate usec
1000))))
33 (defun %poll
(fds timeout
)
34 (repeat-upon-condition-decreasing-timeout
35 ((eintr) remaining-time timeout
)
36 (%sys-poll fds
1 (timeout->milisec remaining-time
))))
38 (defun poll-fd (fd event-type timeout
)
39 "Poll file descriptor `FD' for I/O readiness. `EVENT-TYPE' must be either :INPUT, :OUTPUT or :IO.
40 `TIMEOUT' must be a non-negative integer measured in seconds.
41 If a timeout occurs `POLL-TIMEOUT' is signaled.
42 Returns two boolean values indicating readability and writeability of `FD'."
43 (flet ((poll-error (posix-err)
45 :code
(code-of posix-err
) :identifier
(identifier-of posix-err
)
46 :event-type event-type
:os-handle fd
47 :message
(format nil
"OS error ~A" (identifier-of posix-err
)))))
48 (with-foreign-object (pollfd 'pollfd
)
49 (%sys-bzero pollfd size-of-pollfd
)
50 (with-foreign-slots ((fd events revents
) pollfd pollfd
)
52 events
(compute-poll-flags event-type
))
55 ((plusp (%poll pollfd timeout
))
56 (process-poll-revents fd event-type revents
))
58 (error 'poll-timeout
:os-handle fd
:event-type event-type
)))
59 (posix-error (err) (poll-error err
)))))))
62 ;;;-----------------------------------------------------------------------------
63 ;;; Set FD nonblocking
64 ;;;-----------------------------------------------------------------------------
66 (defun %set-fd-nonblock
(fd)
67 (declare (special *device
*))
69 (with-foreign-object (arg :int
)
70 (setf (mem-aref arg
:int
) 1)
71 (%sys-ioctl
/3 fd fionbio arg
))
73 (posix-file-error err
*device
* "issuing FIONBIO IOCTL on")))
77 ;;;-----------------------------------------------------------------------------
78 ;;; Get number of bytes availabe on FD
79 ;;;-----------------------------------------------------------------------------
81 (defun %get-fd-nbytes
(fd)
82 (declare (special *device
*))
84 (with-foreign-object (arg :int
)
85 (%sys-ioctl
/3 fd fionread arg
)
88 (posix-file-error err
*device
* "issuing FIONREAD IOCTL on"))))
91 ;;;-----------------------------------------------------------------------------
92 ;;; File Descriptor reading
93 ;;;-----------------------------------------------------------------------------
95 (defun %read-octets
/non-blocking
(fd vector start end
)
96 (declare (type ub8-simple-vector vector
)
98 (with-pointer-to-vector-data (buf vector
)
100 (%sys-read fd
(inc-pointer buf start
) (- end start
))
103 (posix-file-error err
*device
* "reading data from"))
105 (if (zerop nbytes
) :eof nbytes
)))))
107 (defun %read-octets
/timeout
(fd vector start end timeout
)
108 (declare (type ub8-simple-vector vector
)
110 (with-pointer-to-vector-data (buf vector
)
111 (repeat-decreasing-timeout (remaining (clamp-timeout timeout
) :rloop
)
112 (flet ((check-timeout ()
113 (if (plusp remaining
)
114 (poll-fd fd
:input remaining
)
115 (return-from :rloop
0))))
117 (%sys-read fd
(inc-pointer buf start
) (- end start
))
118 (ewouldblock () (check-timeout))
120 (posix-file-error err
*device
* "reading data from"))
123 (if (zerop nbytes
) :eof nbytes
))))))))
126 ;;;-----------------------------------------------------------------------------
127 ;;; File Descriptor writing
128 ;;;-----------------------------------------------------------------------------
130 (defun %write-octets
/non-blocking
(fd vector start end
)
131 (declare (type ub8-simple-vector vector
)
133 (with-pointer-to-vector-data (buf vector
)
135 (%sys-write fd
(inc-pointer buf start
) (- end start
))
139 (posix-file-error err
*device
* "writing data to"))
141 (if (zerop nbytes
) :eof nbytes
)))))
143 (defun %write-octets
/timeout
(fd vector start end timeout
)
144 (declare (type ub8-simple-vector vector
)
146 (with-pointer-to-vector-data (buf vector
)
147 (repeat-decreasing-timeout (remaining (clamp-timeout timeout
) :rloop
)
148 (flet ((check-timeout ()
149 (if (plusp remaining
)
150 (poll-fd fd
:output remaining
)
151 (return-from :rloop
0))))
153 (%sys-write fd
(inc-pointer buf start
) (- end start
))
154 (ewouldblock () (check-timeout))
155 (epipe () (return-from :rloop
:eof
))
157 (posix-file-error err
*device
* "writing data to"))
160 (if (zerop nbytes
) :eof nbytes
))))))))