Hash :
03c7425b
Author :
Thomas de Grivel
Date :
2018-06-29T12:10:21
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
;;
;; cffi-epoll - Common Lisp wrapper for Linux epoll syscall
;;
;; Copyright 2017 Thomas de Grivel <thoxdg@gmail.com>
;;
;; Permission to use, copy, modify, and distribute this software for any
;; purpose with or without fee is hereby granted, provided that the above
;; copyright notice and this permission notice appear in all copies.
;;
;; THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
;; WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
;; MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
;; ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
;; WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
;; ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
;; OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
;;
(in-package :cffi-epoll)
(defcfun ("epoll_create" c-epoll-create) :int
(size :int))
(defun create (&optional (size 10))
(let ((fd (c-epoll-create size)))
(when (< fd 0)
(error-errno "epoll_create"))
fd))
(defmacro with ((fdvar &optional (size 10)) &body body)
(let ((fd (gensym "FD-")))
`(let ((,fd (create ,size)))
(unwind-protect (let ((,fdvar ,fd)) ,@body)
(unistd:close ,fd)))))
(defcfun ("epoll_ctl" c-epoll-ctl) :int
(epfd :int)
(op :int)
(fd :int)
(event (:pointer (:struct epoll-event))))
(defun ctl (epfd op fd events &key data-ptr data-fd data-u32 data-u64)
(with-foreign-object (evt '(:struct epoll-event))
(setf (foreign-slot-value evt '(:struct epoll-event) 'events) events)
(let ((data (foreign-slot-value evt '(:struct epoll-event) 'data)))
(with-foreign-slots ((ptr fd u32 u64) data (:union epoll-data))
(cond (data-ptr (setf ptr data-ptr))
(data-fd (setf fd data-fd))
(data-u32 (setf u32 data-u32))
(data-u64 (setf u64 data-u64)))))
(let ((r (c-epoll-ctl epfd op fd evt)))
(when (< r 0)
(error-errno "epoll_ctl"))
r)))
(defun add (epfd fd events &key data-ptr data-fd data-u32 data-u64)
(ctl epfd +ctl-add+ fd events
:data-ptr data-ptr
:data-fd data-fd
:data-u32 data-u32
:data-u64 data-u64))
(defun mod (epfd fd events &key data-ptr data-fd data-u32 data-u64)
(ctl epfd +ctl-mod+ fd events
:data-ptr data-ptr
:data-fd data-fd
:data-u32 data-u32
:data-u64 data-u64))
(defun del (epfd fd)
(ctl epfd +ctl-del+ fd 0))
(defcfun ("epoll_wait" c-epoll-wait) :int
(epfd :int)
(events (:pointer (:struct epoll-event)))
(maxevents :int)
(timeout :int))
(defmacro wait ((events-var fd-var epfd &optional
(max-events 1024)
(timeout 60000))
&body body)
(let ((events (gensym "EVENTS-"))
(evt (gensym "EVT-"))
(e-data (gensym "E-DATA-"))
(n (gensym "N-"))
(i (gensym "I-"))
(g-max-events (gensym "MAX-EVENTS-")))
`(let ((,g-max-events ,max-events))
(with-foreign-object (,events '(:struct epoll-event) ,g-max-events)
(loop
(let ((,n (c-epoll-wait ,epfd ,events ,g-max-events ,timeout)))
(when (< ,n 0)
(handler-case
(error-errno "epoll_wait")
(errno-error (condition)
(when (= +eintr+ (errno-error-errno condition))
(continue)))))
(dotimes (,i ,n)
(let* ((,evt (mem-aptr ,events '(:struct epoll-event) ,i))
(,events-var (foreign-slot-value
,evt '(:struct epoll-event) 'events))
(,e-data (foreign-slot-value
,evt '(:struct epoll-event) 'data))
(,fd-var (foreign-slot-value
,e-data '(:union epoll-data) 'fd)))
,@body))
(return)))))))