once.c 1.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. #include <linux/slab.h>
  2. #include <linux/spinlock.h>
  3. #include <linux/once.h>
  4. #include <linux/random.h>
  5. struct once_work {
  6. struct work_struct work;
  7. struct static_key *key;
  8. };
  9. static void once_deferred(struct work_struct *w)
  10. {
  11. struct once_work *work;
  12. work = container_of(w, struct once_work, work);
  13. BUG_ON(!static_key_enabled(work->key));
  14. static_key_slow_dec(work->key);
  15. kfree(work);
  16. }
  17. static void once_disable_jump(struct static_key *key)
  18. {
  19. struct once_work *w;
  20. w = kmalloc(sizeof(*w), GFP_ATOMIC);
  21. if (!w)
  22. return;
  23. INIT_WORK(&w->work, once_deferred);
  24. w->key = key;
  25. schedule_work(&w->work);
  26. }
  27. static DEFINE_SPINLOCK(once_lock);
  28. bool __do_once_start(bool *done, unsigned long *flags)
  29. __acquires(once_lock)
  30. {
  31. spin_lock_irqsave(&once_lock, *flags);
  32. if (*done) {
  33. spin_unlock_irqrestore(&once_lock, *flags);
  34. /* Keep sparse happy by restoring an even lock count on
  35. * this lock. In case we return here, we don't call into
  36. * __do_once_done but return early in the DO_ONCE() macro.
  37. */
  38. __acquire(once_lock);
  39. return false;
  40. }
  41. return true;
  42. }
  43. EXPORT_SYMBOL(__do_once_start);
  44. void __do_once_done(bool *done, struct static_key *once_key,
  45. unsigned long *flags)
  46. __releases(once_lock)
  47. {
  48. *done = true;
  49. spin_unlock_irqrestore(&once_lock, *flags);
  50. once_disable_jump(once_key);
  51. }
  52. EXPORT_SYMBOL(__do_once_done);