|
From: Torsten J. <t....@gm...> - 2018-01-22 17:41:08
|
# HG changeset patch
# User Torsten Jager <t....@gm...>
# Date 1516642820 -3600
# Node ID 74cd6a4532ed148ea8b5ab6fc9a16ffa291e73f9
# Branch default
# Parent 025fd0efe3baaeea0e563442034ae707de67c9ad
Optimize tickets 6.
- Fall through renew () when not holding that ticket.
- Restore orphaned self grants. Shall fix non-dvbspeed net buf ctrl pause freeze.
- Fix renew () with multiple grants.
- Remove inadequate assert.
- Fix ticket_revoked value. Let engine respect pause consistently.
- Fix port property helpers (irrevocable acquire to work reliably when paused).
- Reuse tests.
- Simplify.
diff --git a/src/xine-engine/xine.c b/src/xine-engine/xine.c
--- a/src/xine-engine/xine.c
+++ b/src/xine-engine/xine.c
@@ -185,10 +185,10 @@
break;
}
- if (i == this->holder_thread_count) {
+ if (i >= this->holder_thread_count) {
/* not found */
- wait = (this->ticket_revoked && !this->irrevocable_tickets) ? !nonblocking
- : (this->atomic_revoke ? !pthread_equal (this->atomic_revoker_thread, self) : 0);
+ wait = this->pending_revocations
+ && (this->rewirers || !irrevocable || (this->atomic_revoke && !pthread_equal (this->atomic_revoker_thread, self)));
if (nonblocking && wait) {
/* not available immediately, bail out */
pthread_mutex_unlock (&this->lock);
@@ -216,8 +216,8 @@
while (wait) {
pthread_cond_wait (&this->issued, &this->lock);
- wait = (this->ticket_revoked && !this->irrevocable_tickets) ? 1
- : (this->atomic_revoke ? !pthread_equal (this->atomic_revoker_thread, self) : 0);
+ wait = this->pending_revocations
+ && (this->rewirers || !irrevocable || (this->atomic_revoke && !pthread_equal (this->atomic_revoker_thread, self)));
}
this->tickets_granted++;
@@ -248,7 +248,7 @@
break;
}
- if (i == this->holder_thread_count) {
+ if (i >= this->holder_thread_count) {
lprintf ("BUG! Ticket 0x%p released by a thread that never took it! Allowing code to continue\n", (void*)this);
_x_assert (0);
} else {
@@ -262,16 +262,13 @@
}
}
- this->tickets_granted--;
- if (this->tickets_granted < 0)
- this->tickets_granted = 0;
- if (irrevocable) {
+ if ((this->irrevocable_tickets > 0) && irrevocable)
this->irrevocable_tickets--;
- if (this->irrevocable_tickets < 0)
- this->irrevocable_tickets = 0;
- }
-
- if (this->ticket_revoked && !this->tickets_granted)
+ if (this->tickets_granted > 0)
+ this->tickets_granted--;
+
+ if (this->pending_revocations
+ && (!this->tickets_granted || (this->rewirers && !this->irrevocable_tickets)))
pthread_cond_broadcast(&this->revoked);
pthread_mutex_unlock(&this->lock);
@@ -286,29 +283,57 @@
}
static void ticket_renew(xine_ticket_t *this, int irrevocable) {
+ int i, grants;
+ pthread_t self = pthread_self ();
pthread_mutex_lock (&this->lock);
+#if 0
+ /* For performance, caller checks ticket_revoked without lock. 0 here is not really a bug. */
_x_assert (this->ticket_revoked);
-
+#endif
+ /* Multithreaded decoders may well allocate frames outside the time window of the main
+ * decoding call. Usually, we cannot make those hidden threads acquire and release
+ * tickets properly. Blocking one of them may freeze main decoder with ticket held.
+ * Lets just not make them wait, not messing with grant count.
+ * There goes an optimization...
+ */
+ for (i = 0; i < this->holder_thread_count; i++) {
+ if (pthread_equal (this->holder_threads[i].holder, self))
+ break;
+ }
+ if (i >= this->holder_thread_count) {
+ pthread_mutex_unlock (&this->lock);
+ return;
+ }
+ /* If our thread still has saved self grants and calls this, restore them.
+ * Assume later reissue by another thread (engine pause).
+ */
+ grants = this->holder_threads[i].count;
+ if (grants >= 0x80000) {
+ grants &= 0x7ffff;
+ this->holder_threads[i].count = grants;
+ this->tickets_granted += grants;
+ }
+ /* Lift _all_ our grants, avoid freeze when we have more than 1. */
if (irrevocable & XINE_TICKET_FLAG_REWIRE) {
/* allow everything */
- this->tickets_granted--;
+ this->tickets_granted -= grants;
if (!this->tickets_granted)
pthread_cond_broadcast (&this->revoked);
- while ((this->pending_revocations > 0)
+ while (this->pending_revocations
&& (!this->irrevocable_tickets || !(irrevocable & ~XINE_TICKET_FLAG_REWIRE)))
pthread_cond_wait (&this->issued, &this->lock);
- this->tickets_granted++;
+ this->tickets_granted += grants;
} else {
/* fair wheather (not rewire) mode */
this->plain_renewers++;
- this->tickets_granted--;
+ this->tickets_granted -= grants;
if (!this->tickets_granted)
pthread_cond_broadcast (&this->revoked);
- while ((this->pending_revocations > 0)
+ while (this->pending_revocations
&& (!this->irrevocable_tickets || !irrevocable)
&& !this->rewirers)
pthread_cond_wait (&this->issued, &this->lock);
- this->tickets_granted++;
+ this->tickets_granted += grants;
this->plain_renewers--;
}
@@ -330,8 +355,14 @@
if (this->pending_revocations > 0)
this->pending_revocations--;
- if (!this->pending_revocations)
+ this->atomic_revoke = 0;
+
+ i = !this->pending_revocations ? 0
+ : (this->rewirers ? (XINE_TICKET_FLAG_REWIRE | 1) : 1);
+ if (this->ticket_revoked != i) {
+ this->ticket_revoked = i;
pthread_cond_broadcast (&this->issued);
+ }
/* HACK: restore self grants. */
for (i = 0; i < this->holder_thread_count; i++) {
@@ -342,7 +373,6 @@
this->holder_threads[i].count = n;
if (n < 0x80000) {
if (this->pending_revocations) {
- this->atomic_revoke = 0;
pthread_mutex_unlock (&this->revoke_lock);
while (this->pending_revocations)
pthread_cond_wait (&this->issued, &this->lock);
@@ -357,8 +387,6 @@
}
}
- this->atomic_revoke = 0;
-
pthread_mutex_unlock(&this->lock);
pthread_mutex_unlock(&this->revoke_lock);
if (flags & XINE_TICKET_FLAG_REWIRE)
@@ -397,11 +425,11 @@
if (this->plain_renewers)
pthread_cond_broadcast (&this->issued);
}
+ this->ticket_revoked = (this->rewirers ? (XINE_TICKET_FLAG_REWIRE | 1) : 1);
if (this->tickets_granted || (this->rewirers && this->plain_renewers)) {
- int i, m = (this->rewirers ? (XINE_TICKET_FLAG_REWIRE | 1) : 1);
+ int i;
/* Notify other holders. */
- this->ticket_revoked = m;
for (i = 0; i < XINE_TICKET_MAX_CB; i++) {
if (!this->revoke_callbacks[i])
break;
@@ -409,15 +437,13 @@
}
/* Wait for them to release/renew. */
do {
- this->ticket_revoked = m;
pthread_cond_wait (&this->revoked, &this->lock);
+ this->ticket_revoked = (this->rewirers ? (XINE_TICKET_FLAG_REWIRE | 1) : 1);
} while (this->tickets_granted || (this->rewirers && this->plain_renewers));
}
- this->ticket_revoked = 0;
-
if (flags & (XINE_TICKET_FLAG_REWIRE | XINE_TICKET_FLAG_ATOMIC))
- this->atomic_revoker_thread = pthread_self();
+ this->atomic_revoker_thread = self;
pthread_mutex_unlock(&this->lock);
if (!(flags & (XINE_TICKET_FLAG_REWIRE | XINE_TICKET_FLAG_ATOMIC)))
@@ -475,8 +501,11 @@
port_ticket->ticket_revoked = 0;
port_ticket->holder_thread_count = 0;
+ port_ticket->tickets_granted = 0;
+ port_ticket->irrevocable_tickets = 0;
+ port_ticket->atomic_revoke = 0;
+ port_ticket->rewirers = 0;
port_ticket->plain_renewers = 0;
- port_ticket->rewirers = 0;
{
int i;
for (i = 0; i < XINE_TICKET_MAX_CB; i++) {
@@ -2140,7 +2169,7 @@
pthread_mutex_lock (&stream->frontend_lock);
stream->spu_channel_user = (channel >= -2 ? channel : -2);
- stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0);
+ stream->xine->port_ticket->acquire(stream->xine->port_ticket, 1);
switch (stream->spu_channel_user) {
case -2:
@@ -2160,7 +2189,7 @@
}
lprintf("set to %d\n",stream->spu_channel);
- stream->xine->port_ticket->release(stream->xine->port_ticket, 0);
+ stream->xine->port_ticket->release(stream->xine->port_ticket, 1);
pthread_mutex_unlock (&stream->frontend_lock);
}
@@ -2314,9 +2343,9 @@
vo_frame_t *frame;
size_t required_size = 0;
- stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0);
+ stream->xine->port_ticket->acquire(stream->xine->port_ticket, 1);
frame = stream->video_out->get_last_frame (stream->video_out);
- stream->xine->port_ticket->release(stream->xine->port_ticket, 0);
+ stream->xine->port_ticket->release(stream->xine->port_ticket, 1);
if (!frame) {
data->img_size = 0;
--git a/src/xine-engine/xine_interface.c b/src/xine-engine/xine_interface.c
--- a/src/xine-engine/xine_interface.c
+++ b/src/xine-engine/xine_interface.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2000-2017 the xine project
+ * Copyright (C) 2000-2018 the xine project
*
* This file is part of xine, a free video player.
*
@@ -394,51 +394,51 @@
break;
case XINE_PARAM_AUDIO_VOLUME:
- stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0);
+ stream->xine->port_ticket->acquire(stream->xine->port_ticket, 1);
if (stream->audio_out)
stream->audio_out->set_property (stream->audio_out, AO_PROP_MIXER_VOL, value);
- stream->xine->port_ticket->release(stream->xine->port_ticket, 0);
+ stream->xine->port_ticket->release(stream->xine->port_ticket, 1);
break;
case XINE_PARAM_AUDIO_MUTE:
- stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0);
+ stream->xine->port_ticket->acquire(stream->xine->port_ticket, 1);
if (stream->audio_out)
stream->audio_out->set_property (stream->audio_out, AO_PROP_MUTE_VOL, value);
- stream->xine->port_ticket->release(stream->xine->port_ticket, 0);
+ stream->xine->port_ticket->release(stream->xine->port_ticket, 1);
break;
case XINE_PARAM_AUDIO_COMPR_LEVEL:
- stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0);
+ stream->xine->port_ticket->acquire(stream->xine->port_ticket, 1);
if (stream->audio_out)
stream->audio_out->set_property (stream->audio_out, AO_PROP_COMPRESSOR, value);
- stream->xine->port_ticket->release(stream->xine->port_ticket, 0);
+ stream->xine->port_ticket->release(stream->xine->port_ticket, 1);
break;
case XINE_PARAM_AUDIO_AMP_LEVEL:
- stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0);
+ stream->xine->port_ticket->acquire(stream->xine->port_ticket, 1);
if (stream->audio_out) {
int old_value = stream->audio_out->get_property (stream->audio_out, AO_PROP_AMP);
if (old_value != stream->audio_out->set_property (stream->audio_out, AO_PROP_AMP, value))
send_audio_amp_event_internal(stream);
}
- stream->xine->port_ticket->release(stream->xine->port_ticket, 0);
+ stream->xine->port_ticket->release(stream->xine->port_ticket, 1);
break;
case XINE_PARAM_AUDIO_AMP_MUTE:
- stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0);
+ stream->xine->port_ticket->acquire(stream->xine->port_ticket, 1);
if (stream->audio_out) {
int old_value = stream->audio_out->get_property (stream->audio_out, AO_PROP_AMP_MUTE);
if (old_value != stream->audio_out->set_property (stream->audio_out, AO_PROP_AMP_MUTE, value))
send_audio_amp_event_internal(stream);
}
- stream->xine->port_ticket->release(stream->xine->port_ticket, 0);
+ stream->xine->port_ticket->release(stream->xine->port_ticket, 1);
break;
case XINE_PARAM_AUDIO_CLOSE_DEVICE:
- stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0);
+ stream->xine->port_ticket->acquire(stream->xine->port_ticket, 1);
if (stream->audio_out)
stream->audio_out->set_property (stream->audio_out, AO_PROP_CLOSE_DEVICE, value);
- stream->xine->port_ticket->release(stream->xine->port_ticket, 0);
+ stream->xine->port_ticket->release(stream->xine->port_ticket, 1);
break;
case XINE_PARAM_EQ_30HZ:
@@ -451,12 +451,12 @@
case XINE_PARAM_EQ_4000HZ:
case XINE_PARAM_EQ_8000HZ:
case XINE_PARAM_EQ_16000HZ:
- stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0);
+ stream->xine->port_ticket->acquire(stream->xine->port_ticket, 1);
if (stream->audio_out)
stream->audio_out->set_property (stream->audio_out,
param - XINE_PARAM_EQ_30HZ + AO_PROP_EQ_30HZ,
value);
- stream->xine->port_ticket->release(stream->xine->port_ticket, 0);
+ stream->xine->port_ticket->release(stream->xine->port_ticket, 1);
break;
case XINE_PARAM_VERBOSITY:
@@ -479,9 +479,9 @@
case XINE_PARAM_VO_CROP_RIGHT:
case XINE_PARAM_VO_CROP_TOP:
case XINE_PARAM_VO_CROP_BOTTOM:
- stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0);
+ stream->xine->port_ticket->acquire(stream->xine->port_ticket, 1);
stream->video_out->set_property(stream->video_out, param, value);
- stream->xine->port_ticket->release(stream->xine->port_ticket, 0);
+ stream->xine->port_ticket->release(stream->xine->port_ticket, 1);
break;
case XINE_PARAM_VO_SINGLE_STEP:
@@ -493,10 +493,10 @@
_x_set_fine_speed (stream, XINE_LIVE_PAUSE_ON);
/* rather miss 1 strobe than wait or freeze. */
if (stream->xine->port_ticket->ticket_revoked == 0) {
- stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0);
+ stream->xine->port_ticket->acquire(stream->xine->port_ticket, 1);
stream->video_out->set_property (stream->video_out, param, value);
stream->audio_out->set_property (stream->audio_out, param, value);
- stream->xine->port_ticket->release(stream->xine->port_ticket, 0);
+ stream->xine->port_ticket->release(stream->xine->port_ticket, 1);
}
}
pthread_mutex_unlock (&stream->frontend_lock);
@@ -581,48 +581,48 @@
break;
case XINE_PARAM_AUDIO_VOLUME:
- stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0);
+ stream->xine->port_ticket->acquire(stream->xine->port_ticket, 1);
if (!stream->audio_out)
ret = -1;
else
ret = stream->audio_out->get_property (stream->audio_out, AO_PROP_MIXER_VOL);
- stream->xine->port_ticket->release(stream->xine->port_ticket, 0);
+ stream->xine->port_ticket->release(stream->xine->port_ticket, 1);
break;
case XINE_PARAM_AUDIO_MUTE:
- stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0);
+ stream->xine->port_ticket->acquire(stream->xine->port_ticket, 1);
if (!stream->audio_out)
ret = -1;
else
ret = stream->audio_out->get_property (stream->audio_out, AO_PROP_MUTE_VOL);
- stream->xine->port_ticket->release(stream->xine->port_ticket, 0);
+ stream->xine->port_ticket->release(stream->xine->port_ticket, 1);
break;
case XINE_PARAM_AUDIO_COMPR_LEVEL:
- stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0);
+ stream->xine->port_ticket->acquire(stream->xine->port_ticket, 1);
if (!stream->audio_out)
ret = -1;
else
ret = stream->audio_out->get_property (stream->audio_out, AO_PROP_COMPRESSOR);
- stream->xine->port_ticket->release(stream->xine->port_ticket, 0);
+ stream->xine->port_ticket->release(stream->xine->port_ticket, 1);
break;
case XINE_PARAM_AUDIO_AMP_LEVEL:
- stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0);
+ stream->xine->port_ticket->acquire(stream->xine->port_ticket, 1);
if (!stream->audio_out)
ret = -1;
else
ret = stream->audio_out->get_property (stream->audio_out, AO_PROP_AMP);
- stream->xine->port_ticket->release(stream->xine->port_ticket, 0);
+ stream->xine->port_ticket->release(stream->xine->port_ticket, 1);
break;
case XINE_PARAM_AUDIO_AMP_MUTE:
- stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0);
+ stream->xine->port_ticket->acquire(stream->xine->port_ticket, 1);
if (!stream->audio_out)
ret = -1;
else
ret = stream->audio_out->get_property (stream->audio_out, AO_PROP_AMP_MUTE);
- stream->xine->port_ticket->release(stream->xine->port_ticket, 0);
+ stream->xine->port_ticket->release(stream->xine->port_ticket, 1);
break;
case XINE_PARAM_EQ_30HZ:
@@ -635,13 +635,13 @@
case XINE_PARAM_EQ_4000HZ:
case XINE_PARAM_EQ_8000HZ:
case XINE_PARAM_EQ_16000HZ:
- stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0);
+ stream->xine->port_ticket->acquire(stream->xine->port_ticket, 1);
if (!stream->audio_out)
ret = -1;
else
ret= stream->audio_out->get_property (stream->audio_out,
param - XINE_PARAM_EQ_30HZ + AO_PROP_EQ_30HZ);
- stream->xine->port_ticket->release(stream->xine->port_ticket, 0);
+ stream->xine->port_ticket->release(stream->xine->port_ticket, 1);
break;
case XINE_PARAM_VERBOSITY:
@@ -666,9 +666,9 @@
case XINE_PARAM_VO_CROP_RIGHT:
case XINE_PARAM_VO_CROP_TOP:
case XINE_PARAM_VO_CROP_BOTTOM:
- stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0);
+ stream->xine->port_ticket->acquire(stream->xine->port_ticket, 1);
ret = stream->video_out->get_property(stream->video_out, param);
- stream->xine->port_ticket->release(stream->xine->port_ticket, 0);
+ stream->xine->port_ticket->release(stream->xine->port_ticket, 1);
break;
case XINE_PARAM_IGNORE_VIDEO:
|