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