Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • videolan/vlc
  • chouquette/vlc
  • bakiewicz.marek122/vlc
  • devnexen/vlc
  • rohanrajpal/vlc
  • blurrrb/vlc
  • gsoc/gsoc2019/darkapex/vlc
  • b1ue/vlc
  • fkuehne/vlc
  • magsoft/vlc
  • chub/vlc
  • cramiro9/vlc
  • robUx4/vlc
  • rom1v/vlc
  • akshayaky/vlc
  • tmk907/vlc
  • akymaster/vlc
  • govind.sharma/vlc
  • psilokos/vlc
  • xjbeta/vlc
  • jahan/vlc
  • 1480c1/vlc
  • amanchande/vlc
  • aaqib/vlc
  • rist/vlc
  • apol/vlc
  • mindfreeze/vlc
  • alexandre-janniaux/vlc
  • sandsmark/vlc
  • jagannatharjun/vlc
  • gsoc/gsoc2020/matiaslgonzalez/vlc
  • gsoc/gsoc2020/jagannatharjun/vlc
  • mstorsjo/vlc
  • gsoc/gsoc2020/vedenta/vlc
  • gsoc/gsoc2020/arnav-ishaan/vlc
  • gsoc/gsoc2020/andreduong/vlc
  • fuzun/vlc
  • gsoc/gsoc2020/vatsin/vlc
  • gsoc/gsoc2020/sagid/vlc
  • yaron/vlc
  • Phoenix/vlc
  • Garf/vlc
  • ePiratWorkarounds/vlc
  • tguillem/vlc
  • jnqnfe/vlc
  • mdc/vlc
  • Vedaa/vlc
  • rasa/vlc
  • quink/vlc
  • yealo/vlc
  • aleksey_ak/vlc
  • ePirat/vlc
  • ilya.yanok/vlc
  • asenat/vlc
  • m/vlc
  • bunjee/vlc
  • BLumia/vlc
  • sagudev/vlc
  • hamedmonji30/vlc
  • nullgemm/vlc
  • DivyamAhuja/vlc
  • thesamesam/vlc
  • dag7/vlc
  • snehil101/vlc
  • haasn/vlc
  • jbk/vlc
  • ValZapod/vlc
  • mfkl/vlc
  • WangChuan/vlc
  • core1024/vlc
  • GhostVaibhav/vlc
  • dfuhrmann/vlc
  • davide.prade/vlc
  • tmatth/vlc
  • Courmisch/vlc
  • zouya/vlc
  • hpi/vlc
  • EwoutH/vlc
  • aleung27/vlc
  • hengwu0/vlc
  • saladin/vlc
  • ashuio/vlc
  • richselwood/vlc
  • verma16Ayush/vlc
  • chemicalflash/vlc
  • PoignardAzur/vlc
  • huangjieNT/vlc
  • Blake-Haydon/vlc
  • AnuthaDev/vlc
  • gsoc/gsoc2021/mpd/vlc
  • nicolas_lequec/vlc
  • sambassaly/vlc
  • thresh/vlc
  • bonniegong/vlc
  • myaashish/vlc
  • stavros.vagionitis/vlc
  • ileoo/vlc
  • louis-santucci/vlc
  • cchristiansen/vlc
  • sabyasachi07/vlc
  • AbduAmeen/vlc
  • ashishb0410/vlc
  • urbanhusky/vlc
  • davidepietrasanta/vlc
  • riksleutelstad/vlc
  • jeremyVignelles/vlc
  • komh/vlc
  • iamjithinjohn/vlc
  • JohannesKauffmann/vlc2
  • kunglao/vlc
  • natzberg/vlc
  • jill/vlc
  • cwendling/vlc
  • adufou/vlc
  • ErwanAirone/vlc
  • HasinduDilshan10/vlc
  • vagrantc/vlc
  • rafiv/macos-bigsur-icon
  • Aymeriic/vlc
  • saranshg20/vlc
  • metzlove24/vlc
  • linkfanel/vlc
  • Ds886/vlc
  • metehan-arslan/vlc
  • Skantes/vlc
  • kgsandundananjaya96/vlc
  • mitchcapper/vlc
  • advaitgupta/vlc
  • StefanBruens/vlc
  • ratajs/vlc
  • T.M.F.B.3761/vlc
  • m222059/vlc
  • casemerrick/vlc
  • joshuaword2alt/vlc
  • sjwaddy/vlc
  • dima/vlc
  • Ybalrid/vlc
  • umxprime/vlc
  • eschmidt/vlc
  • vannieuwenhuysenmichelle/vlc
  • badcf00d/vlc
  • wesinator/vlc
  • louis/vlc
  • xqq/vlc
  • EmperorYP7/vlc
  • NicoLiam/vlc
  • loveleen/vlc
  • rofferom/vlc
  • rbultje/vlc
  • TheUnamed/vlc
  • pratiksharma341/vlc
  • Saurab17/vlc
  • purist.coder/vlc
  • Shuicheng/vlc
  • mdrrubel292/vlc
  • silverbleu00/vlc
  • metif12/vlc
  • asher-m/vlc
  • jeffk/vlc
  • Brandonbr1/vlc
  • beautyyuyanli/vlc
  • rego21/vlc
  • muyangren907/vlc
  • collectionbylawrencejason/vlc
  • evelez/vlc
  • GSMgeeth/vlc
  • Oneric/vlc
  • TJ5/vlc
  • XuanTung95/vlc
  • darrenjenny21/vlc
  • Trenly/vlc
  • RockyTDR/vlc
  • mjakubowski/vlc
  • caprica/vlc
  • ForteFrankie/vlc
  • seannamiller19/vlc
  • junlon2006/vlc
  • kiwiren6666/vlc
  • iuseiphonexs/vlc
  • fenngtun/vlc
  • Rajdutt999/vlc
  • typx/vlc
  • leon.vitanos/vlc
  • robertogarci0938/vlc
  • gsoc/gsoc2022/luc65r/vlc-mpd
  • skeller/vlc
  • MCJack123/vlc
  • luc65r/vlc-mpd
  • popov895/vlc
  • claucambra/vlc
  • brad/vlc
  • matthewmurua88/vlc
  • Tomas8874/vlc
  • philenotfound/vlc
  • makita-do3/vlc
  • LZXCorp/vlc
  • mar0x/vlc
  • senojetkennedy0102/vlc
  • shaneb243/vlc
  • ahmadbader/vlc
  • rajduttcse26/vlc-audio-filters
  • Juniorzito8415/vlc
  • achernyakov/vlc
  • lucasjetgroup/vlc
  • pupdoggy666/vlc
  • gmde9363/vlc
  • alexnwayne/vlc
  • bahareebrahimi781/vlc
  • hamad633666/vlc
  • umghof3112/vlc
  • joe0199771874/vlc
  • Octocats66666666/vlc
  • jjm_223/vlc
  • btech10110.19/vlc
  • sunnykfc028/vlc-audio-filters
  • loic/vlc
  • nguyenminhducmx1/vlc
  • JanekKrueger/vlc
  • bstubbington2/vlc
  • rcombs/vlc
  • Ordissimo/vlc
  • king7532/vlc
  • noobsauce101/vlc
  • schong0525/vlc
  • myQwil/vlc
  • apisbg91/vlc
  • geeboy0101017/vlc
  • kim.faughey/vlc
  • nurupo/vlc
  • yyusea/vlc
  • 0711235879.khco/vlc
  • ialo/vlc
  • iloveyeye2/vlc
  • gdtdftdqtd/vlc
  • leandroconsiglio/vlc
  • AndyHTML2012/vlc
  • ncz/vlc
  • lucenticus/vlc
  • knr1931/vlc
  • kjoonlee/vlc
  • chandrakant100/vlc-qt
  • johge42/vlc
  • polter/vlc
  • hexchain/vlc
  • Tushwrld/vlc
  • mztea928/vlc
  • jbelloncastro/vlc
  • alvinhochun/vlc
  • ghostpiratecrow/vlc
  • ujjwaltwitx/vlc
  • alexsonarin06/vlc
  • adrianbon76/vlc
  • altsod/vlc
  • damien.lucas44/vlc
  • dmytrivtaisa/vlc
  • utk202/vlc
  • aaxhrj/vlc
  • thomas.hermes/vlc
  • structurenewworldorder/vlc
  • slomo/vlc
  • wantlamy/vlc
  • musc.o3cminc/vlc
  • thebarshablog/vlc
  • kerrick/vlc
  • kratos142518/vlc
  • leogps/vlc
  • vacantron/vlc
  • luna_koly/vlc
  • Ratio2/vlc
  • anuoshemohammad/vlc
  • apsun/vlc
  • aaa1115910/vlc
  • alimotmoyo/vlc
  • Ambossmann/vlc
  • Sam-LearnsToCode/vlc
  • Chilledheart/vlc
  • Labnann/vlc
  • ktcoooot1/vlc
  • mohit-marathe/vlc
  • johnddx/vlc
  • manstabuk/vlc
  • Omar-ahmed314/vlc
  • vineethkm/vlc
  • 9Enemi86/vlc
  • radoslav.m.panteleev/vlc
  • ashishami2002/vlc
  • Corbax/vlc
  • firnasahmed/vlc
  • pelayarmalam4/vlc
  • c0ff330k/vlc
  • shikhindahikar/vlc
  • l342723951/vlc
  • christianschwandner/vlc
  • douniwan5788/vlc
  • 7damian7/vlc
  • ferdnyc/vlc
  • f.ales1/vlc
  • pandagby/vlc
  • BaaBaa/vlc
  • jewe37/vlc
  • w00drow/vlc
  • russelltg/vlc
  • ironicallygod/vlc
  • soumyaDghosh/vlc
  • linzihao1999/vlc
  • deyayush6/vlc
  • mibi88/vlc
  • newabdallah10/vlc
  • jhorbincolombia/vlc
  • rimvihaqueshupto/vlc
  • andrewkhon98/vlc
  • fab78/vlc
  • lapaz17/vlc
  • amanna13/vlc
  • mdakram28/vlc
  • 07jw1980/vlc
  • sohamgupta/vlc
  • Eson-Jia1/vlc
  • Sumou/vlc
  • vikram-kangotra/vlc
  • chalice191/vlc
  • olivercalder/vlc
  • aaasg4001/vlc
  • zipdox/vlc
  • kwizart/vlc
  • Dragon-S/vlc
  • jdemeule/vlc
  • gabriel_lt/vlc
  • locutusofborg/vlc
  • sammirata/vlc-librist
  • another/vlc
  • Benjamin_Loison/vlc
  • ahmedmoselhi/vlc
  • petergaal/vlc
  • huynhsontung/vlc
  • dariusmihut/vlc
  • tvermaashutosh/vlc
  • buti/vlc
  • Niram7777/vlc
  • rohan-here/vlc
  • balaji-sivasakthi/vlc
  • rlindner81/vlc
  • Kakadus/vlc
  • djain/vlc
  • ABBurmeister/vlc
  • craighuggins/vlc
  • orbea/vlc
  • maxos/vlc
  • aakarshmj/vlc
  • kblaschke/vlc
  • ankitm/vlc
  • advait-0/vlc
  • mohak2003/vlc
  • yselkowitz/vlc
  • AZM999/vlc-azm
  • andrey.turkin/vlc
  • Disha-Baghel/vlc
  • nowrep/vlc
  • Apeng/vlc
  • Choucroute_melba/vlc
  • autra/vlc
  • eclipseo/vlc
  • fhuber/vlc
  • olafhering/vlc
  • sdasda7777/vlc
  • 1div0/vlc
  • skosnits/vlc-extended-playlist-support
  • dnicolson/vlc
  • Timshel/vlc
  • octopols/vlc
  • MangalK/vlc
  • nima64/vlc
  • misawai/vlc
  • Alexander-Wilms/vlc
  • Maxime2/vlc-fork-for-visualizer
  • ww/vlc
  • jeske/vlc
  • sgross-emlix/vlc
  • morenonatural/vlc
  • freakingLovesVLC/vlc
  • borisgolovnev/vlc
  • mpromonet/vlc
  • diogo.simao-marques/vlc
  • masstock/vlc
  • pratikpatel8982/vlc
  • hugok79/vlc
  • longervision/vlc
  • abhiudaysurya/vlc
  • rishabhgarg/vlc
  • tumic/vlc
  • cart/vlc
  • shubham442/vlc
  • Aditya692005/vlc
  • sammirata/vlc4
  • syrykh/vlc
  • Vvorcun/macos-new-icon
  • AyaanshC/vlc
  • nasso/vlc
  • Quark/vlc
  • sebastinas/vlc
  • rhstone/vlc
  • talregev/vlc
  • Managor/vlc
403 results
Show changes
Commits on Source (8)
......@@ -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 \
......
......@@ -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 *);
......
......@@ -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(&param->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(&param->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(&param->value.str, memory_order_relaxed);
atomic_store_explicit(&param->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(&param->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(&param->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 = &param->item;
if (IsConfigStringType (p_item->i_type))
{
free (p_item->value.psz);
free(atomic_load_explicit(&param->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);
}
......@@ -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(&param->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)
{
......
......@@ -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;
}
......
/**
* \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 = &current;
return self->recursion > 0;
}
static struct vlc_rcu_generation *_Atomic generation;
void vlc_rcu_read_lock(void)
{
struct vlc_rcu_thread *const self = &current;
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 = &current;
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);
}
/**
* \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_ */
......@@ -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(&param->value.str, NULL);
vlc_param_SetString(param, psz);
if (cfg->list_count)
cfg->list.psz = xmalloc (cfg->list_count * sizeof (char *));
......
......@@ -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(&param->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;
}
......