linux/kernel/time/tick-common.c
<<
>>
Prefs
   1/*
   2 * linux/kernel/time/tick-common.c
   3 *
   4 * This file contains the base functions to manage periodic tick
   5 * related events.
   6 *
   7 * Copyright(C) 2005-2006, Thomas Gleixner <tglx@linutronix.de>
   8 * Copyright(C) 2005-2007, Red Hat, Inc., Ingo Molnar
   9 * Copyright(C) 2006-2007, Timesys Corp., Thomas Gleixner
  10 *
  11 * This code is licenced under the GPL version 2. For details see
  12 * kernel-base/COPYING.
  13 */
  14#include <linux/cpu.h>
  15#include <linux/err.h>
  16#include <linux/hrtimer.h>
  17#include <linux/interrupt.h>
  18#include <linux/percpu.h>
  19#include <linux/profile.h>
  20#include <linux/sched.h>
  21
  22#include <asm/irq_regs.h>
  23
  24#include "tick-internal.h"
  25
  26/*
  27 * Tick devices
  28 */
  29DEFINE_PER_CPU(struct tick_device, tick_cpu_device);
  30/*
  31 * Tick next event: keeps track of the tick time
  32 */
  33ktime_t tick_next_period;
  34ktime_t tick_period;
  35int tick_do_timer_cpu __read_mostly = TICK_DO_TIMER_BOOT;
  36static DEFINE_RAW_SPINLOCK(tick_device_lock);
  37
  38/*
  39 * Debugging: see timer_list.c
  40 */
  41struct tick_device *tick_get_device(int cpu)
  42{
  43        return &per_cpu(tick_cpu_device, cpu);
  44}
  45
  46/**
  47 * tick_is_oneshot_available - check for a oneshot capable event device
  48 */
  49int tick_is_oneshot_available(void)
  50{
  51        struct clock_event_device *dev = __this_cpu_read(tick_cpu_device.evtdev);
  52
  53        if (!dev || !(dev->features & CLOCK_EVT_FEAT_ONESHOT))
  54                return 0;
  55        if (!(dev->features & CLOCK_EVT_FEAT_C3STOP))
  56                return 1;
  57        return tick_broadcast_oneshot_available();
  58}
  59
  60/*
  61 * Periodic tick
  62 */
  63static void tick_periodic(int cpu)
  64{
  65        if (tick_do_timer_cpu == cpu) {
  66                write_seqlock(&jiffies_lock);
  67
  68                /* Keep track of the next tick event */
  69                tick_next_period = ktime_add(tick_next_period, tick_period);
  70
  71                do_timer(1);
  72                write_sequnlock(&jiffies_lock);
  73        }
  74
  75        update_process_times(user_mode(get_irq_regs()));
  76        profile_tick(CPU_PROFILING);
  77}
  78
  79/*
  80 * Event handler for periodic ticks
  81 */
  82void tick_handle_periodic(struct clock_event_device *dev)
  83{
  84        int cpu = smp_processor_id();
  85        ktime_t next;
  86
  87        tick_periodic(cpu);
  88
  89        if (dev->mode != CLOCK_EVT_MODE_ONESHOT)
  90                return;
  91        /*
  92         * Setup the next period for devices, which do not have
  93         * periodic mode:
  94         */
  95        next = ktime_add(dev->next_event, tick_period);
  96        for (;;) {
  97                if (!clockevents_program_event(dev, next, false))
  98                        return;
  99                /*
 100                 * Have to be careful here. If we're in oneshot mode,
 101                 * before we call tick_periodic() in a loop, we need
 102                 * to be sure we're using a real hardware clocksource.
 103                 * Otherwise we could get trapped in an infinite
 104                 * loop, as the tick_periodic() increments jiffies,
 105                 * when then will increment time, posibly causing
 106                 * the loop to trigger again and again.
 107                 */
 108                if (timekeeping_valid_for_hres())
 109                        tick_periodic(cpu);
 110                next = ktime_add(next, tick_period);
 111        }
 112}
 113
 114/*
 115 * Setup the device for a periodic tick
 116 */
 117void tick_setup_periodic(struct clock_event_device *dev, int broadcast)
 118{
 119        tick_set_periodic_handler(dev, broadcast);
 120
 121        /* Broadcast setup ? */
 122        if (!tick_device_is_functional(dev))
 123                return;
 124
 125        if ((dev->features & CLOCK_EVT_FEAT_PERIODIC) &&
 126            !tick_broadcast_oneshot_active()) {
 127                clockevents_set_mode(dev, CLOCK_EVT_MODE_PERIODIC);
 128        } else {
 129                unsigned long seq;
 130                ktime_t next;
 131
 132                do {
 133                        seq = read_seqbegin(&jiffies_lock);
 134                        next = tick_next_period;
 135                } while (read_seqretry(&jiffies_lock, seq));
 136
 137                clockevents_set_mode(dev, CLOCK_EVT_MODE_ONESHOT);
 138
 139                for (;;) {
 140                        if (!clockevents_program_event(dev, next, false))
 141                                return;
 142                        next = ktime_add(next, tick_period);
 143                }
 144        }
 145}
 146
 147/*
 148 * Setup the tick device
 149 */
 150static void tick_setup_device(struct tick_device *td,
 151                              struct clock_event_device *newdev, int cpu,
 152                              const struct cpumask *cpumask)
 153{
 154        ktime_t next_event;
 155        void (*handler)(struct clock_event_device *) = NULL;
 156
 157        /*
 158         * First device setup ?
 159         */
 160        if (!td->evtdev) {
 161                /*
 162                 * If no cpu took the do_timer update, assign it to
 163                 * this cpu:
 164                 */
 165                if (tick_do_timer_cpu == TICK_DO_TIMER_BOOT) {
 166                        if (!tick_nohz_full_cpu(cpu))
 167                                tick_do_timer_cpu = cpu;
 168                        else
 169                                tick_do_timer_cpu = TICK_DO_TIMER_NONE;
 170                        tick_next_period = ktime_get();
 171                        tick_period = ktime_set(0, NSEC_PER_SEC / HZ);
 172                }
 173
 174                /*
 175                 * Startup in periodic mode first.
 176                 */
 177                td->mode = TICKDEV_MODE_PERIODIC;
 178        } else {
 179                handler = td->evtdev->event_handler;
 180                next_event = td->evtdev->next_event;
 181                td->evtdev->event_handler = clockevents_handle_noop;
 182        }
 183
 184        td->evtdev = newdev;
 185
 186        /*
 187         * When the device is not per cpu, pin the interrupt to the
 188         * current cpu:
 189         */
 190        if (!cpumask_equal(newdev->cpumask, cpumask))
 191                irq_set_affinity(newdev->irq, cpumask);
 192
 193        /*
 194         * When global broadcasting is active, check if the current
 195         * device is registered as a placeholder for broadcast mode.
 196         * This allows us to handle this x86 misfeature in a generic
 197         * way.
 198         */
 199        if (tick_device_uses_broadcast(newdev, cpu))
 200                return;
 201
 202        if (td->mode == TICKDEV_MODE_PERIODIC)
 203                tick_setup_periodic(newdev, 0);
 204        else
 205                tick_setup_oneshot(newdev, handler, next_event);
 206}
 207
 208/*
 209 * Check, if the new registered device should be used.
 210 */
 211static int tick_check_new_device(struct clock_event_device *newdev)
 212{
 213        struct clock_event_device *curdev;
 214        struct tick_device *td;
 215        int cpu, ret = NOTIFY_OK;
 216        unsigned long flags;
 217
 218        raw_spin_lock_irqsave(&tick_device_lock, flags);
 219
 220        cpu = smp_processor_id();
 221        if (!cpumask_test_cpu(cpu, newdev->cpumask))
 222                goto out_bc;
 223
 224        td = &per_cpu(tick_cpu_device, cpu);
 225        curdev = td->evtdev;
 226
 227        /* cpu local device ? */
 228        if (!cpumask_equal(newdev->cpumask, cpumask_of(cpu))) {
 229
 230                /*
 231                 * If the cpu affinity of the device interrupt can not
 232                 * be set, ignore it.
 233                 */
 234                if (!irq_can_set_affinity(newdev->irq))
 235                        goto out_bc;
 236
 237                /*
 238                 * If we have a cpu local device already, do not replace it
 239                 * by a non cpu local device
 240                 */
 241                if (curdev && cpumask_equal(curdev->cpumask, cpumask_of(cpu)))
 242                        goto out_bc;
 243        }
 244
 245        /*
 246         * If we have an active device, then check the rating and the oneshot
 247         * feature.
 248         */
 249        if (curdev) {
 250                /*
 251                 * Prefer one shot capable devices !
 252                 */
 253                if ((curdev->features & CLOCK_EVT_FEAT_ONESHOT) &&
 254                    !(newdev->features & CLOCK_EVT_FEAT_ONESHOT))
 255                        goto out_bc;
 256                /*
 257                 * Check the rating
 258                 */
 259                if (curdev->rating >= newdev->rating)
 260                        goto out_bc;
 261        }
 262
 263        /*
 264         * Replace the eventually existing device by the new
 265         * device. If the current device is the broadcast device, do
 266         * not give it back to the clockevents layer !
 267         */
 268        if (tick_is_broadcast_device(curdev)) {
 269                clockevents_shutdown(curdev);
 270                curdev = NULL;
 271        }
 272        clockevents_exchange_device(curdev, newdev);
 273        tick_setup_device(td, newdev, cpu, cpumask_of(cpu));
 274        if (newdev->features & CLOCK_EVT_FEAT_ONESHOT)
 275                tick_oneshot_notify();
 276
 277        raw_spin_unlock_irqrestore(&tick_device_lock, flags);
 278        return NOTIFY_STOP;
 279
 280out_bc:
 281        /*
 282         * Can the new device be used as a broadcast device ?
 283         */
 284        if (tick_check_broadcast_device(newdev))
 285                ret = NOTIFY_STOP;
 286
 287        raw_spin_unlock_irqrestore(&tick_device_lock, flags);
 288
 289        return ret;
 290}
 291
 292/*
 293 * Transfer the do_timer job away from a dying cpu.
 294 *
 295 * Called with interrupts disabled.
 296 */
 297static void tick_handover_do_timer(int *cpup)
 298{
 299        if (*cpup == tick_do_timer_cpu) {
 300                int cpu = cpumask_first(cpu_online_mask);
 301
 302                tick_do_timer_cpu = (cpu < nr_cpu_ids) ? cpu :
 303                        TICK_DO_TIMER_NONE;
 304        }
 305}
 306
 307/*
 308 * Shutdown an event device on a given cpu:
 309 *
 310 * This is called on a life CPU, when a CPU is dead. So we cannot
 311 * access the hardware device itself.
 312 * We just set the mode and remove it from the lists.
 313 */
 314static void tick_shutdown(unsigned int *cpup)
 315{
 316        struct tick_device *td = &per_cpu(tick_cpu_device, *cpup);
 317        struct clock_event_device *dev = td->evtdev;
 318        unsigned long flags;
 319
 320        raw_spin_lock_irqsave(&tick_device_lock, flags);
 321        td->mode = TICKDEV_MODE_PERIODIC;
 322        if (dev) {
 323                /*
 324                 * Prevent that the clock events layer tries to call
 325                 * the set mode function!
 326                 */
 327                dev->mode = CLOCK_EVT_MODE_UNUSED;
 328                clockevents_exchange_device(dev, NULL);
 329                dev->event_handler = clockevents_handle_noop;
 330                td->evtdev = NULL;
 331        }
 332        raw_spin_unlock_irqrestore(&tick_device_lock, flags);
 333}
 334
 335static void tick_suspend(void)
 336{
 337        struct tick_device *td = &__get_cpu_var(tick_cpu_device);
 338        unsigned long flags;
 339
 340        raw_spin_lock_irqsave(&tick_device_lock, flags);
 341        clockevents_shutdown(td->evtdev);
 342        raw_spin_unlock_irqrestore(&tick_device_lock, flags);
 343}
 344
 345static void tick_resume(void)
 346{
 347        struct tick_device *td = &__get_cpu_var(tick_cpu_device);
 348        unsigned long flags;
 349        int broadcast = tick_resume_broadcast();
 350
 351        raw_spin_lock_irqsave(&tick_device_lock, flags);
 352        clockevents_set_mode(td->evtdev, CLOCK_EVT_MODE_RESUME);
 353
 354        if (!broadcast) {
 355                if (td->mode == TICKDEV_MODE_PERIODIC)
 356                        tick_setup_periodic(td->evtdev, 0);
 357                else
 358                        tick_resume_oneshot();
 359        }
 360        raw_spin_unlock_irqrestore(&tick_device_lock, flags);
 361}
 362
 363/*
 364 * Notification about clock event devices
 365 */
 366static int tick_notify(struct notifier_block *nb, unsigned long reason,
 367                               void *dev)
 368{
 369        switch (reason) {
 370
 371        case CLOCK_EVT_NOTIFY_ADD:
 372                return tick_check_new_device(dev);
 373
 374        case CLOCK_EVT_NOTIFY_BROADCAST_ON:
 375        case CLOCK_EVT_NOTIFY_BROADCAST_OFF:
 376        case CLOCK_EVT_NOTIFY_BROADCAST_FORCE:
 377                tick_broadcast_on_off(reason, dev);
 378                break;
 379
 380        case CLOCK_EVT_NOTIFY_BROADCAST_ENTER:
 381        case CLOCK_EVT_NOTIFY_BROADCAST_EXIT:
 382                tick_broadcast_oneshot_control(reason);
 383                break;
 384
 385        case CLOCK_EVT_NOTIFY_CPU_DYING:
 386                tick_handover_do_timer(dev);
 387                break;
 388
 389        case CLOCK_EVT_NOTIFY_CPU_DEAD:
 390                tick_shutdown_broadcast_oneshot(dev);
 391                tick_shutdown_broadcast(dev);
 392                tick_shutdown(dev);
 393                break;
 394
 395        case CLOCK_EVT_NOTIFY_SUSPEND:
 396                tick_suspend();
 397                tick_suspend_broadcast();
 398                break;
 399
 400        case CLOCK_EVT_NOTIFY_RESUME:
 401                tick_resume();
 402                break;
 403
 404        default:
 405                break;
 406        }
 407
 408        return NOTIFY_OK;
 409}
 410
 411static struct notifier_block tick_notifier = {
 412        .notifier_call = tick_notify,
 413};
 414
 415/**
 416 * tick_init - initialize the tick control
 417 *
 418 * Register the notifier with the clockevents framework
 419 */
 420void __init tick_init(void)
 421{
 422        clockevents_register_notifier(&tick_notifier);
 423        tick_broadcast_init();
 424}
 425