FreeBSD/Linux Kernel Cross Reference
sys/kern/kern_event.c
1 /*-
2 * Copyright (c) 1999,2000,2001 Jonathan Lemon <jlemon@FreeBSD.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD$
27 */
28
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/kernel.h>
32 #include <sys/proc.h>
33 #include <sys/malloc.h>
34 #include <sys/unistd.h>
35 #include <sys/file.h>
36 #include <sys/fcntl.h>
37 #include <sys/select.h>
38 #include <sys/queue.h>
39 #include <sys/event.h>
40 #include <sys/eventvar.h>
41 #include <sys/poll.h>
42 #include <sys/protosw.h>
43 #include <sys/socket.h>
44 #include <sys/socketvar.h>
45 #include <sys/stat.h>
46 #include <sys/sysctl.h>
47 #include <sys/sysproto.h>
48 #include <sys/uio.h>
49
50 #include <vm/vm_zone.h>
51
52 MALLOC_DEFINE(M_KQUEUE, "kqueue", "memory for kqueue system");
53
54 static int kqueue_scan(struct file *fp, int maxevents,
55 struct kevent *ulistp, const struct timespec *timeout,
56 struct proc *p);
57 static int kqueue_read(struct file *fp, struct uio *uio,
58 struct ucred *cred, int flags, struct proc *p);
59 static int kqueue_write(struct file *fp, struct uio *uio,
60 struct ucred *cred, int flags, struct proc *p);
61 static int kqueue_ioctl(struct file *fp, u_long com, caddr_t data,
62 struct proc *p);
63 static int kqueue_poll(struct file *fp, int events, struct ucred *cred,
64 struct proc *p);
65 static int kqueue_kqfilter(struct file *fp, struct knote *kn);
66 static int kqueue_stat(struct file *fp, struct stat *st, struct proc *p);
67 static int kqueue_close(struct file *fp, struct proc *p);
68 static void kqueue_wakeup(struct kqueue *kq);
69
70 static struct fileops kqueueops = {
71 kqueue_read,
72 kqueue_write,
73 kqueue_ioctl,
74 kqueue_poll,
75 kqueue_kqfilter,
76 kqueue_stat,
77 kqueue_close
78 };
79
80 static void knote_attach(struct knote *kn, struct filedesc *fdp);
81 static void knote_drop(struct knote *kn, struct proc *p);
82 static void knote_enqueue(struct knote *kn);
83 static void knote_dequeue(struct knote *kn);
84 static void knote_init(void);
85 static struct knote *knote_alloc(void);
86 static void knote_free(struct knote *kn);
87
88 static void filt_kqdetach(struct knote *kn);
89 static int filt_kqueue(struct knote *kn, long hint);
90 static int filt_procattach(struct knote *kn);
91 static void filt_procdetach(struct knote *kn);
92 static int filt_proc(struct knote *kn, long hint);
93 static int filt_fileattach(struct knote *kn);
94 static void filt_timerexpire(void *knx);
95 static int filt_timerattach(struct knote *kn);
96 static void filt_timerdetach(struct knote *kn);
97 static int filt_timer(struct knote *kn, long hint);
98
99 static struct filterops file_filtops =
100 { 1, filt_fileattach, NULL, NULL };
101 static struct filterops kqread_filtops =
102 { 1, NULL, filt_kqdetach, filt_kqueue };
103 static struct filterops proc_filtops =
104 { 0, filt_procattach, filt_procdetach, filt_proc };
105 static struct filterops timer_filtops =
106 { 0, filt_timerattach, filt_timerdetach, filt_timer };
107
108 static vm_zone_t knote_zone;
109 static int kq_ncallouts = 0;
110 static int kq_calloutmax = (4 * 1024);
111 SYSCTL_INT(_kern, OID_AUTO, kq_calloutmax, CTLFLAG_RW,
112 &kq_calloutmax, 0, "Maximum number of callouts allocated for kqueue");
113
114 #define KNOTE_ACTIVATE(kn) do { \
115 kn->kn_status |= KN_ACTIVE; \
116 if ((kn->kn_status & (KN_QUEUED | KN_DISABLED)) == 0) \
117 knote_enqueue(kn); \
118 } while(0)
119
120 #define KN_HASHSIZE 64 /* XXX should be tunable */
121 #define KN_HASH(val, mask) (((val) ^ (val >> 8)) & (mask))
122
123 extern struct filterops aio_filtops;
124 extern struct filterops sig_filtops;
125
126 /*
127 * Table for for all system-defined filters.
128 */
129 static struct filterops *sysfilt_ops[] = {
130 &file_filtops, /* EVFILT_READ */
131 &file_filtops, /* EVFILT_WRITE */
132 &aio_filtops, /* EVFILT_AIO */
133 &file_filtops, /* EVFILT_VNODE */
134 &proc_filtops, /* EVFILT_PROC */
135 &sig_filtops, /* EVFILT_SIGNAL */
136 &timer_filtops, /* EVFILT_TIMER */
137 };
138
139 static int
140 filt_fileattach(struct knote *kn)
141 {
142
143 return (fo_kqfilter(kn->kn_fp, kn));
144 }
145
146 /*ARGSUSED*/
147 static int
148 kqueue_kqfilter(struct file *fp, struct knote *kn)
149 {
150 struct kqueue *kq = (struct kqueue *)kn->kn_fp->f_data;
151
152 if (kn->kn_filter != EVFILT_READ)
153 return (1);
154
155 kn->kn_fop = &kqread_filtops;
156 SLIST_INSERT_HEAD(&kq->kq_sel.si_note, kn, kn_selnext);
157 return (0);
158 }
159
160 static void
161 filt_kqdetach(struct knote *kn)
162 {
163 struct kqueue *kq = (struct kqueue *)kn->kn_fp->f_data;
164
165 SLIST_REMOVE(&kq->kq_sel.si_note, kn, knote, kn_selnext);
166 }
167
168 /*ARGSUSED*/
169 static int
170 filt_kqueue(struct knote *kn, long hint)
171 {
172 struct kqueue *kq = (struct kqueue *)kn->kn_fp->f_data;
173
174 kn->kn_data = kq->kq_count;
175 return (kn->kn_data > 0);
176 }
177
178 static int
179 filt_procattach(struct knote *kn)
180 {
181 struct proc *p;
182 int immediate;
183
184 immediate = 0;
185 p = pfind(kn->kn_id);
186 if (p == NULL && (kn->kn_sfflags & NOTE_EXIT)) {
187 p = zpfind(kn->kn_id);
188 immediate = 1;
189 }
190 if (p == NULL)
191 return (ESRCH);
192 if (! PRISON_CHECK(curproc, p))
193 return (EACCES);
194
195 kn->kn_ptr.p_proc = p;
196 kn->kn_flags |= EV_CLEAR; /* automatically set */
197
198 /*
199 * internal flag indicating registration done by kernel
200 */
201 if (kn->kn_flags & EV_FLAG1) {
202 kn->kn_data = kn->kn_sdata; /* ppid */
203 kn->kn_fflags = NOTE_CHILD;
204 kn->kn_flags &= ~EV_FLAG1;
205 }
206
207 /* XXX lock the proc here while adding to the list? */
208 SLIST_INSERT_HEAD(&p->p_klist, kn, kn_selnext);
209
210 /*
211 * Immediately activate any exit notes if the target process is a
212 * zombie. This is necessary to handle the case where the target
213 * process, e.g. a child, dies before the kevent is registered.
214 */
215 if (immediate && filt_proc(kn, NOTE_EXIT))
216 KNOTE_ACTIVATE(kn);
217
218 return (0);
219 }
220
221 /*
222 * The knote may be attached to a different process, which may exit,
223 * leaving nothing for the knote to be attached to. So when the process
224 * exits, the knote is marked as DETACHED and also flagged as ONESHOT so
225 * it will be deleted when read out. However, as part of the knote deletion,
226 * this routine is called, so a check is needed to avoid actually performing
227 * a detach, because the original process does not exist any more.
228 */
229 static void
230 filt_procdetach(struct knote *kn)
231 {
232 struct proc *p = kn->kn_ptr.p_proc;
233
234 if (kn->kn_status & KN_DETACHED)
235 return;
236
237 /* XXX locking? this might modify another process. */
238 SLIST_REMOVE(&p->p_klist, kn, knote, kn_selnext);
239 }
240
241 static int
242 filt_proc(struct knote *kn, long hint)
243 {
244 u_int event;
245
246 /*
247 * mask off extra data
248 */
249 event = (u_int)hint & NOTE_PCTRLMASK;
250
251 /*
252 * if the user is interested in this event, record it.
253 */
254 if (kn->kn_sfflags & event)
255 kn->kn_fflags |= event;
256
257 /*
258 * process is gone, so flag the event as finished.
259 */
260 if (event == NOTE_EXIT) {
261 filt_procdetach(kn);
262 kn->kn_status |= KN_DETACHED;
263 kn->kn_flags |= (EV_EOF | EV_ONESHOT);
264 return (1);
265 }
266
267 /*
268 * process forked, and user wants to track the new process,
269 * so attach a new knote to it, and immediately report an
270 * event with the parent's pid.
271 */
272 if ((event == NOTE_FORK) && (kn->kn_sfflags & NOTE_TRACK)) {
273 struct kevent kev;
274 int error;
275
276 /*
277 * register knote with new process.
278 */
279 kev.ident = hint & NOTE_PDATAMASK; /* pid */
280 kev.filter = kn->kn_filter;
281 kev.flags = kn->kn_flags | EV_ADD | EV_ENABLE | EV_FLAG1;
282 kev.fflags = kn->kn_sfflags;
283 kev.data = kn->kn_id; /* parent */
284 kev.udata = kn->kn_kevent.udata; /* preserve udata */
285 error = kqueue_register(kn->kn_kq, &kev, NULL);
286 if (error)
287 kn->kn_fflags |= NOTE_TRACKERR;
288 }
289
290 return (kn->kn_fflags != 0);
291 }
292
293 static void
294 filt_timerexpire(void *knx)
295 {
296 struct knote *kn = knx;
297 struct callout *calloutp;
298 struct timeval tv;
299 int tticks;
300
301 kn->kn_data++;
302 KNOTE_ACTIVATE(kn);
303
304 if ((kn->kn_flags & EV_ONESHOT) == 0) {
305 tv.tv_sec = kn->kn_sdata / 1000;
306 tv.tv_usec = (kn->kn_sdata % 1000) * 1000;
307 tticks = tvtohz(&tv);
308 calloutp = (struct callout *)kn->kn_hook;
309 callout_reset(calloutp, tticks, filt_timerexpire, kn);
310 }
311 }
312
313 /*
314 * data contains amount of time to sleep, in milliseconds
315 */
316 static int
317 filt_timerattach(struct knote *kn)
318 {
319 struct callout *calloutp;
320 struct timeval tv;
321 int tticks;
322
323 if (kq_ncallouts >= kq_calloutmax)
324 return (ENOMEM);
325 kq_ncallouts++;
326
327 tv.tv_sec = kn->kn_sdata / 1000;
328 tv.tv_usec = (kn->kn_sdata % 1000) * 1000;
329 tticks = tvtohz(&tv);
330
331 kn->kn_flags |= EV_CLEAR; /* automatically set */
332 MALLOC(calloutp, struct callout *, sizeof(*calloutp),
333 M_KQUEUE, M_WAITOK);
334 callout_init(calloutp);
335 kn->kn_hook = (caddr_t)calloutp;
336 callout_reset(calloutp, tticks, filt_timerexpire, kn);
337
338 return (0);
339 }
340
341 static void
342 filt_timerdetach(struct knote *kn)
343 {
344 struct callout *calloutp;
345
346 calloutp = (struct callout *)kn->kn_hook;
347 callout_stop(calloutp);
348 FREE(calloutp, M_KQUEUE);
349 kq_ncallouts--;
350 }
351
352 static int
353 filt_timer(struct knote *kn, long hint)
354 {
355
356 return (kn->kn_data != 0);
357 }
358
359 int
360 kqueue(struct proc *p, struct kqueue_args *uap)
361 {
362 struct filedesc *fdp = p->p_fd;
363 struct kqueue *kq;
364 struct file *fp;
365 int fd, error;
366
367 error = falloc(p, &fp, &fd);
368 if (error)
369 return (error);
370 fp->f_flag = FREAD | FWRITE;
371 fp->f_type = DTYPE_KQUEUE;
372 fp->f_ops = &kqueueops;
373 kq = malloc(sizeof(struct kqueue), M_KQUEUE, M_WAITOK | M_ZERO);
374 TAILQ_INIT(&kq->kq_head);
375 fp->f_data = (caddr_t)kq;
376 p->p_retval[0] = fd;
377 if (fdp->fd_knlistsize < 0)
378 fdp->fd_knlistsize = 0; /* this process has a kq */
379 kq->kq_fdp = fdp;
380 return (error);
381 }
382
383 #ifndef _SYS_SYSPROTO_H_
384 struct kevent_args {
385 int fd;
386 const struct kevent *changelist;
387 int nchanges;
388 struct kevent *eventlist;
389 int nevents;
390 const struct timespec *timeout;
391 };
392 #endif
393 int
394 kevent(struct proc *p, struct kevent_args *uap)
395 {
396 struct filedesc* fdp = p->p_fd;
397 struct kevent *kevp;
398 struct kqueue *kq;
399 struct file *fp = NULL;
400 struct timespec ts;
401 int i, n, nerrors, error;
402
403 if (((u_int)uap->fd) >= fdp->fd_nfiles ||
404 (fp = fdp->fd_ofiles[uap->fd]) == NULL ||
405 (fp->f_type != DTYPE_KQUEUE))
406 return (EBADF);
407
408 fhold(fp);
409
410 if (uap->timeout != NULL) {
411 error = copyin(uap->timeout, &ts, sizeof(ts));
412 if (error)
413 goto done;
414 uap->timeout = &ts;
415 }
416
417 kq = (struct kqueue *)fp->f_data;
418 nerrors = 0;
419
420 while (uap->nchanges > 0) {
421 n = uap->nchanges > KQ_NEVENTS ? KQ_NEVENTS : uap->nchanges;
422 error = copyin(uap->changelist, kq->kq_kev,
423 n * sizeof(struct kevent));
424 if (error)
425 goto done;
426 for (i = 0; i < n; i++) {
427 kevp = &kq->kq_kev[i];
428 kevp->flags &= ~EV_SYSFLAGS;
429 error = kqueue_register(kq, kevp, p);
430 if (error) {
431 if (uap->nevents != 0) {
432 kevp->flags = EV_ERROR;
433 kevp->data = error;
434 (void) copyout((caddr_t)kevp,
435 (caddr_t)uap->eventlist,
436 sizeof(*kevp));
437 uap->eventlist++;
438 uap->nevents--;
439 nerrors++;
440 } else {
441 goto done;
442 }
443 }
444 }
445 uap->nchanges -= n;
446 uap->changelist += n;
447 }
448 if (nerrors) {
449 p->p_retval[0] = nerrors;
450 error = 0;
451 goto done;
452 }
453
454 error = kqueue_scan(fp, uap->nevents, uap->eventlist, uap->timeout, p);
455 done:
456 if (fp != NULL)
457 fdrop(fp, p);
458 return (error);
459 }
460
461 int
462 kqueue_register(struct kqueue *kq, struct kevent *kev, struct proc *p)
463 {
464 struct filedesc *fdp = kq->kq_fdp;
465 struct filterops *fops;
466 struct file *fp = NULL;
467 struct knote *kn = NULL;
468 int s, error = 0;
469
470 if (kev->filter < 0) {
471 if (kev->filter + EVFILT_SYSCOUNT < 0)
472 return (EINVAL);
473 fops = sysfilt_ops[~kev->filter]; /* to 0-base index */
474 } else {
475 /*
476 * XXX
477 * filter attach routine is responsible for insuring that
478 * the identifier can be attached to it.
479 */
480 printf("unknown filter: %d\n", kev->filter);
481 return (EINVAL);
482 }
483
484 if (fops->f_isfd) {
485 /* validate descriptor */
486 if ((u_int)kev->ident >= fdp->fd_nfiles ||
487 (fp = fdp->fd_ofiles[kev->ident]) == NULL)
488 return (EBADF);
489 fhold(fp);
490
491 if (kev->ident < fdp->fd_knlistsize) {
492 SLIST_FOREACH(kn, &fdp->fd_knlist[kev->ident], kn_link)
493 if (kq == kn->kn_kq &&
494 kev->filter == kn->kn_filter)
495 break;
496 }
497 } else {
498 if (fdp->fd_knhashmask != 0) {
499 struct klist *list;
500
501 list = &fdp->fd_knhash[
502 KN_HASH((u_long)kev->ident, fdp->fd_knhashmask)];
503 SLIST_FOREACH(kn, list, kn_link)
504 if (kev->ident == kn->kn_id &&
505 kq == kn->kn_kq &&
506 kev->filter == kn->kn_filter)
507 break;
508 }
509 }
510
511 if (kn == NULL && ((kev->flags & EV_ADD) == 0)) {
512 error = ENOENT;
513 goto done;
514 }
515
516 /*
517 * kn now contains the matching knote, or NULL if no match
518 */
519 if (kev->flags & EV_ADD) {
520
521 if (kn == NULL) {
522 kn = knote_alloc();
523 if (kn == NULL) {
524 error = ENOMEM;
525 goto done;
526 }
527 kn->kn_fp = fp;
528 kn->kn_kq = kq;
529 kn->kn_fop = fops;
530
531 /*
532 * apply reference count to knote structure, and
533 * do not release it at the end of this routine.
534 */
535 fp = NULL;
536
537 kn->kn_sfflags = kev->fflags;
538 kn->kn_sdata = kev->data;
539 kev->fflags = 0;
540 kev->data = 0;
541 kn->kn_kevent = *kev;
542
543 knote_attach(kn, fdp);
544 if ((error = fops->f_attach(kn)) != 0) {
545 knote_drop(kn, p);
546 goto done;
547 }
548 } else {
549 /*
550 * The user may change some filter values after the
551 * initial EV_ADD, but doing so will not reset any
552 * filter which have already been triggered.
553 */
554 kn->kn_sfflags = kev->fflags;
555 kn->kn_sdata = kev->data;
556 kn->kn_kevent.udata = kev->udata;
557 }
558
559 s = splhigh();
560 if (kn->kn_fop->f_event(kn, 0))
561 KNOTE_ACTIVATE(kn);
562 splx(s);
563
564 } else if (kev->flags & EV_DELETE) {
565 kn->kn_fop->f_detach(kn);
566 knote_drop(kn, p);
567 goto done;
568 }
569
570 if ((kev->flags & EV_DISABLE) &&
571 ((kn->kn_status & KN_DISABLED) == 0)) {
572 s = splhigh();
573 kn->kn_status |= KN_DISABLED;
574 splx(s);
575 }
576
577 if ((kev->flags & EV_ENABLE) && (kn->kn_status & KN_DISABLED)) {
578 s = splhigh();
579 kn->kn_status &= ~KN_DISABLED;
580 if ((kn->kn_status & KN_ACTIVE) &&
581 ((kn->kn_status & KN_QUEUED) == 0))
582 knote_enqueue(kn);
583 splx(s);
584 }
585
586 done:
587 if (fp != NULL)
588 fdrop(fp, p);
589 return (error);
590 }
591
592 static int
593 kqueue_scan(struct file *fp, int maxevents, struct kevent *ulistp,
594 const struct timespec *tsp, struct proc *p)
595 {
596 struct kqueue *kq = (struct kqueue *)fp->f_data;
597 struct kevent *kevp;
598 struct timeval atv, rtv, ttv;
599 struct knote *kn, marker;
600 int s, count, timeout, nkev = 0, error = 0;
601
602 count = maxevents;
603 if (count == 0)
604 goto done;
605
606 if (tsp != NULL) {
607 TIMESPEC_TO_TIMEVAL(&atv, tsp);
608 if (itimerfix(&atv)) {
609 error = EINVAL;
610 goto done;
611 }
612 if (tsp->tv_sec == 0 && tsp->tv_nsec == 0)
613 timeout = -1;
614 else
615 timeout = atv.tv_sec > 24 * 60 * 60 ?
616 24 * 60 * 60 * hz : tvtohz(&atv);
617 getmicrouptime(&rtv);
618 timevaladd(&atv, &rtv);
619 } else {
620 atv.tv_sec = 0;
621 atv.tv_usec = 0;
622 timeout = 0;
623 }
624 goto start;
625
626 retry:
627 if (atv.tv_sec || atv.tv_usec) {
628 getmicrouptime(&rtv);
629 if (timevalcmp(&rtv, &atv, >=))
630 goto done;
631 ttv = atv;
632 timevalsub(&ttv, &rtv);
633 timeout = ttv.tv_sec > 24 * 60 * 60 ?
634 24 * 60 * 60 * hz : tvtohz(&ttv);
635 }
636
637 start:
638 kevp = kq->kq_kev;
639 s = splhigh();
640 if (kq->kq_count == 0) {
641 if (timeout < 0) {
642 error = EWOULDBLOCK;
643 } else {
644 kq->kq_state |= KQ_SLEEP;
645 error = tsleep(kq, PSOCK | PCATCH, "kqread", timeout);
646 }
647 splx(s);
648 if (error == 0)
649 goto retry;
650 /* don't restart after signals... */
651 if (error == ERESTART)
652 error = EINTR;
653 else if (error == EWOULDBLOCK)
654 error = 0;
655 goto done;
656 }
657
658 TAILQ_INSERT_TAIL(&kq->kq_head, &marker, kn_tqe);
659 while (count) {
660 kn = TAILQ_FIRST(&kq->kq_head);
661 TAILQ_REMOVE(&kq->kq_head, kn, kn_tqe);
662 if (kn == &marker) {
663 splx(s);
664 if (count == maxevents)
665 goto retry;
666 goto done;
667 }
668 if (kn->kn_status & KN_DISABLED) {
669 kn->kn_status &= ~KN_QUEUED;
670 kq->kq_count--;
671 continue;
672 }
673 if ((kn->kn_flags & EV_ONESHOT) == 0 &&
674 kn->kn_fop->f_event(kn, 0) == 0) {
675 kn->kn_status &= ~(KN_QUEUED | KN_ACTIVE);
676 kq->kq_count--;
677 continue;
678 }
679 *kevp = kn->kn_kevent;
680 kevp++;
681 nkev++;
682 if (kn->kn_flags & EV_ONESHOT) {
683 kn->kn_status &= ~KN_QUEUED;
684 kq->kq_count--;
685 splx(s);
686 kn->kn_fop->f_detach(kn);
687 knote_drop(kn, p);
688 s = splhigh();
689 } else if (kn->kn_flags & EV_CLEAR) {
690 kn->kn_data = 0;
691 kn->kn_fflags = 0;
692 kn->kn_status &= ~(KN_QUEUED | KN_ACTIVE);
693 kq->kq_count--;
694 } else {
695 TAILQ_INSERT_TAIL(&kq->kq_head, kn, kn_tqe);
696 }
697 count--;
698 if (nkev == KQ_NEVENTS) {
699 splx(s);
700 error = copyout((caddr_t)&kq->kq_kev, (caddr_t)ulistp,
701 sizeof(struct kevent) * nkev);
702 ulistp += nkev;
703 nkev = 0;
704 kevp = kq->kq_kev;
705 s = splhigh();
706 if (error)
707 break;
708 }
709 }
710 TAILQ_REMOVE(&kq->kq_head, &marker, kn_tqe);
711 splx(s);
712 done:
713 if (nkev != 0)
714 error = copyout((caddr_t)&kq->kq_kev, (caddr_t)ulistp,
715 sizeof(struct kevent) * nkev);
716 p->p_retval[0] = maxevents - count;
717 return (error);
718 }
719
720 /*
721 * XXX
722 * This could be expanded to call kqueue_scan, if desired.
723 */
724 /*ARGSUSED*/
725 static int
726 kqueue_read(struct file *fp, struct uio *uio, struct ucred *cred,
727 int flags, struct proc *p)
728 {
729 return (ENXIO);
730 }
731
732 /*ARGSUSED*/
733 static int
734 kqueue_write(struct file *fp, struct uio *uio, struct ucred *cred,
735 int flags, struct proc *p)
736 {
737 return (ENXIO);
738 }
739
740 /*ARGSUSED*/
741 static int
742 kqueue_ioctl(struct file *fp, u_long com, caddr_t data, struct proc *p)
743 {
744 return (ENOTTY);
745 }
746
747 /*ARGSUSED*/
748 static int
749 kqueue_poll(struct file *fp, int events, struct ucred *cred, struct proc *p)
750 {
751 struct kqueue *kq = (struct kqueue *)fp->f_data;
752 int revents = 0;
753 int s = splnet();
754
755 if (events & (POLLIN | POLLRDNORM)) {
756 if (kq->kq_count) {
757 revents |= events & (POLLIN | POLLRDNORM);
758 } else {
759 selrecord(p, &kq->kq_sel);
760 kq->kq_state |= KQ_SEL;
761 }
762 }
763 splx(s);
764 return (revents);
765 }
766
767 /*ARGSUSED*/
768 static int
769 kqueue_stat(struct file *fp, struct stat *st, struct proc *p)
770 {
771 struct kqueue *kq = (struct kqueue *)fp->f_data;
772
773 bzero((void *)st, sizeof(*st));
774 st->st_size = kq->kq_count;
775 st->st_blksize = sizeof(struct kevent);
776 st->st_mode = S_IFIFO;
777 return (0);
778 }
779
780 /*ARGSUSED*/
781 static int
782 kqueue_close(struct file *fp, struct proc *p)
783 {
784 struct kqueue *kq = (struct kqueue *)fp->f_data;
785 struct filedesc *fdp = p->p_fd;
786 struct knote **knp, *kn, *kn0;
787 int i;
788
789 for (i = 0; i < fdp->fd_knlistsize; i++) {
790 knp = &SLIST_FIRST(&fdp->fd_knlist[i]);
791 kn = *knp;
792 while (kn != NULL) {
793 kn0 = SLIST_NEXT(kn, kn_link);
794 if (kq == kn->kn_kq) {
795 kn->kn_fop->f_detach(kn);
796 fdrop(kn->kn_fp, p);
797 knote_free(kn);
798 *knp = kn0;
799 } else {
800 knp = &SLIST_NEXT(kn, kn_link);
801 }
802 kn = kn0;
803 }
804 }
805 if (fdp->fd_knhashmask != 0) {
806 for (i = 0; i < fdp->fd_knhashmask + 1; i++) {
807 knp = &SLIST_FIRST(&fdp->fd_knhash[i]);
808 kn = *knp;
809 while (kn != NULL) {
810 kn0 = SLIST_NEXT(kn, kn_link);
811 if (kq == kn->kn_kq) {
812 kn->kn_fop->f_detach(kn);
813 /* XXX non-fd release of kn->kn_ptr */
814 knote_free(kn);
815 *knp = kn0;
816 } else {
817 knp = &SLIST_NEXT(kn, kn_link);
818 }
819 kn = kn0;
820 }
821 }
822 }
823 free(kq, M_KQUEUE);
824 fp->f_data = NULL;
825
826 return (0);
827 }
828
829 static void
830 kqueue_wakeup(struct kqueue *kq)
831 {
832
833 if (kq->kq_state & KQ_SLEEP) {
834 kq->kq_state &= ~KQ_SLEEP;
835 wakeup(kq);
836 }
837 if (kq->kq_state & KQ_SEL) {
838 kq->kq_state &= ~KQ_SEL;
839 selwakeup(&kq->kq_sel);
840 }
841 KNOTE(&kq->kq_sel.si_note, 0);
842 }
843
844 /*
845 * walk down a list of knotes, activating them if their event has triggered.
846 */
847 void
848 knote(struct klist *list, long hint)
849 {
850 struct knote *kn;
851
852 SLIST_FOREACH(kn, list, kn_selnext)
853 if (kn->kn_fop->f_event(kn, hint))
854 KNOTE_ACTIVATE(kn);
855 }
856
857 /*
858 * remove all knotes from a specified klist
859 */
860 void
861 knote_remove(struct proc *p, struct klist *list)
862 {
863 struct knote *kn;
864
865 while ((kn = SLIST_FIRST(list)) != NULL) {
866 kn->kn_fop->f_detach(kn);
867 knote_drop(kn, p);
868 }
869 }
870
871 /*
872 * remove all knotes referencing a specified fd
873 */
874 void
875 knote_fdclose(struct proc *p, int fd)
876 {
877 struct filedesc *fdp = p->p_fd;
878 struct klist *list = &fdp->fd_knlist[fd];
879
880 knote_remove(p, list);
881 }
882
883 static void
884 knote_attach(struct knote *kn, struct filedesc *fdp)
885 {
886 struct klist *list;
887 int size;
888
889 if (! kn->kn_fop->f_isfd) {
890 if (fdp->fd_knhashmask == 0)
891 fdp->fd_knhash = hashinit(KN_HASHSIZE, M_KQUEUE,
892 &fdp->fd_knhashmask);
893 list = &fdp->fd_knhash[KN_HASH(kn->kn_id, fdp->fd_knhashmask)];
894 goto done;
895 }
896
897 if (fdp->fd_knlistsize <= kn->kn_id) {
898 size = fdp->fd_knlistsize;
899 while (size <= kn->kn_id)
900 size += KQEXTENT;
901 MALLOC(list, struct klist *,
902 size * sizeof(struct klist *), M_KQUEUE, M_WAITOK);
903 bcopy((caddr_t)fdp->fd_knlist, (caddr_t)list,
904 fdp->fd_knlistsize * sizeof(struct klist *));
905 bzero((caddr_t)list +
906 fdp->fd_knlistsize * sizeof(struct klist *),
907 (size - fdp->fd_knlistsize) * sizeof(struct klist *));
908 if (fdp->fd_knlist != NULL)
909 FREE(fdp->fd_knlist, M_KQUEUE);
910 fdp->fd_knlistsize = size;
911 fdp->fd_knlist = list;
912 }
913 list = &fdp->fd_knlist[kn->kn_id];
914 done:
915 SLIST_INSERT_HEAD(list, kn, kn_link);
916 kn->kn_status = 0;
917 }
918
919 /*
920 * should be called at spl == 0, since we don't want to hold spl
921 * while calling fdrop and free.
922 */
923 static void
924 knote_drop(struct knote *kn, struct proc *p)
925 {
926 struct filedesc *fdp = p->p_fd;
927 struct klist *list;
928
929 if (kn->kn_fop->f_isfd)
930 list = &fdp->fd_knlist[kn->kn_id];
931 else
932 list = &fdp->fd_knhash[KN_HASH(kn->kn_id, fdp->fd_knhashmask)];
933
934 SLIST_REMOVE(list, kn, knote, kn_link);
935 if (kn->kn_status & KN_QUEUED)
936 knote_dequeue(kn);
937 if (kn->kn_fop->f_isfd)
938 fdrop(kn->kn_fp, p);
939 knote_free(kn);
940 }
941
942
943 static void
944 knote_enqueue(struct knote *kn)
945 {
946 struct kqueue *kq = kn->kn_kq;
947 int s = splhigh();
948
949 if (kn->kn_status & KN_QUEUED) {
950 splx(s);
951 return;
952 }
953
954 TAILQ_INSERT_TAIL(&kq->kq_head, kn, kn_tqe);
955 kn->kn_status |= KN_QUEUED;
956 kq->kq_count++;
957 splx(s);
958 kqueue_wakeup(kq);
959 }
960
961 static void
962 knote_dequeue(struct knote *kn)
963 {
964 struct kqueue *kq = kn->kn_kq;
965 int s = splhigh();
966
967 KASSERT(kn->kn_status & KN_QUEUED, ("knote not queued"));
968
969 TAILQ_REMOVE(&kq->kq_head, kn, kn_tqe);
970 kn->kn_status &= ~KN_QUEUED;
971 kq->kq_count--;
972 splx(s);
973 }
974
975 static void
976 knote_init(void)
977 {
978 knote_zone = zinit("KNOTE", sizeof(struct knote), 0, 0, 1);
979 }
980 SYSINIT(knote, SI_SUB_PSEUDO, SI_ORDER_ANY, knote_init, NULL)
981
982 static struct knote *
983 knote_alloc(void)
984 {
985 return ((struct knote *)zalloc(knote_zone));
986 }
987
988 static void
989 knote_free(struct knote *kn)
990 {
991 zfree(knote_zone, kn);
992 }
Cache object: b09009b5f3c47edd85d0f7b35f511ee1
|