int __init init_module(void) { init_timer(&timer); timer.function = timer_fun; mod_timer(&timer, jiffies + ECHO_PERIOD*HZ); xnintr_init(&intr, 0, isr, NULL, 0); xnintr_attach(&intr, &intr); return 0; }
int rt_intr_create(RT_INTR *intr, const char *name, unsigned irq, rt_isr_t isr, rt_iack_t iack, int mode) { int err; spl_t s; if (xnpod_asynch_p()) return -EPERM; if (name) xnobject_copy_name(intr->name, name); else /* Kernel-side "anonymous" objects (name == NULL) get unique names. * Nevertheless, they will not be exported via the registry. */ xnobject_create_name(intr->name, sizeof(intr->name), isr); xnintr_init(&intr->intr_base, intr->name, irq, isr, iack, mode); #ifdef CONFIG_XENO_OPT_PERVASIVE xnsynch_init(&intr->synch_base, XNSYNCH_PRIO, NULL); intr->pending = 0; intr->cpid = 0; intr->mode = 0; #endif /* CONFIG_XENO_OPT_PERVASIVE */ intr->magic = XENO_INTR_MAGIC; intr->handle = 0; /* i.e. (still) unregistered interrupt. */ inith(&intr->rlink); intr->rqueue = &xeno_get_rholder()->intrq; xnlock_get_irqsave(&nklock, s); appendq(intr->rqueue, &intr->rlink); xnlock_put_irqrestore(&nklock, s); err = xnintr_attach(&intr->intr_base, intr); /* * <!> Since xnregister_enter() may reschedule, only register * complete objects, so that the registry cannot return * handles to half-baked objects... */ if (!err && name) err = xnregistry_enter(intr->name, intr, &intr->handle, &__intr_pnode); if (err) rt_intr_delete(intr); return err; }
int xntimer_grab_hardware(void) { struct xnsched *sched; int ret, cpu, _cpu; spl_t s; #ifdef CONFIG_XENO_OPT_STATS /* * Only for statistical purpose, the timer interrupt is * attached by xntimer_grab_hardware(). */ xnintr_init(&nktimer, "[timer]", per_cpu(ipipe_percpu.hrtimer_irq, 0), NULL, NULL, 0); #endif /* CONFIG_XENO_OPT_STATS */ nkclock.wallclock_offset = xnclock_get_host_time() - xnclock_read_monotonic(&nkclock); ret = xntimer_setup_ipi(); if (ret) return ret; for_each_realtime_cpu(cpu) { ret = grab_hardware_timer(cpu); if (ret < 0) goto fail; xnlock_get_irqsave(&nklock, s); /* * If the current tick device for the target CPU is * periodic, we won't be called back for host tick * emulation. Therefore, we need to start a periodic * nucleus timer which will emulate the ticking for * that CPU, since we are going to hijack the hw clock * chip for managing our own system timer. * * CAUTION: * * - nucleus timers may be started only _after_ the hw * timer has been set up for the target CPU through a * call to xntimer_grab_hardware(). * * - we don't compensate for the elapsed portion of * the current host tick, since we cannot get this * information easily for all CPUs except the current * one, and also because of the declining relevance of * the jiffies clocksource anyway. * * - we must not hold the nklock across calls to * xntimer_grab_hardware(). */ sched = xnsched_struct(cpu); /* Set up timer with host tick period if valid. */ if (ret > 1) xntimer_start(&sched->htimer, ret, ret, XN_RELATIVE); else if (ret == 1) xntimer_start(&sched->htimer, 0, 0, XN_RELATIVE); #ifdef CONFIG_XENO_OPT_WATCHDOG xntimer_start(&sched->wdtimer, 1000000000UL, 1000000000UL, XN_RELATIVE); xnsched_reset_watchdog(sched); #endif xnlock_put_irqrestore(&nklock, s); } return 0; fail: for_each_realtime_cpu(_cpu) { if (_cpu == cpu) break; xnlock_get_irqsave(&nklock, s); sched = xnsched_struct(cpu); xntimer_stop(&sched->htimer); #ifdef CONFIG_XENO_OPT_WATCHDOG xntimer_stop(&sched->wdtimer); #endif xnlock_put_irqrestore(&nklock, s); ipipe_timer_stop(_cpu); } xntimer_release_ipi(); return ret; }