avcodec/bitstream: try to make vlc init code inherently thread safe
authorMichael Niedermayer <michaelni@gmx.at>
Mon, 16 Jun 2014 17:40:02 +0000 (19:40 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Mon, 16 Jun 2014 18:09:21 +0000 (20:09 +0200)
also remove spinlock, it doesnt work on AIX

Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
libavcodec/bitstream.c
libavcodec/get_bits.h

index c61243e..e3e870f 100644 (file)
@@ -163,7 +163,7 @@ static int build_table(VLC *vlc, int table_nb_bits, int nb_codes,
     int table_size, table_index, index, code_prefix, symbol, subtable_bits;
     int i, j, k, n, nb, inc;
     uint32_t code;
-    VLC_TYPE (*table)[2];
+    volatile VLC_TYPE (*table)[2];
 
     table_size = 1 << table_nb_bits;
     if (table_nb_bits > 30)
@@ -172,7 +172,7 @@ static int build_table(VLC *vlc, int table_nb_bits, int nb_codes,
     av_dlog(NULL, "new table index=%d size=%d\n", table_index, table_size);
     if (table_index < 0)
         return table_index;
-    table = &vlc->table[table_index];
+    table = (volatile VLC_TYPE (*)[2])&vlc->table[table_index];
 
     /* first pass: map codes and compute auxiliary table sizes */
     for (i = 0; i < nb_codes; i++) {
@@ -190,8 +190,9 @@ static int build_table(VLC *vlc, int table_nb_bits, int nb_codes,
                 inc = 1 << n;
             }
             for (k = 0; k < nb; k++) {
+                int bits = table[j][1];
                 av_dlog(NULL, "%4x: code=%d n=%d\n", j, i, n);
-                if (table[j][1] /*bits*/ != 0) {
+                if (bits != 0 && bits != n) {
                     av_log(NULL, AV_LOG_ERROR, "incorrect codes\n");
                     return AVERROR_INVALIDDATA;
                 }
@@ -226,7 +227,7 @@ static int build_table(VLC *vlc, int table_nb_bits, int nb_codes,
             if (index < 0)
                 return index;
             /* note: realloc has been done, so reload tables */
-            table = &vlc->table[table_index];
+            table = (volatile VLC_TYPE (*)[2])&vlc->table[table_index];
             table[j][0] = index; //code
             av_assert0(table[j][0] == index);
             i = k-1;
@@ -268,7 +269,7 @@ static int build_table(VLC *vlc, int table_nb_bits, int nb_codes,
    'use_static' should be set to 1 for tables, which should be freed
    with av_free_static(), 0 if ff_free_vlc() will be used.
 */
-int ff_init_vlc_sparse(VLC *vlc, int nb_bits, int nb_codes,
+int ff_init_vlc_sparse(VLC *vlc_arg, int nb_bits, int nb_codes,
                        const void *bits, int bits_wrap, int bits_size,
                        const void *codes, int codes_wrap, int codes_size,
                        const void *symbols, int symbols_wrap, int symbols_size,
@@ -277,19 +278,16 @@ int ff_init_vlc_sparse(VLC *vlc, int nb_bits, int nb_codes,
     VLCcode *buf;
     int i, j, ret;
     VLCcode localbuf[1500]; // the maximum currently needed is 1296 by rv34
-    void *state;
+    VLC localvlc, *vlc;
 
+    vlc = vlc_arg;
     vlc->bits = nb_bits;
     if (flags & INIT_VLC_USE_NEW_STATIC) {
-        while (state = avpriv_atomic_ptr_cas(&vlc->init_state, NULL, vlc)) {
-            if (state == vlc + 1) {
-                av_assert0(vlc->table_size && vlc->table_size == vlc->table_allocated);
-                return 0;
-            }
-        }
-        av_assert0(!vlc->table_size);
         av_assert0(nb_codes + 1 <= FF_ARRAY_ELEMS(localbuf));
         buf = localbuf;
+        localvlc = *vlc_arg;
+        vlc = &localvlc;
+        vlc->table_size = 0;
     } else {
         vlc->table           = NULL;
         vlc->table_allocated = 0;
@@ -342,9 +340,9 @@ int ff_init_vlc_sparse(VLC *vlc, int nb_bits, int nb_codes,
     if (flags & INIT_VLC_USE_NEW_STATIC) {
         if(vlc->table_size != vlc->table_allocated)
             av_log(NULL, AV_LOG_ERROR, "needed %d had %d\n", vlc->table_size, vlc->table_allocated);
-        state = avpriv_atomic_ptr_cas(&vlc->init_state, vlc, vlc+1);
-        av_assert0(state == vlc);
+
         av_assert0(ret >= 0);
+        *vlc_arg = *vlc;
     } else {
         av_free(buf);
         if (ret < 0) {
index ddcef50..d8d7b6e 100644 (file)
@@ -64,7 +64,6 @@ typedef struct VLC {
     int bits;
     VLC_TYPE (*table)[2]; ///< code, bits
     int table_size, table_allocated;
-    void * volatile init_state;
 } VLC;
 
 typedef struct RL_VLC_ELEM {