| 1 | #ifndef _LINUX_CALL_ONCE_H | 
|---|
| 2 | #define _LINUX_CALL_ONCE_H | 
|---|
| 3 |  | 
|---|
| 4 | #include <linux/types.h> | 
|---|
| 5 | #include <linux/mutex.h> | 
|---|
| 6 |  | 
|---|
| 7 | #define ONCE_NOT_STARTED 0 | 
|---|
| 8 | #define ONCE_RUNNING     1 | 
|---|
| 9 | #define ONCE_COMPLETED   2 | 
|---|
| 10 |  | 
|---|
| 11 | struct once { | 
|---|
| 12 | atomic_t state; | 
|---|
| 13 | struct mutex lock; | 
|---|
| 14 | }; | 
|---|
| 15 |  | 
|---|
| 16 | static inline void __once_init(struct once *once, const char *name, | 
|---|
| 17 | struct lock_class_key *key) | 
|---|
| 18 | { | 
|---|
| 19 | atomic_set(v: &once->state, ONCE_NOT_STARTED); | 
|---|
| 20 | __mutex_init(lock: &once->lock, name, key); | 
|---|
| 21 | } | 
|---|
| 22 |  | 
|---|
| 23 | #define once_init(once)							\ | 
|---|
| 24 | do {									\ | 
|---|
| 25 | static struct lock_class_key __key;				\ | 
|---|
| 26 | __once_init((once), #once, &__key);				\ | 
|---|
| 27 | } while (0) | 
|---|
| 28 |  | 
|---|
| 29 | /* | 
|---|
| 30 | * call_once - Ensure a function has been called exactly once | 
|---|
| 31 | * | 
|---|
| 32 | * @once: Tracking struct | 
|---|
| 33 | * @cb: Function to be called | 
|---|
| 34 | * | 
|---|
| 35 | * If @once has never completed successfully before, call @cb and, if | 
|---|
| 36 | * it returns a zero or positive value, mark @once as completed.  Return | 
|---|
| 37 | * the value returned by @cb | 
|---|
| 38 | * | 
|---|
| 39 | * If @once has completed succesfully before, return 0. | 
|---|
| 40 | * | 
|---|
| 41 | * The call to @cb is implicitly surrounded by a mutex, though for | 
|---|
| 42 | * efficiency the * function avoids taking it after the first call. | 
|---|
| 43 | */ | 
|---|
| 44 | static inline int call_once(struct once *once, int (*cb)(struct once *)) | 
|---|
| 45 | { | 
|---|
| 46 | int r, state; | 
|---|
| 47 |  | 
|---|
| 48 | /* Pairs with atomic_set_release() below.  */ | 
|---|
| 49 | if (atomic_read_acquire(v: &once->state) == ONCE_COMPLETED) | 
|---|
| 50 | return 0; | 
|---|
| 51 |  | 
|---|
| 52 | guard(mutex)(T: &once->lock); | 
|---|
| 53 | state = atomic_read(v: &once->state); | 
|---|
| 54 | if (unlikely(state != ONCE_NOT_STARTED)) | 
|---|
| 55 | return WARN_ON_ONCE(state != ONCE_COMPLETED) ? -EINVAL : 0; | 
|---|
| 56 |  | 
|---|
| 57 | atomic_set(v: &once->state, ONCE_RUNNING); | 
|---|
| 58 | r = cb(once); | 
|---|
| 59 | if (r < 0) | 
|---|
| 60 | atomic_set(v: &once->state, ONCE_NOT_STARTED); | 
|---|
| 61 | else | 
|---|
| 62 | atomic_set_release(v: &once->state, ONCE_COMPLETED); | 
|---|
| 63 | return r; | 
|---|
| 64 | } | 
|---|
| 65 |  | 
|---|
| 66 | #endif /* _LINUX_CALL_ONCE_H */ | 
|---|
| 67 |  | 
|---|