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