summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2022-12-16 18:11:33 +0100
committerThomas Haller <thaller@redhat.com>2023-11-22 16:28:07 +0100
commit7bdb606a919ced712d2d300861565090299c099e (patch)
tree981c950c938d3b5c57c2e29be19681bd2b1237b9
parent9f1d4b650c46e99eb8ad4d36788595d26d3840e0 (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.c17
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