FreeBSD/sys/kern/kern_event.c
/*
 * Walk down a list of knotes, activating them if their event has triggered.
 *
 * There is a possibility to optimize in the case of one kq watching another.
 * Instead of scheduling a task to wake it up, you could pass enough state
 * down the chain to make up the parent kqueue.  Make this code functional
 * first.
 */
Walk down a list of knotes, activating them if their event has triggered.
There is a possibility to optimize in the case of one kq watching another.
Instead of scheduling a task to wake it up, you could pass enough state
down the chain to make up the parent kqueue.  Make this code functional
first.
Walk down a list of knotes activating them if their event has triggered . There is a possibility to optimize in the case of one kq watching another . Instead of scheduling a task to wake it up you could pass enough state down the chain to make up the parent kqueue . Make this code functional first .
void
knote(struct knlist *list, long hint, int lockflags)
{
	struct kqueue *kq;
	struct knote *kn, *tkn;
	int error;
	if (list == NULL)
		return;
	KNL_ASSERT_LOCK(list, lockflags & KNF_LISTLOCKED);
	if ((lockflags & KNF_LISTLOCKED) == 0)
		list->kl_lock(list->kl_lockarg); 
	SLIST_FOREACH_SAFE(kn, &list->kl_list, kn_selnext, tkn) {
		kq = kn->kn_kq;
		KQ_LOCK(kq);
		if ((kn->kn_status & (KN_INFLUX | KN_SCAN)) == KN_INFLUX) {
			KQ_UNLOCK(kq);
		} else if ((lockflags & KNF_NOKQLOCK) != 0) {
			kn->kn_status |= KN_INFLUX;
			KQ_UNLOCK(kq);
			error = kn->kn_fop->f_event(kn, hint);
			KQ_LOCK(kq);
			kn->kn_status &= ~KN_INFLUX;
			if (error)
				KNOTE_ACTIVATE(kn, 1);
			KQ_UNLOCK_FLUX(kq);
		} else {
			kn->kn_status |= KN_HASKQLOCK;
			if (kn->kn_fop->f_event(kn, hint))
				KNOTE_ACTIVATE(kn, 1);
			kn->kn_status &= ~KN_HASKQLOCK;
			KQ_UNLOCK(kq);
		}
	}
	if ((lockflags & KNF_LISTLOCKED) == 0)
		list->kl_unlock(list->kl_lockarg); 
}
void knote ( struct knlist * list , long hint , int lockflags ) { struct kqueue * kq ; struct knote * kn , * tkn ; int error ; if ( list == NULL ) return ; KNL_ASSERT_LOCK ( list , lockflags & KNF_LISTLOCKED ) ; if ( ( lockflags & KNF_LISTLOCKED ) == 0 ) list -> kl_lock ( list -> kl_lockarg ) ; SLIST_FOREACH_SAFE ( kn , & list -> kl_list , kn_selnext , tkn ) { kq = kn -> kn_kq ; KQ_LOCK ( kq ) ; if ( ( kn -> kn_status & ( KN_INFLUX | KN_SCAN ) ) == KN_INFLUX ) { KQ_UNLOCK ( kq ) ; } else if ( ( lockflags & KNF_NOKQLOCK ) != 0 ) { kn -> kn_status |= KN_INFLUX ; KQ_UNLOCK ( kq ) ; error = kn -> kn_fop -> f_event ( kn , hint ) ; KQ_LOCK ( kq ) ; kn -> kn_status &= ~ KN_INFLUX ; if ( error ) KNOTE_ACTIVATE ( kn , 1 ) ; KQ_UNLOCK_FLUX ( kq ) ; } else { kn -> kn_status |= KN_HASKQLOCK ; if ( kn -> kn_fop -> f_event ( kn , hint ) ) KNOTE_ACTIVATE ( kn , 1 ) ; kn -> kn_status &= ~ KN_HASKQLOCK ; KQ_UNLOCK ( kq ) ; } } if ( ( lockflags & KNF_LISTLOCKED ) == 0 ) list -> kl_unlock ( list -> kl_lockarg ) ; }
Walk down a list of knotes, activating them if their event has triggered.
Walk down a list of knotes activating them if their event has triggered .
/*
	 * If we unlock the list lock (and set KN_INFLUX), we can
	 * eliminate the kqueue scheduling, but this will introduce
	 * four lock/unlock's for each knote to test.  Also, marker
	 * would be needed to keep iteration position, since filters
	 * or other threads could remove events.
	 */ /*
			 * Do not process the influx notes, except for
			 * the influx coming from the kq unlock in the
			 * kqueue_scan().  In the later case, we do
			 * not interfere with the scan, since the code
			 * fragment in kqueue_scan() locks the knlist,
			 * and cannot proceed until we finished.
			 */