xref: /linux-6.15/include/linux/call_once.h (revision f0ada00a)
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(&once->state, ONCE_NOT_STARTED);
20         __mutex_init(&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 static inline void call_once(struct once *once, void (*cb)(struct once *))
30 {
31         /* Pairs with atomic_set_release() below.  */
32         if (atomic_read_acquire(&once->state) == ONCE_COMPLETED)
33                 return;
34 
35         guard(mutex)(&once->lock);
36         WARN_ON(atomic_read(&once->state) == ONCE_RUNNING);
37         if (atomic_read(&once->state) != ONCE_NOT_STARTED)
38                 return;
39 
40         atomic_set(&once->state, ONCE_RUNNING);
41         cb(once);
42         atomic_set_release(&once->state, ONCE_COMPLETED);
43 }
44 
45 #endif /* _LINUX_CALL_ONCE_H */
46