aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2014-11-28 00:57:32 +0100
committerMichael Niedermayer <michaelni@gmx.at>2014-11-28 01:00:50 +0100
commitb6691fba77afb0ca6ce6d7ca33fa8285f3c78911 (patch)
treef6855016915f724c36ce2c0c2c4111b6549f2eac
parent15fd62110fd82f19f9e127cf8401756231112ce0 (diff)
parent517ce1d09b5e6b72afc2ef9490b5f8ca42fa6a65 (diff)
downloadffmpeg-b6691fba77afb0ca6ce6d7ca33fa8285f3c78911.tar.gz
Merge commit '517ce1d09b5e6b72afc2ef9490b5f8ca42fa6a65' into release/2.4
* 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>
-rw-r--r--libavutil/buffer.c36
-rw-r--r--libavutil/buffer_internal.h6
2 files changed, 39 insertions, 3 deletions
diff --git a/libavutil/buffer.c b/libavutil/buffer.c
index e9bf54b96c..0f9f1a2992 100644
--- a/libavutil/buffer.c
+++ b/libavutil/buffer.c
@@ -23,6 +23,9 @@
#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),
@@ -209,6 +212,8 @@ AVBufferPool *av_buffer_pool_init(int size, AVBufferRef* (*alloc)(int size))
if (!pool)
return NULL;
+ ff_mutex_init(&pool->mutex, NULL);
+
pool->size = size;
pool->alloc = alloc ? alloc : av_buffer_alloc;
@@ -230,6 +235,7 @@ static void buffer_pool_free(AVBufferPool *pool)
buf->free(buf->opaque, buf->data);
av_freep(&buf);
}
+ ff_mutex_destroy(&pool->mutex);
av_freep(&pool);
}
@@ -290,7 +296,15 @@ static void pool_release_buffer(void *opaque, uint8_t *data)
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,8 +334,10 @@ static AVBufferRef *pool_alloc_buffer(AVBufferPool *pool)
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,6 +347,7 @@ AVBufferRef *av_buffer_pool_get(AVBufferPool *pool)
AVBufferRef *ret;
BufferPoolEntry *buf;
+#if USE_ATOMICS
/* check whether the pool is empty */
buf = get_pool(pool);
if (!buf && pool->refcount <= pool->nb_allocated) {
@@ -352,7 +369,24 @@ AVBufferRef *av_buffer_pool_get(AVBufferPool *pool)
add_to_pool(buf);
return NULL;
}
- avpriv_atomic_int_add_and_fetch(&pool->refcount, 1);
+#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;
}
diff --git a/libavutil/buffer_internal.h b/libavutil/buffer_internal.h
index c29190839e..e6530485d3 100644
--- a/libavutil/buffer_internal.h
+++ b/libavutil/buffer_internal.h
@@ -22,6 +22,7 @@
#include <stdint.h>
#include "buffer.h"
+#include "thread.h"
/**
* The buffer is always treated as read-only.
@@ -68,11 +69,12 @@ typedef struct BufferPoolEntry {
void (*free)(void *opaque, uint8_t *data);
AVBufferPool *pool;
- struct BufferPoolEntry * volatile next;
+ struct BufferPoolEntry *next;
} BufferPoolEntry;
struct AVBufferPool {
- BufferPoolEntry * volatile pool;
+ AVMutex mutex;
+ BufferPoolEntry *pool;
/*
* This is used to track when the pool is to be freed.