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 @@ -53,12 +55,28 @@ 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 d_kqfilter_t zero_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 = full_kqfilter, .d_name = "full", }; @@ -67,6 +85,7 @@ .d_read = (d_read_t *)nullop, .d_write = null_write, .d_ioctl = null_ioctl, + .d_kqfilter = null_kqfilter, .d_name = "null", }; @@ -75,6 +94,7 @@ .d_read = zero_read, .d_write = null_write, .d_ioctl = zero_ioctl, + .d_kqfilter = zero_kqfilter, .d_name = "zero", .d_flags = D_MMAP_ANON, }; @@ -197,5 +217,67 @@ 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); + } +} + +static int +zero_kqfilter(struct cdev *dev, struct knote *kn) +{ + + switch (kn->kn_filter) { + case EVFILT_READ: + kn->kn_fop = &never_filterops; + return (0); + case EVFILT_WRITE: + kn->kn_fop = &immediate_filterops; + return (0); + default: + return(EOPNOTSUPP); + } +} + DEV_MODULE(null, null_modevent, NULL); MODULE_VERSION(null, 1);