static ssize_t clocksource_read_time(struct kobj_t * kobj, void * buf, size_t size) { struct clocksource_t * cs = (struct clocksource_t *)kobj->priv; u64_t cycle = clocksource_cycle(cs); u64_t time = clocksource_delta2ns(cs, cycle); return sprintf(buf, "%llu.%09llu", time / 1000000000ULL, time % 1000000000ULL); }
bool_t register_clocksource(struct device_t ** device, struct clocksource_t * cs) { struct device_t * dev; irq_flags_t flags; if(!cs || !cs->name || !cs->read) return FALSE; dev = malloc(sizeof(struct device_t)); if(!dev) return FALSE; cs->keeper.interval = clocksource_deferment(cs) >> 1; cs->keeper.last = clocksource_cycle(cs); cs->keeper.nsec = 0; seqlock_init(&cs->keeper.lock); timer_init(&cs->keeper.timer, clocksource_keeper_timer_function, cs); dev->name = strdup(cs->name); dev->type = DEVICE_TYPE_CLOCKSOURCE; dev->driver = NULL; dev->priv = cs; dev->kobj = kobj_alloc_directory(dev->name); kobj_add_regular(dev->kobj, "mult", clocksource_read_mult, NULL, cs); kobj_add_regular(dev->kobj, "shift", clocksource_read_shift, NULL, cs); kobj_add_regular(dev->kobj, "period", clocksource_read_period, NULL, cs); kobj_add_regular(dev->kobj, "deferment", clocksource_read_deferment, NULL, cs); kobj_add_regular(dev->kobj, "cycle", clocksource_read_cycle, NULL, cs); kobj_add_regular(dev->kobj, "time", clocksource_read_time, NULL, cs); if(!register_device(dev)) { kobj_remove_self(dev->kobj); free(dev->name); free(dev); return FALSE; } if(__clocksource == &__cs_dummy) { spin_lock_irqsave(&__clocksource_lock, flags); __clocksource = cs; spin_unlock_irqrestore(&__clocksource_lock, flags); } timer_start_now(&cs->keeper.timer, ns_to_ktime(cs->keeper.interval)); if(device) *device = dev; return TRUE; }
static int clocksource_keeper_timer_function(struct timer_t * timer, void * data) { struct clocksource_t * cs = (struct clocksource_t *)(data); u64_t now, delta, offset; irq_flags_t flags; write_seqlock_irqsave(&cs->keeper.lock, flags); now = clocksource_cycle(cs); delta = clocksource_delta(cs, cs->keeper.last, now); offset = clocksource_delta2ns(cs, delta); cs->keeper.nsec += offset; cs->keeper.last = now; write_sequnlock_irqrestore(&cs->keeper.lock, flags); timer_forward_now(timer, ns_to_ktime(cs->keeper.interval)); return 1; }
static ssize_t clocksource_read_cycle(struct kobj_t * kobj, void * buf, size_t size) { struct clocksource_t * cs = (struct clocksource_t *)kobj->priv; return sprintf(buf, "%llu", clocksource_cycle(cs)); }