1 /*- 2 * Copyright (c) 1999,2000 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/selinfo.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/sysproto.h> 47 #include <sys/uio.h> 48 49 #include <vm/vm_zone.h> 50 51 static int kqueue_scan(struct file *fp, int maxevents, 52 struct kevent *ulistp, const struct timespec *timeout, 53 struct proc *p); 54 static int kqueue_read(struct file *fp, struct uio *uio, 55 struct ucred *cred, int flags, struct proc *p); 56 static int kqueue_write(struct file *fp, struct uio *uio, 57 struct ucred *cred, int flags, struct proc *p); 58 static int kqueue_ioctl(struct file *fp, u_long com, caddr_t data, 59 struct proc *p); 60 static int kqueue_poll(struct file *fp, int events, struct ucred *cred, 61 struct proc *p); 62 static int kqueue_kqfilter(struct file *fp, struct knote *kn); 63 static int kqueue_stat(struct file *fp, struct stat *st, struct proc *p); 64 static int kqueue_close(struct file *fp, struct proc *p); 65 static void kqueue_wakeup(struct kqueue *kq); 66 67 static struct fileops kqueueops = { 68 kqueue_read, 69 kqueue_write, 70 kqueue_ioctl, 71 kqueue_poll, 72 kqueue_kqfilter, 73 kqueue_stat, 74 kqueue_close 75 }; 76 77 static void knote_attach(struct knote *kn, struct filedesc *fdp); 78 static void knote_drop(struct knote *kn, struct proc *p); 79 static void knote_enqueue(struct knote *kn); 80 static void knote_dequeue(struct knote *kn); 81 static void knote_init(void); 82 static struct knote *knote_alloc(void); 83 static void knote_free(struct knote *kn); 84 85 static void filt_kqdetach(struct knote *kn); 86 static int filt_kqueue(struct knote *kn, long hint); 87 static int filt_procattach(struct knote *kn); 88 static void filt_procdetach(struct knote *kn); 89 static int filt_proc(struct knote *kn, long hint); 90 static int filt_fileattach(struct knote *kn); 91 92 static struct filterops kqread_filtops = 93 { 1, NULL, filt_kqdetach, filt_kqueue }; 94 static struct filterops proc_filtops = 95 { 0, filt_procattach, filt_procdetach, filt_proc }; 96 static struct filterops file_filtops = 97 { 1, filt_fileattach, NULL, NULL }; 98 99 static vm_zone_t knote_zone; 100 101 #define KNOTE_ACTIVATE(kn) do { \ 102 kn->kn_status |= KN_ACTIVE; \ 103 if ((kn->kn_status & (KN_QUEUED | KN_DISABLED)) == 0) \ 104 knote_enqueue(kn); \ 105 } while(0) 106 107 #define KN_HASHSIZE 64 /* XXX should be tunable */ 108 #define KN_HASH(val, mask) (((val) ^ (val >> 8)) & (mask)) 109 110 extern struct filterops aio_filtops; 111 extern struct filterops sig_filtops; 112 113 /* 114 * Table for for all system-defined filters. 115 */ 116 static struct filterops *sysfilt_ops[] = { 117 &file_filtops, /* EVFILT_READ */ 118 &file_filtops, /* EVFILT_WRITE */ 119 &aio_filtops, /* EVFILT_AIO */ 120 &file_filtops, /* EVFILT_VNODE */ 121 &proc_filtops, /* EVFILT_PROC */ 122 &sig_filtops, /* EVFILT_SIGNAL */ 123 }; 124 125 static int 126 filt_fileattach(struct knote *kn) 127 { 128 129 return (fo_kqfilter(kn->kn_fp, kn)); 130 } 131 132 /*ARGSUSED*/ 133 static int 134 kqueue_kqfilter(struct file *fp, struct knote *kn) 135 { 136 struct kqueue *kq = (struct kqueue *)kn->kn_fp->f_data; 137 138 if (kn->kn_filter != EVFILT_READ) 139 return (1); 140 141 kn->kn_fop = &kqread_filtops; 142 SLIST_INSERT_HEAD(&kq->kq_sel.si_note, kn, kn_selnext); 143 return (0); 144 } 145 146 static void 147 filt_kqdetach(struct knote *kn) 148 { 149 struct kqueue *kq = (struct kqueue *)kn->kn_fp->f_data; 150 151 SLIST_REMOVE(&kq->kq_sel.si_note, kn, knote, kn_selnext); 152 } 153 154 /*ARGSUSED*/ 155 static int 156 filt_kqueue(struct knote *kn, long hint) 157 { 158 struct kqueue *kq = (struct kqueue *)kn->kn_fp->f_data; 159 160 kn->kn_data = kq->kq_count; 161 return (kn->kn_data > 0); 162 } 163 164 static int 165 filt_procattach(struct knote *kn) 166 { 167 struct proc *p; 168 169 p = pfind(kn->kn_id); 170 if (p == NULL) 171 return (ESRCH); 172 if (p_can(curproc, p, P_CAN_SEE, NULL)) 173 return (EACCES); 174 175 kn->kn_ptr.p_proc = p; 176 kn->kn_flags |= EV_CLEAR; /* automatically set */ 177 178 /* 179 * internal flag indicating registration done by kernel 180 */ 181 if (kn->kn_flags & EV_FLAG1) { 182 kn->kn_data = kn->kn_sdata; /* ppid */ 183 kn->kn_fflags = NOTE_CHILD; 184 kn->kn_flags &= ~EV_FLAG1; 185 } 186 187 PROC_LOCK(p); 188 SLIST_INSERT_HEAD(&p->p_klist, kn, kn_selnext); 189 PROC_UNLOCK(p); 190 191 return (0); 192 } 193 194 /* 195 * The knote may be attached to a different process, which may exit, 196 * leaving nothing for the knote to be attached to. So when the process 197 * exits, the knote is marked as DETACHED and also flagged as ONESHOT so 198 * it will be deleted when read out. However, as part of the knote deletion, 199 * this routine is called, so a check is needed to avoid actually performing 200 * a detach, because the original process does not exist any more. 201 */ 202 static void 203 filt_procdetach(struct knote *kn) 204 { 205 struct proc *p = kn->kn_ptr.p_proc; 206 207 if (kn->kn_status & KN_DETACHED) 208 return; 209 210 PROC_LOCK(p); 211 SLIST_REMOVE(&p->p_klist, kn, knote, kn_selnext); 212 PROC_UNLOCK(p); 213 } 214 215 static int 216 filt_proc(struct knote *kn, long hint) 217 { 218 u_int event; 219 220 /* 221 * mask off extra data 222 */ 223 event = (u_int)hint & NOTE_PCTRLMASK; 224 225 /* 226 * if the user is interested in this event, record it. 227 */ 228 if (kn->kn_sfflags & event) 229 kn->kn_fflags |= event; 230 231 /* 232 * process is gone, so flag the event as finished. 233 */ 234 if (event == NOTE_EXIT) { 235 kn->kn_status |= KN_DETACHED; 236 kn->kn_flags |= (EV_EOF | EV_ONESHOT); 237 return (1); 238 } 239 240 /* 241 * process forked, and user wants to track the new process, 242 * so attach a new knote to it, and immediately report an 243 * event with the parent's pid. 244 */ 245 if ((event == NOTE_FORK) && (kn->kn_sfflags & NOTE_TRACK)) { 246 struct kevent kev; 247 int error; 248 249 /* 250 * register knote with new process. 251 */ 252 kev.ident = hint & NOTE_PDATAMASK; /* pid */ 253 kev.filter = kn->kn_filter; 254 kev.flags = kn->kn_flags | EV_ADD | EV_ENABLE | EV_FLAG1; 255 kev.fflags = kn->kn_sfflags; 256 kev.data = kn->kn_id; /* parent */ 257 kev.udata = kn->kn_kevent.udata; /* preserve udata */ 258 error = kqueue_register(kn->kn_kq, &kev, NULL); 259 if (error) 260 kn->kn_fflags |= NOTE_TRACKERR; 261 } 262 263 return (kn->kn_fflags != 0); 264 } 265 266 int 267 kqueue(struct proc *p, struct kqueue_args *uap) 268 { 269 struct filedesc *fdp = p->p_fd; 270 struct kqueue *kq; 271 struct file *fp; 272 int fd, error; 273 274 error = falloc(p, &fp, &fd); 275 if (error) 276 return (error); 277 fp->f_flag = FREAD | FWRITE; 278 fp->f_type = DTYPE_KQUEUE; 279 fp->f_ops = &kqueueops; 280 kq = malloc(sizeof(struct kqueue), M_TEMP, M_WAITOK | M_ZERO); 281 TAILQ_INIT(&kq->kq_head); 282 fp->f_data = (caddr_t)kq; 283 p->p_retval[0] = fd; 284 if (fdp->fd_knlistsize < 0) 285 fdp->fd_knlistsize = 0; /* this process has a kq */ 286 kq->kq_fdp = fdp; 287 return (error); 288 } 289 290 #ifndef _SYS_SYSPROTO_H_ 291 struct kevent_args { 292 int fd; 293 const struct kevent *changelist; 294 int nchanges; 295 struct kevent *eventlist; 296 int nevents; 297 const struct timespec *timeout; 298 }; 299 #endif 300 int 301 kevent(struct proc *p, struct kevent_args *uap) 302 { 303 struct filedesc* fdp = p->p_fd; 304 struct kevent *kevp; 305 struct kqueue *kq; 306 struct file *fp = NULL; 307 struct timespec ts; 308 int i, n, nerrors, error; 309 310 if (((u_int)uap->fd) >= fdp->fd_nfiles || 311 (fp = fdp->fd_ofiles[uap->fd]) == NULL || 312 (fp->f_type != DTYPE_KQUEUE)) 313 return (EBADF); 314 315 fhold(fp); 316 317 if (uap->timeout != NULL) { 318 error = copyin(uap->timeout, &ts, sizeof(ts)); 319 if (error) 320 goto done; 321 uap->timeout = &ts; 322 } 323 324 kq = (struct kqueue *)fp->f_data; 325 nerrors = 0; 326 327 while (uap->nchanges > 0) { 328 n = uap->nchanges > KQ_NEVENTS ? KQ_NEVENTS : uap->nchanges; 329 error = copyin(uap->changelist, kq->kq_kev, 330 n * sizeof(struct kevent)); 331 if (error) 332 goto done; 333 for (i = 0; i < n; i++) { 334 kevp = &kq->kq_kev[i]; 335 kevp->flags &= ~EV_SYSFLAGS; 336 error = kqueue_register(kq, kevp, p); 337 if (error) { 338 if (uap->nevents != 0) { 339 kevp->flags = EV_ERROR; 340 kevp->data = error; 341 (void) copyout((caddr_t)kevp, 342 (caddr_t)uap->eventlist, 343 sizeof(*kevp)); 344 uap->eventlist++; 345 uap->nevents--; 346 nerrors++; 347 } else { 348 goto done; 349 } 350 } 351 } 352 uap->nchanges -= n; 353 uap->changelist += n; 354 } 355 if (nerrors) { 356 p->p_retval[0] = nerrors; 357 error = 0; 358 goto done; 359 } 360 361 error = kqueue_scan(fp, uap->nevents, uap->eventlist, uap->timeout, p); 362 done: 363 if (fp != NULL) 364 fdrop(fp, p); 365 return (error); 366 } 367 368 int 369 kqueue_register(struct kqueue *kq, struct kevent *kev, struct proc *p) 370 { 371 struct filedesc *fdp = kq->kq_fdp; 372 struct filterops *fops; 373 struct file *fp = NULL; 374 struct knote *kn = NULL; 375 int s, error = 0; 376 377 if (kev->filter < 0) { 378 if (kev->filter + EVFILT_SYSCOUNT < 0) 379 return (EINVAL); 380 fops = sysfilt_ops[~kev->filter]; /* to 0-base index */ 381 } else { 382 /* 383 * XXX 384 * filter attach routine is responsible for insuring that 385 * the identifier can be attached to it. 386 */ 387 printf("unknown filter: %d\n", kev->filter); 388 return (EINVAL); 389 } 390 391 if (fops->f_isfd) { 392 /* validate descriptor */ 393 if ((u_int)kev->ident >= fdp->fd_nfiles || 394 (fp = fdp->fd_ofiles[kev->ident]) == NULL) 395 return (EBADF); 396 fhold(fp); 397 398 if (kev->ident < fdp->fd_knlistsize) { 399 SLIST_FOREACH(kn, &fdp->fd_knlist[kev->ident], kn_link) 400 if (kq == kn->kn_kq && 401 kev->filter == kn->kn_filter) 402 break; 403 } 404 } else { 405 if (fdp->fd_knhashmask != 0) { 406 struct klist *list; 407 408 list = &fdp->fd_knhash[ 409 KN_HASH((u_long)kev->ident, fdp->fd_knhashmask)]; 410 SLIST_FOREACH(kn, list, kn_link) 411 if (kev->ident == kn->kn_id && 412 kq == kn->kn_kq && 413 kev->filter == kn->kn_filter) 414 break; 415 } 416 } 417 418 if (kn == NULL && ((kev->flags & EV_ADD) == 0)) { 419 error = ENOENT; 420 goto done; 421 } 422 423 /* 424 * kn now contains the matching knote, or NULL if no match 425 */ 426 if (kev->flags & EV_ADD) { 427 428 if (kn == NULL) { 429 kn = knote_alloc(); 430 if (kn == NULL) { 431 error = ENOMEM; 432 goto done; 433 } 434 kn->kn_fp = fp; 435 kn->kn_kq = kq; 436 kn->kn_fop = fops; 437 438 /* 439 * apply reference count to knode structure, so 440 * do not release it at the end of this routine. 441 */ 442 fp = NULL; 443 444 kn->kn_sfflags = kev->fflags; 445 kn->kn_sdata = kev->data; 446 kev->fflags = 0; 447 kev->data = 0; 448 kn->kn_kevent = *kev; 449 450 knote_attach(kn, fdp); 451 if ((error = fops->f_attach(kn)) != 0) { 452 knote_drop(kn, p); 453 goto done; 454 } 455 } else { 456 /* 457 * The user may change some filter values after the 458 * initial EV_ADD, but doing so will not reset any 459 * filter which have already been triggered. 460 */ 461 kn->kn_sfflags = kev->fflags; 462 kn->kn_sdata = kev->data; 463 kn->kn_kevent.udata = kev->udata; 464 } 465 466 s = splhigh(); 467 if (kn->kn_fop->f_event(kn, 0)) 468 KNOTE_ACTIVATE(kn); 469 splx(s); 470 471 } else if (kev->flags & EV_DELETE) { 472 kn->kn_fop->f_detach(kn); 473 knote_drop(kn, p); 474 goto done; 475 } 476 477 if ((kev->flags & EV_DISABLE) && 478 ((kn->kn_status & KN_DISABLED) == 0)) { 479 s = splhigh(); 480 kn->kn_status |= KN_DISABLED; 481 splx(s); 482 } 483 484 if ((kev->flags & EV_ENABLE) && (kn->kn_status & KN_DISABLED)) { 485 s = splhigh(); 486 kn->kn_status &= ~KN_DISABLED; 487 if ((kn->kn_status & KN_ACTIVE) && 488 ((kn->kn_status & KN_QUEUED) == 0)) 489 knote_enqueue(kn); 490 splx(s); 491 } 492 493 done: 494 if (fp != NULL) 495 fdrop(fp, p); 496 return (error); 497 } 498 499 static int 500 kqueue_scan(struct file *fp, int maxevents, struct kevent *ulistp, 501 const struct timespec *tsp, struct proc *p) 502 { 503 struct kqueue *kq = (struct kqueue *)fp->f_data; 504 struct kevent *kevp; 505 struct timeval atv, rtv, ttv; 506 struct knote *kn, marker; 507 int s, count, timeout, nkev = 0, error = 0; 508 509 count = maxevents; 510 if (count == 0) 511 goto done; 512 513 if (tsp != NULL) { 514 TIMESPEC_TO_TIMEVAL(&atv, tsp); 515 if (itimerfix(&atv)) { 516 error = EINVAL; 517 goto done; 518 } 519 if (tsp->tv_sec == 0 && tsp->tv_nsec == 0) 520 timeout = -1; 521 else 522 timeout = atv.tv_sec > 24 * 60 * 60 ? 523 24 * 60 * 60 * hz : tvtohz(&atv); 524 getmicrouptime(&rtv); 525 timevaladd(&atv, &rtv); 526 } else { 527 atv.tv_sec = 0; 528 atv.tv_usec = 0; 529 timeout = 0; 530 } 531 goto start; 532 533 retry: 534 if (atv.tv_sec || atv.tv_usec) { 535 getmicrouptime(&rtv); 536 if (timevalcmp(&rtv, &atv, >=)) 537 goto done; 538 ttv = atv; 539 timevalsub(&ttv, &rtv); 540 timeout = ttv.tv_sec > 24 * 60 * 60 ? 541 24 * 60 * 60 * hz : tvtohz(&ttv); 542 } 543 544 start: 545 kevp = kq->kq_kev; 546 s = splhigh(); 547 if (kq->kq_count == 0) { 548 if (timeout < 0) { 549 error = EWOULDBLOCK; 550 } else { 551 kq->kq_state |= KQ_SLEEP; 552 error = tsleep(kq, PSOCK | PCATCH, "kqread", timeout); 553 } 554 splx(s); 555 if (error == 0) 556 goto retry; 557 /* don't restart after signals... */ 558 if (error == ERESTART) 559 error = EINTR; 560 else if (error == EWOULDBLOCK) 561 error = 0; 562 goto done; 563 } 564 565 TAILQ_INSERT_TAIL(&kq->kq_head, &marker, kn_tqe); 566 while (count) { 567 kn = TAILQ_FIRST(&kq->kq_head); 568 TAILQ_REMOVE(&kq->kq_head, kn, kn_tqe); 569 if (kn == &marker) { 570 splx(s); 571 if (count == maxevents) 572 goto retry; 573 goto done; 574 } 575 if (kn->kn_status & KN_DISABLED) { 576 kn->kn_status &= ~KN_QUEUED; 577 kq->kq_count--; 578 continue; 579 } 580 if ((kn->kn_flags & EV_ONESHOT) == 0 && 581 kn->kn_fop->f_event(kn, 0) == 0) { 582 kn->kn_status &= ~(KN_QUEUED | KN_ACTIVE); 583 kq->kq_count--; 584 continue; 585 } 586 *kevp = kn->kn_kevent; 587 kevp++; 588 nkev++; 589 if (kn->kn_flags & EV_ONESHOT) { 590 kn->kn_status &= ~KN_QUEUED; 591 kq->kq_count--; 592 splx(s); 593 kn->kn_fop->f_detach(kn); 594 knote_drop(kn, p); 595 s = splhigh(); 596 } else if (kn->kn_flags & EV_CLEAR) { 597 kn->kn_data = 0; 598 kn->kn_fflags = 0; 599 kn->kn_status &= ~(KN_QUEUED | KN_ACTIVE); 600 kq->kq_count--; 601 } else { 602 TAILQ_INSERT_TAIL(&kq->kq_head, kn, kn_tqe); 603 } 604 count--; 605 if (nkev == KQ_NEVENTS) { 606 splx(s); 607 error = copyout((caddr_t)&kq->kq_kev, (caddr_t)ulistp, 608 sizeof(struct kevent) * nkev); 609 ulistp += nkev; 610 nkev = 0; 611 kevp = kq->kq_kev; 612 s = splhigh(); 613 if (error) 614 break; 615 } 616 } 617 TAILQ_REMOVE(&kq->kq_head, &marker, kn_tqe); 618 splx(s); 619 done: 620 if (nkev != 0) 621 error = copyout((caddr_t)&kq->kq_kev, (caddr_t)ulistp, 622 sizeof(struct kevent) * nkev); 623 p->p_retval[0] = maxevents - count; 624 return (error); 625 } 626 627 /* 628 * XXX 629 * This could be expanded to call kqueue_scan, if desired. 630 */ 631 /*ARGSUSED*/ 632 static int 633 kqueue_read(struct file *fp, struct uio *uio, struct ucred *cred, 634 int flags, struct proc *p) 635 { 636 return (ENXIO); 637 } 638 639 /*ARGSUSED*/ 640 static int 641 kqueue_write(struct file *fp, struct uio *uio, struct ucred *cred, 642 int flags, struct proc *p) 643 { 644 return (ENXIO); 645 } 646 647 /*ARGSUSED*/ 648 static int 649 kqueue_ioctl(struct file *fp, u_long com, caddr_t data, struct proc *p) 650 { 651 return (ENOTTY); 652 } 653 654 /*ARGSUSED*/ 655 static int 656 kqueue_poll(struct file *fp, int events, struct ucred *cred, struct proc *p) 657 { 658 struct kqueue *kq = (struct kqueue *)fp->f_data; 659 int revents = 0; 660 int s = splnet(); 661 662 if (events & (POLLIN | POLLRDNORM)) { 663 if (kq->kq_count) { 664 revents |= events & (POLLIN | POLLRDNORM); 665 } else { 666 selrecord(p, &kq->kq_sel); 667 kq->kq_state |= KQ_SEL; 668 } 669 } 670 splx(s); 671 return (revents); 672 } 673 674 /*ARGSUSED*/ 675 static int 676 kqueue_stat(struct file *fp, struct stat *st, struct proc *p) 677 { 678 struct kqueue *kq = (struct kqueue *)fp->f_data; 679 680 bzero((void *)st, sizeof(*st)); 681 st->st_size = kq->kq_count; 682 st->st_blksize = sizeof(struct kevent); 683 st->st_mode = S_IFIFO; 684 return (0); 685 } 686 687 /*ARGSUSED*/ 688 static int 689 kqueue_close(struct file *fp, struct proc *p) 690 { 691 struct kqueue *kq = (struct kqueue *)fp->f_data; 692 struct filedesc *fdp = p->p_fd; 693 struct knote **knp, *kn, *kn0; 694 int i; 695 696 for (i = 0; i < fdp->fd_knlistsize; i++) { 697 knp = &SLIST_FIRST(&fdp->fd_knlist[i]); 698 kn = *knp; 699 while (kn != NULL) { 700 kn0 = SLIST_NEXT(kn, kn_link); 701 if (kq == kn->kn_kq) { 702 kn->kn_fop->f_detach(kn); 703 fdrop(kn->kn_fp, p); 704 knote_free(kn); 705 *knp = kn0; 706 } else { 707 knp = &SLIST_NEXT(kn, kn_link); 708 } 709 kn = kn0; 710 } 711 } 712 if (fdp->fd_knhashmask != 0) { 713 for (i = 0; i < fdp->fd_knhashmask + 1; i++) { 714 knp = &SLIST_FIRST(&fdp->fd_knhash[i]); 715 kn = *knp; 716 while (kn != NULL) { 717 kn0 = SLIST_NEXT(kn, kn_link); 718 if (kq == kn->kn_kq) { 719 kn->kn_fop->f_detach(kn); 720 /* XXX non-fd release of kn->kn_ptr */ 721 knote_free(kn); 722 *knp = kn0; 723 } else { 724 knp = &SLIST_NEXT(kn, kn_link); 725 } 726 kn = kn0; 727 } 728 } 729 } 730 free(kq, M_TEMP); 731 fp->f_data = NULL; 732 733 return (0); 734 } 735 736 static void 737 kqueue_wakeup(struct kqueue *kq) 738 { 739 740 if (kq->kq_state & KQ_SLEEP) { 741 kq->kq_state &= ~KQ_SLEEP; 742 wakeup(kq); 743 } 744 if (kq->kq_state & KQ_SEL) { 745 kq->kq_state &= ~KQ_SEL; 746 selwakeup(&kq->kq_sel); 747 } 748 KNOTE(&kq->kq_sel.si_note, 0); 749 } 750 751 /* 752 * walk down a list of knotes, activating them if their event has triggered. 753 */ 754 void 755 knote(struct klist *list, long hint) 756 { 757 struct knote *kn; 758 759 SLIST_FOREACH(kn, list, kn_selnext) 760 if (kn->kn_fop->f_event(kn, hint)) 761 KNOTE_ACTIVATE(kn); 762 } 763 764 /* 765 * remove all knotes from a specified klist 766 */ 767 void 768 knote_remove(struct proc *p, struct klist *list) 769 { 770 struct knote *kn; 771 772 while ((kn = SLIST_FIRST(list)) != NULL) { 773 kn->kn_fop->f_detach(kn); 774 knote_drop(kn, p); 775 } 776 } 777 778 /* 779 * remove all knotes referencing a specified fd 780 */ 781 void 782 knote_fdclose(struct proc *p, int fd) 783 { 784 struct filedesc *fdp = p->p_fd; 785 struct klist *list = &fdp->fd_knlist[fd]; 786 787 knote_remove(p, list); 788 } 789 790 static void 791 knote_attach(struct knote *kn, struct filedesc *fdp) 792 { 793 struct klist *list; 794 int size; 795 796 if (! kn->kn_fop->f_isfd) { 797 if (fdp->fd_knhashmask == 0) 798 fdp->fd_knhash = hashinit(KN_HASHSIZE, M_TEMP, 799 &fdp->fd_knhashmask); 800 list = &fdp->fd_knhash[KN_HASH(kn->kn_id, fdp->fd_knhashmask)]; 801 goto done; 802 } 803 804 if (fdp->fd_knlistsize <= kn->kn_id) { 805 size = fdp->fd_knlistsize; 806 while (size <= kn->kn_id) 807 size += KQEXTENT; 808 MALLOC(list, struct klist *, 809 size * sizeof(struct klist *), M_TEMP, M_WAITOK); 810 bcopy((caddr_t)fdp->fd_knlist, (caddr_t)list, 811 fdp->fd_knlistsize * sizeof(struct klist *)); 812 bzero((caddr_t)list + 813 fdp->fd_knlistsize * sizeof(struct klist *), 814 (size - fdp->fd_knlistsize) * sizeof(struct klist *)); 815 if (fdp->fd_knlist != NULL) 816 FREE(fdp->fd_knlist, M_TEMP); 817 fdp->fd_knlistsize = size; 818 fdp->fd_knlist = list; 819 } 820 list = &fdp->fd_knlist[kn->kn_id]; 821 done: 822 SLIST_INSERT_HEAD(list, kn, kn_link); 823 kn->kn_status = 0; 824 } 825 826 /* 827 * should be called at spl == 0, since we don't want to hold spl 828 * while calling fdrop and free. 829 */ 830 static void 831 knote_drop(struct knote *kn, struct proc *p) 832 { 833 struct filedesc *fdp = p->p_fd; 834 struct klist *list; 835 836 if (kn->kn_fop->f_isfd) 837 list = &fdp->fd_knlist[kn->kn_id]; 838 else 839 list = &fdp->fd_knhash[KN_HASH(kn->kn_id, fdp->fd_knhashmask)]; 840 841 SLIST_REMOVE(list, kn, knote, kn_link); 842 if (kn->kn_status & KN_QUEUED) 843 knote_dequeue(kn); 844 if (kn->kn_fop->f_isfd) 845 fdrop(kn->kn_fp, p); 846 knote_free(kn); 847 } 848 849 850 static void 851 knote_enqueue(struct knote *kn) 852 { 853 struct kqueue *kq = kn->kn_kq; 854 int s = splhigh(); 855 856 KASSERT((kn->kn_status & KN_QUEUED) == 0, ("knote already queued")); 857 858 TAILQ_INSERT_TAIL(&kq->kq_head, kn, kn_tqe); 859 kn->kn_status |= KN_QUEUED; 860 kq->kq_count++; 861 splx(s); 862 kqueue_wakeup(kq); 863 } 864 865 static void 866 knote_dequeue(struct knote *kn) 867 { 868 struct kqueue *kq = kn->kn_kq; 869 int s = splhigh(); 870 871 KASSERT(kn->kn_status & KN_QUEUED, ("knote not queued")); 872 873 TAILQ_REMOVE(&kq->kq_head, kn, kn_tqe); 874 kn->kn_status &= ~KN_QUEUED; 875 kq->kq_count--; 876 splx(s); 877 } 878 879 static void 880 knote_init(void) 881 { 882 knote_zone = zinit("KNOTE", sizeof(struct knote), 0, 0, 1); 883 } 884 SYSINIT(knote, SI_SUB_PSEUDO, SI_ORDER_ANY, knote_init, NULL) 885 886 static struct knote * 887 knote_alloc(void) 888 { 889 return ((struct knote *)zalloc(knote_zone)); 890 } 891 892 static void 893 knote_free(struct knote *kn) 894 { 895 zfree(knote_zone, kn); 896 } 897