Index: sys/kern/kern_synch.c
===================================================================
RCS file: /home/dcvs/src/sys/kern/kern_synch.c,v
retrieving revision 1.48
diff -u -p -r1.48 kern_synch.c
--- sys/kern/kern_synch.c	11 Oct 2005 09:59:56 -0000	1.48
+++ sys/kern/kern_synch.c	22 Oct 2005 17:55:31 -0000
@@ -44,6 +44,7 @@
 
 #include <sys/param.h>
 #include <sys/systm.h>
+#include <sys/malloc.h>
 #include <sys/proc.h>
 #include <sys/kernel.h>
 #include <sys/signalvar.h>
@@ -51,6 +52,8 @@
 #include <sys/vmmeter.h>
 #include <sys/sysctl.h>
 #include <sys/thread2.h>
+#include <sys/msgport.h>
+#include <sys/msgport2.h>
 #ifdef KTRACE
 #include <sys/uio.h>
 #include <sys/ktrace.h>
@@ -209,9 +212,42 @@ updatepcpu(struct lwp *lp, int cpticks, 
  * of 2.  Shift right by 8, i.e. drop the bottom 256 worth.
  */
 #define TABLESIZE	128
-static TAILQ_HEAD(slpquehead, thread) slpque[TABLESIZE];
+static TAILQ_HEAD(slpquehead, thread) slpque[MAXCPU][TABLESIZE];
 #define LOOKUP(x)	(((intptr_t)(x) >> 8) & (TABLESIZE - 1))
 
+void wakeup_service_loop(void *);
+static int _wakeup_handler(struct lwkt_msg *);
+static void _wakeup_oncpu(void *, int, int);
+static void unsleep_oncpu(struct thread *);
+
+lwkt_port wakeup_afree_rport;
+struct thread wakeup_cpu[MAXCPU];
+
+struct msg_wakeup {
+	struct lwkt_msg wu_lmsg;
+	/* unsleep */
+	struct thread *wu_td;
+	/* wakeup */
+	void *wu_ident;
+	int wu_domain;
+	int wu_count;
+};
+
+void
+wakeup_service_loop(void *arg)
+{
+	struct msg_wakeup *msg;
+
+	while ((msg = lwkt_waitport(&curthread->td_msgport, NULL)))
+		msg->wu_lmsg.ms_cmd.cm_func(&msg->wu_lmsg);
+}
+
+static void
+wakeup_autofree_reply(lwkt_port_t port, lwkt_msg_t msg)
+{
+	free(msg, M_LWKTMSG);
+}
+
 /*
  * General scheduler initialization.  We force a reschedule 25 times
  * a second by default.
@@ -219,12 +255,18 @@ static TAILQ_HEAD(slpquehead, thread) sl
 void
 sleepinit(void)
 {
-	int i;
+	int i, j;
 
 	sched_quantum = (hz + 24) / 25;
 	hogticks = 2 * sched_quantum;
-	for (i = 0; i < TABLESIZE; i++)
-		TAILQ_INIT(&slpque[i]);
+	for (i = 0; i < ncpus; i++) {
+		for (j = 0; j < TABLESIZE; j++)
+			TAILQ_INIT(&slpque[i][j]);
+		lwkt_create(wakeup_service_loop, NULL, NULL, &wakeup_cpu[i],
+			    0, i, "wakeup_cpu %d", i);
+	}
+	lwkt_initport(&wakeup_afree_rport, NULL);
+	wakeup_afree_rport.mp_replyport = wakeup_autofree_reply;
 }
 
 /*
@@ -288,7 +330,7 @@ tsleep(void *ident, int flags, const cha
 		p->p_slptime = 0;
 	}
 	lwkt_deschedule_self(td);
-	TAILQ_INSERT_TAIL(&slpque[id], td, td_threadq);
+	TAILQ_INSERT_TAIL(&slpque[mycpu->gd_cpuid][id], td, td_threadq);
 	if (timo) {
 		callout_init(&thandle);
 		callout_reset(&thandle, timo, endtsleep, td);
@@ -393,26 +435,88 @@ endtsleep(void *arg)
 	crit_exit();
 }
 
-/*
- * Remove a process from its wait queue
- */
 void
-unsleep(struct thread *td)
+unsleep_oncpu(struct thread *td)
 {
 	crit_enter();
 	if (td->td_wchan) {
-		TAILQ_REMOVE(&slpque[LOOKUP(td->td_wchan)], td, td_threadq);
+		TAILQ_REMOVE(&slpque[td->td_gd->gd_cpuid][LOOKUP(td->td_wchan)], td, td_threadq);
 		td->td_wchan = NULL;
 	}
 	crit_exit();
 }
 
+static int
+unsleep_handler(struct lwkt_msg *msg)
+{
+	struct msg_wakeup *msg1 = (struct msg_wakeup *)msg;
+
+	unsleep_oncpu(msg1->wu_td);
+	lwkt_replymsg(&msg1->wu_lmsg, 0);
+	return (EASYNC);
+}
+
 /*
- * Make all processes sleeping on the specified identifier runnable.
+ * Remove a process from its wait queue
  */
+void
+unsleep(struct thread *td)
+{
+	struct msg_wakeup *msg;
+
+	if (td->td_gd->gd_cpuid == mycpu->gd_cpuid) {
+		unsleep_oncpu(td);
+		return;
+	}
+	msg = malloc(sizeof(struct msg_wakeup), M_LWKTMSG, M_INTWAIT);
+	lwkt_initmsg(&msg->wu_lmsg, &wakeup_afree_rport, 0,
+		     lwkt_cmd_func(unsleep_handler),
+		     lwkt_cmd_op_none);
+	msg->wu_td = td;
+
+	lwkt_sendmsg(&wakeup_cpu[td->td_gd->gd_cpuid].td_msgport, &msg->wu_lmsg);
+}
+
 static void
 _wakeup(void *ident, int domain, int count)
 {
+	int i;
+
+	for (i = 0; i < ncpus; i++) {
+		struct msg_wakeup *msg;
+
+		if (i == mycpu->gd_cpuid) {
+			_wakeup_oncpu(ident, domain, count);
+			continue;
+		}
+		msg = malloc(sizeof(struct msg_wakeup), M_LWKTMSG, M_INTWAIT);
+		lwkt_initmsg(&msg->wu_lmsg, &wakeup_afree_rport, 0,
+			     lwkt_cmd_func(_wakeup_handler),
+			     lwkt_cmd_op_none);
+		msg->wu_ident = ident;
+		msg->wu_domain = domain;
+		msg->wu_count = count;
+		
+		lwkt_sendmsg(&wakeup_cpu[i].td_msgport, &msg->wu_lmsg);
+	}
+}
+
+static int
+_wakeup_handler(struct lwkt_msg *msg)
+{
+	struct msg_wakeup *msg1 = (struct msg_wakeup *)msg;
+
+	_wakeup_oncpu(msg1->wu_ident, msg1->wu_domain, msg1->wu_count);
+	lwkt_replymsg(&msg1->wu_lmsg, 0);
+	return (EASYNC);
+}
+
+/*
+ * Make all processes sleeping on the specified identifier runnable.
+ */
+static void
+_wakeup_oncpu(void *ident, int domain, int count)
+{
 	struct slpquehead *qp;
 	struct thread *td;
 	struct thread *ntd;
@@ -420,7 +524,7 @@ _wakeup(void *ident, int domain, int cou
 	int id = LOOKUP(ident);
 
 	crit_enter();
-	qp = &slpque[id];
+	qp = &slpque[mycpu->gd_cpuid][id];
 restart:
 	for (td = TAILQ_FIRST(qp); td != NULL; td = ntd) {
 		ntd = TAILQ_NEXT(td, td_threadq);
