Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 27 Feb 2014 19:59:56 +0900 (JST)
From:      Kohji Okuno <okuno.kohji@jp.panasonic.com>
To:        jmg@funkthat.com
Cc:        freebsd-current@freebsd.org, okuno.kohji@jp.panasonic.com
Subject:   Re: kqueue for KBD.
Message-ID:  <20140227.195956.1191893338998586416.okuno.kohji@jp.panasonic.com>
In-Reply-To: <20140227061840.GB47921@funkthat.com>
References:  <20140227.142445.47188371497615592.okuno.kohji@jp.panasonic.com> <20140227061840.GB47921@funkthat.com>

next in thread | previous in thread | raw e-mail | index | archive | help
----Next_Part(Thu_Feb_27_19_59_56_2014_781)--
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Hi John-Mark,

Thank you for your comment.
I added knote_clear() and knote_destroy() in kbd_detach(). I attached
patch, again. But, maybe this patch can not resolve all cases you
pointed.

Regards,
 Kohji Okuno

> Kohji Okuno wrote this message on Thu, Feb 27, 2014 at 14:24 +0900:
>> I tried to add kqueue I/F to kbd.c. I attached patch.
>> What do you think about my patch?
> 
> So, knlist_destroy is missing in this patch too..
> 
> It also needs some style(9) loving in that some blank lines are missing
> and there are some extra curly braces...
> 
> So, knlist_clear is usually used for something like close where it
> cannot be used again...  You use knlist_clear when the kbd goes away,
> but this also means that the user will never be notified that the kbd
> has gone, and could possibly end up leaking resources...
> 
> I guess I should maybe write a function knlist_clearerr or something
> that detaches all the knotes from the knlist and sets the proper flag
> so that they can be reaped by userland...  I believe your usb patch
> had a similar issue and some of the other drivers have this issue too..
> 
> Otherwise looks good...
> 
> -- 
>   John-Mark Gurney				Voice: +1 415 225 5579
> 
>      "All that I will do, has been done, All that I have, has not."

----Next_Part(Thu_Feb_27_19_59_56_2014_781)--
Content-Type: Text/X-Patch; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="kbd_kqueue-2.patch"

diff --git a/sys/dev/kbd/kbd.c b/sys/dev/kbd/kbd.c
index 8036762..26dcaad 100644
--- a/sys/dev/kbd/kbd.c
+++ b/sys/dev/kbd/kbd.c
@@ -59,6 +59,7 @@ typedef struct genkbd_softc {
 	char		gkb_q[KB_QSIZE];		/* input queue */
 	unsigned int	gkb_q_start;
 	unsigned int	gkb_q_length;
+	unsigned int	gkb_index;
 } genkbd_softc_t;
 
 static	SLIST_HEAD(, keyboard_driver) keyboard_drivers =
@@ -472,6 +473,7 @@ static d_read_t		genkbdread;
 static d_write_t	genkbdwrite;
 static d_ioctl_t	genkbdioctl;
 static d_poll_t		genkbdpoll;
+static d_kqfilter_t	genkbdkqfilter;
 
 
 static struct cdevsw kbd_cdevsw = {
@@ -483,12 +485,14 @@ static struct cdevsw kbd_cdevsw = {
 	.d_write =	genkbdwrite,
 	.d_ioctl =	genkbdioctl,
 	.d_poll =	genkbdpoll,
+	.d_kqfilter =	genkbdkqfilter,
 	.d_name =	"kbd",
 };
 
 int
 kbd_attach(keyboard_t *kbd)
 {
+	genkbd_softc_t *sc;
 
 	if (kbd->kb_index >= keyboards)
 		return (EINVAL);
@@ -498,8 +502,11 @@ kbd_attach(keyboard_t *kbd)
 	kbd->kb_dev = make_dev(&kbd_cdevsw, kbd->kb_index, UID_ROOT, GID_WHEEL,
 	    0600, "%s%r", kbd->kb_name, kbd->kb_unit);
 	make_dev_alias(kbd->kb_dev, "kbd%r", kbd->kb_index);
-	kbd->kb_dev->si_drv1 = malloc(sizeof(genkbd_softc_t), M_DEVBUF,
+	sc = malloc(sizeof(genkbd_softc_t), M_DEVBUF,
 	    M_WAITOK | M_ZERO);
+	kbd->kb_dev->si_drv1 = sc;
+	sc->gkb_index = KBD_INDEX(kbd->kb_dev);
+	knlist_init_mtx(&sc->gkb_rsel.si_note, NULL);
 	printf("kbd%d at %s%d\n", kbd->kb_index, kbd->kb_name, kbd->kb_unit);
 	return (0);
 }
@@ -507,12 +514,17 @@ kbd_attach(keyboard_t *kbd)
 int
 kbd_detach(keyboard_t *kbd)
 {
+	genkbd_softc_t *sc;
 
 	if (kbd->kb_index >= keyboards)
 		return (EINVAL);
 	if (keyboard[kbd->kb_index] != kbd)
 		return (EINVAL);
 
+	sc = kbd->kb_dev->si_drv1;
+	knlist_clear(&sc->gkb_rsel.si_note, 0);
+	knlist_destroy(&sc->gkb_rsel.si_note);
+
 	free(kbd->kb_dev->si_drv1, M_DEVBUF);
 	destroy_dev(kbd->kb_dev);
 
@@ -697,6 +709,71 @@ genkbdioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, struct thread *
 	return (error);
 }
 
+static void
+genkbd_kqops_detach(struct knote *kn)
+{
+	genkbd_softc_t *sc;
+	sc = kn->kn_hook;
+	knlist_remove(&sc->gkb_rsel.si_note, kn, 0);
+}
+
+static int
+genkbd_kqops_event(struct knote *kn, long hint)
+{
+	keyboard_t *kbd;
+	genkbd_softc_t *sc;
+
+	sc = kn->kn_hook;
+	kbd = kbd_get_keyboard(sc->gkb_index);
+
+	if ((kbd == NULL) || !KBD_IS_VALID(kbd)) {
+		return 1;	/* the keyboard has gone */
+	}
+	else {
+		if (sc->gkb_q_length > 0)
+			return 1;
+		else
+			return 0;
+	}
+
+}
+static struct filterops genkbd_kqops =
+{
+	.f_isfd		= 1,
+	.f_attach	= NULL,
+	.f_detach	= genkbd_kqops_detach,
+	.f_event	= genkbd_kqops_event,
+};
+static int
+genkbdkqfilter(struct cdev *dev, struct knote *kn)
+{
+	keyboard_t *kbd;
+	genkbd_softc_t *sc;
+	int error = 0;
+	int s;
+
+	s = spltty();
+	sc = dev->si_drv1;
+	kbd = kbd_get_keyboard(KBD_INDEX(dev));
+	if ((sc == NULL) || (kbd == NULL) || !KBD_IS_VALID(kbd)) {
+		error = EIO;
+	}
+	else  {
+		switch (kn->kn_filter) {
+		case EVFILT_READ:
+			kn->kn_fop = &genkbd_kqops;
+			kn->kn_hook = (void *)sc;
+			knlist_add(&sc->gkb_rsel.si_note, kn, 0);
+			break;
+		default:
+			error = EOPNOTSUPP;
+			break;
+		}
+	}
+	splx(s);
+	return (error);
+}
+
 static int
 genkbdpoll(struct cdev *dev, int events, struct thread *td)
 {
@@ -744,6 +821,7 @@ genkbd_event(keyboard_t *kbd, int event, void *arg)
 			wakeup(sc);
 		}
 		selwakeuppri(&sc->gkb_rsel, PZERO);
+		KNOTE_UNLOCKED(&sc->gkb_rsel.si_note, 0);
 		return (0);
 	default:
 		return (EINVAL);
@@ -814,6 +892,7 @@ genkbd_event(keyboard_t *kbd, int event, void *arg)
 			wakeup(sc);
 		}
 		selwakeuppri(&sc->gkb_rsel, PZERO);
+		KNOTE_UNLOCKED(&sc->gkb_rsel.si_note, 0);
 	}
 
 	return (0);

----Next_Part(Thu_Feb_27_19_59_56_2014_781)----



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20140227.195956.1191893338998586416.okuno.kohji>