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>
9 struct work_struct work
;
10 struct static_key_true
*key
;
11 struct module
*module
;
14 static void once_deferred(struct work_struct
*w
)
16 struct once_work
*work
;
18 work
= container_of(w
, struct once_work
, work
);
19 BUG_ON(!static_key_enabled(work
->key
));
20 static_branch_disable(work
->key
);
21 module_put(work
->module
);
25 static void once_disable_jump(struct static_key_true
*key
, struct module
*mod
)
29 w
= kmalloc(sizeof(*w
), GFP_ATOMIC
);
33 INIT_WORK(&w
->work
, once_deferred
);
37 schedule_work(&w
->work
);
40 static DEFINE_SPINLOCK(once_lock
);
42 bool __do_once_start(bool *done
, unsigned long *flags
)
45 spin_lock_irqsave(&once_lock
, *flags
);
47 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.
58 EXPORT_SYMBOL(__do_once_start
);
60 void __do_once_done(bool *done
, struct static_key_true
*once_key
,
61 unsigned long *flags
, struct module
*mod
)
65 spin_unlock_irqrestore(&once_lock
, *flags
);
66 once_disable_jump(once_key
, mod
);
68 EXPORT_SYMBOL(__do_once_done
);
70 static DEFINE_MUTEX(once_mutex
);
72 bool __do_once_sleepable_start(bool *done
)
73 __acquires(once_mutex
)
75 mutex_lock(&once_mutex
);
77 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.
82 __acquire(once_mutex
);
88 EXPORT_SYMBOL(__do_once_sleepable_start
);
90 void __do_once_sleepable_done(bool *done
, struct static_key_true
*once_key
,
92 __releases(once_mutex
)
95 mutex_unlock(&once_mutex
);
96 once_disable_jump(once_key
, mod
);
98 EXPORT_SYMBOL(__do_once_sleepable_done
);