Module Name:    src
Committed By:   rmind
Date:           Sun May 22 04:27:16 UTC 2011

Modified Files:
        src/sys/arch/xen/xen: xenevt.c
        src/sys/arch/xen/xenbus: xenbus_xs.c

Log Message:
- Replace uses of simple_lock and ltsleep with mutex and condvar.
- Improve some parts of the code to be more MP-friendly.

Tested by jakllsch@.


To generate a diff of this commit:
cvs rdiff -u -r1.36 -r1.37 src/sys/arch/xen/xen/xenevt.c
cvs rdiff -u -r1.18 -r1.19 src/sys/arch/xen/xenbus/xenbus_xs.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/xen/xen/xenevt.c
diff -u src/sys/arch/xen/xen/xenevt.c:1.36 src/sys/arch/xen/xen/xenevt.c:1.37
--- src/sys/arch/xen/xen/xenevt.c:1.36	Sun Dec 20 09:36:05 2009
+++ src/sys/arch/xen/xen/xenevt.c	Sun May 22 04:27:15 2011
@@ -1,4 +1,4 @@
-/*      $NetBSD: xenevt.c,v 1.36 2009/12/20 09:36:05 dsl Exp $      */
+/*      $NetBSD: xenevt.c,v 1.37 2011/05/22 04:27:15 rmind Exp $      */
 
 /*
  * Copyright (c) 2005 Manuel Bouyer.
@@ -26,12 +26,13 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: xenevt.c,v 1.36 2009/12/20 09:36:05 dsl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xenevt.c,v 1.37 2011/05/22 04:27:15 rmind Exp $");
 
 #include "opt_xen.h"
 #include <sys/param.h>
 #include <sys/kernel.h>
 #include <sys/malloc.h>
+#include <sys/mutex.h>
 #include <sys/systm.h>
 #include <sys/device.h>
 #include <sys/file.h>
@@ -42,7 +43,6 @@
 #include <sys/conf.h>
 #include <sys/intr.h>
 #include <sys/kmem.h>
-#include <sys/simplelock.h>
 
 #include <uvm/uvm_extern.h>
 
@@ -103,7 +103,8 @@
 #define BYTES_PER_PORT (sizeof(evtchn_port_t) / sizeof(uint8_t))
 
 struct xenevt_d {
-	struct simplelock lock;
+	kmutex_t lock;
+	kcondvar_t cv;
 	STAILQ_ENTRY(xenevt_d) pendingq;
 	bool pending;
 	evtchn_port_t ring[2048]; 
@@ -119,9 +120,8 @@
 
 /* pending events */
 static void *devevent_sih;
-struct simplelock devevent_pending_lock = SIMPLELOCK_INITIALIZER;
-STAILQ_HEAD(, xenevt_d) devevent_pending =
-    STAILQ_HEAD_INITIALIZER(devevent_pending);
+static kmutex_t devevent_lock;
+static STAILQ_HEAD(, xenevt_d) devevent_pending;
 
 static void xenevt_donotify(struct xenevt_d *);
 static void xenevt_record(struct xenevt_d *, evtchn_port_t);
@@ -142,6 +142,8 @@
 	bool mpsafe = (level != IPL_VM);
 #endif /* MULTIPROCESSOR */
 
+	mutex_init(&devevent_lock, MUTEX_DEFAULT, IPL_HIGH);
+	STAILQ_INIT(&devevent_pending);
 
 	devevent_sih = softint_establish(SOFTINT_SERIAL,
 	    (void (*)(void *))xenevt_notify, NULL);
@@ -218,10 +220,11 @@
 			return;
 		}
 
-		simple_lock(&devevent_pending_lock);
+		mutex_enter(&devevent_lock);
 		STAILQ_INSERT_TAIL(&devevent_pending, d, pendingq);
-		simple_unlock(&devevent_pending_lock);
 		d->pending = true;
+		mutex_exit(&devevent_lock);
+
 		softint_schedule(devevent_sih);
 	}
 }
@@ -229,43 +232,31 @@
 void
 xenevt_notify(void)
 {
+	struct xenevt_d *d;
 
-	int s = splhigh();
-	simple_lock(&devevent_pending_lock);
-	while (/* CONSTCOND */ 1) {
-		struct xenevt_d *d;
-
+	for (;;) {
+		mutex_enter(&devevent_lock);
 		d = STAILQ_FIRST(&devevent_pending);
 		if (d == NULL) {
+			mutex_exit(&devevent_lock);
 			break;
 		}
 		STAILQ_REMOVE_HEAD(&devevent_pending, pendingq);
-		simple_unlock(&devevent_pending_lock);
-		splx(s);
-
 		d->pending = false;
-		xenevt_donotify(d);
+		mutex_exit(&devevent_lock);
 
-		s = splhigh();
-		simple_lock(&devevent_pending_lock);
+		xenevt_donotify(d);
 	}
-	simple_unlock(&devevent_pending_lock);
-	splx(s);
 }
 
 static void
 xenevt_donotify(struct xenevt_d *d)
 {
-	int s;
 
-	s = splsoftserial();
-	simple_lock(&d->lock);
-	 
+	mutex_enter(&d->lock);
 	selnotify(&d->sel, 0, 1);
-	wakeup(&d->ring_read);
-
-	simple_unlock(&d->lock);
-	splx(s);
+	cv_broadcast(&d->cv);
+	mutex_exit(&d->lock);
 }
 
 static void
@@ -303,7 +294,8 @@
 			return error;
 
 		d = malloc(sizeof(*d), M_DEVBUF, M_WAITOK | M_ZERO);
-		simple_lock_init(&d->lock);
+		mutex_init(&d->lock, MUTEX_DEFAULT, IPL_SOFTSERIAL);
+		cv_init(&d->cv, "xenevt");
 		selinit(&d->sel);
 		return fd_clone(fp, fd, flags, &xenevt_fileops, d);
 	case DEV_XSD:
@@ -380,8 +372,10 @@
 		}
 	}
 	seldestroy(&d->sel);
-	free(d, M_DEVBUF);
+	cv_destroy(&d->cv);
+	mutex_destroy(&d->lock);
 	fp->f_data = NULL;
+	free(d, M_DEVBUF);
 
 	return (0);
 }
@@ -391,15 +385,11 @@
     kauth_cred_t cred, int flags)
 {
 	struct xenevt_d *d = fp->f_data;
-	int error;
+	int error, ring_read, ring_write;
 	size_t len, uio_len;
-	int ring_read;
-	int ring_write;
-	int s;
 
 	error = 0;
-	s = splsoftserial();
-	simple_lock(&d->lock);
+	mutex_enter(&d->lock);
 	while (error == 0) {
 		ring_read = d->ring_read;
 		ring_write = d->ring_write;
@@ -411,18 +401,16 @@
 		}
 
 		/* nothing to read */
-		if (fp->f_flag & FNONBLOCK) {
-			error = EAGAIN;
+		if ((fp->f_flag & FNONBLOCK) == 0) {
+			error = cv_wait_sig(&d->cv, &d->lock);
 		} else {
-			error = ltsleep(&d->ring_read, PRIBIO | PCATCH,
-			    "xenevt", 0, &d->lock);
+			error = EAGAIN;
 		}
 	}
 	if (error == 0 && (d->flags & XENEVT_F_OVERFLOW)) {
 		error = EFBIG;
 	}
-	simple_unlock(&d->lock);
-	splx(s);
+	mutex_exit(&d->lock);
 
 	if (error) {
 		return error;
@@ -452,11 +440,9 @@
 	ring_read = (ring_read + len) & XENEVT_RING_MASK;
 
 done:
-	s = splsoftserial();
-	simple_lock(&d->lock);
+	mutex_enter(&d->lock);
 	d->ring_read = ring_read;
-	simple_unlock(&d->lock);
-	splx(s);
+	mutex_exit(&d->lock);
 
 	return 0;
 }
@@ -591,10 +577,8 @@
 {
 	struct xenevt_d *d = fp->f_data;
 	int revents = events & (POLLOUT | POLLWRNORM); /* we can always write */
-	int s;
 
-	s = splsoftserial();
-	simple_lock(&d->lock);
+	mutex_enter(&d->lock);
 	if (events & (POLLIN | POLLRDNORM)) {
 		if (d->ring_read != d->ring_write) {
 			revents |= events & (POLLIN | POLLRDNORM);
@@ -603,7 +587,6 @@
 			selrecord(curlwp, &d->sel);
 		}
 	}
-	simple_unlock(&d->lock);
-	splx(s);
+	mutex_exit(&d->lock);
 	return (revents);
 }

Index: src/sys/arch/xen/xenbus/xenbus_xs.c
diff -u src/sys/arch/xen/xenbus/xenbus_xs.c:1.18 src/sys/arch/xen/xenbus/xenbus_xs.c:1.19
--- src/sys/arch/xen/xenbus/xenbus_xs.c:1.18	Tue Apr 28 05:44:43 2009
+++ src/sys/arch/xen/xenbus/xenbus_xs.c	Sun May 22 04:27:15 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: xenbus_xs.c,v 1.18 2009/04/28 05:44:43 cegger Exp $ */
+/* $NetBSD: xenbus_xs.c,v 1.19 2011/05/22 04:27:15 rmind Exp $ */
 /******************************************************************************
  * xenbus_xs.c
  *
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: xenbus_xs.c,v 1.18 2009/04/28 05:44:43 cegger Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xenbus_xs.c,v 1.19 2011/05/22 04:27:15 rmind Exp $");
 
 #if 0
 #define DPRINTK(fmt, args...) \
@@ -48,7 +48,6 @@
 #include <sys/proc.h>
 #include <sys/mutex.h>
 #include <sys/kthread.h>
-#include <sys/simplelock.h>
 
 #include <machine/stdarg.h>
 
@@ -81,7 +80,8 @@
 struct xs_handle {
 	/* A list of replies. Currently only one will ever be outstanding. */
 	SIMPLEQ_HEAD(, xs_stored_msg) reply_list;
-	struct simplelock reply_lock;
+	kmutex_t reply_lock;
+	kcondvar_t reply_cv;
 	kmutex_t xs_lock; /* serialize access to xenstore */
 	int suspend_spl;
 
@@ -90,14 +90,13 @@
 static struct xs_handle xs_state;
 
 /* List of registered watches, and a lock to protect it. */
-static SLIST_HEAD(, xenbus_watch) watches =
-    SLIST_HEAD_INITIALIZER(watches);
-static struct simplelock watches_lock = SIMPLELOCK_INITIALIZER;
+static SLIST_HEAD(, xenbus_watch) watches;
+static kmutex_t watches_lock;
 
 /* List of pending watch callback events, and a lock to protect it. */
-static SIMPLEQ_HEAD(, xs_stored_msg) watch_events =
-    SIMPLEQ_HEAD_INITIALIZER(watch_events);
-static struct simplelock watch_events_lock = SIMPLELOCK_INITIALIZER;
+static SIMPLEQ_HEAD(, xs_stored_msg) watch_events;
+static kmutex_t watch_events_lock;
+static kcondvar_t watch_cv;
 
 static int
 get_error(const char *errorstring)
@@ -120,21 +119,14 @@
 {
 	struct xs_stored_msg *msg;
 	char *body;
-	int s;
-
-	simple_lock(&xs_state.reply_lock);
-	s = spltty();
 
+	mutex_enter(&xs_state.reply_lock);
 	while (SIMPLEQ_EMPTY(&xs_state.reply_list)) {
-		ltsleep(&xs_state.reply_list, PRIBIO, "rplq", 0,
-		    &xs_state.reply_lock);
+		cv_wait(&xs_state.reply_cv, &xs_state.reply_lock);
 	}
-
 	msg = SIMPLEQ_FIRST(&xs_state.reply_list);
 	SIMPLEQ_REMOVE_HEAD(&xs_state.reply_list, msg_next);
-
-	splx(s);
-	simple_unlock(&xs_state.reply_lock);
+	mutex_exit(&xs_state.reply_lock);
 
 	*type = msg->hdr.type;
 	if (len)
@@ -649,67 +641,64 @@
 	/* Pointer in ascii is the token. */
 	char token[sizeof(watch) * 2 + 1];
 	int err;
-	int s;
 
 	snprintf(token, sizeof(token), "%lX", (long)watch);
 
-	s = spltty();
-
-	simple_lock(&watches_lock);
+	mutex_enter(&watches_lock);
 	KASSERT(find_watch(token) == 0);
 	SLIST_INSERT_HEAD(&watches, watch, watch_next);
-	simple_unlock(&watches_lock);
+	mutex_exit(&watches_lock);
 
 	err = xs_watch(watch->node, token);
 
 	/* Ignore errors due to multiple registration. */
 	if ((err != 0) && (err != EEXIST)) {
-		simple_lock(&watches_lock);
+		mutex_enter(&watches_lock);
 		SLIST_REMOVE(&watches, watch, xenbus_watch, watch_next);
-		simple_unlock(&watches_lock);
+		mutex_exit(&watches_lock);
 	}
-
-	splx(s);
-
 	return err;
 }
 
 void
 unregister_xenbus_watch(struct xenbus_watch *watch)
 {
+	SIMPLEQ_HEAD(, xs_stored_msg) gclist;
 	struct xs_stored_msg *msg, *next_msg;
 	char token[sizeof(watch) * 2 + 1];
-	int err, s;
+	int err;
 
 	snprintf(token, sizeof(token), "%lX", (long)watch);
 
-	s = spltty();
-
-	simple_lock(&watches_lock);
+	mutex_enter(&watches_lock);
 	KASSERT(find_watch(token));
 	SLIST_REMOVE(&watches, watch, xenbus_watch, watch_next);
-	simple_unlock(&watches_lock);
+	mutex_exit(&watches_lock);
 
 	err = xs_unwatch(watch->node, token);
-	if (err)
+	if (err) {
 		printf(
 		       "XENBUS Failed to release watch %s: %i\n",
 		       watch->node, err);
-
-	splx(s);
+	}
 
 	/* Cancel pending watch events. */
-	simple_lock(&watch_events_lock);
+	SIMPLEQ_INIT(&gclist);
+	mutex_enter(&watch_events_lock);
 	for (msg = SIMPLEQ_FIRST(&watch_events); msg != NULL; msg = next_msg) {
 		next_msg = SIMPLEQ_NEXT(msg, msg_next);
 		if (msg->u.watch.handle != watch)
 			continue;
 		SIMPLEQ_REMOVE(&watch_events, msg, xs_stored_msg, msg_next);
+		SIMPLEQ_INSERT_TAIL(&gclist, msg, msg_next);
+	}
+	mutex_exit(&watch_events_lock);
+
+	while ((msg = SIMPLEQ_FIRST(&gclist)) != NULL) {
+		SIMPLEQ_REMOVE(&gclist, msg, xs_stored_msg, msg_next);
 		free(msg->u.watch.vec, M_DEVBUF);
 		free(msg, M_DEVBUF);
 	}
-	simple_unlock(&watch_events_lock);
-
 }
 
 void
@@ -735,20 +724,20 @@
 static void
 xenwatch_thread(void *unused)
 {
+	SIMPLEQ_HEAD(, xs_stored_msg) events_to_proces;
 	struct xs_stored_msg *msg;
-	int s;
 
+	SIMPLEQ_INIT(&events_to_proces);
 	for (;;) {
-		tsleep(&watch_events, PRIBIO, "evtsq", 0);
-		s = spltty(); /* to block IPL_CTRL */
-		while (!SIMPLEQ_EMPTY(&watch_events)) {
-			msg = SIMPLEQ_FIRST(&watch_events);
-
-			simple_lock(&watch_events_lock);
-			SIMPLEQ_REMOVE_HEAD(&watch_events, msg_next);
-			simple_unlock(&watch_events_lock);
-			DPRINTK("xenwatch_thread: got event");
+		mutex_enter(&watch_events_lock);
+		cv_wait(&watch_cv, &watch_events_lock);
+		SIMPLEQ_CONCAT(&events_to_proces, &watch_events);
+		mutex_exit(&watch_events_lock);
 
+		DPRINTK("xenwatch_thread: processing events");
+
+		while ((msg = SIMPLEQ_FIRST(&events_to_proces)) != NULL) {
+			SIMPLEQ_REMOVE_HEAD(&events_to_proces, msg_next);
 			msg->u.watch.handle->xbw_callback(
 				msg->u.watch.handle,
 				(const char **)msg->u.watch.vec,
@@ -756,8 +745,6 @@
 			free(msg->u.watch.vec, M_DEVBUF);
 			free(msg, M_DEVBUF);
 		}
-
-		splx(s);
 	}
 }
 
@@ -766,7 +753,7 @@
 {
 	struct xs_stored_msg *msg;
 	char *body;
-	int err, s;
+	int err;
 
 	msg = malloc(sizeof(*msg), M_DEVBUF, M_NOWAIT);
 	if (msg == NULL)
@@ -795,6 +782,8 @@
 	body[msg->hdr.len] = '\0';
 
 	if (msg->hdr.type == XS_WATCH_EVENT) {
+		bool found;
+
 		DPRINTK("process_msg: XS_WATCH_EVENT");
 		msg->u.watch.vec = split(body, msg->hdr.len,
 					 &msg->u.watch.vec_size);
@@ -803,31 +792,29 @@
 			return ENOMEM;
 		}
 
-		simple_lock(&watches_lock);
-		s = spltty();
+		mutex_enter(&watches_lock);
 		msg->u.watch.handle = find_watch(
-			msg->u.watch.vec[XS_WATCH_TOKEN]);
-		if (msg->u.watch.handle != NULL) {
-			simple_lock(&watch_events_lock);
+		    msg->u.watch.vec[XS_WATCH_TOKEN]);
+		found = (msg->u.watch.handle != NULL);
+		if (found) {
+			mutex_enter(&watch_events_lock);
 			SIMPLEQ_INSERT_TAIL(&watch_events, msg, msg_next);
-			wakeup(&watch_events);
-			simple_unlock(&watch_events_lock);
-		} else {
+			cv_broadcast(&watch_cv);
+			mutex_exit(&watch_events_lock);
+		}
+		mutex_exit(&watches_lock);
+		if (!found) {
 			free(msg->u.watch.vec, M_DEVBUF);
 			free(msg, M_DEVBUF);
 		}
-		splx(s);
-		simple_unlock(&watches_lock);
 	} else {
 		DPRINTK("process_msg: type %d body %s", msg->hdr.type, body);
-		    
+
 		msg->u.reply.body = body;
-		simple_lock(&xs_state.reply_lock);
-		s = spltty();
+		mutex_enter(&xs_state.reply_lock);
 		SIMPLEQ_INSERT_TAIL(&xs_state.reply_list, msg, msg_next);
-		splx(s);
-		simple_unlock(&xs_state.reply_lock);
-		wakeup(&xs_state.reply_list);
+		cv_broadcast(&xs_state.reply_cv);
+		mutex_exit(&xs_state.reply_lock);
 	}
 
 	return 0;
@@ -850,9 +837,17 @@
 {
 	int err;
 
+	SLIST_INIT(&watches);
+	mutex_init(&watches_lock, MUTEX_DEFAULT, IPL_TTY);
+
+	SIMPLEQ_INIT(&watch_events);
+	mutex_init(&watch_events_lock, MUTEX_DEFAULT, IPL_TTY);
+	cv_init(&watch_cv, "evtsq");
+
 	SIMPLEQ_INIT(&xs_state.reply_list);
-	simple_lock_init(&xs_state.reply_lock);
 	mutex_init(&xs_state.xs_lock, MUTEX_DEFAULT, IPL_NONE);
+	mutex_init(&xs_state.reply_lock, MUTEX_DEFAULT, IPL_TTY);
+	cv_init(&xs_state.reply_cv, "rplq");
 
 	err = kthread_create(PRI_NONE, 0, NULL, xenwatch_thread,
 	    NULL, NULL, "xenwatch");

Reply via email to