xref: /aosp_15_r20/external/mesa3d/src/util/u_call_once.h (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright 2022 Yonggang Luo
3*61046927SAndroid Build Coastguard Worker  * SPDX-License-Identifier: MIT
4*61046927SAndroid Build Coastguard Worker  *
5*61046927SAndroid Build Coastguard Worker  * Extend C11 call_once to support context parameter
6*61046927SAndroid Build Coastguard Worker  */
7*61046927SAndroid Build Coastguard Worker 
8*61046927SAndroid Build Coastguard Worker #ifndef U_CALL_ONCE_H_
9*61046927SAndroid Build Coastguard Worker #define U_CALL_ONCE_H_
10*61046927SAndroid Build Coastguard Worker 
11*61046927SAndroid Build Coastguard Worker #include <stdbool.h>
12*61046927SAndroid Build Coastguard Worker 
13*61046927SAndroid Build Coastguard Worker #include "c11/threads.h"
14*61046927SAndroid Build Coastguard Worker #include "macros.h"
15*61046927SAndroid Build Coastguard Worker #include "u_atomic.h"
16*61046927SAndroid Build Coastguard Worker 
17*61046927SAndroid Build Coastguard Worker #ifdef __cplusplus
18*61046927SAndroid Build Coastguard Worker extern "C" {
19*61046927SAndroid Build Coastguard Worker #endif
20*61046927SAndroid Build Coastguard Worker 
21*61046927SAndroid Build Coastguard Worker /* The data can be mutable or immutable. */
22*61046927SAndroid Build Coastguard Worker typedef void (*util_call_once_data_func)(const void *data);
23*61046927SAndroid Build Coastguard Worker 
24*61046927SAndroid Build Coastguard Worker struct util_once_flag {
25*61046927SAndroid Build Coastguard Worker    bool called;
26*61046927SAndroid Build Coastguard Worker    once_flag flag;
27*61046927SAndroid Build Coastguard Worker };
28*61046927SAndroid Build Coastguard Worker typedef struct util_once_flag util_once_flag;
29*61046927SAndroid Build Coastguard Worker 
30*61046927SAndroid Build Coastguard Worker #define UTIL_ONCE_FLAG_INIT { false, ONCE_FLAG_INIT }
31*61046927SAndroid Build Coastguard Worker 
32*61046927SAndroid Build Coastguard Worker /**
33*61046927SAndroid Build Coastguard Worker  * This is used to optimize the call to call_once out when the func are
34*61046927SAndroid Build Coastguard Worker  * already called and finished, so when util_call_once are called in
35*61046927SAndroid Build Coastguard Worker  * hot path it's only incur an extra load instruction cost.
36*61046927SAndroid Build Coastguard Worker  */
37*61046927SAndroid Build Coastguard Worker static ALWAYS_INLINE void
util_call_once(util_once_flag * flag,void (* func)(void))38*61046927SAndroid Build Coastguard Worker util_call_once(util_once_flag *flag, void (*func)(void))
39*61046927SAndroid Build Coastguard Worker {
40*61046927SAndroid Build Coastguard Worker    if (unlikely(!p_atomic_read_relaxed(&flag->called))) {
41*61046927SAndroid Build Coastguard Worker       call_once(&flag->flag, func);
42*61046927SAndroid Build Coastguard Worker       p_atomic_set(&flag->called, true);
43*61046927SAndroid Build Coastguard Worker    }
44*61046927SAndroid Build Coastguard Worker }
45*61046927SAndroid Build Coastguard Worker 
46*61046927SAndroid Build Coastguard Worker /**
47*61046927SAndroid Build Coastguard Worker  * @brief Wrapper around call_once to pass data to func
48*61046927SAndroid Build Coastguard Worker  */
49*61046927SAndroid Build Coastguard Worker void
50*61046927SAndroid Build Coastguard Worker util_call_once_data_slow(once_flag *once, util_call_once_data_func func, const void *data);
51*61046927SAndroid Build Coastguard Worker 
52*61046927SAndroid Build Coastguard Worker /**
53*61046927SAndroid Build Coastguard Worker  * This is used to optimize the call to util_call_once_data_slow out when
54*61046927SAndroid Build Coastguard Worker  * the func function are already called and finished,
55*61046927SAndroid Build Coastguard Worker  * so when util_call_once_data are called in hot path it's only incur an extra
56*61046927SAndroid Build Coastguard Worker  * load instruction cost.
57*61046927SAndroid Build Coastguard Worker  */
58*61046927SAndroid Build Coastguard Worker static ALWAYS_INLINE void
util_call_once_data(util_once_flag * flag,util_call_once_data_func func,const void * data)59*61046927SAndroid Build Coastguard Worker util_call_once_data(util_once_flag *flag, util_call_once_data_func func, const void *data)
60*61046927SAndroid Build Coastguard Worker {
61*61046927SAndroid Build Coastguard Worker    if (unlikely(!p_atomic_read_relaxed(&flag->called))) {
62*61046927SAndroid Build Coastguard Worker       util_call_once_data_slow(&(flag->flag), func, data);
63*61046927SAndroid Build Coastguard Worker       p_atomic_set(&flag->called, true);
64*61046927SAndroid Build Coastguard Worker    }
65*61046927SAndroid Build Coastguard Worker }
66*61046927SAndroid Build Coastguard Worker 
67*61046927SAndroid Build Coastguard Worker #ifdef __cplusplus
68*61046927SAndroid Build Coastguard Worker }
69*61046927SAndroid Build Coastguard Worker #endif
70*61046927SAndroid Build Coastguard Worker 
71*61046927SAndroid Build Coastguard Worker #endif /* U_CALL_ONCE_H_ */
72