diff options
author | Thomas Haller <thaller@redhat.com> | 2022-12-16 18:11:33 +0100 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2023-11-22 16:28:07 +0100 |
commit | 7bdb606a919ced712d2d300861565090299c099e (patch) | |
tree | 981c950c938d3b5c57c2e29be19681bd2b1237b9 | |
parent | 9f1d4b650c46e99eb8ad4d36788595d26d3840e0 (diff) |
l3cfg: make nm_l3_config_data_cmp_full() thread-safe
Let's not have unexpected, non-thread-safe functions somewhere deep down.
NML3ConfigData -- as a data structure -- is not thread-safe, nor aims it to
be. However, our code(!) should be thread-safe. That means, it should be
possible to call our code on separate data from multiple threads.
Violating that is a code smell and a foot gun.
This basically means that code should not access global data (unless
thread-local) or that the access to global-data needs to be
synchronized.
-rw-r--r-- | src/core/nm-l3-config-data.c | 17 |
1 files changed, 12 insertions, 5 deletions
diff --git a/src/core/nm-l3-config-data.c b/src/core/nm-l3-config-data.c index 347332933a..cccb23a60b 100644 --- a/src/core/nm-l3-config-data.c +++ b/src/core/nm-l3-config-data.c @@ -2231,14 +2231,21 @@ static const NML3ConfigData * get_empty_l3cd(void) { static NML3ConfigData *empty_l3cd; + NML3ConfigData *l3cd; - if (!empty_l3cd) { - empty_l3cd = - nm_l3_config_data_new(nm_dedup_multi_index_new(), 1, NM_IP_CONFIG_SOURCE_UNKNOWN); - empty_l3cd->ifindex = 0; +again: + l3cd = g_atomic_pointer_get(&empty_l3cd); + if (G_UNLIKELY(!l3cd)) { + l3cd = nm_l3_config_data_new(nm_dedup_multi_index_new(), 1, NM_IP_CONFIG_SOURCE_UNKNOWN); + l3cd->ifindex = 0; + + if (!g_atomic_pointer_compare_and_exchange(&empty_l3cd, NULL, l3cd)) { + nm_l3_config_data_unref(l3cd); + goto again; + } } - return empty_l3cd; + return l3cd; } int |