From: Vitaliy Makkoveev Subject: wsmouse(4) and wstpad: mp-safe filterops To: Alexander Bluhm , "Kirill A. Korinsky" , tech@openbsd.org Date: Thu, 23 Jan 2025 13:14:31 +0300 The last one. As in wskbd(4), we don't share `sc_refcnt' with interrupts, so we don't need to protect it. May be `sc_refcnt' should be replaced with refcnt structure, may be completely removed - it's not yet clean to me. Please note, filt_wseventread() is the only thread that runs simultaneously with the rest of the wscons(4). This thread only compare `ws_get' with `ws_put'. wscons(4) drivers only increment `ws_put' index so at driver side we only need to protect this increment to ensure `ws_put' is consistent with WSEVENT_QSIZE. I wrapped `ws_put' and `ws_get' access with `ws_mtx' mutex(9) but this is not required. Index: sys/dev/wscons/wsmouse.c =================================================================== RCS file: /cvs/src/sys/dev/wscons/wsmouse.c,v diff -u -p -r1.74 wsmouse.c --- sys/dev/wscons/wsmouse.c 30 Dec 2024 02:46:00 -0000 1.74 +++ sys/dev/wscons/wsmouse.c 23 Jan 2025 09:43:25 -0000 @@ -249,7 +249,6 @@ wsmouse_detach(struct device *self, int struct wsmouse_softc *sc = (struct wsmouse_softc *)self; struct wseventvar *evar; int maj, mn; - int s; #if NWSMUX > 0 /* Tell parent mux we're leaving. */ @@ -262,18 +261,18 @@ wsmouse_detach(struct device *self, int /* If we're open ... */ evar = sc->sc_base.me_evp; if (evar != NULL) { - s = spltty(); if (--sc->sc_refcnt >= 0) { + mtx_enter(&evar->ws_mtx); /* Wake everyone by generating a dummy event. */ if (++evar->ws_put >= WSEVENT_QSIZE) evar->ws_put = 0; - WSEVENT_WAKEUP(evar); + mtx_leave(&evar->ws_mtx); + wsevent_wakeup(evar); /* Wait for processes to go away. */ if (tsleep_nsec(sc, PZERO, "wsmdet", SEC_TO_NSEC(60))) printf("wsmouse_detach: %s didn't detach\n", sc->sc_base.me_dv.dv_xname); } - splx(s); } /* locate the major number */ @@ -326,7 +325,7 @@ wsmouseopen(dev_t dev, int flags, int mo return (EBUSY); evar = &sc->sc_base.me_evar; - if (wsevent_init(evar)) + if (wsevent_init_flags(evar, WSEVENT_MPSAFE)) return (EBUSY); error = wsmousedoopen(sc, evar); @@ -495,7 +494,9 @@ wsmouse_do_ioctl(struct wsmouse_softc *s case FIOASYNC: if (sc->sc_base.me_evp == NULL) return (EINVAL); + mtx_enter(&sc->sc_base.me_evp->ws_mtx); sc->sc_base.me_evp->ws_async = *(int *)data != 0; + mtx_leave(&sc->sc_base.me_evp->ws_mtx); return (0); case FIOGETOWN: @@ -955,7 +956,10 @@ wsmouse_evq_put(struct evq_access *evq, struct wscons_event *ev; int space; + mtx_enter(&evq->evar->ws_mtx); space = evq->evar->ws_get - evq->put; + mtx_leave(&evq->evar->ws_mtx); + if (space != 1 && space != 1 - WSEVENT_QSIZE) { ev = &evq->evar->ws_q[evq->put++]; evq->put %= WSEVENT_QSIZE; @@ -1099,7 +1103,11 @@ void wsmouse_log_events(struct wsmouseinput *input, struct evq_access *evq) { struct wscons_event *ev; - int n = evq->evar->ws_put; + int n; + + mtx_enter(&evq->evar->ws_mtx); + n = evq->evar->ws_put; + mtx_leave(&evq->evar->ws_mtx); if (n != evq->put) { printf("[%s-ev][%04d]", DEVNAME(input), LOGTIME(&evq->ts)); @@ -1138,7 +1146,9 @@ wsmouse_input_sync(struct device *sc) evq.evar = *input->evar; if (evq.evar == NULL) return; + mtx_enter(&evq.evar->ws_mtx); evq.put = evq.evar->ws_put; + mtx_leave(&evq.evar->ws_mtx); evq.result = EVQ_RESULT_NONE; getnanotime(&evq.ts); @@ -1181,8 +1191,10 @@ wsmouse_input_sync(struct device *sc) if (input->flags & LOG_EVENTS) { wsmouse_log_events(input, &evq); } + mtx_enter(&evq.evar->ws_mtx); evq.evar->ws_put = evq.put; - WSEVENT_WAKEUP(evq.evar); + mtx_leave(&evq.evar->ws_mtx); + wsevent_wakeup(evq.evar); } } Index: sys/dev/wscons/wstpad.c =================================================================== RCS file: /cvs/src/sys/dev/wscons/wstpad.c,v diff -u -p -r1.34 wstpad.c --- sys/dev/wscons/wstpad.c 25 Mar 2024 13:01:49 -0000 1.34 +++ sys/dev/wscons/wstpad.c 23 Jan 2025 09:43:25 -0000 @@ -931,7 +931,9 @@ wstpad_tap_timeout(void *p) tp->tap.state = TAP_DETECT; } if (ev) { + mtx_enter(&evq.evar->ws_mtx); evq.put = evq.evar->ws_put; + mtx_leave(&evq.evar->ws_mtx); evq.result = EVQ_RESULT_NONE; getnanotime(&evq.ts); wsmouse_evq_put(&evq, ev, btn); @@ -940,8 +942,10 @@ wstpad_tap_timeout(void *p) if (input->flags & LOG_EVENTS) { wsmouse_log_events(input, &evq); } + mtx_enter(&evq.evar->ws_mtx); evq.evar->ws_put = evq.put; - WSEVENT_WAKEUP(evq.evar); + mtx_leave(&evq.evar->ws_mtx); + wsevent_wakeup(evq.evar); } else { input->sbtn.sync |= tp->tap.button; }