Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/kqueue]: src/sys/kern * update for differences between netbsd & freebsd ...



details:   https://anonhg.NetBSD.org/src/rev/218ac7bb14be
branches:  kqueue
changeset: 512348:218ac7bb14be
user:      lukem <lukem%NetBSD.org@localhost>
date:      Tue Jul 10 13:42:29 2001 +0000

description:
* update for differences between netbsd & freebsd WRT:
        - header files
        - struct locking
        - pool (& other memory) allocation
        - timeouts
* add kqueue_ioctl(), to support ioctl(2) operations on a kqueue fd.
* change the way that system filters are referenced to support name lookups
  and unimplemented (yet known about) filter types (such as EVFILT_AIO)
* add kfilter_register(9): register filter with given name to map to given
  filterops. filter must not exist
* add kfilter_unregister(9): unregister user filter
* add kfilter_byname(): lookup filter by name, which can be a system filter
  or a user-added filter
* add kfilter_byfilter(): lookup filter by filter number
* in kqueue_register(), use kfilter_byfilter() to determine filterops rather
  than using obscure ~ operation (which was now incorrect due to renumbering)
* cleanup whitespace, improve comments
* check return code of all copyouts()s

diffstat:

 sys/kern/kern_event.c |  851 +++++++++++++++++++++++++++++++++++--------------
 1 files changed, 610 insertions(+), 241 deletions(-)

diffs (truncated from 1358 to 300 lines):

diff -r 044d41ea6052 -r 218ac7bb14be sys/kern/kern_event.c
--- a/sys/kern/kern_event.c     Tue Jul 10 13:30:17 2001 +0000
+++ b/sys/kern/kern_event.c     Tue Jul 10 13:42:29 2001 +0000
@@ -1,3 +1,4 @@
+/*     $NetBSD: kern_event.c,v 1.1.1.1.2.1 2001/07/10 13:42:29 lukem Exp $     */
 /*-
  * Copyright (c) 1999,2000,2001 Jonathan Lemon <jlemon%FreeBSD.org@localhost>
  * All rights reserved.
@@ -29,60 +30,56 @@
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/kernel.h>
-#include <sys/lock.h>
-#include <sys/mutex.h>
 #include <sys/proc.h>
 #include <sys/malloc.h> 
 #include <sys/unistd.h>
 #include <sys/file.h>
 #include <sys/fcntl.h>
-#include <sys/selinfo.h>
+#include <sys/select.h>
 #include <sys/queue.h>
 #include <sys/event.h>
 #include <sys/eventvar.h>
 #include <sys/poll.h>
+#include <sys/pool.h>
 #include <sys/protosw.h>
 #include <sys/socket.h>
 #include <sys/socketvar.h>
 #include <sys/stat.h>
-#include <sys/sysproto.h>
 #include <sys/uio.h>
-
-#include <vm/vm_zone.h>
+#include <sys/mount.h>
+#include <sys/filedesc.h>
+#include <sys/syscallargs.h>
 
 static int     kqueue_scan(struct file *fp, int maxevents,
                    struct kevent *ulistp, const struct timespec *timeout,
-                   struct proc *p);
-static int     kqueue_read(struct file *fp, struct uio *uio,
-                   struct ucred *cred, int flags, struct proc *p);
-static int     kqueue_write(struct file *fp, struct uio *uio,
-                   struct ucred *cred, int flags, struct proc *p);
+                   struct proc *p, register_t *retval);
+static void    kqueue_wakeup(struct kqueue *kq);
+
+static int     kqueue_read(struct file *fp, off_t *offset, struct uio *uio,
+                   struct ucred *cred, int flags);
+static int     kqueue_write(struct file *fp, off_t *offset, struct uio *uio,
+                   struct ucred *cred, int flags);
 static int     kqueue_ioctl(struct file *fp, u_long com, caddr_t data,
                    struct proc *p);
-static int     kqueue_poll(struct file *fp, int events, struct ucred *cred,
+static int     kqueue_fcntl(struct file *fp, u_int com, caddr_t data,
                    struct proc *p);
-static int     kqueue_kqfilter(struct file *fp, struct knote *kn);
-static int     kqueue_stat(struct file *fp, struct stat *st, struct proc *p);
-static int     kqueue_close(struct file *fp, struct proc *p);
-static void    kqueue_wakeup(struct kqueue *kq);
+static int     kqueue_poll(struct file *fp, int events, struct proc *p);
+static int     kqueue_kqfilter(struct file *fp, struct knote *kn);
+static int     kqueue_stat(struct file *fp, struct stat *sp, struct proc *p);
+static int     kqueue_close(struct file *fp, struct proc *p);
 
 static struct fileops kqueueops = {
-       kqueue_read,
-       kqueue_write,
-       kqueue_ioctl,
-       kqueue_poll,
-       kqueue_kqfilter,
-       kqueue_stat,
-       kqueue_close
+       kqueue_read, kqueue_write, kqueue_ioctl, kqueue_fcntl, kqueue_poll,
+       kqueue_stat, kqueue_close, kqueue_kqfilter
 };
 
-static void    knote_attach(struct knote *kn, struct filedesc *fdp);
-static void    knote_drop(struct knote *kn, struct proc *p);
-static void    knote_enqueue(struct knote *kn);
-static void    knote_dequeue(struct knote *kn);
-static void    knote_init(void);
-static struct  knote *knote_alloc(void);
-static void    knote_free(struct knote *kn);
+static void    knote_attach(struct knote *kn, struct filedesc *fdp);
+static void    knote_drop(struct knote *kn, struct proc *p);
+static void    knote_enqueue(struct knote *kn);
+static void    knote_dequeue(struct knote *kn);
+static void    knote_init(void);
+static struct knote *knote_alloc(void);
+static void    knote_free(struct knote *kn);
 
 static void    filt_kqdetach(struct knote *kn);
 static int     filt_kqueue(struct knote *kn, long hint);
@@ -98,104 +95,260 @@
 static struct filterops file_filtops =
        { 1, filt_fileattach, NULL, NULL };
 
-static vm_zone_t       knote_zone;
+struct pool    knote_pool;
 
-#define KNOTE_ACTIVATE(kn) do {                                        \
+#define        KNOTE_ACTIVATE(kn)                                              \
+do {                                                                   \
        kn->kn_status |= KN_ACTIVE;                                     \
        if ((kn->kn_status & (KN_QUEUED | KN_DISABLED)) == 0)           \
                knote_enqueue(kn);                                      \
 } while(0)
 
 #define        KN_HASHSIZE             64              /* XXX should be tunable */
-#define KN_HASH(val, mask)     (((val) ^ (val >> 8)) & (mask))
+#define        KN_HASH(val, mask)      (((val) ^ (val >> 8)) & (mask))
 
-extern struct filterops aio_filtops;
 extern struct filterops sig_filtops;
 
 /*
  * Table for for all system-defined filters.
+ * These should be listed in the numeric order of the EVFILT_* defines.
+ * If filtops is NULL, the filter isn't implemented in NetBSD.
+ * End of list is when name is NULL.
  */
-static struct filterops *sysfilt_ops[] = {
-       &file_filtops,                  /* EVFILT_READ */
-       &file_filtops,                  /* EVFILT_WRITE */
-       &aio_filtops,                   /* EVFILT_AIO */
-       &file_filtops,                  /* EVFILT_VNODE */
-       &proc_filtops,                  /* EVFILT_PROC */
-       &sig_filtops,                   /* EVFILT_SIGNAL */
+struct kfilter {
+       char             *name;         /* name of filter */
+       uint32_t          filter;       /* id of filter */
+       struct filterops *filtops;      /* operations for filter */
+};
+
+               /* System defined filters */
+static struct kfilter sys_kfilters[] = {
+       { "EVFILT_READ",        EVFILT_READ,    &file_filtops },
+       { "EVFILT_WRITE",       EVFILT_WRITE,   &file_filtops },
+       { "EVFILT_AIO",         EVFILT_AIO,     NULL },
+       { "EVFILT_VNODE",       EVFILT_VNODE,   &file_filtops },
+       { "EVFILT_PROC",        EVFILT_PROC,    &proc_filtops },
+       { "EVFILT_SIGNAL",      EVFILT_SIGNAL,  &sig_filtops },
+       { NULL,                 0,              NULL }, /* end of list */ 
 };
 
+               /* User defined kfilters */
+static struct kfilter  *user_kfilters;         /* array */
+static int             user_kfilterc;          /* current offset */
+static int             user_kfiltermaxc;       /* max size so far */
+
+static struct kfilter *kfilter_byname(const char *);
+static struct kfilter *kfilter_byfilter(uint32_t);
+
+/*
+ * Find kfilter entry by name, or NULL if not found.
+ */
+static struct kfilter *
+kfilter_byname(const char *name)
+{
+       struct kfilter *kfilter;
+       int i;
+
+       kfilter = sys_kfilters;         /* first look in system kfilters */
+       while (kfilter != NULL) {
+               for (i = 0; kfilter[i].name != NULL; i++) {
+                                       /* search for matching name */
+                       if (kfilter[i].name[0] != '\0' &&
+                           (strcmp(name, kfilter[i].name) == 0))
+                               return (&kfilter[i]);
+               }
+                                       /* swap to user kfilters */
+               if (kfilter == sys_kfilters)
+                       kfilter = user_kfilters;
+               else
+                       kfilter = NULL;
+       }
+       return (NULL);
+}
+
+/*
+ * Find kfilter entry by filter id, or NULL if not found.
+ * Assumes entries are indexed in filter id order, for speed.
+ */
+static struct kfilter *
+kfilter_byfilter(uint32_t filter)
+{
+       struct kfilter *kfilter;
+
+       if (filter < EVFILT_SYSCOUNT)   /* it's a system filter */
+               kfilter = &sys_kfilters[filter];
+       else if (user_kfilters != NULL &&
+           filter < EVFILT_SYSCOUNT + user_kfilterc)
+                                       /* it's a user filter */
+               kfilter = &user_kfilters[filter - EVFILT_SYSCOUNT];
+       else
+               return (NULL);          /* out of range */
+       KASSERT(kfilter->filter == filter);     /* sanity check! */
+       return (kfilter);
+}
+
+/*
+ * Register a new kfilter. Stores the entry in user_kfilters.
+ * Returns 0 if operation succeeded, or an appropriate errno(2) otherwise.
+ * If retfilter != NULL, the new filterid is returned in it.
+ */
+int
+kfilter_register(const char *name, struct filterops *filtops, int *retfilter)
+{
+       struct kfilter *kfilter;
+       int len;
+
+       if (name == NULL || name[0] == '\0' || filtops == NULL)
+               return (EINVAL);        /* invalid args */
+       kfilter = kfilter_byname(name);
+       if (kfilter != NULL)            /* already exists */
+               return (EEXIST);
+       if (user_kfilterc > 0xffffffff - EVFILT_SYSCOUNT)
+               return (EINVAL);        /* too many */
+
+                                       /* need to grow user_kfilters */
+       if (user_kfilterc + 1 > user_kfiltermaxc) {
+                                       /*
+                                        * grow in KFILTER_EXTENT chunks. use
+                                        * malloc(9), because we want to
+                                        * traverse user_kfilters as an array.
+                                        */
+               user_kfiltermaxc += KFILTER_EXTENT;
+               kfilter = malloc(user_kfiltermaxc * sizeof(struct filter *),
+                   M_KEVENT, M_WAITOK);
+                                       /* copy existing user_kfilters */
+               if (user_kfilters != NULL)
+                       memcpy((caddr_t)kfilter, (caddr_t)user_kfilters,
+                           user_kfilterc * sizeof(struct kfilter *));
+                                       /* zero new sections */
+               memset((caddr_t)kfilter +
+                   user_kfilterc * sizeof(struct kfilter *), 0,
+                   (user_kfiltermaxc - user_kfilterc) *
+                   sizeof(struct kfilter *));
+                                       /* switch to new kfilter */
+               if (user_kfilters != NULL)
+                       FREE(user_kfilters, M_KEVENT);
+               user_kfilters = kfilter;
+       }
+       len = strlen(name) + 1;         /* copy name */
+       user_kfilters[user_kfilterc].name = (char *)
+           malloc(len, M_KEVENT, M_WAITOK);
+       memcpy(user_kfilters[user_kfilterc].name, name, len);
+       user_kfilters[user_kfilterc].filter = user_kfilterc + EVFILT_SYSCOUNT;
+       len = sizeof(struct filterops); /* copy filtops */
+       user_kfilters[user_kfilterc].filtops = (struct filterops *)
+           malloc(len, M_KEVENT, M_WAITOK);
+       memcpy(user_kfilters[user_kfilterc].filtops, filtops, len);
+       if (retfilter != NULL)
+               *retfilter = user_kfilters[user_kfilterc].filter;
+       user_kfilterc++;                /* finally, increment count */
+       return (0);
+}
+
+/*
+ * Unregister a kfilter previously registered with kfilter_register.
+ * This retains the filter id, but clears the name and frees filtops (filter
+ * operations), so that the number isn't reused during a boot.
+ * Returns 0 if operation succeeded, or an appropriate errno(2) otherwise.
+ */
+int
+kfilter_unregister(const char *name)
+{
+       struct kfilter *kfilter;
+
+       if (name == NULL || name[0] == '\0')
+               return (EINVAL);        /* invalid name */
+       kfilter = kfilter_byname(name);
+       if (kfilter == NULL)            /* not found */
+               return (ENOENT);
+       if (kfilter->filter < EVFILT_SYSCOUNT)
+               return (EINVAL);        /* can't detach system filters */
+
+       if (kfilter->name[0] != '\0') {
+               free(kfilter->name, M_KEVENT);
+               kfilter->name = "";     /* mark as `not implemented' */
+       }
+       if (kfilter->filtops != NULL) {
+               free(kfilter->filtops, M_KEVENT);
+               kfilter->filtops = NULL; /* mark as `not implemented' */
+       }
+       return (0);
+}
+
+
+/*
+ * Filter attach method for EVFILT_READ and EVFILT_WRITE on normal file
+ * descriptors. Calls struct fileops kqfilter method for given file descriptor.
+ */
 static int
 filt_fileattach(struct knote *kn)
 {
-       
-       return (fo_kqfilter(kn->kn_fp, kn));



Home | Main Index | Thread Index | Old Index