mirror of https://github.com/mpv-player/mpv
msg: move central msg lock to mp_log_root
This is a central lock (that is to stay and has no reason to go away), and it was simply made global. This reduces complexity when the original MPlayer code was changed from single thread + global state to a context handle. Having the global lock was still a bit silly if there were multiple mpv instances in the process, because it would make the instances wait for each other for no reason. So move it to the per-instance context, which is trivial enough.
This commit is contained in:
parent
355bb5b1e6
commit
6c2cc20a53
70
common/msg.c
70
common/msg.c
|
@ -47,9 +47,10 @@
|
||||||
|
|
||||||
struct mp_log_root {
|
struct mp_log_root {
|
||||||
struct mpv_global *global;
|
struct mpv_global *global;
|
||||||
|
pthread_mutex_t lock;
|
||||||
pthread_mutex_t log_file_lock;
|
pthread_mutex_t log_file_lock;
|
||||||
pthread_cond_t log_file_wakeup;
|
pthread_cond_t log_file_wakeup;
|
||||||
// --- protected by mp_msg_lock
|
// --- protected by lock
|
||||||
char **msg_levels;
|
char **msg_levels;
|
||||||
bool use_terminal; // make accesses to stderr/stdout
|
bool use_terminal; // make accesses to stderr/stdout
|
||||||
bool module;
|
bool module;
|
||||||
|
@ -64,13 +65,12 @@ struct mp_log_root {
|
||||||
int num_buffers;
|
int num_buffers;
|
||||||
struct mp_log_buffer *early_buffer;
|
struct mp_log_buffer *early_buffer;
|
||||||
FILE *stats_file;
|
FILE *stats_file;
|
||||||
|
bstr buffer;
|
||||||
// --- must be accessed atomically
|
// --- must be accessed atomically
|
||||||
/* This is incremented every time the msglevels must be reloaded.
|
/* This is incremented every time the msglevels must be reloaded.
|
||||||
* (This is perhaps better than maintaining a globally accessible and
|
* (This is perhaps better than maintaining a globally accessible and
|
||||||
* synchronized mp_log tree.) */
|
* synchronized mp_log tree.) */
|
||||||
atomic_ulong reload_counter;
|
atomic_ulong reload_counter;
|
||||||
// --- protected by mp_msg_lock
|
|
||||||
bstr buffer;
|
|
||||||
// --- owner thread only (caller of mp_msg_init() etc.)
|
// --- owner thread only (caller of mp_msg_init() etc.)
|
||||||
char *log_path;
|
char *log_path;
|
||||||
char *stats_path;
|
char *stats_path;
|
||||||
|
@ -108,9 +108,6 @@ struct mp_log_buffer {
|
||||||
int level;
|
int level;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Protects some (not all) state in mp_log_root
|
|
||||||
static pthread_mutex_t mp_msg_lock = PTHREAD_MUTEX_INITIALIZER;
|
|
||||||
|
|
||||||
static const struct mp_log null_log = {0};
|
static const struct mp_log null_log = {0};
|
||||||
struct mp_log *const mp_null_log = (struct mp_log *)&null_log;
|
struct mp_log *const mp_null_log = (struct mp_log *)&null_log;
|
||||||
|
|
||||||
|
@ -126,7 +123,7 @@ static bool match_mod(const char *name, const char *mod)
|
||||||
static void update_loglevel(struct mp_log *log)
|
static void update_loglevel(struct mp_log *log)
|
||||||
{
|
{
|
||||||
struct mp_log_root *root = log->root;
|
struct mp_log_root *root = log->root;
|
||||||
pthread_mutex_lock(&mp_msg_lock);
|
pthread_mutex_lock(&root->lock);
|
||||||
log->level = MSGL_STATUS + root->verbose; // default log level
|
log->level = MSGL_STATUS + root->verbose; // default log level
|
||||||
if (root->really_quiet)
|
if (root->really_quiet)
|
||||||
log->level -= 10;
|
log->level -= 10;
|
||||||
|
@ -147,7 +144,7 @@ static void update_loglevel(struct mp_log *log)
|
||||||
if (log->root->stats_file)
|
if (log->root->stats_file)
|
||||||
log->level = MPMAX(log->level, MSGL_STATS);
|
log->level = MPMAX(log->level, MSGL_STATS);
|
||||||
atomic_store(&log->reload_counter, atomic_load(&log->root->reload_counter));
|
atomic_store(&log->reload_counter, atomic_load(&log->root->reload_counter));
|
||||||
pthread_mutex_unlock(&mp_msg_lock);
|
pthread_mutex_unlock(&root->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the current effective msg level.
|
// Get the current effective msg level.
|
||||||
|
@ -212,17 +209,19 @@ static void flush_status_line(struct mp_log_root *root)
|
||||||
|
|
||||||
void mp_msg_flush_status_line(struct mp_log *log)
|
void mp_msg_flush_status_line(struct mp_log *log)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&mp_msg_lock);
|
if (log->root) {
|
||||||
if (log->root)
|
pthread_mutex_lock(&log->root->lock);
|
||||||
flush_status_line(log->root);
|
flush_status_line(log->root);
|
||||||
pthread_mutex_unlock(&mp_msg_lock);
|
pthread_mutex_unlock(&log->root->lock);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mp_msg_has_status_line(struct mpv_global *global)
|
bool mp_msg_has_status_line(struct mpv_global *global)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&mp_msg_lock);
|
struct mp_log_root *root = global->log->root;
|
||||||
bool r = global->log->root->status_lines > 0;
|
pthread_mutex_lock(&root->lock);
|
||||||
pthread_mutex_unlock(&mp_msg_lock);
|
bool r = root->status_lines > 0;
|
||||||
|
pthread_mutex_unlock(&root->lock);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -379,10 +378,10 @@ void mp_msg_va(struct mp_log *log, int lev, const char *format, va_list va)
|
||||||
if (!mp_msg_test(log, lev))
|
if (!mp_msg_test(log, lev))
|
||||||
return; // do not display
|
return; // do not display
|
||||||
|
|
||||||
pthread_mutex_lock(&mp_msg_lock);
|
|
||||||
|
|
||||||
struct mp_log_root *root = log->root;
|
struct mp_log_root *root = log->root;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&root->lock);
|
||||||
|
|
||||||
root->buffer.len = 0;
|
root->buffer.len = 0;
|
||||||
|
|
||||||
if (log->partial[0])
|
if (log->partial[0])
|
||||||
|
@ -427,7 +426,7 @@ void mp_msg_va(struct mp_log *log, int lev, const char *format, va_list va)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_mutex_unlock(&mp_msg_lock);
|
pthread_mutex_unlock(&root->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void destroy_log(void *ptr)
|
static void destroy_log(void *ptr)
|
||||||
|
@ -492,6 +491,7 @@ void mp_msg_init(struct mpv_global *global)
|
||||||
.reload_counter = ATOMIC_VAR_INIT(1),
|
.reload_counter = ATOMIC_VAR_INIT(1),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pthread_mutex_init(&root->lock, NULL);
|
||||||
pthread_mutex_init(&root->log_file_lock, NULL);
|
pthread_mutex_init(&root->log_file_lock, NULL);
|
||||||
pthread_cond_init(&root->log_file_wakeup, NULL);
|
pthread_cond_init(&root->log_file_wakeup, NULL);
|
||||||
|
|
||||||
|
@ -595,7 +595,7 @@ void mp_msg_update_msglevels(struct mpv_global *global, struct MPOpts *opts)
|
||||||
{
|
{
|
||||||
struct mp_log_root *root = global->log->root;
|
struct mp_log_root *root = global->log->root;
|
||||||
|
|
||||||
pthread_mutex_lock(&mp_msg_lock);
|
pthread_mutex_lock(&root->lock);
|
||||||
|
|
||||||
root->verbose = opts->verbose;
|
root->verbose = opts->verbose;
|
||||||
root->really_quiet = opts->msg_really_quiet;
|
root->really_quiet = opts->msg_really_quiet;
|
||||||
|
@ -609,7 +609,7 @@ void mp_msg_update_msglevels(struct mpv_global *global, struct MPOpts *opts)
|
||||||
m_option_type_msglevels.copy(NULL, &root->msg_levels, &opts->msg_levels);
|
m_option_type_msglevels.copy(NULL, &root->msg_levels, &opts->msg_levels);
|
||||||
|
|
||||||
atomic_fetch_add(&root->reload_counter, 1);
|
atomic_fetch_add(&root->reload_counter, 1);
|
||||||
pthread_mutex_unlock(&mp_msg_lock);
|
pthread_mutex_unlock(&root->lock);
|
||||||
|
|
||||||
if (check_new_path(global, opts->log_file, &root->log_path)) {
|
if (check_new_path(global, opts->log_file, &root->log_path)) {
|
||||||
terminate_log_file_thread(root);
|
terminate_log_file_thread(root);
|
||||||
|
@ -636,7 +636,7 @@ void mp_msg_update_msglevels(struct mpv_global *global, struct MPOpts *opts)
|
||||||
if (check_new_path(global, opts->dump_stats, &root->stats_path)) {
|
if (check_new_path(global, opts->dump_stats, &root->stats_path)) {
|
||||||
bool open_error = false;
|
bool open_error = false;
|
||||||
|
|
||||||
pthread_mutex_lock(&mp_msg_lock);
|
pthread_mutex_lock(&root->lock);
|
||||||
if (root->stats_file)
|
if (root->stats_file)
|
||||||
fclose(root->stats_file);
|
fclose(root->stats_file);
|
||||||
root->stats_file = NULL;
|
root->stats_file = NULL;
|
||||||
|
@ -644,7 +644,7 @@ void mp_msg_update_msglevels(struct mpv_global *global, struct MPOpts *opts)
|
||||||
root->stats_file = fopen(root->stats_path, "wb");
|
root->stats_file = fopen(root->stats_path, "wb");
|
||||||
open_error = !root->stats_file;
|
open_error = !root->stats_file;
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&mp_msg_lock);
|
pthread_mutex_unlock(&root->lock);
|
||||||
|
|
||||||
if (open_error) {
|
if (open_error) {
|
||||||
mp_err(global->log, "Failed to open stats file '%s'\n",
|
mp_err(global->log, "Failed to open stats file '%s'\n",
|
||||||
|
@ -657,9 +657,9 @@ void mp_msg_force_stderr(struct mpv_global *global, bool force_stderr)
|
||||||
{
|
{
|
||||||
struct mp_log_root *root = global->log->root;
|
struct mp_log_root *root = global->log->root;
|
||||||
|
|
||||||
pthread_mutex_lock(&mp_msg_lock);
|
pthread_mutex_lock(&root->lock);
|
||||||
root->force_stderr = force_stderr;
|
root->force_stderr = force_stderr;
|
||||||
pthread_mutex_unlock(&mp_msg_lock);
|
pthread_mutex_unlock(&root->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only to be called from the main thread.
|
// Only to be called from the main thread.
|
||||||
|
@ -681,6 +681,7 @@ void mp_msg_uninit(struct mpv_global *global)
|
||||||
talloc_free(root->stats_path);
|
talloc_free(root->stats_path);
|
||||||
talloc_free(root->log_path);
|
talloc_free(root->log_path);
|
||||||
m_option_type_msglevels.free(&root->msg_levels);
|
m_option_type_msglevels.free(&root->msg_levels);
|
||||||
|
pthread_mutex_destroy(&root->lock);
|
||||||
pthread_mutex_destroy(&root->log_file_lock);
|
pthread_mutex_destroy(&root->log_file_lock);
|
||||||
pthread_cond_destroy(&root->log_file_wakeup);
|
pthread_cond_destroy(&root->log_file_wakeup);
|
||||||
talloc_free(root);
|
talloc_free(root);
|
||||||
|
@ -690,27 +691,27 @@ void mp_msg_uninit(struct mpv_global *global)
|
||||||
void mp_msg_set_early_logging(struct mpv_global *global, bool enable)
|
void mp_msg_set_early_logging(struct mpv_global *global, bool enable)
|
||||||
{
|
{
|
||||||
struct mp_log_root *root = global->log->root;
|
struct mp_log_root *root = global->log->root;
|
||||||
pthread_mutex_lock(&mp_msg_lock);
|
pthread_mutex_lock(&root->lock);
|
||||||
|
|
||||||
if (enable != !!root->early_buffer) {
|
if (enable != !!root->early_buffer) {
|
||||||
if (enable) {
|
if (enable) {
|
||||||
pthread_mutex_unlock(&mp_msg_lock);
|
pthread_mutex_unlock(&root->lock);
|
||||||
struct mp_log_buffer *buf =
|
struct mp_log_buffer *buf =
|
||||||
mp_msg_log_buffer_new(global, TERM_BUF, MP_LOG_BUFFER_MSGL_TERM,
|
mp_msg_log_buffer_new(global, TERM_BUF, MP_LOG_BUFFER_MSGL_TERM,
|
||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
pthread_mutex_lock(&mp_msg_lock);
|
pthread_mutex_lock(&root->lock);
|
||||||
assert(!root->early_buffer); // no concurrent calls to this function
|
assert(!root->early_buffer); // no concurrent calls to this function
|
||||||
root->early_buffer = buf;
|
root->early_buffer = buf;
|
||||||
} else {
|
} else {
|
||||||
struct mp_log_buffer *buf = root->early_buffer;
|
struct mp_log_buffer *buf = root->early_buffer;
|
||||||
root->early_buffer = NULL;
|
root->early_buffer = NULL;
|
||||||
pthread_mutex_unlock(&mp_msg_lock);
|
pthread_mutex_unlock(&root->lock);
|
||||||
mp_msg_log_buffer_destroy(buf);
|
mp_msg_log_buffer_destroy(buf);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_mutex_unlock(&mp_msg_lock);
|
pthread_mutex_unlock(&root->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct mp_log_buffer *mp_msg_log_buffer_new(struct mpv_global *global,
|
struct mp_log_buffer *mp_msg_log_buffer_new(struct mpv_global *global,
|
||||||
|
@ -720,7 +721,7 @@ struct mp_log_buffer *mp_msg_log_buffer_new(struct mpv_global *global,
|
||||||
{
|
{
|
||||||
struct mp_log_root *root = global->log->root;
|
struct mp_log_root *root = global->log->root;
|
||||||
|
|
||||||
pthread_mutex_lock(&mp_msg_lock);
|
pthread_mutex_lock(&root->lock);
|
||||||
|
|
||||||
if (level == MP_LOG_BUFFER_MSGL_TERM) {
|
if (level == MP_LOG_BUFFER_MSGL_TERM) {
|
||||||
size = TERM_BUF;
|
size = TERM_BUF;
|
||||||
|
@ -734,7 +735,7 @@ struct mp_log_buffer *mp_msg_log_buffer_new(struct mpv_global *global,
|
||||||
root->early_buffer = NULL;
|
root->early_buffer = NULL;
|
||||||
buffer->wakeup_cb = wakeup_cb;
|
buffer->wakeup_cb = wakeup_cb;
|
||||||
buffer->wakeup_cb_ctx = wakeup_cb_ctx;
|
buffer->wakeup_cb_ctx = wakeup_cb_ctx;
|
||||||
pthread_mutex_unlock(&mp_msg_lock);
|
pthread_mutex_unlock(&root->lock);
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -756,7 +757,7 @@ struct mp_log_buffer *mp_msg_log_buffer_new(struct mpv_global *global,
|
||||||
MP_TARRAY_APPEND(root, root->buffers, root->num_buffers, buffer);
|
MP_TARRAY_APPEND(root, root->buffers, root->num_buffers, buffer);
|
||||||
|
|
||||||
atomic_fetch_add(&root->reload_counter, 1);
|
atomic_fetch_add(&root->reload_counter, 1);
|
||||||
pthread_mutex_unlock(&mp_msg_lock);
|
pthread_mutex_unlock(&root->lock);
|
||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
@ -773,9 +774,10 @@ void mp_msg_log_buffer_destroy(struct mp_log_buffer *buffer)
|
||||||
if (!buffer)
|
if (!buffer)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
pthread_mutex_lock(&mp_msg_lock);
|
|
||||||
|
|
||||||
struct mp_log_root *root = buffer->root;
|
struct mp_log_root *root = buffer->root;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&root->lock);
|
||||||
|
|
||||||
for (int n = 0; n < root->num_buffers; n++) {
|
for (int n = 0; n < root->num_buffers; n++) {
|
||||||
if (root->buffers[n] == buffer) {
|
if (root->buffers[n] == buffer) {
|
||||||
MP_TARRAY_REMOVE_AT(root->buffers, root->num_buffers, n);
|
MP_TARRAY_REMOVE_AT(root->buffers, root->num_buffers, n);
|
||||||
|
@ -794,7 +796,7 @@ found:
|
||||||
talloc_free(buffer);
|
talloc_free(buffer);
|
||||||
|
|
||||||
atomic_fetch_add(&root->reload_counter, 1);
|
atomic_fetch_add(&root->reload_counter, 1);
|
||||||
pthread_mutex_unlock(&mp_msg_lock);
|
pthread_mutex_unlock(&root->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return a queued message, or if the buffer is empty, NULL.
|
// Return a queued message, or if the buffer is empty, NULL.
|
||||||
|
|
Loading…
Reference in New Issue