mpegts: add MT_DEFER tables for descrambler
This patch tries to fix mutex deadlocks: descrambler_lock <-> input_lock The defered table type allows to move the critical (pid open/close) calls outside the table registration calls.
This commit is contained in:
parent
d81a612c5d
commit
1f2e33b864
5 changed files with 113 additions and 13 deletions
|
@ -442,7 +442,8 @@ descrambler_open_pid_( mpegts_mux_t *mux, void *opaque, int pid,
|
|||
dt = calloc(1, sizeof(*dt));
|
||||
TAILQ_INIT(&dt->sections);
|
||||
dt->table = mpegts_table_add(mux, 0, 0, descrambler_table_callback,
|
||||
dt, "descrambler", MT_FULL | flags, pid);
|
||||
dt, "descrambler",
|
||||
MT_FULL | MT_DEFER | flags, pid);
|
||||
if (dt->table)
|
||||
dt->table->mt_service = (mpegts_service_t *)service;
|
||||
TAILQ_INSERT_TAIL(&mux->mm_descrambler_tables, dt, link);
|
||||
|
|
|
@ -142,14 +142,15 @@ struct mpegts_table
|
|||
*/
|
||||
int mt_flags;
|
||||
|
||||
#define MT_CRC 0x01
|
||||
#define MT_FULL 0x02
|
||||
#define MT_QUICKREQ 0x04
|
||||
#define MT_RECORD 0x08
|
||||
#define MT_SKIPSUBS 0x10
|
||||
#define MT_SCANSUBS 0x20
|
||||
#define MT_FAST 0x40
|
||||
#define MT_SLOW 0x80
|
||||
#define MT_CRC 0x0001
|
||||
#define MT_FULL 0x0002
|
||||
#define MT_QUICKREQ 0x0004
|
||||
#define MT_RECORD 0x0008
|
||||
#define MT_SKIPSUBS 0x0010
|
||||
#define MT_SCANSUBS 0x0020
|
||||
#define MT_FAST 0x0040
|
||||
#define MT_SLOW 0x0080
|
||||
#define MT_DEFER 0x0100
|
||||
|
||||
/**
|
||||
* Cycle queue
|
||||
|
@ -164,6 +165,7 @@ struct mpegts_table
|
|||
*/
|
||||
|
||||
LIST_ENTRY(mpegts_table) mt_link;
|
||||
LIST_ENTRY(mpegts_table) mt_defer_link;
|
||||
mpegts_mux_t *mt_mux;
|
||||
|
||||
char *mt_name;
|
||||
|
@ -174,8 +176,10 @@ struct mpegts_table
|
|||
RB_HEAD(,mpegts_table_state) mt_state;
|
||||
int mt_complete;
|
||||
int mt_incomplete;
|
||||
int mt_finished;
|
||||
int mt_subscribed;
|
||||
uint8_t mt_finished;
|
||||
uint8_t mt_subscribed;
|
||||
uint8_t mt_defer_cmd;
|
||||
uint8_t mt_defer_reg;
|
||||
|
||||
int mt_count;
|
||||
|
||||
|
@ -371,6 +375,8 @@ struct mpegts_mux
|
|||
|
||||
int mm_num_tables;
|
||||
LIST_HEAD(, mpegts_table) mm_tables;
|
||||
LIST_HEAD(, mpegts_table) mm_defer_tables;
|
||||
pthread_mutex_t mm_defer_tables_lock;
|
||||
TAILQ_HEAD(, mpegts_table) mm_table_queue;
|
||||
|
||||
LIST_HEAD(, caid) mm_descrambler_caids;
|
||||
|
|
|
@ -576,6 +576,51 @@ mpegts_input_table_dispatch ( mpegts_mux_t *mm, const uint8_t *tsb )
|
|||
}
|
||||
}
|
||||
|
||||
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_defer_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) {
|
||||
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_defer_tables_lock);
|
||||
mi->mi_open_pid(mi, mm, mt->mt_pid, type, mt);
|
||||
}
|
||||
} else if (mt->mt_defer_cmd == 2) {
|
||||
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_defer_tables_lock);
|
||||
mi->mi_close_pid(mi, mm, mt->mt_pid, type, mt);
|
||||
}
|
||||
} else {
|
||||
pthread_mutex_unlock(&mm->mm_defer_tables_lock);
|
||||
}
|
||||
mpegts_table_release(mt);
|
||||
pthread_mutex_lock(&mm->mm_defer_tables_lock);
|
||||
}
|
||||
pthread_mutex_unlock(&mm->mm_defer_tables_lock);
|
||||
}
|
||||
|
||||
static void
|
||||
mpegts_input_process
|
||||
( mpegts_input_t *mi, mpegts_packet_t *mpkt )
|
||||
|
@ -723,8 +768,10 @@ mpegts_input_thread ( void * p )
|
|||
|
||||
/* Process */
|
||||
pthread_mutex_lock(&mi->mi_output_lock);
|
||||
if (mp->mp_mux && mp->mp_mux->mm_active)
|
||||
if (mp->mp_mux && mp->mp_mux->mm_active) {
|
||||
mpegts_input_table_waiting(mi, mp->mp_mux);
|
||||
mpegts_input_process(mi, mp);
|
||||
}
|
||||
pthread_mutex_unlock(&mi->mi_output_lock);
|
||||
|
||||
/* Cleanup */
|
||||
|
|
|
@ -720,6 +720,18 @@ mpegts_mux_open_table ( mpegts_mux_t *mm, mpegts_table_t *mt, int subscribe )
|
|||
mm->mm_num_tables++;
|
||||
return;
|
||||
}
|
||||
if (mt->mt_flags & MT_DEFER) {
|
||||
pthread_mutex_lock(&mm->mm_defer_tables_lock);
|
||||
if (mt->mt_defer_reg || mt->mt_defer_cmd == 1) {
|
||||
pthread_mutex_unlock(&mm->mm_defer_tables_lock);
|
||||
return;
|
||||
}
|
||||
mpegts_table_grab(mt); /* thread will release the table */
|
||||
mt->mt_defer_cmd = 1;
|
||||
LIST_INSERT_HEAD(&mm->mm_defer_tables, mt, mt_defer_link);
|
||||
pthread_mutex_unlock(&mm->mm_defer_tables_lock);
|
||||
return;
|
||||
}
|
||||
mi = mm->mm_active->mmi_input;
|
||||
pthread_mutex_lock(&mi->mi_output_lock);
|
||||
LIST_INSERT_HEAD(&mm->mm_tables, mt, mt_link);
|
||||
|
@ -747,6 +759,29 @@ mpegts_mux_close_table ( mpegts_mux_t *mm, mpegts_table_t *mt )
|
|||
mm->mm_num_tables--;
|
||||
return;
|
||||
}
|
||||
if (mt->mt_flags & MT_DEFER) {
|
||||
pthread_mutex_lock(&mm->mm_defer_tables_lock);
|
||||
if (mt->mt_defer_cmd == 2) {
|
||||
pthread_mutex_unlock(&mm->mm_defer_tables_lock);
|
||||
return;
|
||||
}
|
||||
if (mt->mt_defer_cmd == 1) {
|
||||
LIST_REMOVE(mt, mt_defer_link);
|
||||
mt->mt_defer_cmd = 0;
|
||||
pthread_mutex_unlock(&mm->mm_defer_tables_lock);
|
||||
mpegts_table_release(mt);
|
||||
return;
|
||||
}
|
||||
if (!mt->mt_defer_reg) {
|
||||
pthread_mutex_unlock(&mm->mm_defer_tables_lock);
|
||||
return;
|
||||
}
|
||||
mpegts_table_grab(mt); /* thread will release the table */
|
||||
mt->mt_defer_cmd = 2;
|
||||
LIST_INSERT_HEAD(&mm->mm_defer_tables, mt, mt_defer_link);
|
||||
pthread_mutex_unlock(&mm->mm_defer_tables_lock);
|
||||
return;
|
||||
}
|
||||
mi = mm->mm_active->mmi_input;
|
||||
pthread_mutex_lock(&mi->mi_output_lock);
|
||||
LIST_REMOVE(mt, mt_link);
|
||||
|
@ -876,6 +911,7 @@ mpegts_mux_create0
|
|||
/* Table processing */
|
||||
mm->mm_open_table = mpegts_mux_open_table;
|
||||
mm->mm_close_table = mpegts_mux_close_table;
|
||||
pthread_mutex_init(&mm->mm_defer_tables_lock, NULL);
|
||||
TAILQ_INIT(&mm->mm_table_queue);
|
||||
LIST_INIT(&mm->mm_descrambler_caids);
|
||||
TAILQ_INIT(&mm->mm_descrambler_tables);
|
||||
|
|
|
@ -197,8 +197,18 @@ mpegts_table_flush_all ( mpegts_mux_t *mm )
|
|||
{
|
||||
mpegts_table_t *mt;
|
||||
descrambler_flush_tables(mm);
|
||||
while ((mt = LIST_FIRST(&mm->mm_tables)))
|
||||
pthread_mutex_lock(&mm->mm_defer_tables_lock);
|
||||
while ((mt = LIST_FIRST(&mm->mm_defer_tables))) {
|
||||
LIST_REMOVE(mt, mt_defer_link);
|
||||
mt->mt_defer_cmd = 0;
|
||||
mpegts_table_release(mt);
|
||||
}
|
||||
pthread_mutex_unlock(&mm->mm_defer_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 */
|
||||
mpegts_table_destroy(mt);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Add table
Reference in a new issue