mpegts tables: fix the deferred tables locking mechanism

This commit is contained in:
Jaroslav Kysela 2014-07-25 20:53:34 +02:00
parent f72733ff08
commit 98473cd229
4 changed files with 63 additions and 50 deletions

View file

@ -179,7 +179,9 @@ struct mpegts_table
uint8_t mt_finished;
uint8_t mt_subscribed;
uint8_t mt_defer_cmd;
uint8_t mt_defer_reg;
#define MT_DEFER_OPEN_PID 1
#define MT_DEFER_CLOSE_PID 2
int mt_count;
@ -769,6 +771,8 @@ static inline void mpegts_table_release
assert(mt->mt_refcount > 0);
if(--mt->mt_refcount == 0) mpegts_table_release_(mt);
}
int mpegts_table_type
( mpegts_table_t *mt );
mpegts_table_t *mpegts_table_add
(mpegts_mux_t *mm, int tableid, int mask,
mpegts_table_callback_t callback, void *opaque,

View file

@ -590,37 +590,23 @@ static void
mpegts_input_table_waiting ( mpegts_input_t *mi, mpegts_mux_t *mm )
{
mpegts_table_t *mt;
int type;
pthread_mutex_lock(&mm->mm_tables_lock);
while ((mt = LIST_FIRST(&mm->mm_defer_tables)) != NULL) {
LIST_REMOVE(mt, mt_defer_link);
if (mt->mt_destroyed)
continue;
type = 0;
if (mt->mt_flags & MT_FAST) type |= MPS_FTABLE;
if (mt->mt_flags & MT_SLOW) type |= MPS_TABLE;
if (mt->mt_flags & MT_RECORD) type |= MPS_STREAM;
if ((type & (MPS_FTABLE | MPS_TABLE)) == 0) type |= MPS_TABLE;
if (mt->mt_defer_cmd == 1) {
if (mt->mt_defer_cmd == MT_DEFER_OPEN_PID && !mt->mt_destroyed) {
mt->mt_defer_cmd = 0;
mt->mt_defer_reg = 1;
LIST_INSERT_HEAD(&mm->mm_tables, mt, mt_link);
mm->mm_num_tables++;
if (!mt->mt_subscribed) {
mt->mt_subscribed = 1;
pthread_mutex_unlock(&mm->mm_tables_lock);
mi->mi_open_pid(mi, mm, mt->mt_pid, type, mt);
mi->mi_open_pid(mi, mm, mt->mt_pid, mpegts_table_type(mt), mt);
}
} else if (mt->mt_defer_cmd == 2) {
} else if (mt->mt_defer_cmd == MT_DEFER_CLOSE_PID) {
mt->mt_defer_cmd = 0;
mt->mt_defer_reg = 0;
LIST_REMOVE(mt, mt_link);
mm->mm_num_tables--;
if (mt->mt_subscribed) {
mt->mt_subscribed = 0;
pthread_mutex_unlock(&mm->mm_tables_lock);
mi->mi_close_pid(mi, mm, mt->mt_pid, type, mt);
mi->mi_close_pid(mi, mm, mt->mt_pid, mpegts_table_type(mt), mt);
}
} else {
pthread_mutex_unlock(&mm->mm_tables_lock);

View file

@ -708,13 +708,12 @@ void
mpegts_mux_open_table ( mpegts_mux_t *mm, mpegts_table_t *mt, int subscribe )
{
mpegts_input_t *mi;
int type = 0;
if (mt->mt_flags & MT_FAST) type |= MPS_FTABLE;
if (mt->mt_flags & MT_SLOW) type |= MPS_TABLE;
if (mt->mt_flags & MT_RECORD) type |= MPS_STREAM;
if ((type & (MPS_FTABLE | MPS_TABLE)) == 0) type |= MPS_TABLE;
pthread_mutex_lock(&mm->mm_tables_lock);
if (mt->mt_destroyed) {
pthread_mutex_unlock(&mm->mm_tables_lock);
return;
}
if (!mm->mm_active || !mm->mm_active->mmi_input) {
mt->mt_subscribed = 0;
LIST_INSERT_HEAD(&mm->mm_tables, mt, mt_link);
@ -723,12 +722,14 @@ mpegts_mux_open_table ( mpegts_mux_t *mm, mpegts_table_t *mt, int subscribe )
return;
}
if (mt->mt_flags & MT_DEFER) {
if (mt->mt_defer_reg || mt->mt_defer_cmd == 1) {
if (mt->mt_defer_cmd == MT_DEFER_OPEN_PID) {
pthread_mutex_unlock(&mm->mm_tables_lock);
return;
}
mpegts_table_grab(mt); /* thread will release the table */
mt->mt_defer_cmd = 1;
LIST_INSERT_HEAD(&mm->mm_tables, mt, mt_link);
mm->mm_num_tables++;
mt->mt_defer_cmd = MT_DEFER_OPEN_PID;
LIST_INSERT_HEAD(&mm->mm_defer_tables, mt, mt_defer_link);
pthread_mutex_unlock(&mm->mm_tables_lock);
return;
@ -739,7 +740,7 @@ mpegts_mux_open_table ( mpegts_mux_t *mm, mpegts_table_t *mt, int subscribe )
pthread_mutex_unlock(&mm->mm_tables_lock);
pthread_mutex_lock(&mi->mi_output_lock);
if (subscribe) {
mi->mi_open_pid(mi, mm, mt->mt_pid, type, mt);
mi->mi_open_pid(mi, mm, mt->mt_pid, mpegts_table_type(mt), mt);
mt->mt_subscribed = 1;
}
pthread_mutex_unlock(&mi->mi_output_lock);
@ -749,14 +750,13 @@ void
mpegts_mux_close_table ( mpegts_mux_t *mm, mpegts_table_t *mt )
{
mpegts_input_t *mi;
int type = 0;
if (mt->mt_flags & MT_FAST) type |= MPS_FTABLE;
if (mt->mt_flags & MT_SLOW) type |= MPS_TABLE;
if (mt->mt_flags & MT_RECORD) type |= MPS_STREAM;
if ((type & (MPS_FTABLE | MPS_TABLE)) == 0) type |= MPS_TABLE;
pthread_mutex_lock(&mm->mm_tables_lock);
if (!mm->mm_active || !mm->mm_active->mmi_input) {
if (mt->mt_defer_cmd) {
LIST_REMOVE(mt, mt_defer_link);
mt->mt_defer_cmd = 0;
}
mt->mt_subscribed = 0;
LIST_REMOVE(mt, mt_link);
mm->mm_num_tables--;
@ -764,23 +764,21 @@ mpegts_mux_close_table ( mpegts_mux_t *mm, mpegts_table_t *mt )
return;
}
if (mt->mt_flags & MT_DEFER) {
if (mt->mt_defer_cmd == 2) {
if (mt->mt_defer_cmd == MT_DEFER_CLOSE_PID) {
pthread_mutex_unlock(&mm->mm_tables_lock);
return;
}
if (mt->mt_defer_cmd == 1) {
if (mt->mt_defer_cmd == MT_DEFER_OPEN_PID) {
LIST_REMOVE(mt, mt_defer_link);
mt->mt_defer_cmd = 0;
pthread_mutex_unlock(&mm->mm_tables_lock);
mpegts_table_release(mt);
return;
}
if (!mt->mt_defer_reg) {
pthread_mutex_unlock(&mm->mm_tables_lock);
return;
}
mpegts_table_grab(mt); /* thread will release the table */
mt->mt_defer_cmd = 2;
mpegts_table_grab(mt); /* thread will free the table */
LIST_REMOVE(mt, mt_link);
mm->mm_num_tables--;
mt->mt_defer_cmd = MT_DEFER_CLOSE_PID;
LIST_INSERT_HEAD(&mm->mm_defer_tables, mt, mt_defer_link);
pthread_mutex_unlock(&mm->mm_tables_lock);
return;
@ -791,7 +789,7 @@ mpegts_mux_close_table ( mpegts_mux_t *mm, mpegts_table_t *mt )
pthread_mutex_unlock(&mm->mm_tables_lock);
pthread_mutex_lock(&mi->mi_output_lock);
if (mt->mt_subscribed) {
mi->mi_close_pid(mi, mm, mt->mt_pid, type, mt);
mi->mi_close_pid(mi, mm, mt->mt_pid, mpegts_table_type(mt), mt);
mt->mt_subscribed = 0;
}
pthread_mutex_unlock(&mi->mi_output_lock);

View file

@ -126,6 +126,19 @@ mpegts_table_destroy ( mpegts_table_t *mt )
mpegts_table_release(mt);
}
/**
* Determine table type
*/
int
mpegts_table_type ( mpegts_table_t *mt )
{
int type = 0;
if (mt->mt_flags & MT_FAST) type |= MPS_FTABLE;
if (mt->mt_flags & MT_SLOW) type |= MPS_TABLE;
if (mt->mt_flags & MT_RECORD) type |= MPS_STREAM;
if ((type & (MPS_FTABLE | MPS_TABLE)) == 0) type |= MPS_TABLE;
return type;
}
/**
* Add a new DVB table
@ -206,26 +219,38 @@ void
mpegts_table_flush_all ( mpegts_mux_t *mm )
{
mpegts_table_t *mt;
mpegts_input_t *mi;
descrambler_flush_tables(mm);
mi = mm->mm_active ? mm->mm_active->mmi_input : NULL;
pthread_mutex_lock(&mm->mm_tables_lock);
while ((mt = LIST_FIRST(&mm->mm_defer_tables))) {
LIST_REMOVE(mt, mt_defer_link);
if (!mt->mt_defer_reg) {
/* registration not fished, but ... */
/* allow the table free in next table destroy loop */
mt->mt_defer_reg = 1;
LIST_INSERT_HEAD(&mm->mm_tables, mt, mt_link);
mm->mm_num_tables++;
if (mt->mt_defer_cmd == MT_DEFER_CLOSE_PID) {
if (mi) {
pthread_mutex_unlock(&mm->mm_tables_lock);
pthread_mutex_lock(&mi->mi_output_lock);
if (mt->mt_subscribed) {
mi->mi_close_pid(mi, mm, mt->mt_pid, mpegts_table_type(mt), mt);
mt->mt_subscribed = 0;
}
pthread_mutex_unlock(&mi->mi_output_lock);
pthread_mutex_lock(&mm->mm_tables_lock);
} else{
mt->mt_subscribed = 0;
}
}
mt->mt_defer_cmd = 0;
mpegts_table_release(mt);
}
pthread_mutex_unlock(&mm->mm_tables_lock);
while ((mt = LIST_FIRST(&mm->mm_tables))) {
if ((mt->mt_flags & MT_DEFER) && mt->mt_defer_reg)
mt->mt_flags &= ~MT_DEFER; /* force destroy */
mt->mt_flags &= ~MT_DEFER; /* force destroy */
mt->mt_destroyed = 1; /* early destroy mark */
pthread_mutex_unlock(&mm->mm_tables_lock);
mpegts_table_destroy(mt);
pthread_mutex_lock(&mm->mm_tables_lock);
}
pthread_mutex_unlock(&mm->mm_tables_lock);
}
/*