/* * User-level interface: read, poll. * (User cannot write an event queue.) */ int wsevent_read(struct wseventvar *ev, struct uio *uio, int flags) { int s, error; u_int cnt; size_t n; /* * Make sure we can return at least 1. */ if (uio->uio_resid < sizeof(struct wscons_event)) return (EMSGSIZE); /* ??? */ s = splwsevent(); while (ev->get == ev->put) { if (flags & IO_NDELAY) { splx(s); return (EWOULDBLOCK); } ev->wanted = 1; error = tsleep(ev, PWSEVENT | PCATCH, "wsevent_read", 0); if (error) { splx(s); return (error); } } /* * Move wscons_event from tail end of queue (there is at least one * there). */ if (ev->put < ev->get) cnt = WSEVENT_QSIZE - ev->get; /* events in [get..QSIZE) */ else cnt = ev->put - ev->get; /* events in [get..put) */ splx(s); n = howmany(uio->uio_resid, sizeof(struct wscons_event)); if (cnt > n) cnt = n; error = uiomove((caddr_t)&ev->q[ev->get], cnt * sizeof(struct wscons_event), uio); n -= cnt; /* * If we do not wrap to 0, used up all our space, or had an error, * stop. Otherwise move from front of queue to put index, if there * is anything there to move. */ if ((ev->get = (ev->get + cnt) % WSEVENT_QSIZE) != 0 || n == 0 || error || (cnt = ev->put) == 0) return (error); if (cnt > n) cnt = n; error = uiomove((caddr_t)&ev->q[0], cnt * sizeof(struct wscons_event), uio); ev->get = cnt; return (error); }
void filt_wseventdetach(struct knote *kn) { struct wseventvar *ev = kn->kn_hook; struct klist *klist = &ev->sel.si_note; int s; s = splwsevent(); SLIST_REMOVE(klist, kn, knote, kn_selnext); splx(s); }
int wsevent_poll(struct wseventvar *ev, int events, struct proc *p) { int revents = 0; int s = splwsevent(); if (events & (POLLIN | POLLRDNORM)) { if (ev->get != ev->put) revents |= events & (POLLIN | POLLRDNORM); else selrecord(p, &ev->sel); } splx(s); return (revents); }
int wsevent_kqfilter(struct wseventvar *ev, struct knote *kn) { struct klist *klist; int s; klist = &ev->sel.si_note; switch (kn->kn_filter) { case EVFILT_READ: kn->kn_fop = &wsevent_filtops; break; default: return (EINVAL); } kn->kn_hook = ev; s = splwsevent(); SLIST_INSERT_HEAD(klist, kn, kn_selnext); splx(s); return (0); }