/* * Event timer interrupt. * * XXX a drawback of this implementation is that events serviced earlier must not set deadlines * that occur before the entire chain completes. * * XXX a better implementation would use a set of generic callouts and iterate over them */ void etimer_intr( __unused int inuser, __unused uint64_t iaddr) { uint64_t abstime; rtclock_timer_t *mytimer; struct per_proc_info *pp; pp = getPerProc(); mytimer = &pp->rtclock_timer; /* Point to the event timer */ abstime = mach_absolute_time(); /* Get the time now */ /* is it time for power management state change? */ if (pp->pms.pmsPop <= abstime) { KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_EXCP_DECI, 3) | DBG_FUNC_START, 0, 0, 0, 0, 0); pmsStep(1); /* Yes, advance step */ KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_EXCP_DECI, 3) | DBG_FUNC_END, 0, 0, 0, 0, 0); abstime = mach_absolute_time(); /* Get the time again since we ran a bit */ } /* has a pending clock timer expired? */ if (mytimer->deadline <= abstime) { /* Have we expired the deadline? */ mytimer->has_expired = TRUE; /* Remember that we popped */ mytimer->deadline = timer_queue_expire(&mytimer->queue, abstime); mytimer->has_expired = FALSE; } /* schedule our next deadline */ pp->rtcPop = EndOfAllTime; /* any real deadline will be earlier */ etimer_resync_deadlines(); }
/** * etimer_intr * * Timer interrupt routine, called from the realtime clock interrupt * routine. */ void etimer_intr(int inuser, uint64_t iaddr) { uint64_t abstime; rtclock_timer_t *mytimer; cpu_data_t *pp; int32_t latency; pp = current_cpu_datap(); SCHED_STATS_TIMER_POP(current_processor()); abstime = mach_absolute_time(); /* Get the time now */ /* * has a pending clock timer expired? */ mytimer = &pp->rt_timer; /* Point to the event timer */ if (mytimer->deadline <= abstime) { mytimer->has_expired = TRUE; /* Remember that we popped */ mytimer->deadline = timer_queue_expire(&mytimer->queue, abstime); mytimer->has_expired = FALSE; } pp->rtcPop = EndOfAllTime; /* any real deadline will be earlier */ /* * schedule our next deadline */ etimer_resync_deadlines(); }
/* * Routine: cpu_init * Function: */ void cpu_init( void) { struct per_proc_info *proc_info; proc_info = getPerProc(); /* * Restore the TBR. */ if (proc_info->save_tbu != 0 || proc_info->save_tbl != 0) { mttb(0); mttbu(proc_info->save_tbu); mttb(proc_info->save_tbl); } proc_info->rtcPop = EndOfAllTime; /* forget any existing decrementer setting */ etimer_resync_deadlines(); /* Now that the time base is sort of correct, request the next timer pop */ proc_info->cpu_type = CPU_TYPE_POWERPC; proc_info->cpu_subtype = (cpu_subtype_t)proc_info->pf.rptdProc; proc_info->cpu_threadtype = CPU_THREADTYPE_NONE; proc_info->running = TRUE; }
static void pmReSyncDeadlines(int cpu) { static boolean_t registered = FALSE; if (!registered) { PM_interrupt_register(&etimer_resync_deadlines); registered = TRUE; } if ((uint32_t)cpu == current_cpu_datap()->lcpu.cpu_num) etimer_resync_deadlines(); else cpu_PM_interrupt(cpu); }
/* * Set the clock deadline. */ void etimer_set_deadline(uint64_t deadline) { rtclock_timer_t *mytimer; spl_t s; struct per_proc_info *pp; s = splclock(); /* no interruptions */ pp = getPerProc(); mytimer = &pp->rtclock_timer; /* Point to the timer itself */ mytimer->deadline = deadline; /* Set the new expiration time */ etimer_resync_deadlines(); splx(s); }
/** * etimer_set_deadline * * Set the clock deadline. */ void etimer_set_deadline(uint64_t deadline) { rtclock_timer_t *mytimer; spl_t s; cpu_data_t *pp; s = splclock(); /* no interruptions */ pp = current_cpu_datap(); mytimer = &pp->rt_timer; /* Point to the timer itself */ mytimer->deadline = deadline; /* Set the new expiration time */ etimer_resync_deadlines(); splx(s); }