#include <sys/types.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/machintr.h>
#include <sys/errno.h>
#include <sys/mman.h>
#include <sys/globaldata.h>
#include <sys/interrupt.h>
#include <stdio.h>
#include <signal.h>
#include <machine/globaldata.h>
#include <machine/md_var.h>
#include <sys/thread2.h>
#include <unistd.h>
static void dummy_intr_disable(int);
static void dummy_intr_enable(int);
static void dummy_intr_setup(int, int);
static void dummy_intr_teardown(int);
static int dummy_legacy_intr_cpuid(int);
static void dummy_finalize(void);
static void dummy_intrcleanup(void);
static void dummy_stabilize(void);
struct machintr_abi MachIntrABI = {
MACHINTR_GENERIC,
.intr_disable = dummy_intr_disable,
.intr_enable = dummy_intr_enable,
.intr_setup = dummy_intr_setup,
.intr_teardown = dummy_intr_teardown,
.legacy_intr_cpuid = dummy_legacy_intr_cpuid,
.finalize = dummy_finalize,
.cleanup = dummy_intrcleanup,
.stabilize = dummy_stabilize
};
static void
dummy_intr_disable(int intr)
{
}
static void
dummy_intr_enable(int intr)
{
}
static void
dummy_intr_setup(int intr, int flags)
{
}
static void
dummy_intr_teardown(int intr)
{
}
static void
dummy_finalize(void)
{
}
static void
dummy_intrcleanup(void)
{
}
static void
dummy_stabilize(void)
{
}
static int
dummy_legacy_intr_cpuid(int irq __unused)
{
return 0;
}
void
splz(void)
{
struct mdglobaldata *gd = mdcpu;
thread_t td = gd->mi.gd_curthread;
int irq;
while (gd->mi.gd_reqflags & (RQF_IPIQ|RQF_INTPEND|
RQF_TIMER|RQF_KQUEUE)) {
crit_enter_quick(td);
if (gd->mi.gd_reqflags & RQF_IPIQ) {
atomic_clear_int(&gd->mi.gd_reqflags, RQF_IPIQ);
atomic_swap_int(&gd->mi.gd_npoll, 0);
lwkt_process_ipiq();
}
if (gd->mi.gd_reqflags & RQF_INTPEND) {
atomic_clear_int(&gd->mi.gd_reqflags, RQF_INTPEND);
while ((irq = ffs(gd->gd_spending)) != 0) {
--irq;
atomic_clear_int(&gd->gd_spending, 1 << irq);
irq += FIRST_SOFTINT;
sched_ithd_soft(irq);
}
while ((irq = ffs(gd->gd_fpending)) != 0) {
--irq;
atomic_clear_int(&gd->gd_fpending, 1 << irq);
sched_ithd_hard_virtual(irq);
}
}
if (gd->mi.gd_reqflags & RQF_TIMER) {
atomic_clear_int(&gd->mi.gd_reqflags, RQF_TIMER);
vktimer_intr(NULL);
}
if (gd->mi.gd_reqflags & RQF_KQUEUE) {
atomic_clear_int(&gd->mi.gd_reqflags, RQF_KQUEUE);
kqueue_intr(NULL);
}
crit_exit_noyield(td);
}
}
void
signalintr(int intr)
{
struct mdglobaldata *gd = mdcpu;
thread_t td = gd->mi.gd_curthread;
if (td->td_critcount || td->td_nest_count) {
atomic_set_int_nonlocked(&gd->gd_fpending, 1 << intr);
atomic_set_int(&gd->mi.gd_reqflags, RQF_INTPEND);
umtx_wakeup(&gd->mi.gd_reqflags, 0);
} else {
++td->td_nest_count;
cpu_ccfence();
atomic_clear_int(&gd->gd_fpending, 1 << intr);
sched_ithd_hard_virtual(intr);
cpu_ccfence();
--td->td_nest_count;
}
}
void
cpu_disable_intr(void)
{
sigblock(sigmask(SIGALRM)|sigmask(SIGIO)|sigmask(SIGUSR1)|
sigmask(SIGURG));
}
void
cpu_enable_intr(void)
{
sigsetmask(0);
}
void
cpu_mask_all_signals(void)
{
sigblock(sigmask(SIGALRM)|sigmask(SIGIO)|sigmask(SIGQUIT)|
sigmask(SIGUSR1)|sigmask(SIGTERM)|sigmask(SIGWINCH)|
sigmask(SIGUSR2)|sigmask(SIGURG));
}
void
cpu_unmask_all_signals(void)
{
sigsetmask(0);
}
int
cpu_interrupt_running(struct thread *td)
{
struct mdglobaldata *gd = mdcpu;
if ((td->td_flags & TDF_INTTHREAD) ||
gd->gd_fpending ||
gd->gd_spending) {
return 1;
}
return 0;
}