mirror of https://git.ffmpeg.org/ffmpeg.git
lavu: add support for atomic operations.
These could be used for reference counting, or for keeping track of decoding progress in references in multithreaded decoders. Support is provided by gcc/msvc/suncc intrinsics, with a fallback using pthread mutexes. Signed-off-by: Anton Khirnov <anton@khirnov.net>
This commit is contained in:
parent
eae0879d96
commit
65f1d45dcc
|
@ -1285,9 +1285,11 @@ HAVE_LIST="
|
|||
loongson
|
||||
machine_ioctl_bt848_h
|
||||
machine_ioctl_meteor_h
|
||||
machine_rw_barrier
|
||||
malloc_h
|
||||
MapViewOfFile
|
||||
memalign
|
||||
MemoryBarrier
|
||||
mkstemp
|
||||
mm_empty
|
||||
mmap
|
||||
|
@ -1322,6 +1324,7 @@ HAVE_LIST="
|
|||
struct_v4l2_frmivalenum_discrete
|
||||
symver_asm_label
|
||||
symver_gnu_asm
|
||||
sync_synchronize
|
||||
sysconf
|
||||
sysctl
|
||||
sys_mman_h
|
||||
|
@ -3453,6 +3456,9 @@ check_func strerror_r
|
|||
check_func strptime
|
||||
check_func strtok_r
|
||||
check_func sched_getaffinity
|
||||
check_builtin sync_synchronize "" "__sync_synchronize()"
|
||||
check_builtin machine_rw_barrier mbarrier.h "__machine_rw_barrier()"
|
||||
check_builtin MemoryBarrier windows.h "MemoryBarrier()"
|
||||
check_func sysconf
|
||||
check_func sysctl
|
||||
check_func usleep
|
||||
|
|
|
@ -54,6 +54,7 @@ BUILT_HEADERS = avconfig.h
|
|||
|
||||
OBJS = adler32.o \
|
||||
aes.o \
|
||||
atomic.o \
|
||||
audio_fifo.o \
|
||||
avstring.o \
|
||||
base64.o \
|
||||
|
@ -100,6 +101,7 @@ SKIPHEADERS = old_pix_fmts.h
|
|||
|
||||
TESTPROGS = adler32 \
|
||||
aes \
|
||||
atomic \
|
||||
avstring \
|
||||
base64 \
|
||||
blowfish \
|
||||
|
|
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* Copyright (c) 2012 Ronald S. Bultje <rsbultje@gmail.com>
|
||||
*
|
||||
* This file is part of Libav.
|
||||
*
|
||||
* Libav is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* Libav is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with Libav; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "atomic.h"
|
||||
|
||||
#if !HAVE_MEMORYBARRIER && !HAVE_SYNC_SYNCHRONIZE && !HAVE_MACHINE_RW_BARRIER
|
||||
|
||||
#if HAVE_PTHREADS
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
static pthread_mutex_t atomic_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
int avpriv_atomic_int_get(volatile int *ptr)
|
||||
{
|
||||
int res;
|
||||
|
||||
pthread_mutex_lock(&atomic_lock);
|
||||
res = *ptr;
|
||||
pthread_mutex_unlock(&atomic_lock);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void avpriv_atomic_int_set(volatile int *ptr, int val)
|
||||
{
|
||||
pthread_mutex_lock(&atomic_lock);
|
||||
*ptr = val;
|
||||
pthread_mutex_unlock(&atomic_lock);
|
||||
}
|
||||
|
||||
int avpriv_atomic_int_add_and_fetch(volatile int *ptr, int inc)
|
||||
{
|
||||
int res;
|
||||
|
||||
pthread_mutex_lock(&atomic_lock);
|
||||
*ptr += inc;
|
||||
res = *ptr;
|
||||
pthread_mutex_unlock(&atomic_lock);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void *avpriv_atomic_ptr_cas(void * volatile *ptr, void *oldval, void *newval)
|
||||
{
|
||||
void *ret;
|
||||
pthread_mutex_lock(&atomic_lock);
|
||||
ret = *ptr;
|
||||
if (*ptr == oldval)
|
||||
*ptr = newval;
|
||||
pthread_mutex_unlock(&atomic_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#elif !HAVE_THREADS
|
||||
|
||||
int avpriv_atomic_int_get(volatile int *ptr)
|
||||
{
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
void avpriv_atomic_int_set(volatile int *ptr, int val)
|
||||
{
|
||||
*ptr = val;
|
||||
}
|
||||
|
||||
int avpriv_atomic_int_add_and_fetch(volatile int *ptr, int inc)
|
||||
{
|
||||
*ptr += inc;
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
void *avpriv_atomic_ptr_cas(void * volatile *ptr, void *oldval, void *newval)
|
||||
{
|
||||
if (*ptr == oldval) {
|
||||
*ptr = newval;
|
||||
return oldval;
|
||||
}
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#error "Threading is enabled, but there is no implementation of atomic operations available"
|
||||
|
||||
#endif /* HAVE_PTHREADS */
|
||||
|
||||
#endif /* !HAVE_MEMORYBARRIER && !HAVE_SYNC_SYNCHRONIZE && !HAVE_MACHINE_RW_BARRIER */
|
||||
|
||||
#ifdef TEST
|
||||
#include <assert.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
volatile int val = 1;
|
||||
int res;
|
||||
|
||||
res = avpriv_atomic_int_add_and_fetch(&val, 1);
|
||||
assert(res == 2);
|
||||
avpriv_atomic_int_set(&val, 3);
|
||||
res = avpriv_atomic_int_get(&val);
|
||||
assert(res == 3);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright (c) 2012 Ronald S. Bultje <rsbultje@gmail.com>
|
||||
*
|
||||
* This file is part of Libav.
|
||||
*
|
||||
* Libav is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* Libav is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with Libav; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef AVUTIL_ATOMIC_H
|
||||
#define AVUTIL_ATOMIC_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#if HAVE_MEMORYBARRIER
|
||||
#include "atomic_win32.h"
|
||||
#elif HAVE_SYNC_SYNCHRONIZE
|
||||
#include "atomic_gcc.h"
|
||||
#elif HAVE_MACHINE_RW_BARRIER
|
||||
#include "atomic_suncc.h"
|
||||
#else
|
||||
|
||||
/**
|
||||
* Load the current value stored in an atomic integer.
|
||||
*
|
||||
* @param ptr atomic integer
|
||||
* @return the current value of the atomic integer
|
||||
* @note This acts as a memory barrier.
|
||||
*/
|
||||
int avpriv_atomic_int_get(volatile int *ptr);
|
||||
|
||||
/**
|
||||
* Store a new value in an atomic integer.
|
||||
*
|
||||
* @param ptr atomic integer
|
||||
* @param val the value to store in the atomic integer
|
||||
* @note This acts as a memory barrier.
|
||||
*/
|
||||
void avpriv_atomic_int_set(volatile int *ptr, int val);
|
||||
|
||||
/**
|
||||
* Add a value to an atomic integer.
|
||||
*
|
||||
* @param ptr atomic integer
|
||||
* @param inc the value to add to the atomic integer (may be negative)
|
||||
* @return the new value of the atomic integer.
|
||||
* @note This does NOT act as a memory barrier. This is primarily
|
||||
* intended for reference counting.
|
||||
*/
|
||||
int avpriv_atomic_int_add_and_fetch(volatile int *ptr, int inc);
|
||||
|
||||
/**
|
||||
* Atomic pointer compare and swap.
|
||||
*
|
||||
* @param ptr pointer to the pointer to operate on
|
||||
* @param oldval do the swap if the current value of *ptr equals to oldval
|
||||
* @param newval value to replace *ptr with
|
||||
* @return the value of *ptr before comparison
|
||||
*/
|
||||
void *avpriv_atomic_ptr_cas(void * volatile *ptr, void *oldval, void *newval);
|
||||
|
||||
#endif /* HAVE_MEMORYBARRIER */
|
||||
#endif /* AVUTIL_ATOMIC_H */
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (c) 2012 Ronald S. Bultje <rsbultje@gmail.com>
|
||||
*
|
||||
* This file is part of Libav.
|
||||
*
|
||||
* Libav is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* Libav is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with Libav; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "atomic.h"
|
||||
|
||||
#define avpriv_atomic_int_get atomic_int_get_gcc
|
||||
static inline int atomic_int_get_gcc(volatile int *ptr)
|
||||
{
|
||||
__sync_synchronize();
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
#define avpriv_atomic_int_set atomic_int_set_gcc
|
||||
static inline void atomic_int_set_gcc(volatile int *ptr, int val)
|
||||
{
|
||||
*ptr = val;
|
||||
__sync_synchronize();
|
||||
}
|
||||
|
||||
#define avpriv_atomic_int_add_and_fetch atomic_int_add_and_fetch_gcc
|
||||
static inline int atomic_int_add_and_fetch_gcc(volatile int *ptr, int inc)
|
||||
{
|
||||
return __sync_add_and_fetch(ptr, inc);
|
||||
}
|
||||
|
||||
#define avpriv_atomic_ptr_cas atomic_ptr_cas_gcc
|
||||
static inline void *atomic_ptr_cas_gcc(void * volatile *ptr,
|
||||
void *oldval, void *newval)
|
||||
{
|
||||
return __sync_val_compare_and_swap(ptr, oldval, newval);
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
*
|
||||
* This file is part of Libav.
|
||||
*
|
||||
* Libav is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* Libav is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with Libav; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <atomic.h>
|
||||
#include <mbarrier.h>
|
||||
|
||||
#include "atomic.h"
|
||||
|
||||
#define avpriv_atomic_int_get atomic_int_get_suncc
|
||||
static inline int atomic_int_get_suncc(volatile int *ptr)
|
||||
{
|
||||
__machine_rw_barrier();
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
#define avpriv_atomic_int_set atomic_int_set_suncc
|
||||
static inline void atomic_int_set_suncc(volatile int *ptr, int val)
|
||||
{
|
||||
*ptr = val;
|
||||
__machine_rw_barrier();
|
||||
}
|
||||
|
||||
#define avpriv_atomic_int_add_and_fetch atomic_int_add_and_fetch_suncc
|
||||
static inline int atomic_int_add_and_fetch_suncc(volatile int *ptr, int inc)
|
||||
{
|
||||
return atomic_add_int_nv(ptr, inc);
|
||||
}
|
||||
|
||||
#define avpriv_atomic_ptr_cas atomic_ptr_cas_suncc
|
||||
static inline void *atomic_ptr_cas_suncc(void * volatile *ptr,
|
||||
void *oldval, void *newval)
|
||||
{
|
||||
return atomic_cas_ptr(ptr, oldval, newval);
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright (c) 2012 Ronald S. Bultje <rsbultje@gmail.com>
|
||||
*
|
||||
* This file is part of Libav.
|
||||
*
|
||||
* Libav is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* Libav is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with Libav; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "atomic.h"
|
||||
|
||||
#define avpriv_atomic_int_get atomic_int_get_win32
|
||||
static inline int atomic_int_get_win32(volatile int *ptr)
|
||||
{
|
||||
MemoryBarrier();
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
#define avpriv_atomic_int_set atomic_int_set_win32
|
||||
static inline void atomic_int_set_win32(volatile int *ptr, int val)
|
||||
{
|
||||
*ptr = val;
|
||||
MemoryBarrier();
|
||||
}
|
||||
|
||||
#define avpriv_atomic_int_add_and_fetch atomic_int_add_and_fetch_win32
|
||||
static inline int atomic_int_add_and_fetch_win32(volatile int *ptr, int inc)
|
||||
{
|
||||
return inc + InterlockedExchangeAdd(ptr, inc);
|
||||
}
|
||||
|
||||
#define avpriv_atomic_ptr_cas atomic_ptr_cas_win32
|
||||
static inline void *atomic_ptr_cas_win32(void * volatile *ptr,
|
||||
void *oldval, void *newval)
|
||||
{
|
||||
return InterlockedCompareExchangePointer(ptr, newval, oldval);
|
||||
}
|
|
@ -8,6 +8,11 @@ fate-aes: libavutil/aes-test$(EXESUF)
|
|||
fate-aes: CMD = run libavutil/aes-test
|
||||
fate-aes: REF = /dev/null
|
||||
|
||||
FATE_LIBAVUTIL += fate-atomic
|
||||
fate-atomic: libavutil/atomic-test$(EXESUF)
|
||||
fate-atomic: CMD = run libavutil/atomic-test
|
||||
fate-atomic: REF = /dev/null
|
||||
|
||||
FATE_LIBAVUTIL += fate-avstring
|
||||
fate-avstring: libavutil/avstring-test$(EXESUF)
|
||||
fate-avstring: CMD = run libavutil/avstring-test
|
||||
|
|
Loading…
Reference in New Issue