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");