summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKacper Michajłow <kasper93@gmail.com>2023-10-21 04:55:41 +0200
committerDudemanguy <random342@airmail.cc>2023-11-05 17:36:17 +0000
commit174df99ffa53f1091589eaa4fa0c16cdd55a9326 (patch)
tree3a60d45615f18beed98a9b08267c28ed7e05dd5f
parent3a8b107f6216b38a151d5ca1e9d4f2727e3418f5 (diff)
downloadmpv-174df99ffa53f1091589eaa4fa0c16cdd55a9326.tar.bz2
mpv-174df99ffa53f1091589eaa4fa0c16cdd55a9326.tar.xz
ALL: use new mp_thread abstraction
-rw-r--r--DOCS/tech-overview.txt48
-rw-r--r--audio/out/ao_audiotrack.c39
-rw-r--r--audio/out/ao_lavc.c6
-rw-r--r--audio/out/ao_opensles.c13
-rw-r--r--audio/out/ao_pulse.c1
-rw-r--r--audio/out/ao_wasapi.c2
-rw-r--r--audio/out/buffer.c117
-rw-r--r--audio/out/internal.h1
-rw-r--r--common/av_log.c20
-rw-r--r--common/encode_lavc.c32
-rw-r--r--common/encode_lavc.h4
-rw-r--r--common/msg.c143
-rw-r--r--common/stats.c64
-rw-r--r--common/stats.h2
-rw-r--r--demux/demux.c198
-rw-r--r--demux/demux_lavf.c1
-rw-r--r--filters/f_async_queue.c60
-rw-r--r--filters/f_decoder_wrapper.c75
-rw-r--r--filters/filter.c24
-rw-r--r--input/input.c24
-rw-r--r--input/ipc-unix.c25
-rw-r--r--input/ipc-win.c24
-rw-r--r--input/sdl_gamepad.c10
-rw-r--r--libmpv/render.h2
-rw-r--r--misc/dispatch.c93
-rw-r--r--misc/jni.c12
-rw-r--r--misc/random.c12
-rw-r--r--misc/rendezvous.c15
-rw-r--r--misc/thread_pool.c74
-rw-r--r--misc/thread_tools.c70
-rw-r--r--misc/thread_tools.h11
-rw-r--r--options/m_config_core.c34
-rw-r--r--options/m_config_frontend.c10
-rw-r--r--osdep/io.c10
-rw-r--r--osdep/macosx_application.m11
-rw-r--r--osdep/path-darwin.c6
-rw-r--r--osdep/path-unix.c6
-rw-r--r--osdep/path-win.c10
-rw-r--r--osdep/semaphore.h4
-rw-r--r--osdep/semaphore_osx.c8
-rw-r--r--osdep/subprocess-posix.c1
-rw-r--r--osdep/subprocess.c2
-rw-r--r--osdep/terminal-unix.c13
-rw-r--r--osdep/terminal-win.c13
-rw-r--r--osdep/timer.c5
-rw-r--r--osdep/win32/include/semaphore.h6
-rw-r--r--player/client.c208
-rw-r--r--player/command.c11
-rw-r--r--player/core.h10
-rw-r--r--player/loadfile.c22
-rw-r--r--player/main.c13
-rw-r--r--player/scripting.c13
-rw-r--r--stream/stream_dvb.c22
-rw-r--r--stream/stream_lavf.c3
-rw-r--r--sub/dec_sub.c55
-rw-r--r--sub/osd.c52
-rw-r--r--sub/osd_libass.c12
-rw-r--r--sub/osd_state.h4
-rw-r--r--ta/ta.c20
-rw-r--r--video/d3d.c13
-rw-r--r--video/decode/vd_lavc.c14
-rw-r--r--video/filter/vf_vapoursynth.c74
-rw-r--r--video/hwdec.c25
-rw-r--r--video/mp_image.c4
-rw-r--r--video/mp_image_pool.c10
-rw-r--r--video/out/cocoa_common.m100
-rw-r--r--video/out/dr_helper.c32
-rw-r--r--video/out/dr_helper.h2
-rw-r--r--video/out/gpu/d3d11_helpers.c6
-rw-r--r--video/out/hwdec/hwdec_aimagereader.c27
-rw-r--r--video/out/opengl/angle_dynamic.c6
-rw-r--r--video/out/vo.c184
-rw-r--r--video/out/vo_gpu_next.c22
-rw-r--r--video/out/vo_lavc.c4
-rw-r--r--video/out/vo_libmpv.c134
-rw-r--r--video/out/vo_rpi.c36
-rw-r--r--video/out/w32_common.c19
-rw-r--r--video/out/win32/displayconfig.c1
-rw-r--r--video/vaapi.h1
-rw-r--r--video/vdpau.c24
-rw-r--r--video/vdpau.h7
81 files changed, 1252 insertions, 1299 deletions
diff --git a/DOCS/tech-overview.txt b/DOCS/tech-overview.txt
index fefca1431d..e723f78cb8 100644
--- a/DOCS/tech-overview.txt
+++ b/DOCS/tech-overview.txt
@@ -430,7 +430,7 @@ like a log file or the internal console.lua script.
Locking
-------
-See generally available literature. In mpv, we use pthread for this.
+See generally available literature. In mpv, we use mp_thread for this.
Always keep locking clean. Don't skip locking just because it will work "in
practice". (See undefined behavior section.) If your use case is simple, you may
@@ -555,13 +555,13 @@ Condition variables
-------------------
They're used whenever a thread needs to wait for something, without nonsense
-like sleep calls or busy waiting. mpv uses the standard pthread API for this.
-There's a lot of literature on it. Read it.
+like sleep calls or busy waiting. mpv uses the mp_thread API for this.
+There's a lot of literature on condition variables, threading in general. Read it.
For initial understanding, it may be helpful to know that condition variables
-are not variables that signal a condition. pthread_cond_t does not have any
-state per-se. Maybe pthread_cond_t would better be named pthread_interrupt_t,
-because its sole purpose is to interrupt a thread waiting via pthread_cond_wait()
+are not variables that signal a condition. mp_cond does not have any
+state per-se. Maybe mp_cond would better be named mp_interrupt,
+because its sole purpose is to interrupt a thread waiting via mp_cond_wait()
(or similar). The "something" in "waiting for something" can be called
predicate (to avoid confusing it with "condition"). Consult literature for the
proper terms.
@@ -570,24 +570,24 @@ The very short version is...
Shared declarations:
- pthread_mutex_t lock;
- pthread_cond_t cond_var;
+ mp_mutex lock;
+ mp_cond cond_var;
struct something state_var; // protected by lock, changes signaled by cond_var
Waiter thread:
- pthread_mutex_lock(&lock);
+ mp_mutex_lock(&lock);
// Wait for a change in state_var. We want to wait until predicate_fulfilled()
// returns true.
// Must be a loop for 2 reasons:
// 1. cond_var may be associated with other conditions too
- // 2. pthread_cond_wait() can have sporadic wakeups
+ // 2. mp_cond_wait() can have sporadic wakeups
while (!predicate_fulfilled(&state_var)) {
// This unlocks, waits for cond_var to be signaled, and then locks again.
// The _whole_ point of cond_var is that unlocking and waiting for the
// signal happens atomically.
- pthread_cond_wait(&cond_var, &lock);
+ mp_cond_wait(&cond_var, &lock);
}
// Here you may react to the state change. The state cannot change
@@ -595,43 +595,43 @@ Waiter thread:
// and reacquire it).
// ...
- pthread_mutex_unlock(&lock);
+ mp_mutex_unlock(&lock);
Signaler thread:
- pthread_mutex_lock(&lock);
+ mp_mutex_lock(&lock);
// Something changed. Update the shared variable with the new state.
update_state(&state_var);
// Notify that something changed. This will wake up the waiter thread if
- // it's blocked in pthread_cond_wait(). If not, nothing happens.
- pthread_cond_broadcast(&cond_var);
+ // it's blocked in mp_cond_wait(). If not, nothing happens.
+ mp_cond_broadcast(&cond_var);
// Fun fact: good implementations wake up the waiter only when the lock is
// released, to reduce kernel scheduling overhead.
- pthread_mutex_unlock(&lock);
+ mp_mutex_unlock(&lock);
Some basic rules:
1. Always access your state under proper locking
- 2. Always check your predicate before every call to pthread_cond_wait()
- (And don't call pthread_cond_wait() if the predicate is fulfilled.)
- 3. Always call pthread_cond_wait() in a loop
+ 2. Always check your predicate before every call to mp_cond_wait()
+ (And don't call mp_cond_wait() if the predicate is fulfilled.)
+ 3. Always call mp_cond_wait() in a loop
(And only if your predicate failed without releasing the lock..)
- 4. Always call pthread_cond_broadcast()/_signal() inside of its associated
+ 4. Always call mp_cond_broadcast()/_signal() inside of its associated
lock
mpv sometimes violates rule 3, and leaves "retrying" (i.e. looping) to the
caller.
Common pitfalls:
- - Thinking that pthread_cond_t is some kind of semaphore, or holds any
+ - Thinking that mp_cond is some kind of semaphore, or holds any
application state or the user predicate (it _only_ wakes up threads
- that are at the same time blocking on pthread_cond_wait() and friends,
+ that are at the same time blocking on mp_cond_wait() and friends,
nothing else)
- - Changing the predicate, but not updating all pthread_cond_broadcast()/
+ - Changing the predicate, but not updating all mp_cond_broadcast()/
_signal() calls correctly
- - Forgetting that pthread_cond_wait() unlocks the lock (other threads can
+ - Forgetting that mp_cond_wait() unlocks the lock (other threads can
and must acquire the lock)
- Holding multiple nested locks while trying to wait (=> deadlock, violates
the lock order anyway)
diff --git a/audio/out/ao_audiotrack.c b/audio/out/ao_audiotrack.c
index 321e3cb851..fcb9aae4e8 100644
--- a/audio/out/ao_audiotrack.c
+++ b/audio/out/ao_audiotrack.c
@@ -62,9 +62,9 @@ struct priv {
bool thread_terminate;
bool thread_created;
- pthread_t thread;
- pthread_mutex_t lock;
- pthread_cond_t wakeup;
+ mp_thread thread;
+ mp_mutex lock;
+ mp_cond wakeup;
};
struct JNIByteBuffer {
@@ -549,13 +549,13 @@ static int init_jni(struct ao *ao)
return 0;
}
-static void *playthread(void *arg)
+static MP_THREAD_VOID playthread(void *arg)
{
struct ao *ao = arg;
struct priv *p = ao->priv;
JNIEnv *env = MP_JNI_GET_ENV(ao);
- mpthread_set_name("ao/audiotrack");
- pthread_mutex_lock(&p->lock);
+ mp_thread_set_name("ao/audiotrack");
+ mp_mutex_lock(&p->lock);
while (!p->thread_terminate) {
int state = AudioTrack.PLAYSTATE_PAUSED;
if (p->audiotrack) {
@@ -579,12 +579,11 @@ static void *playthread(void *arg)
MP_ERR(ao, "AudioTrack.write failed with %d\n", ret);
}
} else {
- struct timespec wait = mp_rel_time_to_timespec(0.300);
- pthread_cond_timedwait(&p->wakeup, &p->lock, &wait);
+ mp_cond_timedwait(&p->wakeup, &p->lock, MP_TIME_MS_TO_NS(300));
}
}
- pthread_mutex_unlock(&p->lock);
- return NULL;
+ mp_mutex_unlock(&p->lock);
+ MP_THREAD_RETURN();
}
static void uninit(struct ao *ao)
@@ -598,13 +597,13 @@ static void uninit(struct ao *ao)
MP_JNI_EXCEPTION_LOG(ao);
}
- pthread_mutex_lock(&p->lock);
+ mp_mutex_lock(&p->lock);
p->thread_terminate = true;
- pthread_cond_signal(&p->wakeup);
- pthread_mutex_unlock(&p->lock);
+ mp_cond_signal(&p->wakeup);
+ mp_mutex_unlock(&p->lock);
if (p->thread_created)
- pthread_join(p->thread, NULL);
+ mp_thread_join(p->thread);
if (p->audiotrack) {
MP_JNI_CALL_VOID(p->audiotrack, AudioTrack.release);
@@ -638,8 +637,8 @@ static void uninit(struct ao *ao)
p->timestamp = NULL;
}
- pthread_cond_destroy(&p->wakeup);
- pthread_mutex_destroy(&p->lock);
+ mp_cond_destroy(&p->wakeup);
+ mp_mutex_destroy(&p->lock);
uninit_jni(ao);
}
@@ -651,8 +650,8 @@ static int init(struct ao *ao)
if (!env)
return -1;
- pthread_mutex_init(&p->lock, NULL);
- pthread_cond_init(&p->wakeup, NULL);
+ mp_mutex_init(&p->lock);
+ mp_cond_init(&p->wakeup);
if (init_jni(ao) < 0)
return -1;
@@ -781,7 +780,7 @@ static int init(struct ao *ao)
goto error;
}
- if (pthread_create(&p->thread, NULL, playthread, ao)) {
+ if (mp_thread_create(&p->thread, playthread, ao)) {
MP_ERR(ao, "pthread creation failed\n");
goto error;
}
@@ -828,7 +827,7 @@ static void start(struct ao *ao)
MP_JNI_CALL_VOID(p->audiotrack, AudioTrack.play);
MP_JNI_EXCEPTION_LOG(ao);
- pthread_cond_signal(&p->wakeup);
+ mp_cond_signal(&p->wakeup);
}
#define OPT_BASE_STRUCT struct priv
diff --git a/audio/out/ao_lavc.c b/audio/out/ao_lavc.c
index 0f176cb54e..163fdcae4f 100644
--- a/audio/out/ao_lavc.c
+++ b/audio/out/ao_lavc.c
@@ -173,7 +173,7 @@ static int init(struct ao *ao)
return 0;
fail:
- pthread_mutex_unlock(&ao->encode_lavc_ctx->lock);
+ mp_mutex_unlock(&ao->encode_lavc_ctx->lock);
ac->shutdown = true;
return -1;
}
@@ -261,7 +261,7 @@ static bool audio_write(struct ao *ao, void **data, int samples)
double outpts = pts;
// for ectx PTS fields
- pthread_mutex_lock(&ectx->lock);
+ mp_mutex_lock(&ectx->lock);
if (!ectx->options->rawts) {
// Fix and apply the discontinuity pts offset.
@@ -290,7 +290,7 @@ static bool audio_write(struct ao *ao, void **data, int samples)
ectx->next_in_pts = nextpts;
}
- pthread_mutex_unlock(&ectx->lock);
+ mp_mutex_unlock(&ectx->lock);
mp_aframe_set_pts(af, outpts);
diff --git a/audio/out/ao_opensles.c b/audio/out/ao_opensles.c
index 9ade73c857..ddcff1904a 100644
--- a/audio/out/ao_opensles.c
+++ b/audio/out/ao_opensles.c
@@ -23,13 +23,12 @@
#include "common/msg.h"
#include "audio/format.h"
#include "options/m_option.h"
+#include "osdep/threads.h"
#include "osdep/timer.h"
#include <SLES/OpenSLES.h>
#include <SLES/OpenSLES_Android.h>
-#include <pthread.h>
-
struct priv {
SLObjectItf sl, output_mix, player;
SLBufferQueueItf buffer_queue;
@@ -37,7 +36,7 @@ struct priv {
SLPlayItf play;
void *buf;
int bytes_per_enqueue;
- pthread_mutex_t buffer_lock;
+ mp_mutex buffer_lock;
double audio_latency;
int frames_per_enqueue;
@@ -62,7 +61,7 @@ static void uninit(struct ao *ao)
p->engine = NULL;
p->play = NULL;
- pthread_mutex_destroy(&p->buffer_lock);
+ mp_mutex_destroy(&p->buffer_lock);
free(p->buf);
p->buf = NULL;
@@ -77,7 +76,7 @@ static void buffer_callback(SLBufferQueueItf buffer_queue, void *context)
SLresult res;
double delay;
- pthread_mutex_lock(&p->buffer_lock);
+ mp_mutex_lock(&p->buffer_lock);
delay = p->frames_per_enqueue / (double)ao->samplerate;
delay += p->audio_latency;
@@ -88,7 +87,7 @@ static void buffer_callback(SLBufferQueueItf buffer_queue, void *context)
if (res != SL_RESULT_SUCCESS)
MP_ERR(ao, "Failed to Enqueue: %d\n", res);
- pthread_mutex_unlock(&p->buffer_lock);
+ mp_mutex_unlock(&p->buffer_lock);
}
#define CHK(stmt) \
@@ -170,7 +169,7 @@ static int init(struct ao *ao)
goto error;
}
- int r = pthread_mutex_init(&p->buffer_lock, NULL);
+ int r = mp_mutex_init(&p->buffer_lock);
if (r) {
MP_ERR(ao, "Failed to initialize the mutex: %d\n", r);
goto error;
diff --git a/audio/out/ao_pulse.c b/audio/out/ao_pulse.c
index ae19c875c0..3b29b1a3ad 100644
--- a/audio/out/ao_pulse.c
+++ b/audio/out/ao_pulse.c
@@ -24,7 +24,6 @@
#include <string.h>
#include <stdint.h>
#include <math.h>
-#include <pthread.h>
#include <pulse/pulseaudio.h>
diff --git a/audio/out/ao_wasapi.c b/audio/out/ao_wasapi.c
index 5f6468f33e..b201f260e6 100644
--- a/audio/out/ao_wasapi.c
+++ b/audio/out/ao_wasapi.c
@@ -199,7 +199,7 @@ static DWORD __stdcall AudioThread(void *lpParameter)
{
struct ao *ao = lpParameter;
struct wasapi_state *state = ao->priv;
- mpthread_set_name("ao/wasapi");
+ mp_thread_set_name("ao/wasapi");
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
state->init_ok = wasapi_thread_init(ao);
diff --git a/audio/out/buffer.c b/audio/out/buffer.c
index c0457ba279..4ab3e405bc 100644
--- a/audio/out/buffer.c
+++ b/audio/out/buffer.c
@@ -16,7 +16,6 @@
*/
#include <stddef.h>
-#include <pthread.h>
#include <inttypes.h>
#include <math.h>
#include <unistd.h>
@@ -39,12 +38,12 @@
struct buffer_state {
// Buffer and AO
- pthread_mutex_t lock;
- pthread_cond_t wakeup;
+ mp_mutex lock;
+ mp_cond wakeup;
// Playthread sleep
- pthread_mutex_t pt_lock;
- pthread_cond_t pt_wakeup;
+ mp_mutex pt_lock;
+ mp_cond pt_wakeup;
// Access from AO driver's thread only.
char *convert_buffer;
@@ -70,7 +69,7 @@ struct buffer_state {
bool hw_paused; // driver->set_pause() was used successfully
bool recover_pause; // non-hw_paused: needs to recover delay
struct mp_pcm_state prepause_state;
- pthread_t thread; // thread shoveling data to AO
+ mp_thread thread; // thread shoveling data to AO
bool thread_valid; // thread is running
struct mp_aframe *temp_buf;
@@ -79,15 +78,15 @@ struct buffer_state {
bool terminate; // exit thread
};
-static void *playthread(void *arg);
+static MP_THREAD_VOID playthread(void *arg);
void ao_wakeup_playthread(struct ao *ao)
{
struct buffer_state *p = ao->buffer_state;
- pthread_mutex_lock(&p->pt_lock);
+ mp_mutex_lock(&p->pt_lock);
p->need_wakeup = true;
- pthread_cond_broadcast(&p->pt_wakeup);
- pthread_mutex_unlock(&p->pt_lock);
+ mp_cond_broadcast(&p->pt_wakeup);
+ mp_mutex_unlock(&p->pt_lock);
}
// called locked
@@ -184,7 +183,7 @@ int ao_read_data(struct ao *ao, void **data, int samples, int64_t out_time_ns)
struct buffer_state *p = ao->buffer_state;
assert(!ao->driver->write);
- pthread_mutex_lock(&p->lock);
+ mp_mutex_lock(&p->lock);
int pos = read_buffer(ao, data, samples, &(bool){0});
@@ -195,10 +194,10 @@ int ao_read_data(struct ao *ao, void **data, int samples, int64_t out_time_ns)
p->playing = false;
ao->wakeup_cb(ao->wakeup_ctx);
// For ao_drain().
- pthread_cond_broadcast(&p->wakeup);
+ mp_cond_broadcast(&p->wakeup);
}
- pthread_mutex_unlock(&p->lock);
+ mp_mutex_unlock(&p->lock);
return pos;
}
@@ -248,12 +247,12 @@ int ao_control(struct ao *ao, enum aocontrol cmd, void *arg)
if (ao->driver->control) {
// Only need to lock in push mode.
if (ao->driver->write)
- pthread_mutex_lock(&p->lock);
+ mp_mutex_lock(&p->lock);
r = ao->driver->control(ao, cmd, arg);
if (ao->driver->write)
- pthread_mutex_unlock(&p->lock);
+ mp_mutex_unlock(&p->lock);
}
return r;
}
@@ -262,7 +261,7 @@ double ao_get_delay(struct ao *ao)
{
struct buffer_state *p = ao->buffer_state;