LCOV - code coverage report
Current view: top level - lib - once.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 35 0.0 %
Date: 2023-07-19 18:55:55 Functions: 0 6 0.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : #include <linux/slab.h>
       3             : #include <linux/spinlock.h>
       4             : #include <linux/once.h>
       5             : #include <linux/random.h>
       6             : #include <linux/module.h>
       7             : 
       8             : struct once_work {
       9             :         struct work_struct work;
      10             :         struct static_key_true *key;
      11             :         struct module *module;
      12             : };
      13             : 
      14           0 : static void once_deferred(struct work_struct *w)
      15             : {
      16             :         struct once_work *work;
      17             : 
      18           0 :         work = container_of(w, struct once_work, work);
      19           0 :         BUG_ON(!static_key_enabled(work->key));
      20           0 :         static_branch_disable(work->key);
      21           0 :         module_put(work->module);
      22           0 :         kfree(work);
      23           0 : }
      24             : 
      25           0 : static void once_disable_jump(struct static_key_true *key, struct module *mod)
      26             : {
      27             :         struct once_work *w;
      28             : 
      29           0 :         w = kmalloc(sizeof(*w), GFP_ATOMIC);
      30           0 :         if (!w)
      31             :                 return;
      32             : 
      33           0 :         INIT_WORK(&w->work, once_deferred);
      34           0 :         w->key = key;
      35           0 :         w->module = mod;
      36           0 :         __module_get(mod);
      37           0 :         schedule_work(&w->work);
      38             : }
      39             : 
      40             : static DEFINE_SPINLOCK(once_lock);
      41             : 
      42           0 : bool __do_once_start(bool *done, unsigned long *flags)
      43             :         __acquires(once_lock)
      44             : {
      45           0 :         spin_lock_irqsave(&once_lock, *flags);
      46           0 :         if (*done) {
      47           0 :                 spin_unlock_irqrestore(&once_lock, *flags);
      48             :                 /* Keep sparse happy by restoring an even lock count on
      49             :                  * this lock. In case we return here, we don't call into
      50             :                  * __do_once_done but return early in the DO_ONCE() macro.
      51             :                  */
      52             :                 __acquire(once_lock);
      53           0 :                 return false;
      54             :         }
      55             : 
      56             :         return true;
      57             : }
      58             : EXPORT_SYMBOL(__do_once_start);
      59             : 
      60           0 : void __do_once_done(bool *done, struct static_key_true *once_key,
      61             :                     unsigned long *flags, struct module *mod)
      62             :         __releases(once_lock)
      63             : {
      64           0 :         *done = true;
      65           0 :         spin_unlock_irqrestore(&once_lock, *flags);
      66           0 :         once_disable_jump(once_key, mod);
      67           0 : }
      68             : EXPORT_SYMBOL(__do_once_done);
      69             : 
      70             : static DEFINE_MUTEX(once_mutex);
      71             : 
      72           0 : bool __do_once_sleepable_start(bool *done)
      73             :         __acquires(once_mutex)
      74             : {
      75           0 :         mutex_lock(&once_mutex);
      76           0 :         if (*done) {
      77           0 :                 mutex_unlock(&once_mutex);
      78             :                 /* Keep sparse happy by restoring an even lock count on
      79             :                  * this mutex. In case we return here, we don't call into
      80             :                  * __do_once_done but return early in the DO_ONCE_SLEEPABLE() macro.
      81             :                  */
      82             :                 __acquire(once_mutex);
      83           0 :                 return false;
      84             :         }
      85             : 
      86             :         return true;
      87             : }
      88             : EXPORT_SYMBOL(__do_once_sleepable_start);
      89             : 
      90           0 : void __do_once_sleepable_done(bool *done, struct static_key_true *once_key,
      91             :                          struct module *mod)
      92             :         __releases(once_mutex)
      93             : {
      94           0 :         *done = true;
      95           0 :         mutex_unlock(&once_mutex);
      96           0 :         once_disable_jump(once_key, mod);
      97           0 : }
      98             : EXPORT_SYMBOL(__do_once_sleepable_done);

Generated by: LCOV version 1.14