kern_event.c (1c0336c1c15b6db161745ec494aba4d69e865d78) | kern_event.c (95c05062ec15cf323488d4c5e1986f5866bf7464) |
---|---|
1/*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 1999,2000,2001 Jonathan Lemon <jlemon@FreeBSD.org> 5 * Copyright 2004 John-Mark Gurney <jmg@FreeBSD.org> 6 * Copyright (c) 2009 Apple, Inc. 7 * All rights reserved. 8 * --- 148 unchanged lines hidden (view full) --- 157static int filt_kqueue(struct knote *kn, long hint); 158static int filt_procattach(struct knote *kn); 159static void filt_procdetach(struct knote *kn); 160static int filt_proc(struct knote *kn, long hint); 161static int filt_fileattach(struct knote *kn); 162static void filt_timerexpire(void *knx); 163static int filt_timerattach(struct knote *kn); 164static void filt_timerdetach(struct knote *kn); | 1/*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 1999,2000,2001 Jonathan Lemon <jlemon@FreeBSD.org> 5 * Copyright 2004 John-Mark Gurney <jmg@FreeBSD.org> 6 * Copyright (c) 2009 Apple, Inc. 7 * All rights reserved. 8 * --- 148 unchanged lines hidden (view full) --- 157static int filt_kqueue(struct knote *kn, long hint); 158static int filt_procattach(struct knote *kn); 159static void filt_procdetach(struct knote *kn); 160static int filt_proc(struct knote *kn, long hint); 161static int filt_fileattach(struct knote *kn); 162static void filt_timerexpire(void *knx); 163static int filt_timerattach(struct knote *kn); 164static void filt_timerdetach(struct knote *kn); |
165static void filt_timerstart(struct knote *kn, sbintime_t to); 166static void filt_timertouch(struct knote *kn, struct kevent *kev, 167 u_long type); 168static int filt_timervalidate(struct knote *kn, sbintime_t *to); |
|
165static int filt_timer(struct knote *kn, long hint); 166static int filt_userattach(struct knote *kn); 167static void filt_userdetach(struct knote *kn); 168static int filt_user(struct knote *kn, long hint); 169static void filt_usertouch(struct knote *kn, struct kevent *kev, 170 u_long type); 171 172static struct filterops file_filtops = { --- 12 unchanged lines hidden (view full) --- 185 .f_detach = filt_procdetach, 186 .f_event = filt_proc, 187}; 188static struct filterops timer_filtops = { 189 .f_isfd = 0, 190 .f_attach = filt_timerattach, 191 .f_detach = filt_timerdetach, 192 .f_event = filt_timer, | 169static int filt_timer(struct knote *kn, long hint); 170static int filt_userattach(struct knote *kn); 171static void filt_userdetach(struct knote *kn); 172static int filt_user(struct knote *kn, long hint); 173static void filt_usertouch(struct knote *kn, struct kevent *kev, 174 u_long type); 175 176static struct filterops file_filtops = { --- 12 unchanged lines hidden (view full) --- 189 .f_detach = filt_procdetach, 190 .f_event = filt_proc, 191}; 192static struct filterops timer_filtops = { 193 .f_isfd = 0, 194 .f_attach = filt_timerattach, 195 .f_detach = filt_timerdetach, 196 .f_event = filt_timer, |
197 .f_touch = filt_timertouch, |
|
193}; 194static struct filterops user_filtops = { 195 .f_attach = filt_userattach, 196 .f_detach = filt_userdetach, 197 .f_event = filt_user, 198 .f_touch = filt_usertouch, 199}; 200 --- 493 unchanged lines hidden (view full) --- 694 callout_reset_sbt_on(&kc->c, kc->next, 0, filt_timerexpire, kn, 695 PCPU_GET(cpuid), C_ABSOLUTE); 696} 697 698/* 699 * data contains amount of time to sleep 700 */ 701static int | 198}; 199static struct filterops user_filtops = { 200 .f_attach = filt_userattach, 201 .f_detach = filt_userdetach, 202 .f_event = filt_user, 203 .f_touch = filt_usertouch, 204}; 205 --- 493 unchanged lines hidden (view full) --- 699 callout_reset_sbt_on(&kc->c, kc->next, 0, filt_timerexpire, kn, 700 PCPU_GET(cpuid), C_ABSOLUTE); 701} 702 703/* 704 * data contains amount of time to sleep 705 */ 706static int |
702filt_timerattach(struct knote *kn) | 707filt_timervalidate(struct knote *kn, sbintime_t *to) |
703{ | 708{ |
704 struct kq_timer_cb_data *kc; | |
705 struct bintime bt; | 709 struct bintime bt; |
706 sbintime_t to, sbt; 707 unsigned int ncallouts; | 710 sbintime_t sbt; |
708 709 if (kn->kn_sdata < 0) 710 return (EINVAL); 711 if (kn->kn_sdata == 0 && (kn->kn_flags & EV_ONESHOT) == 0) 712 kn->kn_sdata = 1; | 711 712 if (kn->kn_sdata < 0) 713 return (EINVAL); 714 if (kn->kn_sdata == 0 && (kn->kn_flags & EV_ONESHOT) == 0) 715 kn->kn_sdata = 1; |
713 /* Only precision unit are supported in flags so far */ | 716 /* 717 * The only fflags values supported are the timer unit 718 * (precision) and the absolute time indicator. 719 */ |
714 if ((kn->kn_sfflags & ~(NOTE_TIMER_PRECMASK | NOTE_ABSTIME)) != 0) 715 return (EINVAL); 716 | 720 if ((kn->kn_sfflags & ~(NOTE_TIMER_PRECMASK | NOTE_ABSTIME)) != 0) 721 return (EINVAL); 722 |
717 to = timer2sbintime(kn->kn_sdata, kn->kn_sfflags); | 723 *to = timer2sbintime(kn->kn_sdata, kn->kn_sfflags); |
718 if ((kn->kn_sfflags & NOTE_ABSTIME) != 0) { 719 getboottimebin(&bt); 720 sbt = bttosbt(bt); | 724 if ((kn->kn_sfflags & NOTE_ABSTIME) != 0) { 725 getboottimebin(&bt); 726 sbt = bttosbt(bt); |
721 to -= sbt; | 727 *to -= sbt; |
722 } | 728 } |
723 if (to < 0) | 729 if (*to < 0) |
724 return (EINVAL); | 730 return (EINVAL); |
731 return (0); 732} |
|
725 | 733 |
734static int 735filt_timerattach(struct knote *kn) 736{ 737 struct kq_timer_cb_data *kc; 738 sbintime_t to; 739 unsigned int ncallouts; 740 int error; 741 742 error = filt_timervalidate(kn, &to); 743 if (error != 0) 744 return (error); 745 |
|
726 do { 727 ncallouts = kq_ncallouts; 728 if (ncallouts >= kq_calloutmax) 729 return (ENOMEM); 730 } while (!atomic_cmpset_int(&kq_ncallouts, ncallouts, ncallouts + 1)); 731 732 if ((kn->kn_sfflags & NOTE_ABSTIME) == 0) 733 kn->kn_flags |= EV_CLEAR; /* automatically set */ 734 kn->kn_status &= ~KN_DETACHED; /* knlist_add clears it */ 735 kn->kn_ptr.p_v = kc = malloc(sizeof(*kc), M_KQUEUE, M_WAITOK); 736 callout_init(&kc->c, 1); | 746 do { 747 ncallouts = kq_ncallouts; 748 if (ncallouts >= kq_calloutmax) 749 return (ENOMEM); 750 } while (!atomic_cmpset_int(&kq_ncallouts, ncallouts, ncallouts + 1)); 751 752 if ((kn->kn_sfflags & NOTE_ABSTIME) == 0) 753 kn->kn_flags |= EV_CLEAR; /* automatically set */ 754 kn->kn_status &= ~KN_DETACHED; /* knlist_add clears it */ 755 kn->kn_ptr.p_v = kc = malloc(sizeof(*kc), M_KQUEUE, M_WAITOK); 756 callout_init(&kc->c, 1); |
757 filt_timerstart(kn, to); 758 759 return (0); 760} 761 762static void 763filt_timerstart(struct knote *kn, sbintime_t to) 764{ 765 struct kq_timer_cb_data *kc; 766 767 kc = kn->kn_ptr.p_v; |
|
737 if ((kn->kn_sfflags & NOTE_ABSTIME) != 0) { 738 kc->next = to; 739 kc->to = 0; 740 } else { 741 kc->next = to + sbinuptime(); 742 kc->to = to; 743 } 744 callout_reset_sbt_on(&kc->c, kc->next, 0, filt_timerexpire, kn, 745 PCPU_GET(cpuid), C_ABSOLUTE); | 768 if ((kn->kn_sfflags & NOTE_ABSTIME) != 0) { 769 kc->next = to; 770 kc->to = 0; 771 } else { 772 kc->next = to + sbinuptime(); 773 kc->to = to; 774 } 775 callout_reset_sbt_on(&kc->c, kc->next, 0, filt_timerexpire, kn, 776 PCPU_GET(cpuid), C_ABSOLUTE); |
746 747 return (0); | |
748} 749 750static void 751filt_timerdetach(struct knote *kn) 752{ 753 struct kq_timer_cb_data *kc; 754 unsigned int old __unused; 755 756 kc = kn->kn_ptr.p_v; 757 callout_drain(&kc->c); 758 free(kc, M_KQUEUE); 759 old = atomic_fetchadd_int(&kq_ncallouts, -1); 760 KASSERT(old > 0, ("Number of callouts cannot become negative")); 761 kn->kn_status |= KN_DETACHED; /* knlist_remove sets it */ 762} 763 | 777} 778 779static void 780filt_timerdetach(struct knote *kn) 781{ 782 struct kq_timer_cb_data *kc; 783 unsigned int old __unused; 784 785 kc = kn->kn_ptr.p_v; 786 callout_drain(&kc->c); 787 free(kc, M_KQUEUE); 788 old = atomic_fetchadd_int(&kq_ncallouts, -1); 789 KASSERT(old > 0, ("Number of callouts cannot become negative")); 790 kn->kn_status |= KN_DETACHED; /* knlist_remove sets it */ 791} 792 |
793static void 794filt_timertouch(struct knote *kn, struct kevent *kev, u_long type) 795{ 796 struct kq_timer_cb_data *kc; 797 struct kqueue *kq; 798 sbintime_t to; 799 int error; 800 801 switch (type) { 802 case EVENT_REGISTER: 803 /* Handle re-added timers that update data/fflags */ 804 if (kev->flags & EV_ADD) { 805 kc = kn->kn_ptr.p_v; 806 807 /* Drain any existing callout. */ 808 callout_drain(&kc->c); 809 810 /* Throw away any existing undelivered record 811 * of the timer expiration. This is done under 812 * the presumption that if a process is 813 * re-adding this timer with new parameters, 814 * it is no longer interested in what may have 815 * happened under the old parameters. If it is 816 * interested, it can wait for the expiration, 817 * delete the old timer definition, and then 818 * add the new one. 819 * 820 * This has to be done while the kq is locked: 821 * - if enqueued, dequeue 822 * - make it no longer active 823 * - clear the count of expiration events 824 */ 825 kq = kn->kn_kq; 826 KQ_LOCK(kq); 827 if (kn->kn_status & KN_QUEUED) 828 knote_dequeue(kn); 829 830 kn->kn_status &= ~KN_ACTIVE; 831 kn->kn_data = 0; 832 KQ_UNLOCK(kq); 833 834 /* Reschedule timer based on new data/fflags */ 835 kn->kn_sfflags = kev->fflags; 836 kn->kn_sdata = kev->data; 837 error = filt_timervalidate(kn, &to); 838 if (error != 0) { 839 kn->kn_flags |= EV_ERROR; 840 kn->kn_data = error; 841 } else 842 filt_timerstart(kn, to); 843 } 844 break; 845 846 case EVENT_PROCESS: 847 *kev = kn->kn_kevent; 848 if (kn->kn_flags & EV_CLEAR) { 849 kn->kn_data = 0; 850 kn->kn_fflags = 0; 851 } 852 break; 853 854 default: 855 panic("filt_timertouch() - invalid type (%ld)", type); 856 break; 857 } 858} 859 |
|
764static int 765filt_timer(struct knote *kn, long hint) 766{ 767 768 return (kn->kn_data != 0); 769} 770 771static int --- 1867 unchanged lines hidden --- | 860static int 861filt_timer(struct knote *kn, long hint) 862{ 863 864 return (kn->kn_data != 0); 865} 866 867static int --- 1867 unchanged lines hidden --- |