LCOV - code coverage report
Current view: top level - kernel/time - tick-oneshot.c (source / functions) Hit Total Coverage
Test: landlock.info Lines: 22 43 51.2 %
Date: 2021-04-22 12:43:58 Functions: 3 5 60.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : /*
       3             :  * This file contains functions which manage high resolution tick
       4             :  * related events.
       5             :  *
       6             :  * Copyright(C) 2005-2006, Thomas Gleixner <tglx@linutronix.de>
       7             :  * Copyright(C) 2005-2007, Red Hat, Inc., Ingo Molnar
       8             :  * Copyright(C) 2006-2007, Timesys Corp., Thomas Gleixner
       9             :  */
      10             : #include <linux/cpu.h>
      11             : #include <linux/err.h>
      12             : #include <linux/hrtimer.h>
      13             : #include <linux/interrupt.h>
      14             : #include <linux/percpu.h>
      15             : #include <linux/profile.h>
      16             : #include <linux/sched.h>
      17             : 
      18             : #include "tick-internal.h"
      19             : 
      20             : /**
      21             :  * tick_program_event
      22             :  */
      23       31083 : int tick_program_event(ktime_t expires, int force)
      24             : {
      25       31083 :         struct clock_event_device *dev = __this_cpu_read(tick_cpu_device.evtdev);
      26             : 
      27       31083 :         if (unlikely(expires == KTIME_MAX)) {
      28             :                 /*
      29             :                  * We don't need the clock event device any more, stop it.
      30             :                  */
      31           0 :                 clockevents_switch_state(dev, CLOCK_EVT_STATE_ONESHOT_STOPPED);
      32           0 :                 dev->next_event = KTIME_MAX;
      33           0 :                 return 0;
      34             :         }
      35             : 
      36       31083 :         if (unlikely(clockevent_state_oneshot_stopped(dev))) {
      37             :                 /*
      38             :                  * We need the clock event again, configure it in ONESHOT mode
      39             :                  * before using it.
      40             :                  */
      41           0 :                 clockevents_switch_state(dev, CLOCK_EVT_STATE_ONESHOT);
      42             :         }
      43             : 
      44       31083 :         return clockevents_program_event(dev, expires, force);
      45             : }
      46             : 
      47             : /**
      48             :  * tick_resume_onshot - resume oneshot mode
      49             :  */
      50           0 : void tick_resume_oneshot(void)
      51             : {
      52           0 :         struct clock_event_device *dev = __this_cpu_read(tick_cpu_device.evtdev);
      53             : 
      54           0 :         clockevents_switch_state(dev, CLOCK_EVT_STATE_ONESHOT);
      55           0 :         clockevents_program_event(dev, ktime_get(), true);
      56           0 : }
      57             : 
      58             : /**
      59             :  * tick_setup_oneshot - setup the event device for oneshot mode (hres or nohz)
      60             :  */
      61           0 : void tick_setup_oneshot(struct clock_event_device *newdev,
      62             :                         void (*handler)(struct clock_event_device *),
      63             :                         ktime_t next_event)
      64             : {
      65           0 :         newdev->event_handler = handler;
      66           0 :         clockevents_switch_state(newdev, CLOCK_EVT_STATE_ONESHOT);
      67           0 :         clockevents_program_event(newdev, next_event, true);
      68           0 : }
      69             : 
      70             : /**
      71             :  * tick_switch_to_oneshot - switch to oneshot mode
      72             :  */
      73           4 : int tick_switch_to_oneshot(void (*handler)(struct clock_event_device *))
      74             : {
      75           4 :         struct tick_device *td = this_cpu_ptr(&tick_cpu_device);
      76           4 :         struct clock_event_device *dev = td->evtdev;
      77             : 
      78           4 :         if (!dev || !(dev->features & CLOCK_EVT_FEAT_ONESHOT) ||
      79           4 :                     !tick_device_is_functional(dev)) {
      80             : 
      81           0 :                 pr_info("Clockevents: could not switch to one-shot mode:");
      82           0 :                 if (!dev) {
      83           0 :                         pr_cont(" no tick device\n");
      84             :                 } else {
      85           0 :                         if (!tick_device_is_functional(dev))
      86           0 :                                 pr_cont(" %s is not functional.\n", dev->name);
      87             :                         else
      88           0 :                                 pr_cont(" %s does not support one-shot mode.\n",
      89             :                                         dev->name);
      90             :                 }
      91           0 :                 return -EINVAL;
      92             :         }
      93             : 
      94           4 :         td->mode = TICKDEV_MODE_ONESHOT;
      95           4 :         dev->event_handler = handler;
      96           4 :         clockevents_switch_state(dev, CLOCK_EVT_STATE_ONESHOT);
      97           4 :         tick_broadcast_switch_to_oneshot();
      98           4 :         return 0;
      99             : }
     100             : 
     101             : /**
     102             :  * tick_check_oneshot_mode - check whether the system is in oneshot mode
     103             :  *
     104             :  * returns 1 when either nohz or highres are enabled. otherwise 0.
     105             :  */
     106           6 : int tick_oneshot_mode_active(void)
     107             : {
     108           6 :         unsigned long flags;
     109           6 :         int ret;
     110             : 
     111          12 :         local_irq_save(flags);
     112           6 :         ret = __this_cpu_read(tick_cpu_device.mode) == TICKDEV_MODE_ONESHOT;
     113           6 :         local_irq_restore(flags);
     114             : 
     115           6 :         return ret;
     116             : }
     117             : 
     118             : #ifdef CONFIG_HIGH_RES_TIMERS
     119             : /**
     120             :  * tick_init_highres - switch to high resolution mode
     121             :  *
     122             :  * Called with interrupts disabled.
     123             :  */
     124             : int tick_init_highres(void)
     125             : {
     126             :         return tick_switch_to_oneshot(hrtimer_interrupt);
     127             : }
     128             : #endif

Generated by: LCOV version 1.14