pthread_mutex_lock(&mm->mm_tables_lock);
while ((mt = TAILQ_FIRST(&mm->mm_defer_tables)) != NULL) {
+ mpegts_table_consistency_check(mm);
TAILQ_REMOVE(&mm->mm_defer_tables, mt, mt_defer_link);
if (mt->mt_defer_cmd == MT_DEFER_OPEN_PID && !mt->mt_destroyed) {
mt->mt_defer_cmd = 0;
mpegts_table_release(mt);
pthread_mutex_lock(&mm->mm_tables_lock);
}
+ mpegts_table_consistency_check(mm);
pthread_mutex_unlock(&mm->mm_tables_lock);
}
}
pthread_mutex_unlock(&mi->mi_input_lock);
- /* Flush table Q */
- pthread_mutex_lock(&mi->mi_output_lock);
+ /* Flush table Q - the global lock is already held */
TAILQ_FOREACH(mtf, &mi->mi_table_queue, mtf_link) {
if (mtf->mtf_mux == mm)
mtf->mtf_mux = NULL;
(mi->mi_destroyed_muxes_count + 1) *
sizeof(mpegts_mux_t *));
mi->mi_destroyed_muxes[mi->mi_destroyed_muxes_count++] = mm;
- pthread_mutex_unlock(&mi->mi_output_lock);
}
static void
/* Log */
pthread_mutex_lock(&mm->mm_tables_lock);
+ mpegts_table_consistency_check(mm);
LIST_FOREACH(mt, &mm->mm_tables, mt_link) {
if (mt->mt_flags & MT_QUICKREQ) {
const char *s = "not found";
int c, q;
char buf[256];
mpegts_mux_t *mm = aux;
- mpegts_table_t *mt, *nxt;
+ mpegts_table_t *mt;
mpegts_mux_nice_name(mm, buf, sizeof(buf));
/* Timeout */
/* Check tables */
again:
pthread_mutex_lock(&mm->mm_tables_lock);
+ mpegts_table_consistency_check(mm);
c = q = 0;
- for (mt = LIST_FIRST(&mm->mm_tables); mt != NULL; mt = nxt) {
- nxt = LIST_NEXT(mt, mt_link);
+ LIST_FOREACH(mt, &mm->mm_tables, mt_link) {
if (!(mt->mt_flags & MT_QUICKREQ)) continue;
if (!mt->mt_count) {
+ mpegts_table_grab(mt);
pthread_mutex_unlock(&mm->mm_tables_lock);
mpegts_table_destroy(mt);
+ mpegts_table_release(mt);
goto again;
} else if (!mt->mt_complete) {
q++;
#include <assert.h>
+void
+mpegts_table_consistency_check ( mpegts_mux_t *mm )
+{
+#if ENABLE_TRACE
+ int i, c = 0;
+ mpegts_table_t *mt;
+
+ lock_assert(&mm->mm_tables_lock);
+
+ i = mm->mm_num_tables;
+ LIST_FOREACH(mt, &mm->mm_tables, mt_link)
+ c++;
+
+ if (i != c) {
+ tvherror("mpegts", "tables count inconsistency (num %d, list %d)", i, c);
+ abort();
+ }
+#endif
+}
+
static void
mpegts_table_fastswitch ( mpegts_mux_t *mm )
{
mpegts_mux_t *mm = mt->mt_mux;
pthread_mutex_lock(&mm->mm_tables_lock);
+ mpegts_table_consistency_check(mm);
mt->mt_destroyed = 1;
mt->mt_mux->mm_close_table(mt->mt_mux, mt);
+ mpegts_table_consistency_check(mm);
pthread_mutex_unlock(&mm->mm_tables_lock);
mpegts_table_release(mt);
}
/* Check for existing */
pthread_mutex_lock(&mm->mm_tables_lock);
+ mpegts_table_consistency_check(mm);
LIST_FOREACH(mt, &mm->mm_tables, mt_link) {
if (mt->mt_opaque != opaque)
continue;
if (!(flags & MT_SKIPSUBS) && !mt->mt_subscribed)
mm->mm_open_table(mm, mt, 1);
}
+ mpegts_table_consistency_check(mm);
pthread_mutex_unlock(&mm->mm_tables_lock);
return mt;
}
subscribe = 0;
}
mm->mm_open_table(mm, mt, subscribe);
+ mpegts_table_consistency_check(mm);
pthread_mutex_unlock(&mm->mm_tables_lock);
return mt;
}
descrambler_flush_tables(mm);
pthread_mutex_lock(&mm->mm_tables_lock);
+ mpegts_table_consistency_check(mm);
while ((mt = TAILQ_FIRST(&mm->mm_defer_tables))) {
TAILQ_REMOVE(&mm->mm_defer_tables, mt, mt_defer_link);
mt->mt_defer_cmd = 0;
while ((mt = LIST_FIRST(&mm->mm_tables))) {
mt->mt_flags &= ~MT_DEFER; /* force destroy */
mt->mt_destroyed = 1; /* early destroy mark */
+ mpegts_table_grab(mt);
+ mpegts_table_consistency_check(mm);
pthread_mutex_unlock(&mm->mm_tables_lock);
mpegts_table_destroy(mt);
+ mpegts_table_release(mt);
pthread_mutex_lock(&mm->mm_tables_lock);
+ mpegts_table_consistency_check(mm);
}
+ assert(mm->mm_num_tables == 0);
+ assert(TAILQ_FIRST(&mm->mm_defer_tables) == NULL);
+ assert(LIST_FIRST(&mm->mm_tables) == NULL);
pthread_mutex_unlock(&mm->mm_tables_lock);
}