diff --git a/sys/dev/null/null.c b/sys/dev/null/null.c --- a/sys/dev/null/null.c +++ b/sys/dev/null/null.c @@ -4,6 +4,7 @@ * Copyright (c) 2000 Mark R. V. Murray & Jeroen C. van Gelderen * Copyright (c) 2001-2004 Mark R. V. Murray * Copyright (c) 2014 Eitan Adler + * Copyright (c) 2025 Pietro Cerutti * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -39,6 +40,7 @@ #include #include #include +#include #include #include @@ -48,17 +50,36 @@ static struct cdev *null_dev; static struct cdev *zero_dev; +#define "full" "full" +#define "null" "null" +#define "zero" "zero" + static d_write_t full_write; static d_write_t null_write; static d_ioctl_t null_ioctl; static d_ioctl_t zero_ioctl; static d_read_t zero_read; +static d_kqfilter_t full_kqfilter; +static d_kqfilter_t null_kqfilter; +static int immediate_event(struct knote *kn, long hint); +static int never_event(struct knote *kn, long hint); + +static const struct filterops immediate_filterops = { + .f_isfd = 1, + .f_event = immediate_event +}; + +static const struct filterops never_filterops = { + .f_isfd = 1, + .f_event = never_event +}; static struct cdevsw full_cdevsw = { .d_version = D_VERSION, .d_read = zero_read, .d_write = full_write, .d_ioctl = zero_ioctl, + .d_kqfilter = null_kqfilter, .d_name = "full", }; @@ -67,6 +88,7 @@ .d_read = (d_read_t *)nullop, .d_write = null_write, .d_ioctl = null_ioctl, + .d_kqfilter = null_kqfilter, .d_name = "null", }; @@ -75,6 +97,7 @@ .d_read = zero_read, .d_write = null_write, .d_ioctl = zero_ioctl, + .d_kqfilter = null_kqfilter, .d_name = "zero", .d_flags = D_MMAP_ANON, }; @@ -197,5 +220,47 @@ return (0); } +static int +immediate_event(struct knote *kn, long hint) +{ + return 1; +} + +static int +never_event(struct knote *kn, long hint) +{ + return 0; +} + +static int +full_kqfilter(struct cdev *dev, struct knote *kn) +{ + switch (kn->kn_filter) + { + case EVFILT_READ: + kn->kn_fop = &immediate_filterops; + return (0); + case EVFILT_WRITE: + kn->kn_fop = &never_filterops; + return (0); + default: + return(EOPNOTSUPP); + } +} + +static int +null_kqfilter(struct cdev *dev, struct knote *kn) +{ + switch (kn->kn_filter) + { + case EVFILT_READ: + case EVFILT_WRITE: + kn->kn_fop = &immediate_filterops; + return (0); + default: + return(EOPNOTSUPP); + } +} + DEV_MODULE(null, null_modevent, NULL); MODULE_VERSION(null, 1);