FreeBSD/sys/kern/kern_event.c
/*
 * Expand the kq to make sure we have storage for fops/ident pair.
 *
 * Return 0 on success (or no work necessary), return errno on failure.
 *
 * Not calling hashinit w/ waitok (proper malloc flag) should be safe.
 * If kqueue_register is called from a non-fd context, there usually/should
 * be no locks held.
 */
Expand the kq to make sure we have storage for fops/ident pair.
Return 0 on success (or no work necessary), return errno on failure.

Not calling hashinit w/ waitok (proper malloc flag) should be safe.
If kqueue_register is called from a non-fd context, there usually/should
be no locks held.
Expand the kq to make sure we have storage for fops / ident pair . Return 0 on success ( or no work necessary ) return errno on failure . Not calling hashinit w / waitok ( proper malloc flag ) should be safe . If kqueue_register is called from a non - fd context there usually / should be no locks held .
static int
kqueue_expand(struct kqueue *kq, struct filterops *fops, uintptr_t ident,
	int waitok)
{
	struct klist *list, *tmp_knhash, *to_free;
	u_long tmp_knhashmask;
	int size;
	int fd;
	int mflag = waitok ? M_WAITOK : M_NOWAIT;
	KQ_NOTOWNED(kq);
	to_free = NULL;
	if (fops->f_isfd) {
		fd = ident;
		if (kq->kq_knlistsize <= fd) {
			size = kq->kq_knlistsize;
			while (size <= fd)
				size += KQEXTENT;
			list = malloc(size * sizeof(*list), M_KQUEUE, mflag);
			if (list == NULL)
				return ENOMEM;
			KQ_LOCK(kq);
			if (kq->kq_knlistsize > fd) {
				to_free = list;
				list = NULL;
			} else {
				if (kq->kq_knlist != NULL) {
					bcopy(kq->kq_knlist, list,
					    kq->kq_knlistsize * sizeof(*list));
					to_free = kq->kq_knlist;
					kq->kq_knlist = NULL;
				}
				bzero((caddr_t)list +
				    kq->kq_knlistsize * sizeof(*list),
				    (size - kq->kq_knlistsize) * sizeof(*list));
				kq->kq_knlistsize = size;
				kq->kq_knlist = list;
			}
			KQ_UNLOCK(kq);
		}
	} else {
		if (kq->kq_knhashmask == 0) {
			tmp_knhash = hashinit(KN_HASHSIZE, M_KQUEUE,
			    &tmp_knhashmask);
			if (tmp_knhash == NULL)
				return ENOMEM;
			KQ_LOCK(kq);
			if (kq->kq_knhashmask == 0) {
				kq->kq_knhash = tmp_knhash;
				kq->kq_knhashmask = tmp_knhashmask;
			} else {
				to_free = tmp_knhash;
			}
			KQ_UNLOCK(kq);
		}
	}
	free(to_free, M_KQUEUE);
	KQ_NOTOWNED(kq);
	return 0;
}
static int kqueue_expand ( struct kqueue * kq , struct filterops * fops , uintptr_t ident , int waitok ) { struct klist * list , * tmp_knhash , * to_free ; u_long tmp_knhashmask ; int size ; int fd ; int mflag = waitok ? M_WAITOK : M_NOWAIT ; KQ_NOTOWNED ( kq ) ; to_free = NULL ; if ( fops -> f_isfd ) { fd = ident ; if ( kq -> kq_knlistsize <= fd ) { size = kq -> kq_knlistsize ; while ( size <= fd ) size += KQEXTENT ; list = malloc ( size * sizeof ( * list ) , M_KQUEUE , mflag ) ; if ( list == NULL ) return ENOMEM ; KQ_LOCK ( kq ) ; if ( kq -> kq_knlistsize > fd ) { to_free = list ; list = NULL ; } else { if ( kq -> kq_knlist != NULL ) { bcopy ( kq -> kq_knlist , list , kq -> kq_knlistsize * sizeof ( * list ) ) ; to_free = kq -> kq_knlist ; kq -> kq_knlist = NULL ; } bzero ( ( caddr_t ) list + kq -> kq_knlistsize * sizeof ( * list ) , ( size - kq -> kq_knlistsize ) * sizeof ( * list ) ) ; kq -> kq_knlistsize = size ; kq -> kq_knlist = list ; } KQ_UNLOCK ( kq ) ; } } else { if ( kq -> kq_knhashmask == 0 ) { tmp_knhash = hashinit ( KN_HASHSIZE , M_KQUEUE , & tmp_knhashmask ) ; if ( tmp_knhash == NULL ) return ENOMEM ; KQ_LOCK ( kq ) ; if ( kq -> kq_knhashmask == 0 ) { kq -> kq_knhash = tmp_knhash ; kq -> kq_knhashmask = tmp_knhashmask ; } else { to_free = tmp_knhash ; } KQ_UNLOCK ( kq ) ; } } free ( to_free , M_KQUEUE ) ; KQ_NOTOWNED ( kq ) ; return 0 ; }
Expand the kq to make sure we have storage for fops/ident pair.
Expand the kq to make sure we have storage for fops / ident pair .