Merge commit '517ce1d09b5e6b72afc2ef9490b5f8ca42fa6a65' into release/2.4
authorMichael Niedermayer <michaelni@gmx.at>
Thu, 27 Nov 2014 23:57:32 +0000 (00:57 +0100)
committerMichael Niedermayer <michaelni@gmx.at>
Fri, 28 Nov 2014 00:00:50 +0000 (01:00 +0100)
* commit '517ce1d09b5e6b72afc2ef9490b5f8ca42fa6a65':
  lavu: fix memory leaks by using a mutex instead of atomics

Conflicts:
libavutil/buffer.c

The atomics code is left in place as a fallback for synchronization in the
absence of p/w32 threads. Our ABI did not requires applications to
only use threads (and matching ones) to what libavutil was build with
Our code also was not affected by the leak this change fixes, though
no question the atomics based implementation is not pretty at all.
First and foremost the code must work, being pretty comes after that.

If this causes problems, for example when libavutil is used by multiple
applications each using a different kind of threading system then the
default possibly has to be changed to the uglier atomics.

See: cea3a63ba3d89d8403eef008f7a7c54d645cff70
Merged-by: Michael Niedermayer <michaelni@gmx.at>
1  2 
libavutil/buffer.c
libavutil/buffer_internal.h

  #include "buffer_internal.h"
  #include "common.h"
  #include "mem.h"
+ #include "thread.h"
++#define USE_ATOMICS !(HAVE_PTHREADS || HAVE_W32THREADS)
 +
  AVBufferRef *av_buffer_create(uint8_t *data, int size,
                                void (*free)(void *opaque, uint8_t *data),
                                void *opaque, int flags)
@@@ -287,10 -245,11 +293,18 @@@ static void pool_release_buffer(void *o
      BufferPoolEntry *buf = opaque;
      AVBufferPool *pool = buf->pool;
  
 +    if(CONFIG_MEMORY_POISONING)
 +        memset(buf->data, FF_MEMORY_POISON, pool->size);
 +
++#if USE_ATOMICS
 +    add_to_pool(buf);
++#else
+     ff_mutex_lock(&pool->mutex);
+     buf->next = pool->pool;
+     pool->pool = buf;
+     ff_mutex_unlock(&pool->mutex);
++#endif
      if (!avpriv_atomic_int_add_and_fetch(&pool->refcount, -1))
          buffer_pool_free(pool);
  }
@@@ -320,9 -279,6 +334,11 @@@ static AVBufferRef *pool_alloc_buffer(A
      ret->buffer->opaque = buf;
      ret->buffer->free   = pool_release_buffer;
  
++#if USE_ATOMICS
 +    avpriv_atomic_int_add_and_fetch(&pool->refcount, 1);
 +    avpriv_atomic_int_add_and_fetch(&pool->nb_allocated, 1);
++#endif
 +
      return ret;
  }
  
@@@ -331,28 -287,22 +347,46 @@@ AVBufferRef *av_buffer_pool_get(AVBuffe
      AVBufferRef *ret;
      BufferPoolEntry *buf;
  
-     avpriv_atomic_int_add_and_fetch(&pool->refcount, 1);
++#if USE_ATOMICS
 +    /* check whether the pool is empty */
 +    buf = get_pool(pool);
 +    if (!buf && pool->refcount <= pool->nb_allocated) {
 +        av_log(NULL, AV_LOG_DEBUG, "Pool race dectected, spining to avoid overallocation and eventual OOM\n");
 +        while (!buf && avpriv_atomic_int_get(&pool->refcount) <= avpriv_atomic_int_get(&pool->nb_allocated))
 +            buf = get_pool(pool);
 +    }
 +
 +    if (!buf)
 +        return pool_alloc_buffer(pool);
 +
 +    /* keep the first entry, return the rest of the list to the pool */
 +    add_to_pool(buf->next);
 +    buf->next = NULL;
 +
 +    ret = av_buffer_create(buf->data, pool->size, pool_release_buffer,
 +                           buf, 0);
 +    if (!ret) {
 +        add_to_pool(buf);
 +        return NULL;
 +    }
++#else
+     ff_mutex_lock(&pool->mutex);
+     buf = pool->pool;
+     if (buf) {
+         ret = av_buffer_create(buf->data, pool->size, pool_release_buffer,
+                                buf, 0);
+         if (ret) {
+             pool->pool = buf->next;
+             buf->next = NULL;
+         }
+     } else {
+         ret = pool_alloc_buffer(pool);
+     }
+     ff_mutex_unlock(&pool->mutex);
++#endif
+     if (ret)
+         avpriv_atomic_int_add_and_fetch(&pool->refcount, 1);
  
      return ret;
  }
Simple merge