#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/thread.h>
#include <sys/cpuhelper.h>
static struct thread *cpuhelper[MAXCPU];
static int (*cpuhelper_saved_putport)(lwkt_port_t, lwkt_msg_t);
static __inline lwkt_port_t
cpuhelper_port(int cpuid)
{
return (&cpuhelper[cpuid]->td_msgport);
}
static int
cpuhelper_putport(lwkt_port_t port, lwkt_msg_t lmsg)
{
struct cpuhelper_msg *msg = (struct cpuhelper_msg *)lmsg;
if ((lmsg->ms_flags & MSGF_SYNC) && port == &curthread->td_msgport) {
msg->ch_cb(msg);
return (EASYNC);
} else {
return (cpuhelper_saved_putport(port, lmsg));
}
}
static void
cpuhelper_mainloop(void *arg __unused)
{
struct cpuhelper_msg *msg;
while ((msg = lwkt_waitport(&curthread->td_msgport, 0))) {
KASSERT(msg->ch_cb != NULL, ("cpuhelper%d: badmsg", mycpuid));
msg->ch_cb(msg);
}
}
void
cpuhelper_initmsg(struct cpuhelper_msg *msg, lwkt_port_t rport,
cpuhelper_cb_t cb, void *cbarg, int flags)
{
lwkt_initmsg(&msg->ch_lmsg, rport, flags);
msg->ch_cb = cb;
msg->ch_cbarg = cbarg;
msg->ch_cbarg1 = 0;
}
void
cpuhelper_replymsg(struct cpuhelper_msg *msg, int error)
{
lwkt_replymsg(&msg->ch_lmsg, error);
}
int
cpuhelper_domsg(struct cpuhelper_msg *msg, int cpuid)
{
KASSERT(cpuid >= 0 && cpuid < ncpus, ("invalid cpuid"));
return (lwkt_domsg(cpuhelper_port(cpuid), &msg->ch_lmsg, 0));
}
void
cpuhelper_assert(int cpuid, bool in)
{
#ifdef INVARIANTS
KASSERT(cpuid >= 0 && cpuid < ncpus, ("invalid cpuid"));
if (in) {
KASSERT(&curthread->td_msgport == cpuhelper_port(cpuid),
("not in cpuhelper%d", cpuid));
} else {
KASSERT(&curthread->td_msgport != cpuhelper_port(cpuid),
("in cpuhelper%d", cpuid));
}
#endif
}
static void
cpuhelper_init(void)
{
int i;
for (i = 0; i < ncpus; ++i) {
lwkt_port_t port;
lwkt_create(cpuhelper_mainloop, NULL, &cpuhelper[i], NULL,
TDF_NOSTART|TDF_FORCE_SPINPORT|TDF_FIXEDCPU, i,
"cpuhelper %d", i);
port = cpuhelper_port(i);
if (cpuhelper_saved_putport == NULL)
cpuhelper_saved_putport = port->mp_putport;
KKASSERT(cpuhelper_saved_putport == port->mp_putport);
port->mp_putport = cpuhelper_putport;
lwkt_schedule(cpuhelper[i]);
}
}
SYSINIT(cpuhelper, SI_SUB_PRE_DRIVERS, SI_ORDER_FIRST, cpuhelper_init, NULL);