notification chain
Class:
notifier_block
member:
notifier_call: callback function
next:
single list
notifier_block --> notifier_block --> ... --> notifier_block --> notifier_block
four flavors
atomic_notifier_head
blocking_notifier_head
raw_notifier_head
srcu_notifier_head
method:
notifier_chain_register
notifier_chain_unregister
run:
notifier_call_chain
instance:
clockevents_chain
type
raw_notifier_head
method
clockevents_register_notifier
-- raw_notifier_chain_register
-- notifier_chain_register
clockevents_unregister_notifier (x)
raw_notifier_chain_unregister
-- notifier_chain_unregister
run:
clockevents_do_notify
-- raw_notifier_call_chain
-- __raw_notifier_call_chain
-- notifier_call_chain
element:
static struct notifier_block tick_notifier = {
.notifier_call = tick_notify,
};
clockevents_chain
tick_notify <--> watch_notify <--> horologe_notify <--> sun_notify <--> ...
implement:
clockevents_register_device
<-- setup_APIC_timer
<-- setup_pit_timer
<-- hpet_legacy_clockevent_register
instance
cpu_chain
type
raw_notifier_head
method
register_cpu_notifier
unregister_cpu_notifier
cpu_chain
timers_nb <--> amd_cpu_notifier <--> hrtimers_nb <-->
perf_cpu_notify <--> migration_notifier <--> cpucache_notifier <-->
slab_notifier <--> hotplug_cfd_notifier <--> cpu_nfb <--> vmstat_notifier
hardware clock
struct clocksource
clocksource_list
lguest_clock <--> clocksource_hpet <-->
<--> pit_cs <--> clocksource_jiffies <--> kvm_clock <--> xen_clocksource
<--> clocksource_tsc <--> clocksource_uv <--> clocksource_vmi
clocksource_register
clocksource_unregister
struct clock_event_device
clockevent_devices
struct clock_event_device <--> struct clock_event_device <--> struct clock_event_device
event_handler
clock
{
struct clocksource: static
struct clock_event_device: dynamic
}
struct tick_device {
struct clock_event_device *evtdev;
enum tick_device_mode mode;
};
对于tick设备,event_handler 总是被设置为同一个
void tick_set_periodic_handler(struct clock_event_device *dev, int broadcast)
{
if (!broadcast)
/* global_clock_event->event_handler = tick_handle_periodic */
dev->event_handler = tick_handle_periodic;
else
dev->event_handler = tick_handle_periodic_broadcast;
}
time_init
x86_late_time_init
hpet_time_init
hpet_enable
hpet_clocksource_register
clocksource_register(&clocksource_hpet);
hpet_legacy_clockevent_register
clockevents_register_device -- hpet_clockevent
global_clock_event = &hpet_clockevent;
setup_pit_timer
setup_boot_APIC_clock
setup_APIC_timer
clockevents_register_device
x86 arch initialization
x86_init
irq0->handler
= timer_event_interrupt
= global_clock_event->event_handler(global_clock_event);
= tick_handle_periodic
add_timer
mod_timer
internal_add_timer
run_timer_softirq
__run_timers