Changeset View
Changeset View
Standalone View
Standalone View
head/sys/kern/kern_event.c
Show First 20 Lines • Show All 731 Lines • ▼ Show 20 Lines | default: | ||||
panic("filt_usertouch() - invalid type (%ld)", type); | panic("filt_usertouch() - invalid type (%ld)", type); | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
int | int | ||||
sys_kqueue(struct thread *td, struct kqueue_args *uap) | sys_kqueue(struct thread *td, struct kqueue_args *uap) | ||||
{ | { | ||||
return (kern_kqueue(td, 0)); | |||||
} | |||||
int | |||||
kern_kqueue(struct thread *td, int flags) | |||||
{ | |||||
struct filedesc *fdp; | struct filedesc *fdp; | ||||
struct kqueue *kq; | struct kqueue *kq; | ||||
struct file *fp; | struct file *fp; | ||||
struct proc *p; | struct proc *p; | ||||
struct ucred *cred; | struct ucred *cred; | ||||
int fd, error; | int fd, error; | ||||
p = td->td_proc; | p = td->td_proc; | ||||
cred = td->td_ucred; | cred = td->td_ucred; | ||||
crhold(cred); | crhold(cred); | ||||
PROC_LOCK(p); | PROC_LOCK(p); | ||||
if (!chgkqcnt(cred->cr_ruidinfo, 1, lim_cur(td->td_proc, | if (!chgkqcnt(cred->cr_ruidinfo, 1, lim_cur(td->td_proc, | ||||
RLIMIT_KQUEUES))) { | RLIMIT_KQUEUES))) { | ||||
PROC_UNLOCK(p); | PROC_UNLOCK(p); | ||||
crfree(cred); | crfree(cred); | ||||
return (ENOMEM); | return (ENOMEM); | ||||
} | } | ||||
PROC_UNLOCK(p); | PROC_UNLOCK(p); | ||||
fdp = p->p_fd; | fdp = p->p_fd; | ||||
error = falloc(td, &fp, &fd, 0); | error = falloc(td, &fp, &fd, flags); | ||||
if (error) | if (error) | ||||
goto done2; | goto done2; | ||||
/* An extra reference on `fp' has been held for us by falloc(). */ | /* An extra reference on `fp' has been held for us by falloc(). */ | ||||
kq = malloc(sizeof *kq, M_KQUEUE, M_WAITOK | M_ZERO); | kq = malloc(sizeof *kq, M_KQUEUE, M_WAITOK | M_ZERO); | ||||
mtx_init(&kq->kq_lock, "kqueue", NULL, MTX_DEF|MTX_DUPOK); | mtx_init(&kq->kq_lock, "kqueue", NULL, MTX_DEF|MTX_DUPOK); | ||||
TAILQ_INIT(&kq->kq_head); | TAILQ_INIT(&kq->kq_head); | ||||
kq->kq_fdp = fdp; | kq->kq_fdp = fdp; | ||||
▲ Show 20 Lines • Show All 114 Lines • ▼ Show 20 Lines | if (error == 0) | ||||
uap->changelist += count; | uap->changelist += count; | ||||
return (error); | return (error); | ||||
} | } | ||||
int | int | ||||
kern_kevent(struct thread *td, int fd, int nchanges, int nevents, | kern_kevent(struct thread *td, int fd, int nchanges, int nevents, | ||||
struct kevent_copyops *k_ops, const struct timespec *timeout) | struct kevent_copyops *k_ops, const struct timespec *timeout) | ||||
{ | { | ||||
struct kevent keva[KQ_NEVENTS]; | |||||
struct kevent *kevp, *changes; | |||||
struct kqueue *kq; | |||||
struct file *fp; | |||||
cap_rights_t rights; | cap_rights_t rights; | ||||
int i, n, nerrors, error; | struct file *fp; | ||||
int error; | |||||
cap_rights_init(&rights); | cap_rights_init(&rights); | ||||
if (nchanges > 0) | if (nchanges > 0) | ||||
cap_rights_set(&rights, CAP_KQUEUE_CHANGE); | cap_rights_set(&rights, CAP_KQUEUE_CHANGE); | ||||
if (nevents > 0) | if (nevents > 0) | ||||
cap_rights_set(&rights, CAP_KQUEUE_EVENT); | cap_rights_set(&rights, CAP_KQUEUE_EVENT); | ||||
error = fget(td, fd, &rights, &fp); | error = fget(td, fd, &rights, &fp); | ||||
if (error != 0) | if (error != 0) | ||||
return (error); | return (error); | ||||
error = kern_kevent_fp(td, fp, nchanges, nevents, k_ops, timeout); | |||||
fdrop(fp, td); | |||||
return (error); | |||||
} | |||||
int | |||||
kern_kevent_fp(struct thread *td, struct file *fp, int nchanges, int nevents, | |||||
struct kevent_copyops *k_ops, const struct timespec *timeout) | |||||
{ | |||||
struct kevent keva[KQ_NEVENTS]; | |||||
struct kevent *kevp, *changes; | |||||
struct kqueue *kq; | |||||
int i, n, nerrors, error; | |||||
error = kqueue_acquire(fp, &kq); | error = kqueue_acquire(fp, &kq); | ||||
if (error != 0) | if (error != 0) | ||||
goto done_norel; | return (error); | ||||
nerrors = 0; | nerrors = 0; | ||||
while (nchanges > 0) { | while (nchanges > 0) { | ||||
n = nchanges > KQ_NEVENTS ? KQ_NEVENTS : nchanges; | n = nchanges > KQ_NEVENTS ? KQ_NEVENTS : nchanges; | ||||
error = k_ops->k_copyin(k_ops->arg, keva, n); | error = k_ops->k_copyin(k_ops->arg, keva, n); | ||||
if (error) | if (error) | ||||
goto done; | goto done; | ||||
Show All 23 Lines | if (nerrors) { | ||||
td->td_retval[0] = nerrors; | td->td_retval[0] = nerrors; | ||||
error = 0; | error = 0; | ||||
goto done; | goto done; | ||||
} | } | ||||
error = kqueue_scan(kq, nevents, k_ops, timeout, keva, td); | error = kqueue_scan(kq, nevents, k_ops, timeout, keva, td); | ||||
done: | done: | ||||
kqueue_release(kq, 0); | kqueue_release(kq, 0); | ||||
done_norel: | |||||
fdrop(fp, td); | |||||
return (error); | return (error); | ||||
} | } | ||||
int | int | ||||
kqueue_add_filteropts(int filt, struct filterops *filtops) | kqueue_add_filteropts(int filt, struct filterops *filtops) | ||||
{ | { | ||||
int error; | int error; | ||||
▲ Show 20 Lines • Show All 1,409 Lines • Show Last 20 Lines |