[vlc-commits] [Git][videolan/vlc][master] 8 commits: rcu: add initial RCU implementation and docs
Rémi Denis-Courmont (@Courmisch)
gitlab at videolan.org
Tue Nov 30 13:27:29 UTC 2021
Rémi Denis-Courmont pushed to branch master at VideoLAN / VLC
Commits:
e2649592 by Rémi Denis-Courmont at 2021-11-30T13:10:36+00:00
rcu: add initial RCU implementation and docs
See built-in Doxygen for details.
- - - - -
e8700cbd by Rémi Denis-Courmont at 2021-11-30T13:10:36+00:00
messages: remove bogus assignment
- - - - -
fc91bb73 by Rémi Denis-Courmont at 2021-11-30T13:10:36+00:00
messages: use RCU for switching log backend
...instead of read-write lock. This provides for lock-free wait-free
log output, which is orders of magnitude more frequent than switching
log backend.
- - - - -
6911b612 by Rémi Denis-Courmont at 2021-11-30T13:10:36+00:00
config: factor string item setter
This factors the common code to set a string variable value. This also
makes the handling of the empty string consistent across all paths.
- - - - -
51366d08 by Rémi Denis-Courmont at 2021-11-30T13:10:36+00:00
config: simplify expressions
No functional changes.
- - - - -
05d1bc33 by Rémi Denis-Courmont at 2021-11-30T13:10:36+00:00
config: use RCU for string items
This makes config_GetStr() lock-less.
- - - - -
f57ddf14 by Rémi Denis-Courmont at 2021-11-30T13:10:36+00:00
config: remove dead code
- - - - -
dbbe239f by Rémi Denis-Courmont at 2021-11-30T13:10:36+00:00
config: convert R/W lock to mutex
The lock is no longer taken for reading ever, so it is equivalent to a
mutex. In fact, the lock is only needed to prevent concurrent writes
to the same config_item_t::value.
- - - - -
9 changed files:
- src/Makefile.am
- src/config/configuration.h
- src/config/core.c
- src/config/file.c
- src/misc/messages.c
- + src/misc/rcu.c
- + src/misc/rcu.h
- src/modules/cache.c
- src/modules/entry.c
Changes:
=====================================
src/Makefile.am
=====================================
@@ -371,6 +371,8 @@ libvlccore_la_SOURCES = \
misc/interrupt.h \
misc/interrupt.c \
misc/keystore.c \
+ misc/rcu.h \
+ misc/rcu.c \
misc/renderer_discovery.c \
misc/threads.c \
misc/cpu.c \
=====================================
src/config/configuration.h
=====================================
@@ -29,6 +29,7 @@ struct vlc_param {
union {
_Atomic int64_t i; /**< Current value (if integer or boolean) */
_Atomic float f; /**< Current value (if floating point) */
+ char *_Atomic str; /**< Current value (if character string) */
} value;
struct vlc_plugin_t *owner;
@@ -47,6 +48,8 @@ struct vlc_param {
*/
struct vlc_param *vlc_param_Find(const char *name);
+int vlc_param_SetString(struct vlc_param *param, const char *value);
+
int config_AutoSaveConfigFile( vlc_object_t * );
void config_Free(struct vlc_param *, size_t);
@@ -60,7 +63,7 @@ bool config_PrintHelp (vlc_object_t *);
int config_SortConfig (void);
void config_UnsortConfig (void);
-extern vlc_rwlock_t config_lock;
+extern vlc_mutex_t config_lock;
extern _Atomic bool config_dirty;
bool config_IsSafe (const char *);
=====================================
src/config/core.c
=====================================
@@ -37,8 +37,9 @@
#include "configuration.h"
#include "modules/modules.h"
+#include "misc/rcu.h"
-vlc_rwlock_t config_lock = VLC_STATIC_RWLOCK;
+vlc_mutex_t config_lock = VLC_STATIC_MUTEX;
atomic_bool config_dirty = ATOMIC_VAR_INIT(false);
static inline char *strdupnull (const char *src)
@@ -75,16 +76,6 @@ bool config_IsSafe( const char *name )
return (param != NULL) ? param->safe : false;
}
-static module_config_t * config_FindConfigChecked( const char *psz_name )
-{
- module_config_t *p_config = config_FindConfig( psz_name );
-#ifndef NDEBUG
- if (p_config == NULL)
- fprintf(stderr, "Unknown vlc configuration variable named %s\n", psz_name);
-#endif
- return p_config;
-}
-
int64_t config_GetInt(const char *name)
{
const struct vlc_param *param = vlc_param_Find(name);
@@ -107,43 +98,51 @@ float config_GetFloat(const char *name)
return atomic_load_explicit(¶m->value.f, memory_order_relaxed);
}
-char *config_GetPsz(const char *psz_name)
+char *config_GetPsz(const char *name)
{
- module_config_t *p_config = config_FindConfigChecked( psz_name );
+ const struct vlc_param *param = vlc_param_Find(name);
+ char *str;
/* sanity checks */
- assert(p_config != NULL);
- assert(IsConfigStringType (p_config->i_type));
+ assert(param != NULL);
+ assert(IsConfigStringType(param->item.i_type));
/* return a copy of the string */
- vlc_rwlock_rdlock (&config_lock);
- char *psz_value = strdupnull (p_config->value.psz);
- vlc_rwlock_unlock (&config_lock);
+ vlc_rcu_read_lock();
+ str = atomic_load_explicit(¶m->value.str, memory_order_acquire);
+ if (str != NULL)
+ str = strdup(str);
+ vlc_rcu_read_unlock();
+ return str;
+}
+
+int vlc_param_SetString(struct vlc_param *param, const char *value)
+{
+ char *str = NULL, *oldstr;
- return psz_value;
+ assert(param != NULL);
+ assert(IsConfigStringType(param->item.i_type));
+
+ if (value != NULL && value[0] != '\0') {
+ str = strdup(value);
+ if (unlikely(str == NULL))
+ return -1;
+ }
+
+ oldstr = atomic_load_explicit(¶m->value.str, memory_order_relaxed);
+ atomic_store_explicit(¶m->value.str, str, memory_order_release);
+ param->item.value.psz = str;
+ vlc_rcu_synchronize();
+ free(oldstr);
+ return 0;
}
void config_PutPsz(const char *psz_name, const char *psz_value)
{
- module_config_t *p_config = config_FindConfigChecked( psz_name );
-
- /* sanity checks */
- assert(p_config != NULL);
- assert(IsConfigStringType(p_config->i_type));
-
- char *str, *oldstr;
- if ((psz_value != NULL) && *psz_value)
- str = strdup (psz_value);
- else
- str = NULL;
-
- vlc_rwlock_wrlock (&config_lock);
- oldstr = (char *)p_config->value.psz;
- p_config->value.psz = str;
- vlc_rwlock_unlock (&config_lock);
+ vlc_mutex_lock(&config_lock);
+ vlc_param_SetString(vlc_param_Find(psz_name), psz_value);
+ vlc_mutex_unlock(&config_lock);
atomic_store_explicit(&config_dirty, true, memory_order_release);
-
- free (oldstr);
}
void config_PutInt(const char *name, int64_t i_value)
@@ -161,9 +160,9 @@ void config_PutInt(const char *name, int64_t i_value)
i_value = p_config->max.i;
atomic_store_explicit(¶m->value.i, i_value, memory_order_relaxed);
- vlc_rwlock_wrlock (&config_lock);
+ vlc_mutex_lock(&config_lock);
p_config->value.i = i_value;
- vlc_rwlock_unlock (&config_lock);
+ vlc_mutex_unlock(&config_lock);
atomic_store_explicit(&config_dirty, true, memory_order_release);
}
@@ -185,9 +184,9 @@ void config_PutFloat(const char *name, float f_value)
f_value = p_config->max.f;
atomic_store_explicit(¶m->value.f, f_value, memory_order_relaxed);
- vlc_rwlock_wrlock (&config_lock);
+ vlc_mutex_lock(&config_lock);
p_config->value.f = f_value;
- vlc_rwlock_unlock (&config_lock);
+ vlc_mutex_unlock(&config_lock);
atomic_store_explicit(&config_dirty, true, memory_order_release);
}
@@ -474,11 +473,13 @@ void config_Free(struct vlc_param *tab, size_t confsize)
{
for (size_t j = 0; j < confsize; j++)
{
- module_config_t *p_item = &tab[j].item;
+ struct vlc_param *param = &tab[j];
+ module_config_t *p_item = ¶m->item;
if (IsConfigStringType (p_item->i_type))
{
- free (p_item->value.psz);
+ free(atomic_load_explicit(¶m->value.str,
+ memory_order_relaxed));
if (p_item->list_count)
free (p_item->list.psz);
}
@@ -491,7 +492,7 @@ void config_Free(struct vlc_param *tab, size_t confsize)
void config_ResetAll(void)
{
- vlc_rwlock_wrlock (&config_lock);
+ vlc_mutex_lock(&config_lock);
for (vlc_plugin_t *p = vlc_plugins; p != NULL; p = p->next)
{
for (size_t i = 0; i < p->conf.size; i++ )
@@ -514,13 +515,9 @@ void config_ResetAll(void)
}
else
if (IsConfigStringType (p_config->i_type))
- {
- free ((char *)p_config->value.psz);
- p_config->value.psz =
- strdupnull (p_config->orig.psz);
- }
+ vlc_param_SetString(param, p_config->orig.psz);
}
}
- vlc_rwlock_unlock (&config_lock);
+ vlc_mutex_lock(&config_lock);
atomic_store_explicit(&config_dirty, true, memory_order_release);
}
=====================================
src/config/file.c
=====================================
@@ -47,6 +47,7 @@
#include "configuration.h"
#include "modules/modules.h"
+#include "misc/rcu.h"
static inline char *strdupnull (const char *src)
{
@@ -185,7 +186,7 @@ int config_LoadConfigFile( vlc_object_t *p_this )
locale_t loc = newlocale (LC_NUMERIC_MASK, "C", NULL);
locale_t baseloc = uselocale (loc);
- vlc_rwlock_wrlock (&config_lock);
+ vlc_mutex_lock(&config_lock);
while ((linelen = getline (&line, &bufsize, file)) != -1)
{
line[linelen - 1] = '\0'; /* trim newline */
@@ -252,12 +253,11 @@ int config_LoadConfigFile( vlc_object_t *p_this )
}
default:
- free (item->value.psz);
- item->value.psz = strdupnull (psz_option_value);
+ vlc_param_SetString(param, psz_option_value);
break;
}
}
- vlc_rwlock_unlock (&config_lock);
+ vlc_mutex_unlock(&config_lock);
free (line);
if (ferror (file))
@@ -391,9 +391,6 @@ int config_SaveConfigFile (vlc_object_t *p_this)
}
}
- /* Configuration lock must be taken before vlcrc serializer below. */
- vlc_rwlock_rdlock (&config_lock);
-
/* The temporary configuration file is per-PID. Therefore this function
* should be serialized against itself within a given process. */
static vlc_mutex_t lock = VLC_STATIC_MUTEX;
@@ -402,7 +399,6 @@ int config_SaveConfigFile (vlc_object_t *p_this)
int fd = vlc_open (temporary, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR|S_IWUSR);
if (fd == -1)
{
- vlc_rwlock_unlock (&config_lock);
vlc_mutex_unlock (&lock);
goto error;
}
@@ -411,7 +407,6 @@ int config_SaveConfigFile (vlc_object_t *p_this)
{
msg_Err (p_this, "cannot create configuration file: %s",
vlc_strerror_c(errno));
- vlc_rwlock_unlock (&config_lock);
vlc_close (fd);
vlc_mutex_unlock (&lock);
goto error;
@@ -431,9 +426,7 @@ int config_SaveConfigFile (vlc_object_t *p_this)
locale_t loc = newlocale (LC_NUMERIC_MASK, "C", NULL);
locale_t baseloc = uselocale (loc);
- /* We would take the config lock here. But this would cause a lock
- * inversion with the serializer above and config_AutoSaveConfigFile().
- vlc_rwlock_rdlock (&config_lock);*/
+ vlc_rcu_read_lock(); /* preserve string values */
/* Look for the selected module, if NULL then save everything */
for (vlc_plugin_t *p = vlc_plugins; p != NULL; p = p->next)
@@ -482,20 +475,23 @@ int config_SaveConfigFile (vlc_object_t *p_this)
}
else
{
- const char *psz_value = p_item->value.psz;
- bool modified;
-
- assert (IsConfigStringType (p_item->i_type));
-
- modified = !!strcmp (psz_value ? psz_value : "",
- p_item->orig.psz ? p_item->orig.psz : "");
- config_Write (file, p_item->psz_text, N_("string"),
- !modified, p_item->psz_name, "%s",
- psz_value ? psz_value : "");
+ const char *val = atomic_load_explicit(¶m->value.str,
+ memory_order_relaxed);
+ const char *orig = p_item->orig.psz;
+
+ if (val == NULL)
+ val = "";
+ if (orig == NULL)
+ orig = "";
+
+ assert(IsConfigStringType(p_item->i_type));
+ config_Write(file, p_item->psz_text, N_("string"),
+ strcmp(val, orig) == 0, p_item->psz_name, "%s",
+ val);
}
}
}
- vlc_rwlock_unlock (&config_lock);
+ vlc_rcu_read_unlock();
if (loc != (locale_t)0)
{
=====================================
src/misc/messages.c
=====================================
@@ -40,6 +40,7 @@
#include <vlc_interface.h>
#include <vlc_charset.h>
#include <vlc_modules.h>
+#include "rcu.h"
#include "../libvlc.h"
static void vlc_LogSpam(vlc_object_t *obj)
@@ -303,9 +304,8 @@ static struct vlc_logger discard_log = { &discard_ops };
* A message log that can be redirected live.
*/
struct vlc_logger_switch {
- struct vlc_logger *backend;
+ struct vlc_logger *_Atomic backend;
struct vlc_logger frontend;
- vlc_rwlock_t lock;
};
static void vlc_vaLogSwitch(void *d, int type, const vlc_log_t *item,
@@ -316,10 +316,10 @@ static void vlc_vaLogSwitch(void *d, int type, const vlc_log_t *item,
container_of(logger, struct vlc_logger_switch, frontend);
struct vlc_logger *backend;
- vlc_rwlock_rdlock(&logswitch->lock);
- backend = logswitch->backend;
+ vlc_rcu_read_lock();
+ backend = atomic_load_explicit(&logswitch->backend, memory_order_acquire);
backend->ops->log(backend, type, item, format, ap);
- vlc_rwlock_unlock(&logswitch->lock);
+ vlc_rcu_read_unlock();
}
static void vlc_LogSwitchClose(void *d)
@@ -327,11 +327,10 @@ static void vlc_LogSwitchClose(void *d)
struct vlc_logger *logger = d;
struct vlc_logger_switch *logswitch =
container_of(logger, struct vlc_logger_switch, frontend);
- struct vlc_logger *backend = logswitch->backend;
+ struct vlc_logger *backend = atomic_load_explicit(&logswitch->backend,
+ memory_order_relaxed);
- logswitch->backend = &discard_log;
backend->ops->destroy(backend);
-
free(logswitch);
}
@@ -351,11 +350,9 @@ static void vlc_LogSwitch(vlc_logger_t *logger, vlc_logger_t *new_logger)
if (new_logger == NULL)
new_logger = &discard_log;
- vlc_rwlock_wrlock(&logswitch->lock);
- old_logger = logswitch->backend;
- logswitch->backend = new_logger;
- vlc_rwlock_unlock(&logswitch->lock);
-
+ old_logger = atomic_exchange_explicit(&logswitch->backend, new_logger,
+ memory_order_acq_rel);
+ vlc_rcu_synchronize();
old_logger->ops->destroy(old_logger);
}
@@ -366,8 +363,7 @@ static struct vlc_logger *vlc_LogSwitchCreate(void)
return NULL;
logswitch->frontend.ops = &switch_ops;
- logswitch->backend = &discard_log;
- vlc_rwlock_init(&logswitch->lock);
+ atomic_init(&logswitch->backend, &discard_log);
return &logswitch->frontend;
}
=====================================
src/misc/rcu.c
=====================================
@@ -0,0 +1,119 @@
+/**
+ * \file rcu.c Read-Copy-Update (RCU) definitions
+ * \ingroup rcu
+ */
+/*****************************************************************************
+ * Copyright © 2021 Rémi Denis-Courmont
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <stdint.h>
+#include <vlc_common.h>
+#include <vlc_atomic.h>
+#include "rcu.h"
+
+struct vlc_rcu_generation {
+ atomic_uintptr_t readers;
+ atomic_uint writer;
+};
+
+struct vlc_rcu_thread {
+ struct vlc_rcu_generation *generation;
+ uintptr_t recursion;
+};
+
+static _Thread_local struct vlc_rcu_thread current;
+
+bool vlc_rcu_read_held(void)
+{
+ const struct vlc_rcu_thread *const self = ¤t;
+
+ return self->recursion > 0;
+}
+
+static struct vlc_rcu_generation *_Atomic generation;
+
+void vlc_rcu_read_lock(void)
+{
+ struct vlc_rcu_thread *const self = ¤t;
+ struct vlc_rcu_generation *gen;
+
+ if (self->recursion++ > 0)
+ return; /* recursion: nothing to do */
+
+ assert(self->generation == NULL);
+ gen = atomic_load_explicit(&generation, memory_order_acquire);
+ self->generation = gen;
+ atomic_fetch_add_explicit(&gen->readers, 1, memory_order_relaxed);
+}
+
+void vlc_rcu_read_unlock(void)
+{
+ struct vlc_rcu_thread *const self = ¤t;
+ struct vlc_rcu_generation *gen;
+
+ assert(vlc_rcu_read_held());
+
+ if (--self->recursion > 0)
+ return; /* recursion: nothing to do */
+
+ gen = self->generation;
+ self->generation = NULL;
+
+ uintptr_t readers = atomic_fetch_sub_explicit(&gen->readers, 1,
+ memory_order_relaxed);
+ if (readers == 0)
+ vlc_assert_unreachable();
+ if (readers > 1)
+ return; /* Other reader threads remain: nothing to do */
+
+ if (unlikely(atomic_exchange_explicit(&gen->writer, 0,
+ memory_order_release)))
+ vlc_atomic_notify_one(&gen->writer); /* Last reader wakes writer up */
+}
+
+static vlc_mutex_t writer_lock = VLC_STATIC_MUTEX;
+static struct vlc_rcu_generation gens[2];
+static struct vlc_rcu_generation *_Atomic generation = &gens[0];
+
+void vlc_rcu_synchronize(void)
+{
+ struct vlc_rcu_generation *gen;
+ size_t idx;
+
+ assert(!vlc_rcu_read_held()); /* cannot wait for thyself */
+ vlc_mutex_lock(&writer_lock);
+
+ /* Start a new generation for (and synchronise with) future readers */
+ gen = atomic_load_explicit(&generation, memory_order_relaxed);
+ idx = gen - gens;
+ idx = (idx + 1) % ARRAY_SIZE(gens);
+ atomic_store_explicit(&generation, &gens[idx], memory_order_release);
+
+ /* Let old generation readers know that we are waiting for them. */
+ atomic_exchange_explicit(&gen->writer, 1, memory_order_acquire);
+
+ while (atomic_load_explicit(&gen->readers, memory_order_relaxed) > 0)
+ vlc_atomic_wait(&gen->writer, 1);
+
+ atomic_store_explicit(&gen->writer, 0, memory_order_relaxed);
+ vlc_mutex_unlock(&writer_lock);
+}
=====================================
src/misc/rcu.h
=====================================
@@ -0,0 +1,116 @@
+/**
+ * \file rcu.h Read-Copy-Update (RCU) declarations
+ * \ingroup rcu
+ */
+/*****************************************************************************
+ * Copyright © 2021 Rémi Denis-Courmont
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifndef VLC_RCU_H_
+#define VLC_RCU_H_
+
+#include <stdatomic.h>
+
+/**
+ * \defgroup rcu Read-Copy-Update synchronisation
+ * \ingroup threads
+ * The Read-Copy-Update (RCU) mechanism is a paradigm of memory synchronisation
+ * first popularised by the Linux kernel.
+ * It is essentially a mean to safely use atomic pointers, without encountering
+ * use-after-free and other lifecycle bugs.
+ *
+ * It is an advantageous substitute for
+ * the classic reader/writer lock with the following notable differences:
+ * - The read side is completely lock-free and wait-free.
+ * - The write side is guaranteed to make forward progress even if there are
+ * perpetually active readers, provided that all read sides are each
+ * individually finitely long.
+ * - The protected data consists of a single atomic object,
+ * typically an atomic pointer
+ * (not to be confused with a pointer to an atomic object).
+ * - There is no synchronisation object. RCU maintains its state globally,
+ * and with a modicum of per-thread state.
+ *
+ * The practical use of RCU differs from reader/writer lock in the following
+ * ways:
+ * - There is no synchronisation object, so there are no needs for
+ * initialisation and destruction.
+ * - The directly protected objects are atom, so they must be accessed with
+ * atomic type-generics. Specifically:
+ * - Objects are read with atomic load-acquire.
+ * - Objects are written with atomic store-release.
+ * - There are no writer lock and unlock functions. Instead there is a
+ * synchronisation function, vlc_rcu_synchronize(), which waits for all
+ * earlier read-side critical sections to complete.
+ * - Synchronisation between concurrent writers is not provided. If multiple
+ * writers can race against each other, a separate mutual exclusion lock
+ * for interlocking.
+ *
+ * @{
+ */
+
+/**
+ * Begins a read-side RCU critical section.
+ *
+ * This function marks the beginning of a read-side RCU critical section..
+ * For the duration of the critical section, RCU-protected data is guaranteed
+ * to remain valid, although it might be slightly stale.
+ *
+ * To access RCU-protect data, an atomic load-acquire should be used.
+ *
+ * \note Read-side RCU critical section can be nested.
+ */
+void vlc_rcu_read_lock(void);
+
+/**
+ * Ends a read-side RCU critical section.
+ *
+ * This function marks the end of a read-side RCU critical section. After this
+ * function is called, RCU-protected data may be destroyed and can no longer
+ * be accessed safely.
+ *
+ * \note In the case of nested critical sections, this function notionally ends
+ * the inner-most critical section. In practice, this makes no differences, as
+ * the calling thread remains in a critical section until the number of
+ * vlc_rcu_read_unlock() calls equals that of vlc_rcu_read_lock() calls.
+ */
+void vlc_rcu_read_unlock(void);
+
+/**
+ * Checks if the thread is in an read-side RCU critical section.
+ *
+ * This function checks if the thread is in a middle of one or more read-side
+ * RCU critical section(s). It has no side effects and is primarily meant for
+ * self-debugging.
+ *
+ * \retval true the calling thread is in a read-side RCU critical section.
+ * \retval false the calling thread is not in a read-side RCU critical section.
+ */
+VLC_USED
+bool vlc_rcu_read_held(void);
+
+/**
+ * Waits for completion of earlier read-side RCU critical section.
+ *
+ * This functions waits until all read-side RCU critical sections that had
+ * begun before to complete. Then it is safe to release resources associated
+ * with the earlier value(s) of any RCU-protected atomic object.
+ */
+void vlc_rcu_synchronize(void);
+
+/** @} */
+#endif /* !VLC_RCU_H_ */
=====================================
src/modules/cache.c
=====================================
@@ -200,7 +200,8 @@ static int vlc_cache_load_config(struct vlc_param *param, block_t *file)
const char *psz;
LOAD_STRING(psz);
cfg->orig.psz = (char *)psz;
- cfg->value.psz = (psz != NULL) ? strdup (cfg->orig.psz) : NULL;
+ atomic_init(¶m->value.str, NULL);
+ vlc_param_SetString(param, psz);
if (cfg->list_count)
cfg->list.psz = xmalloc (cfg->list_count * sizeof (char *));
=====================================
src/modules/entry.c
=====================================
@@ -169,6 +169,8 @@ static struct vlc_param *vlc_config_create(vlc_plugin_t *plugin, int type)
item->max.f = FLT_MAX;
item->min.f = -FLT_MAX;
}
+ else
+ atomic_init(¶m->value.str, NULL);
item->i_type = type;
if (CONFIG_ITEM(type))
@@ -347,8 +349,8 @@ static int vlc_plugin_desc_cb(void *ctx, void *tgt, int propid, ...)
if (IsConfigStringType (item->i_type))
{
const char *value = va_arg (ap, const char *);
- item->value.psz = value ? strdup (value) : NULL;
item->orig.psz = (char *)value;
+ vlc_param_SetString(param, value);
}
break;
}
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/3e47a7cb8bff9135e08c8ff6731fac0afe87facd...dbbe239ff36f2da9339a8f2a6198ca91284c9e55
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/3e47a7cb8bff9135e08c8ff6731fac0afe87facd...dbbe239ff36f2da9339a8f2a6198ca91284c9e55
You're receiving this email because of your account on code.videolan.org.
More information about the vlc-commits
mailing list