mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-23 12:43:46 +02:00
Merge commit 'fbd6c97f9ca858140df16dd07200ea0d4bdc1a83'
* commit 'fbd6c97f9ca858140df16dd07200ea0d4bdc1a83':
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: cea3a63ba3
Merged-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
commit
6db8cd8f37
@ -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;
|
||||
}
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user