Blame view

lib/once.c 1.36 KB
b24413180   Greg Kroah-Hartman   License cleanup: ...
1
  // SPDX-License-Identifier: GPL-2.0
46234253b   Hannes Frederic Sowa   net: move net_get...
2
3
4
5
  #include <linux/slab.h>
  #include <linux/spinlock.h>
  #include <linux/once.h>
  #include <linux/random.h>
c90aeb948   Hannes Frederic Sowa   once: make helper...
6
  struct once_work {
46234253b   Hannes Frederic Sowa   net: move net_get...
7
  	struct work_struct work;
cf4c950b8   Eric Biggers   once: switch to n...
8
  	struct static_key_true *key;
46234253b   Hannes Frederic Sowa   net: move net_get...
9
  };
c90aeb948   Hannes Frederic Sowa   once: make helper...
10
  static void once_deferred(struct work_struct *w)
46234253b   Hannes Frederic Sowa   net: move net_get...
11
  {
c90aeb948   Hannes Frederic Sowa   once: make helper...
12
  	struct once_work *work;
46234253b   Hannes Frederic Sowa   net: move net_get...
13

c90aeb948   Hannes Frederic Sowa   once: make helper...
14
  	work = container_of(w, struct once_work, work);
46234253b   Hannes Frederic Sowa   net: move net_get...
15
  	BUG_ON(!static_key_enabled(work->key));
cf4c950b8   Eric Biggers   once: switch to n...
16
  	static_branch_disable(work->key);
46234253b   Hannes Frederic Sowa   net: move net_get...
17
18
  	kfree(work);
  }
cf4c950b8   Eric Biggers   once: switch to n...
19
  static void once_disable_jump(struct static_key_true *key)
46234253b   Hannes Frederic Sowa   net: move net_get...
20
  {
c90aeb948   Hannes Frederic Sowa   once: make helper...
21
  	struct once_work *w;
46234253b   Hannes Frederic Sowa   net: move net_get...
22
23
24
25
  
  	w = kmalloc(sizeof(*w), GFP_ATOMIC);
  	if (!w)
  		return;
c90aeb948   Hannes Frederic Sowa   once: make helper...
26
  	INIT_WORK(&w->work, once_deferred);
46234253b   Hannes Frederic Sowa   net: move net_get...
27
28
29
  	w->key = key;
  	schedule_work(&w->work);
  }
c90aeb948   Hannes Frederic Sowa   once: make helper...
30
  static DEFINE_SPINLOCK(once_lock);
46234253b   Hannes Frederic Sowa   net: move net_get...
31

c90aeb948   Hannes Frederic Sowa   once: make helper...
32
33
34
35
  bool __do_once_start(bool *done, unsigned long *flags)
  	__acquires(once_lock)
  {
  	spin_lock_irqsave(&once_lock, *flags);
46234253b   Hannes Frederic Sowa   net: move net_get...
36
  	if (*done) {
c90aeb948   Hannes Frederic Sowa   once: make helper...
37
38
39
40
41
42
  		spin_unlock_irqrestore(&once_lock, *flags);
  		/* Keep sparse happy by restoring an even lock count on
  		 * this lock. In case we return here, we don't call into
  		 * __do_once_done but return early in the DO_ONCE() macro.
  		 */
  		__acquire(once_lock);
46234253b   Hannes Frederic Sowa   net: move net_get...
43
44
  		return false;
  	}
46234253b   Hannes Frederic Sowa   net: move net_get...
45
46
  	return true;
  }
c90aeb948   Hannes Frederic Sowa   once: make helper...
47
  EXPORT_SYMBOL(__do_once_start);
cf4c950b8   Eric Biggers   once: switch to n...
48
  void __do_once_done(bool *done, struct static_key_true *once_key,
c90aeb948   Hannes Frederic Sowa   once: make helper...
49
50
51
52
53
54
55
56
  		    unsigned long *flags)
  	__releases(once_lock)
  {
  	*done = true;
  	spin_unlock_irqrestore(&once_lock, *flags);
  	once_disable_jump(once_key);
  }
  EXPORT_SYMBOL(__do_once_done);