예제 #1
0
fastcall notrace void smp_apic_timer_interrupt(struct pt_regs *regs)
{
	int cpu = smp_processor_id();

	/*
	 * the NMI deadlock-detector uses this.
	 */
	irq_stat[cpu].apic_timer_irqs++;

        trace_special(regs->eip, 0, 0);

	/*
	 * NOTE! We'd better ACK the irq immediately,
	 * because timer handling can be slow.
	 */
	ack_APIC_irq();
	/*
	 * update_process_times() expects us to have done irq_enter().
	 * Besides, if we don't timer interrupts ignore the global
	 * interrupt lock, which is the WrongThing (tm) to do.
	 */
	irq_enter();
	vst_wakeup(regs, 1);
	smp_local_timer_interrupt(regs);
	irq_exit();
}
예제 #2
0
파일: apic.c 프로젝트: cilynx/dd-wrt
/*
 * Local APIC timer interrupt. This is the most natural way for doing
 * local interrupts, but local timer interrupts can be emulated by
 * broadcast interrupts too. [in case the hw doesn't support APIC timers]
 *
 * [ if a single-CPU system runs an SMP kernel then we call the local
 *   interrupt as well. Thus we cannot inline the local irq ... ]
 */
void smp_apic_timer_interrupt(struct pt_regs *regs)
{
	struct pt_regs *old_regs = set_irq_regs(regs);

	/*
	 * the NMI deadlock-detector uses this.
	 */
	add_pda(apic_timer_irqs, 1);

	/*
	 * NOTE! We'd better ACK the irq immediately,
	 * because timer handling can be slow.
	 */
	ack_APIC_irq();
	/*
	 * update_process_times() expects us to have done irq_enter().
	 * Besides, if we don't timer interrupts ignore the global
	 * interrupt lock, which is the WrongThing (tm) to do.
	 */
	exit_idle();
	irq_enter();
	smp_local_timer_interrupt();
	irq_exit();
	set_irq_regs(old_regs);
}
예제 #3
0
void smp_apic_timer_interrupt(struct pt_regs * regs)
{
	int cpu = smp_processor_id();

	/*
	 * the NMI deadlock-detector uses this.
	 */
	apic_timer_irqs[cpu]++;

	/*
	 * NOTE! We'd better ACK the irq immediately,
	 * because timer handling can be slow.
	 */
	ack_APIC_irq();
	/*
	 * update_process_times() expects us to have done irq_enter().
	 * Besides, if we don't timer interrupts ignore the global
	 * interrupt lock, which is the WrongThing (tm) to do.
	 */
	irq_enter(cpu, 0);
	smp_local_timer_interrupt(regs);
	irq_exit(cpu, 0);

	if (softirq_pending(cpu))
		do_softirq();
}
예제 #4
0
/*
 * timer_interrupt() needs to keep up the real-time clock,
 * as well as call the "do_timer()" routine every clocktick
 */
static inline void
do_timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{
#ifndef CONFIG_SMP
	profile_tick(CPU_PROFILING, regs);
#endif
	do_timer(regs);

#ifndef CONFIG_SMP
	update_process_times(user_mode(regs));
#endif
	/*
	 * If we have an externally synchronized Linux clock, then update
	 * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
	 * called as close as possible to 500 ms before the new second starts.
	 */
	if ((time_status & STA_UNSYNC) == 0
		&& xtime.tv_sec > last_rtc_update + 660
		&& (xtime.tv_nsec / 1000) >= 500000 - ((unsigned)TICK_SIZE) / 2
		&& (xtime.tv_nsec / 1000) <= 500000 + ((unsigned)TICK_SIZE) / 2)
	{
		if (set_rtc_mmss(xtime.tv_sec) == 0)
			last_rtc_update = xtime.tv_sec;
		else	/* do it again in 60 s */
			last_rtc_update = xtime.tv_sec - 600;
	}
	/* As we return to user mode fire off the other CPU schedulers..
	   this is basically because we don't yet share IRQ's around.
	   This message is rigged to be safe on the 386 - basically it's
	   a hack, so don't look closely for now.. */

#ifdef CONFIG_SMP
	smp_local_timer_interrupt(regs);
#endif
}
예제 #5
0
/*==========================================================================*
 * Name:         smp_send_timer
 *
 * Description:  This routine executes on CPU which received
 *               'LOCAL_TIMER_IPI'.
 *
 * Born on Date: 2002.02.05
 *
 * Arguments:    *regs - a pointer to the saved regster info
 *
 * Returns:      void (cannot fail)
 *
 * Modification log:
 * Date       Who Description
 * ---------- --- --------------------------------------------------------
 *
 *==========================================================================*/
void smp_ipi_timer_interrupt(struct pt_regs *regs)
{
	struct pt_regs *old_regs;
	old_regs = set_irq_regs(regs);
	irq_enter();
	smp_local_timer_interrupt();
	irq_exit();
	set_irq_regs(old_regs);
}
예제 #6
0
파일: apic.c 프로젝트: ut-osa/syncchar
static void up_apic_timer_interrupt_call(struct pt_regs *regs)
{
	int cpu = smp_processor_id();

	/*
	 * the NMI deadlock-detector uses this.
	 */
	per_cpu(irq_stat, cpu).apic_timer_irqs++;

	smp_local_timer_interrupt(regs);
}
예제 #7
0
파일: time.c 프로젝트: sarnobat/knoppix
/*
 * timer_interrupt - gets called when the decrementer overflows,
 * with interrupts disabled.
 */
int timer_interrupt(struct pt_regs * regs)
{
	int next_dec;
	unsigned long cur_tb;
	struct paca_struct *lpaca = get_paca();
	unsigned long cpu = lpaca->xPacaIndex;

	irq_enter();

#ifndef CONFIG_PPC_ISERIES
	ppc64_do_profile(regs);
#endif

	lpaca->xLpPaca.xIntDword.xFields.xDecrInt = 0;

	while (lpaca->next_jiffy_update_tb <= (cur_tb = get_tb())) {

#ifdef CONFIG_SMP
		smp_local_timer_interrupt(regs);
#endif
		if (cpu == boot_cpuid) {
			write_seqlock(&xtime_lock);
			tb_last_stamp = lpaca->next_jiffy_update_tb;
			do_timer(regs);
			timer_sync_xtime( cur_tb );
			timer_check_rtc();
			write_sequnlock(&xtime_lock);
			if ( adjusting_time && (time_adjust == 0) )
				ppc_adjtimex();
		}
		lpaca->next_jiffy_update_tb += tb_ticks_per_jiffy;
	}
	
	next_dec = lpaca->next_jiffy_update_tb - cur_tb;
	if (next_dec > lpaca->default_decr)
        	next_dec = lpaca->default_decr;
	set_dec(next_dec);

#ifdef CONFIG_PPC_ISERIES
	{
		struct ItLpQueue *lpq = lpaca->lpQueuePtr;
		if (lpq && ItLpQueue_isLpIntPending(lpq))
			lpEvent_count += ItLpQueue_process(lpq, regs);
	}
#endif

	irq_exit();

	return 1;
}
예제 #8
0
void smp_send_timer_broadcast_ipi(void)
{
	int cpu = smp_processor_id();
	cpumask_t mask;

	cpus_and(mask, cpu_online_map, timer_interrupt_broadcast_ipi_mask);

	if (cpu_isset(cpu, mask)) {
		cpu_clear(cpu, mask);
		add_pda(apic_timer_irqs, 1);
		smp_local_timer_interrupt();
	}

	if (!cpus_empty(mask)) {
		send_IPI_mask(mask, LOCAL_TIMER_VECTOR);
	}
}
예제 #9
0
파일: time.c 프로젝트: 274914765/C
/*
 * timer_interrupt() needs to keep up the real-time clock,
 * as well as call the "do_timer()" routine every clocktick
 */
irqreturn_t timer_interrupt(int irq, void *dev_id)
{
#ifndef CONFIG_SMP
    profile_tick(CPU_PROFILING);
#endif
    do_timer(1);

#ifndef CONFIG_SMP
    update_process_times(user_mode(get_irq_regs()));
#endif
    /*
     * If we have an externally synchronized Linux clock, then update
     * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
     * called as close as possible to 500 ms before the new second starts.
     */
    write_seqlock(&xtime_lock);
    if (ntp_synced()
        && xtime.tv_sec > last_rtc_update + 660
        && (xtime.tv_nsec / 1000) >= 500000 - ((unsigned)TICK_SIZE) / 2
        && (xtime.tv_nsec / 1000) <= 500000 + ((unsigned)TICK_SIZE) / 2)
    {
        if (set_rtc_mmss(xtime.tv_sec) == 0)
            last_rtc_update = xtime.tv_sec;
        else    /* do it again in 60 s */
            last_rtc_update = xtime.tv_sec - 600;
    }
    write_sequnlock(&xtime_lock);
    /* As we return to user mode fire off the other CPU schedulers..
       this is basically because we don't yet share IRQ's around.
       This message is rigged to be safe on the 386 - basically it's
       a hack, so don't look closely for now.. */

#ifdef CONFIG_SMP
    smp_local_timer_interrupt();
    smp_send_timer();
#endif

    return IRQ_HANDLED;
}
예제 #10
0
파일: time.c 프로젝트: CSCLOG/beaglebone
/*
 * timer_interrupt() needs to keep up the real-time clock,
 * as well as call the "xtime_update()" routine every clocktick
 */
static irqreturn_t timer_interrupt(int irq, void *dev_id)
{
#ifndef CONFIG_SMP
	profile_tick(CPU_PROFILING);
#endif
	xtime_update(1);

#ifndef CONFIG_SMP
	update_process_times(user_mode(get_irq_regs()));
#endif
	/* As we return to user mode fire off the other CPU schedulers..
	   this is basically because we don't yet share IRQ's around.
	   This message is rigged to be safe on the 386 - basically it's
	   a hack, so don't look closely for now.. */

#ifdef CONFIG_SMP
	smp_local_timer_interrupt();
	smp_send_timer();
#endif

	return IRQ_HANDLED;
}
예제 #11
0
/*
 * timer_interrupt - gets called when the decrementer overflows,
 * with interrupts disabled.
 * We set it up to overflow again in 1/HZ seconds.
 */
int timer_interrupt(struct pt_regs * regs)
{
	int next_dec;
	unsigned long cpu = smp_processor_id();
	unsigned jiffy_stamp = last_jiffy_stamp(cpu);
	extern void do_IRQ(struct pt_regs *);

	if (atomic_read(&ppc_n_lost_interrupts) != 0)
		do_IRQ(regs);

	hardirq_enter(cpu);

	while ((next_dec = tb_ticks_per_jiffy - tb_delta(&jiffy_stamp)) < 0) {
		jiffy_stamp += tb_ticks_per_jiffy;
		if (!user_mode(regs))
			ppc_do_profile(instruction_pointer(regs));
		if (unlikely(!heartbeat_count(cpu)--)
				&& heartbeat_reset(cpu)) {
			ppc_md.heartbeat();
			heartbeat_count(cpu) = heartbeat_reset(cpu);
		}
	  	if (cpu)
			continue;

		/* We are in an interrupt, no need to save/restore flags */
		write_lock(&xtime_lock);
		tb_last_stamp = jiffy_stamp;
		do_timer(regs);

		/*
		 * update the rtc when needed, this should be performed on the
		 * right fraction of a second. Half or full second ?
		 * Full second works on mk48t59 clocks, others need testing.
		 * Note that this update is basically only used through
		 * the adjtimex system calls. Setting the HW clock in
		 * any other way is a /dev/rtc and userland business.
		 * This is still wrong by -0.5/+1.5 jiffies because of the
		 * timer interrupt resolution and possible delay, but here we
		 * hit a quantization limit which can only be solved by higher
		 * resolution timers and decoupling time management from timer
		 * interrupts. This is also wrong on the clocks
		 * which require being written at the half second boundary.
		 * We should have an rtc call that only sets the minutes and
		 * seconds like on Intel to avoid problems with non UTC clocks.
		 */
		if ( ppc_md.set_rtc_time && (time_status & STA_UNSYNC) == 0 &&
		     xtime.tv_sec - last_rtc_update >= 659 &&
		     abs(xtime.tv_usec - (1000000-1000000/HZ)) < 500000/HZ &&
		     jiffies - wall_jiffies == 1) {
		  	if (ppc_md.set_rtc_time(xtime.tv_sec+1 + time_offset) == 0)
				last_rtc_update = xtime.tv_sec+1;
			else
				/* Try again one minute later */
				last_rtc_update += 60;
		}
		write_unlock(&xtime_lock);
	}
	if (!disarm_decr[cpu])
		set_dec(next_dec);
	last_jiffy_stamp(cpu) = jiffy_stamp;

#ifdef CONFIG_SMP
	smp_local_timer_interrupt(regs);
#endif /* CONFIG_SMP */

	hardirq_exit(cpu);

	if (softirq_pending(cpu))
		do_softirq();

	return 1; /* lets ret_from_int know we can do checks */
}
예제 #12
0
/*==========================================================================*
 * Name:         smp_send_timer
 *
 * Description:  This routine executes on CPU which received
 *               'LOCAL_TIMER_IPI'.
 *
 * Born on Date: 2002.02.05
 *
 * Arguments:    *regs - a pointer to the saved regster info
 *
 * Returns:      void (cannot fail)
 *
 * Modification log:
 * Date       Who Description
 * ---------- --- --------------------------------------------------------
 *
 *==========================================================================*/
void smp_ipi_timer_interrupt(struct pt_regs *regs)
{
	irq_enter();
	smp_local_timer_interrupt(regs);
	irq_exit();
}