From 98473cd229c28e6d026a93a5f5c17aa8a426caa4 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Fri, 25 Jul 2014 20:53:34 +0200 Subject: [PATCH] mpegts tables: fix the deferred tables locking mechanism --- src/input/mpegts.h | 6 ++++- src/input/mpegts/mpegts_input.c | 22 +++-------------- src/input/mpegts/mpegts_mux.c | 42 +++++++++++++++----------------- src/input/mpegts/mpegts_table.c | 43 ++++++++++++++++++++++++++------- 4 files changed, 63 insertions(+), 50 deletions(-) diff --git a/src/input/mpegts.h b/src/input/mpegts.h index 258e524b..bcd56c00 100644 --- a/src/input/mpegts.h +++ b/src/input/mpegts.h @@ -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, diff --git a/src/input/mpegts/mpegts_input.c b/src/input/mpegts/mpegts_input.c index 2cfa2a0a..55caae25 100644 --- a/src/input/mpegts/mpegts_input.c +++ b/src/input/mpegts/mpegts_input.c @@ -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); diff --git a/src/input/mpegts/mpegts_mux.c b/src/input/mpegts/mpegts_mux.c index 3744cf97..01a92b3a 100644 --- a/src/input/mpegts/mpegts_mux.c +++ b/src/input/mpegts/mpegts_mux.c @@ -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); diff --git a/src/input/mpegts/mpegts_table.c b/src/input/mpegts/mpegts_table.c index 89f100f5..4fea27c1 100644 --- a/src/input/mpegts/mpegts_table.c +++ b/src/input/mpegts/mpegts_table.c @@ -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); } /*