callout: Add callout_reset_bycpu, which dispatches callout to the specified CPU
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Tue, 24 Jul 2012 10:59:31 +0000 (18:59 +0800)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Thu, 26 Jul 2012 09:21:20 +0000 (17:21 +0800)
sys/kern/kern_timeout.c
sys/sys/callout.h

index 37af44f..68d2f05 100644 (file)
@@ -380,6 +380,54 @@ callout_reset(struct callout *c, int to_ticks, void (*ftn)(void *),
        crit_exit_gd(gd);
 }
 
+#ifdef SMP
+
+struct callout_remote_arg {
+       struct callout  *c;
+       void            (*ftn)(void *);
+       void            *arg;
+       int             to_ticks;
+};
+
+static void
+callout_reset_ipi(void *arg)
+{
+       struct callout_remote_arg *rmt = arg;
+
+       callout_reset(rmt->c, rmt->to_ticks, rmt->ftn, rmt->arg);
+}
+
+#endif
+
+void
+callout_reset_bycpu(struct callout *c, int to_ticks, void (*ftn)(void *),
+    void *arg, int cpuid)
+{
+       KASSERT(cpuid >= 0 && cpuid < ncpus, ("invalid cpuid %d", cpuid));
+
+#ifndef SMP
+       callout_reset(c, to_ticks, ftn, arg);
+#else
+       if (cpuid == mycpuid) {
+               callout_reset(c, to_ticks, ftn, arg);
+       } else {
+               struct globaldata *target_gd;
+               struct callout_remote_arg rmt;
+               int seq;
+
+               rmt.c = c;
+               rmt.ftn = ftn;
+               rmt.arg = arg;
+               rmt.to_ticks = to_ticks;
+
+               target_gd = globaldata_find(cpuid);
+
+               seq = lwkt_send_ipiq(target_gd, callout_reset_ipi, &rmt);
+               lwkt_wait_ipiq(target_gd, seq);
+       }
+#endif
+}
+
 /*
  * Stop a running timer.  WARNING!  If called on a cpu other then the one
  * the callout was started on this function will liveloop on its IPI to
index a74d1ca..a2ff2ec 100644 (file)
@@ -96,6 +96,8 @@ void  callout_reset (struct callout *, int, void (*)(void *), void *);
 int    callout_stop (struct callout *);
 void   callout_stop_sync (struct callout *);
 void   callout_terminate (struct callout *);
+void   callout_reset_bycpu (struct callout *, int, void (*)(void *), void *,
+           int);
 
 #endif