LCOV - code coverage report
Current view: top level - kernel/time - tick-oneshot.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 27 44 61.4 %
Date: 2022-04-01 14:17:54 Functions: 4 6 66.7 %
Branches: 9 16 56.2 %

           Branch data     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                 :      21898 : int tick_program_event(ktime_t expires, int force)
      24                 :            : {
      25         [ +  + ]:      21898 :         struct clock_event_device *dev = __this_cpu_read(tick_cpu_device.evtdev);
      26                 :            : 
      27         [ +  + ]:      21898 :         if (unlikely(expires == KTIME_MAX)) {
      28                 :            :                 /*
      29                 :            :                  * We don't need the clock event device any more, stop it.
      30                 :            :                  */
      31                 :        195 :                 clockevents_switch_state(dev, CLOCK_EVT_STATE_ONESHOT_STOPPED);
      32                 :        195 :                 dev->next_event = KTIME_MAX;
      33                 :        195 :                 return 0;
      34                 :            :         }
      35                 :            : 
      36         [ +  + ]:      21703 :         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                 :        195 :                 clockevents_switch_state(dev, CLOCK_EVT_STATE_ONESHOT);
      42                 :            :         }
      43                 :            : 
      44                 :      21703 :         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                 :         11 : int tick_switch_to_oneshot(void (*handler)(struct clock_event_device *))
      74                 :            : {
      75                 :         11 :         struct tick_device *td = this_cpu_ptr(&tick_cpu_device);
      76                 :         11 :         struct clock_event_device *dev = td->evtdev;
      77                 :            : 
      78   [ +  -  +  -  :         11 :         if (!dev || !(dev->features & CLOCK_EVT_FEAT_ONESHOT) ||
                   -  + ]
      79                 :            :                     !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                 :         11 :         td->mode = TICKDEV_MODE_ONESHOT;
      95                 :         11 :         dev->event_handler = handler;
      96                 :         11 :         clockevents_switch_state(dev, CLOCK_EVT_STATE_ONESHOT);
      97                 :         11 :         tick_broadcast_switch_to_oneshot();
      98                 :         11 :         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                 :         88 : int tick_oneshot_mode_active(void)
     107                 :            : {
     108                 :         88 :         unsigned long flags;
     109                 :         88 :         int ret;
     110                 :            : 
     111                 :         88 :         local_irq_save(flags);
     112                 :         88 :         ret = __this_cpu_read(tick_cpu_device.mode) == TICKDEV_MODE_ONESHOT;
     113                 :         88 :         local_irq_restore(flags);
     114                 :            : 
     115                 :         88 :         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                 :         11 : int tick_init_highres(void)
     125                 :            : {
     126                 :         11 :         return tick_switch_to_oneshot(hrtimer_interrupt);
     127                 :            : }
     128                 :            : #endif

Generated by: LCOV version 1.14