Blame view

lib/once.c 1.31 KB
46234253b   Hannes Frederic Sowa   net: move net_get...
1
2
3
4
  #include <linux/slab.h>
  #include <linux/spinlock.h>
  #include <linux/once.h>
  #include <linux/random.h>
c90aeb948   Hannes Frederic Sowa   once: make helper...
5
  struct once_work {
46234253b   Hannes Frederic Sowa   net: move net_get...
6
7
8
  	struct work_struct work;
  	struct static_key *key;
  };
c90aeb948   Hannes Frederic Sowa   once: make helper...
9
  static void once_deferred(struct work_struct *w)
46234253b   Hannes Frederic Sowa   net: move net_get...
10
  {
c90aeb948   Hannes Frederic Sowa   once: make helper...
11
  	struct once_work *work;
46234253b   Hannes Frederic Sowa   net: move net_get...
12

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

c90aeb948   Hannes Frederic Sowa   once: make helper...
31
32
33
34
  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...
35
  	if (*done) {
c90aeb948   Hannes Frederic Sowa   once: make helper...
36
37
38
39
40
41
  		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...
42
43
  		return false;
  	}
46234253b   Hannes Frederic Sowa   net: move net_get...
44
45
  	return true;
  }
c90aeb948   Hannes Frederic Sowa   once: make helper...
46
47
48
49
50
51
52
53
54
55
56
  EXPORT_SYMBOL(__do_once_start);
  
  void __do_once_done(bool *done, struct static_key *once_key,
  		    unsigned long *flags)
  	__releases(once_lock)
  {
  	*done = true;
  	spin_unlock_irqrestore(&once_lock, *flags);
  	once_disable_jump(once_key);
  }
  EXPORT_SYMBOL(__do_once_done);