本文共 3504 字,大约阅读时间需要 11 分钟。
#define DECREMENTER_EXCEPTION \ START_EXCEPTION(Decrementer) \ NORMAL_EXCEPTION_PROLOG; \ lis r0,TSR_DIS@h; /* Setup the DEC interrupt mask */ \ mtspr SPRN_TSR,r0; /* Clear the DEC interrupt */ \ addi r3,r1,STACK_FRAME_OVERHEAD; \ EXC_XFER_LITE(0x0900, timer_interrupt) void timer_interrupt(struct pt_regs * regs) =>int cpu = smp_processor_id(); =>if (atomic_read(&ppc_n_lost_interrupts) != 0)//如果还有未处理的外部中断处理函数,则处理 do_IRQ(regs); =>old_regs = set_irq_regs(regs);//保存寄存器现场,注意old_regs是指针,指向现场全局寄存器的指针 =>struct pt_regs *old_regs, **pp_regs = &__get_cpu_var(__irq_regs);//保存在__irq_regs全局变量里面,每个核一个 old_regs = *pp_regs; *pp_regs = new_regs; return old_regs =>irq_enter();//中断计数加一,进入中断上下文 =>while ((ticks = tb_ticks_since(per_cpu(last_jiffy, cpu))) >= tb_ticks_per_jiffy) per_cpu(last_jiffy, cpu) += tb_ticks_per_jiffy; account_process_time(regs);//#define account_process_time(regs) update_process_times(user_mode(regs)) =>scheduler_tick();//选择合适的进程,用于时钟中断返回继续调度 =>curr->sched_class->task_tick(rq, curr);//.task_tick = task_tick_fair =>struct sched_entity *se = &curr->se; =>for_each_sched_entity(se) { cfs_rq = cfs_rq_of(se); entity_tick(cfs_rq, se); =>update_curr(cfs_rq); =>if (cfs_rq->nr_running > 1 || !sched_feat(WAKEUP_PREEMPT)) check_preempt_tick(cfs_rq, curr); =>ideal_runtime = sched_slice(cfs_rq, curr);//计算理想调度时间 =>delta_exec = curr->sum_exec_runtime - curr->prev_sum_exec_runtime; =>if (delta_exec > ideal_runtime) {//实际时间大于理想时间,则调度 resched_task(rq_of(cfs_rq)->curr); /* * The current task ran long enough, ensure it doesn't get * re-elected due to buddy favours. */ clear_buddies(cfs_rq, curr); return; } } if (cpu != boot_cpuid) continue; tb_next_jiffy = tb_last_jiffy + tb_ticks_per_jiffy; if (per_cpu(last_jiffy, cpu) >= tb_next_jiffy) { tb_last_jiffy = tb_next_jiffy; do_timer(1); timer_recalc_offset(tb_last_jiffy); timer_check_rtc(); } =>next_dec = tb_ticks_per_jiffy - ticks; =>set_dec(next_dec);//设置DEC寄存器,用于触发下一次的时钟中断 =>irq_exit(); =>set_irq_regs(old_regs); void timer_interrupt(struct pt_regs * regs) =>struct decrementer_clock *decrementer = &__get_cpu_var(decrementers); =>set_dec(DECREMENTER_MAX);//重新设置最大值 =>mtspr(SPRN_DEC, val); =>__get_cpu_var(irq_stat).timer_irqs++; =>old_regs = set_irq_regs(regs);//保存寄存器现场,注意old_regs是指针,指向现场全局寄存器的指针 =>struct pt_regs *old_regs; old_regs = __this_cpu_read(__irq_regs);//保存在__irq_regs全局变量里面,每个核一个 __this_cpu_write(__irq_regs, new_regs); return old_regs; =>irq_enter();//中断计数加一,进入中断上下文 desc->handle_irq = handle_level_irq;//Mpc8xx_pic.c (c:\linux\linux-2.6.23\arch\powerpc\sysdev): =>desc->chip->ack(irq);/* Start handling the irq */ =>desc->status |= IRQ_INPROGRESS;/* Mark the IRQ currently in progress.*/ =>do//可能好几个中断都上报 desc->status &= ~IRQ_PENDING; action_ret = handle_IRQ_event(irq, action); =>do//依次查看是否共享中断 ret = action->handler(irq, action->dev_id); retval |= ret; action = action->next; =>while (action); =>while ((desc->status & (IRQ_PENDING | IRQ_DISABLED)) == IRQ_PENDING);
转载地址:http://eplji.baihongyu.com/