The branch main has been updated by dumbbell:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=5931649751847cc3ca54255bb767424dcb8a3e97

commit 5931649751847cc3ca54255bb767424dcb8a3e97
Author:     Jean-Sébastien Pédron <[email protected]>
AuthorDate: 2025-05-26 17:18:24 +0000
Commit:     Jean-Sébastien Pédron <[email protected]>
CommitDate: 2026-01-25 16:04:40 +0000

    eventfd: Add refcounting
    
    An eventfd file descriptor can be used by drivers such as DRM drivers
    through linuxkpi. A driver can hold a reference to such a file
    regardless of the fact it is used by userland or not.
    
    This patch introduces a refcount in `struct eventfd`, plus the
    `eventfd_get()` and `eventfd_put()` functions to acquire and release
    references. These functions will be used by DRM drivers for instance.
    
    This structure is internal to `sys/kern/sys_eventfd.c` and not used
    anywhere else. Thus it is safe to add a field without breaking anything.
    
    Reviewed by:    markj
    Sponsored by:   The FreeBSD Foundation
    Differential Revision: https://reviews.freebsd.org/D50849
---
 sys/kern/sys_eventfd.c | 30 ++++++++++++++++++++++++++++--
 sys/sys/eventfd.h      |  4 ++++
 2 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/sys/kern/sys_eventfd.c b/sys/kern/sys_eventfd.c
index 04ed107c933d..433bcb57b2b3 100644
--- a/sys/kern/sys_eventfd.c
+++ b/sys/kern/sys_eventfd.c
@@ -40,6 +40,7 @@
 #include <sys/mutex.h>
 #include <sys/poll.h>
 #include <sys/proc.h>
+#include <sys/refcount.h>
 #include <sys/selinfo.h>
 #include <sys/stat.h>
 #include <sys/uio.h>
@@ -102,6 +103,7 @@ struct eventfd {
        uint32_t        efd_flags;
        struct selinfo  efd_sel;
        struct mtx      efd_lock;
+       unsigned int    efd_refcount;
 };
 
 int
@@ -119,6 +121,7 @@ eventfd_create_file(struct thread *td, struct file *fp, 
uint32_t initval,
        efd->efd_count = initval;
        mtx_init(&efd->efd_lock, "eventfd", NULL, MTX_DEF);
        knlist_init_mtx(&efd->efd_sel.si_note, &efd->efd_lock);
+       refcount_init(&efd->efd_refcount, 1);
 
        fflags = FREAD | FWRITE;
        if ((flags & EFD_NONBLOCK) != 0)
@@ -128,16 +131,39 @@ eventfd_create_file(struct thread *td, struct file *fp, 
uint32_t initval,
        return (0);
 }
 
-static int
-eventfd_close(struct file *fp, struct thread *td)
+struct eventfd *
+eventfd_get(struct file *fp)
 {
        struct eventfd *efd;
 
+       if (fp->f_data == NULL || fp->f_ops != &eventfdops)
+               return (NULL);
+
        efd = fp->f_data;
+       refcount_acquire(&efd->efd_refcount);
+
+       return (efd);
+}
+
+void
+eventfd_put(struct eventfd *efd)
+{
+       if (!refcount_release(&efd->efd_refcount))
+               return;
+
        seldrain(&efd->efd_sel);
        knlist_destroy(&efd->efd_sel.si_note);
        mtx_destroy(&efd->efd_lock);
        free(efd, M_EVENTFD);
+}
+
+static int
+eventfd_close(struct file *fp, struct thread *td)
+{
+       struct eventfd *efd;
+
+       efd = fp->f_data;
+       eventfd_put(efd);
        return (0);
 }
 
diff --git a/sys/sys/eventfd.h b/sys/sys/eventfd.h
index 0f64483753e5..1f36dbecb92d 100644
--- a/sys/sys/eventfd.h
+++ b/sys/sys/eventfd.h
@@ -38,8 +38,12 @@ typedef uint64_t eventfd_t;
 
 #ifdef _KERNEL
 
+struct eventfd;
+
 int eventfd_create_file(struct thread *td, struct file *fp, uint32_t initval,
     int flags);
+struct eventfd *eventfd_get(struct file *fp);
+void eventfd_put(struct eventfd *efd);
 
 #else
 

Reply via email to