From 4795cd4e7a8f775b961bce0ee70c5b9794b9a06d Mon Sep 17 00:00:00 2001 From: mheily Date: Sat, 27 Feb 2010 22:05:16 +0000 Subject: [PATCH] fixup queue.h git-svn-id: svn://svn.code.sf.net/p/libkqueue/code/trunk@218 fb4e3144-bc1c-4b72-a658-5bcd248dd7f7 --- kern/Makefile | 12 ++- kern/kqueue.c | 201 ++++++++++++++++++++++++++++++++++++++++++-------- kern/queue.h | 5 +- kern/test.c | 10 ++- 4 files changed, 191 insertions(+), 37 deletions(-) diff --git a/kern/Makefile b/kern/Makefile index 1c18d9d..eed45e6 100644 --- a/kern/Makefile +++ b/kern/Makefile @@ -17,15 +17,25 @@ obj-m = kqueue.o KVERSION = $(shell uname -r) -all: +all: kqueue.ko modtest + +kqueue.ko: kqueue.c make -C /lib/modules/`uname -r`/build M=$(PWD) modules clean: make -C /lib/modules/`uname -r`/build M=$(PWD) clean rm -f modtest +update: all + rmmod kqueue + insmod ./kqueue.ko + chmod 777 /dev/kqueue + modtest: test.c gcc -o modtest -Wall -Werror test.c +edit: + $(EDITOR) Makefile *.[ch] + check: modtest ./modtest diff --git a/kern/kqueue.c b/kern/kqueue.c index fb25a77..6b16037 100644 --- a/kern/kqueue.c +++ b/kern/kqueue.c @@ -1,17 +1,36 @@ -/* +/*- * Copyright (c) 2010 Mark Heily * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. + * Includes portions of /usr/src/sys/kern/kern_event.c which is * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * Copyright (c) 1999,2000,2001 Jonathan Lemon + * Copyright 2004 John-Mark Gurney + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* Portions based on + $FreeBSD: src/sys/kern/kern_event.c,v 1.126.2.1.2.1 2009/10/25 01:10:29 kensmith Exp $ */ #include @@ -25,9 +44,7 @@ #include #include "../include/sys/event.h" - -/* Max. number of descriptors that can be associated with a kqueue descriptor */ -#define KQUEUE_FD_MAX 10 +#include "queue.h" static int kqueue_open (struct inode *inode, struct file *file); static int kqueue_release (struct inode *inode, struct file *file); @@ -35,7 +52,7 @@ static int kqueue_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); static ssize_t kqueue_read(struct file *file, char __user *buf, size_t lbuf, loff_t *ppos); -static ssize_t kqueue_write(struct file *file, char __user *buf, +static ssize_t kqueue_write(struct file *file, const char __user *buf, size_t lbuf, loff_t *ppos); struct file_operations fops = { @@ -48,8 +65,128 @@ struct file_operations fops = { }; struct kqueue_data { - int kq_fd[KQUEUE_FD_MAX]; - size_t kq_cnt; + spinlock_t kq_lock; +}; + +/* + * Flags for knote call + */ +#define KNF_LISTLOCKED 0x0001 /* knlist is locked */ +#define KNF_NOKQLOCK 0x0002 /* do not keep KQ_LOCK */ + +#define KNOTE(list, hist, flags) knote(list, hist, flags) +#define KNOTE_LOCKED(list, hint) knote(list, hint, KNF_LISTLOCKED) +#define KNOTE_UNLOCKED(list, hint) knote(list, hint, 0) + +#define KNLIST_EMPTY(list) SLIST_EMPTY(&(list)->kl_list) + +/************* BEGIN COPY FROM sys/event.h ***************************/ +struct knote; + +/* + * Flag indicating hint is a signal. Used by EVFILT_SIGNAL, and also + * shared by EVFILT_PROC (all knotes attached to p->p_klist) + */ +#define NOTE_SIGNAL 0x08000000 + +struct filterops { + int f_isfd; /* true if ident == filedescriptor */ + int (*f_attach)(struct knote *kn); + void (*f_detach)(struct knote *kn); + int (*f_event)(struct knote *kn, long hint); +}; + +/* + * Setting the KN_INFLUX flag enables you to unlock the kq that this knote + * is on, and modify kn_status as if you had the KQ lock. + * + * kn_sfflags, kn_sdata, and kn_kevent are protected by the knlist lock. + */ +struct knote { + SLIST_ENTRY(knote) kn_link; /* for kq */ + SLIST_ENTRY(knote) kn_selnext; /* for struct selinfo */ + struct knlist *kn_knlist; /* f_attach populated */ + TAILQ_ENTRY(knote) kn_tqe; + struct kqueue *kn_kq; /* which queue we are on */ + struct kevent kn_kevent; + int kn_status; /* protected by kq lock */ +#define KN_ACTIVE 0x01 /* event has been triggered */ +#define KN_QUEUED 0x02 /* event is on queue */ +#define KN_DISABLED 0x04 /* event is disabled */ +#define KN_DETACHED 0x08 /* knote is detached */ +#define KN_INFLUX 0x10 /* knote is in flux */ +#define KN_MARKER 0x20 /* ignore this knote */ +#define KN_KQUEUE 0x40 /* this knote belongs to a kq */ +#define KN_HASKQLOCK 0x80 /* for _inevent */ + int kn_sfflags; /* saved filter flags */ + intptr_t kn_sdata; /* saved data field */ + union { + struct file *p_fp; /* file data pointer */ + struct proc *p_proc; /* proc pointer */ + struct aiocblist *p_aio; /* AIO job pointer */ + struct aioliojob *p_lio; /* LIO job pointer */ + } kn_ptr; + struct filterops *kn_fop; + void *kn_hook; + +#define kn_id kn_kevent.ident +#define kn_filter kn_kevent.filter +#define kn_flags kn_kevent.flags +#define kn_fflags kn_kevent.fflags +#define kn_data kn_kevent.data +#define kn_fp kn_ptr.p_fp +}; +static void filt_kqdetach(struct knote *kn); +static int filt_kqueue(struct knote *kn, long hint); +static int filt_procattach(struct knote *kn); +static void filt_procdetach(struct knote *kn); +static int filt_proc(struct knote *kn, long hint); +static int filt_fileattach(struct knote *kn); +static void filt_timerexpire(void *knx); +static int filt_timerattach(struct knote *kn); +static void filt_timerdetach(struct knote *kn); +static int filt_timer(struct knote *kn, long hint); + +static struct filterops file_filtops = + { 1, filt_fileattach, NULL, NULL }; +static struct filterops kqread_filtops = + { 1, NULL, filt_kqdetach, filt_kqueue }; +/* XXX - move to kern_proc.c? */ +static struct filterops proc_filtops = + { 0, filt_procattach, filt_procdetach, filt_proc }; +static struct filterops timer_filtops = + { 0, filt_timerattach, filt_timerdetach, filt_timer }; + +/************* END COPY FROM sys/event.h ***************************/ + +struct kfilter { + + /* filter operations */ + + int (*kf_init)(struct filter *); + void (*kf_destroy)(struct filter *); + int (*kf_copyout)(struct filter *, struct kevent *, int); + + /* knote operations */ + + int (*kn_create)(struct filter *, struct knote *); + int (*kn_modify)(struct filter *, struct knote *, + const struct kevent *); + int (*kn_delete)(struct filter *, struct knote *); + int (*kn_enable)(struct filter *, struct knote *); + int (*kn_disable)(struct filter *, struct knote *); + +#if DEADWOOD + struct eventfd *kf_efd; /* Used by user.c */ + int kf_pfd; /* fd to poll(2) for readiness */ + int kf_wfd; /* fd to write when an event occurs */ + u_int kf_timeres; /* timer resolution, in miliseconds */ + sigset_t kf_sigmask; + struct evfilt_data *kf_data; /* filter-specific data */ + RB_HEAD(knt, knote) kf_knote; + TAILQ_HEAD(, knote) kf_event; /* events that have occurred */ + struct kqueue *kf_kqueue; +#endif }; static int major; @@ -81,7 +218,7 @@ static int kqueue_open (struct inode *inode, struct file *file) printk("kqueue: kmalloc failed\n"); return -1; } - memset(kq, 0, sizeof(*kq)); + spin_lock_init(&kq->kq_lock); file->private_data = kq; /* FIXME Unresolved symbols kq->kq_fd[0] = epoll_create1(0); @@ -93,14 +230,7 @@ static int kqueue_open (struct inode *inode, struct file *file) static int kqueue_release (struct inode *inode, struct file *file) { - struct kqueue_data *kq = file->private_data; - int i; - printk("kqueue_release\n"); - for (i = 0; i < kq->kq_cnt; i++) { - printk(KERN_INFO "also close fd %d...\n", kq->kq_fd[i]); - sys_close(kq->kq_fd[i]); - } kfree(file->private_data); return 0; @@ -109,16 +239,11 @@ static int kqueue_release (struct inode *inode, struct file *file) static int kqueue_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - struct kqueue_data *kq = file->private_data; int fd; if (copy_from_user(&fd, (int *)arg, sizeof(int))) return -EFAULT; - if (kq->kq_cnt >= KQUEUE_FD_MAX) - return -EMFILE; - kq->kq_fd[kq->kq_cnt++] = fd; - printk(KERN_INFO "added fd %d\n", fd); return 0; @@ -127,13 +252,27 @@ static int kqueue_ioctl(struct inode *inode, struct file *file, static ssize_t kqueue_read(struct file *file, char __user *buf, size_t lbuf, loff_t *ppos) { + struct kqueue_data *kq = file->private_data; + + spin_lock(&kq->kq_lock); + //STUB + spin_unlock(&kq->kq_lock); return sizeof(struct kevent); } -static ssize_t kqueue_write(struct file *file, char __user *buf, +static ssize_t kqueue_write(struct file *file, const char __user *buf, size_t lbuf, loff_t *ppos) { + struct kqueue_data *kq = file->private_data; + + char kbuf[4]; + + spin_lock(&kq->kq_lock); + copy_from_user(kbuf, buf, 4); + printk("%zu bytes: %s", lbuf, kbuf); + spin_unlock(&kq->kq_lock); + return sizeof(struct kevent); } diff --git a/kern/queue.h b/kern/queue.h index 8f24204..c79c08a 100644 --- a/kern/queue.h +++ b/kern/queue.h @@ -33,8 +33,6 @@ #ifndef _SYS_QUEUE_H_ #define _SYS_QUEUE_H_ -#include - /* * This file defines four types of data structures: singly-linked lists, * singly-linked tail queues, lists and tail queues. @@ -325,8 +323,9 @@ struct { \ /* * List declarations. + * NOTE: LIST_HEAD conflicts with a Linux macro. */ -#define LIST_HEAD(name, type) \ +#define FIXME_LIST_HEAD(name, type) \ struct name { \ struct type *lh_first; /* first element */ \ } diff --git a/kern/test.c b/kern/test.c index 3d60daf..89ac260 100644 --- a/kern/test.c +++ b/kern/test.c @@ -25,11 +25,15 @@ int main(int argc, char **argv) { - int fd, x; + int fd; - fd = open("/dev/kqueue", 0); + fd = open("/dev/kqueue", O_RDWR); if (fd < 0) err(1, "open()"); + printf("kqfd = %d\n", fd); + +#if OLD + int x; x = 1; if (ioctl(fd, 1234, (char *) &x) < 0) @@ -37,6 +41,8 @@ main(int argc, char **argv) x = 2; if (ioctl(fd, 1234, (char *) &x) < 0) err(1, "ioctl"); +#endif + write(fd, "hi\n", 3); close(fd); puts("ok");