Skip to content

Conversation

christophejunke
Copy link

@christophejunke christophejunke commented Aug 5, 2025

Hi,

This patch exposes eventfd(2).

For reference I also wrote the following read/write functions to interact with the file descriptor returned by the call, but these are not in the patch:

(defun efd-read% (ptr fd)
  (let ((ret (isys:read fd ptr (cffi:foreign-type-size :uint64))))
    (assert (= ret (cffi:foreign-type-size :uint64)))
    (cffi:mem-ref ptr :uint64)))

(defun efd-write% (ptr fd value)
  (check-type value (unsigned-byte 64))
  (setf (cffi:mem-ref ptr :uint64) value)
  (prog1 T
    (let ((ret (isys:write fd ptr (cffi:foreign-type-size :uint64))))
      (assert (= ret (cffi:foreign-type-size :uint64))))))

(defun efd-read (fd)
  (cffi:with-foreign-object (ptr :uint64 1)
    (efd-read% ptr fd)))

(defun efd-write (fd value)
  (check-type value (unsigned-byte 64))
  (cffi:with-foreign-object (ptr :uint64 1)
    (efd-write% ptr fd value)))

If for example we define the following macro:

(defmacro with-eventfd
    ((&key get set efd ((:ptr ptr%)) (initial 0) (flags 0)) &body body)
  (with-gensyms (new)
    (let* ((efd (or efd (gensym "EFD")))
           (ptr (or ptr% (gensym "PTR")))
           (get@ (and get `((,get () (efd-read% ,ptr ,efd)))))
           (set@ (and set `((,set (,new) (efd-write% ,ptr ,efd ,new)))))
           (core `(let ((,efd (iolib/syscalls:eventfd ,initial ,flags)))
                    (unwind-protect (flet (,@get@ ,@set@) ,@body)
                      (isys:close ,efd)))))
      (if ptr%
          core
          `(cffi:with-foreign-object (,ptr :uint64 1) ,core)))))

Then here is a usage example of the syscal to have an interruptible event loop:

  (with-event-base (base)
    (with-eventfd (:efd wakeupfd :get read-wfd :set write-wfd)
      (set-io-handler base wakeupfd :read 
        (lambda (args)
          (declare (ignore args))
          (read-wfd)))
    
      ;; ... others may call (write-wfd 1) to wakeup the event loop

      (event-dispatch base)))

Without eventfd(2), the typical way of doing this is with a pipe.
Context: https://stackoverflow.com/questions/79724520/signal-handling-in-multi-threaded-scenario

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant