mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 19:51:11 +00:00
- Added a bunch of fast atomic operations on x86 with C fallbacks
Original commit message from CVS: - Added a bunch of fast atomic operations on x86 with C fallbacks - Added the code for refcounting in GstData - Added a gstmemchunk allocator using atomic operations
This commit is contained in:
parent
80c371342b
commit
74b6b732f1
5 changed files with 640 additions and 0 deletions
213
gst/gstatomic.h
Normal file
213
gst/gstatomic.h
Normal file
|
@ -0,0 +1,213 @@
|
||||||
|
/* GStreamer
|
||||||
|
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GST_ATOMIC_H__
|
||||||
|
#define __GST_ATOMIC_H__
|
||||||
|
|
||||||
|
/* FIXME */
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_ATOMIC_H
|
||||||
|
# include <asm/atomic.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
typedef struct _GstAtomicInt GstAtomicInt;
|
||||||
|
|
||||||
|
struct _GstAtomicInt {
|
||||||
|
#ifdef HAVE_ATOMIC_H
|
||||||
|
atomic_t value;
|
||||||
|
#else
|
||||||
|
int value;
|
||||||
|
GMutex *lock;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef HAVE_ATOMIC_H
|
||||||
|
|
||||||
|
/* atomic functions */
|
||||||
|
#define GST_ATOMIC_INT_INIT(ref, val) (atomic_set(&((ref)->value), (val)))
|
||||||
|
#define GST_ATOMIC_INT_FREE(ref)
|
||||||
|
|
||||||
|
#define GST_ATOMIC_INT_SET(ref,val) (atomic_set(&((ref)->value), (val)))
|
||||||
|
#define GST_ATOMIC_INT_VALUE(ref) (atomic_read(&((ref)->value)))
|
||||||
|
#define GST_ATOMIC_INT_READ(ref,res) (*res = atomic_read(&((ref)->value)))
|
||||||
|
#define GST_ATOMIC_INT_INC(ref) (atomic_inc (&((ref)->value)))
|
||||||
|
#define GST_ATOMIC_INT_DEC_AND_TEST(ref,zero) (*zero = atomic_dec_and_test (&((ref)->value)))
|
||||||
|
#define GST_ATOMIC_INT_ADD(ref, count) (atomic_add ((count), &((ref)->value)))
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
/* fallback using a lock */
|
||||||
|
#define GST_ATOMIC_INT_INIT(ref, val) \
|
||||||
|
G_STMT_START { \
|
||||||
|
(ref)->value = (val); \
|
||||||
|
(ref)->lock = g_mutex_new(); \
|
||||||
|
} G_STMT_END
|
||||||
|
|
||||||
|
#define GST_ATOMIC_INT_FREE(ref) g_mutex_free (&(ref)->lock)
|
||||||
|
|
||||||
|
#define GST_ATOMIC_INT_SET(ref,val) \
|
||||||
|
G_STMT_START { \
|
||||||
|
g_mutex_lock ((ref)->lock); \
|
||||||
|
(ref)->value = (val); \
|
||||||
|
g_mutex_unlock ((ref)->lock); \
|
||||||
|
} G_STMT_END
|
||||||
|
|
||||||
|
#define GST_ATOMIC_INT_VALUE(ref) ((ref)->value)
|
||||||
|
#define GST_ATOMIC_INT_READ(ref,res) \
|
||||||
|
G_STMT_START { \
|
||||||
|
g_mutex_lock ((ref)->lock); \
|
||||||
|
*res = (ref)->value; \
|
||||||
|
g_mutex_unlock ((ref)->lock); \
|
||||||
|
} G_STMT_END
|
||||||
|
|
||||||
|
#define GST_ATOMIC_INT_INC(ref) \
|
||||||
|
G_STMT_START { \
|
||||||
|
g_mutex_lock ((ref)->lock); \
|
||||||
|
(ref)->value++; \
|
||||||
|
g_mutex_unlock ((ref)->lock); \
|
||||||
|
} G_STMT_END
|
||||||
|
|
||||||
|
#define GST_ATOMIC_INT_DEC_AND_TEST(ref,zero) \
|
||||||
|
G_STMT_START { \
|
||||||
|
g_mutex_lock ((ref)->lock); \
|
||||||
|
(ref)->value--; \
|
||||||
|
*zero = ((ref)->value == 0); \
|
||||||
|
g_mutex_unlock ((ref)->lock); \
|
||||||
|
} G_STMT_END
|
||||||
|
|
||||||
|
#define GST_ATOMIC_INT_ADD(ref, count) \
|
||||||
|
G_STMT_START { \
|
||||||
|
g_mutex_lock ((ref)->lock); \
|
||||||
|
(ref)->value += count; \
|
||||||
|
g_mutex_unlock ((ref)->lock); \
|
||||||
|
} G_STMT_END
|
||||||
|
|
||||||
|
#endif /* HAVE_ATOMIC_H */
|
||||||
|
|
||||||
|
typedef struct _GstAtomicSwap GstAtomicSwap;
|
||||||
|
|
||||||
|
#define GST_ATOMIC_SWAP_VALUE(swap) ((swap)->value)
|
||||||
|
|
||||||
|
struct _GstAtomicSwap {
|
||||||
|
volatile gpointer value;
|
||||||
|
volatile gulong cnt; /* for the ABA problem */
|
||||||
|
GMutex *lock; /* lock for C fallback */
|
||||||
|
};
|
||||||
|
|
||||||
|
#if defined (__i386__) && defined (__GNUC__) && __GNUC__ >= 2
|
||||||
|
|
||||||
|
# ifdef __SMP__
|
||||||
|
# define GST_ATOMIC_LOCK "lock ; "
|
||||||
|
# else
|
||||||
|
# define GST_ATOMIC_LOCK ""
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#define _GST_ATOMIC_SWAP_INIT(swap,val) \
|
||||||
|
G_STMT_START { \
|
||||||
|
(swap)->value = (gpointer)(val); \
|
||||||
|
(swap)->cnt = 0; \
|
||||||
|
} G_STMT_END
|
||||||
|
|
||||||
|
#define _GST_ATOMIC_SWAP(swap, val) \
|
||||||
|
G_STMT_START { \
|
||||||
|
__asm__ __volatile__ ("1:" \
|
||||||
|
" movl %2, (%1);" \
|
||||||
|
GST_ATOMIC_LOCK "cmpxchg %1, %0;" \
|
||||||
|
" jnz 1b;" \
|
||||||
|
: \
|
||||||
|
: "m" (*swap), \
|
||||||
|
"r" (val), \
|
||||||
|
"a" ((swap)->value)); \
|
||||||
|
} G_STMT_END
|
||||||
|
|
||||||
|
#define _GST_ATOMIC_SWAP_GET(swap, val, res) \
|
||||||
|
G_STMT_START { \
|
||||||
|
__asm__ __volatile__ (" testl %%eax, %%eax;" \
|
||||||
|
" jz 20f;" \
|
||||||
|
"10:" \
|
||||||
|
" movl (%%eax), %%ebx;" \
|
||||||
|
" movl %%edx, %%ecx;" \
|
||||||
|
" incl %%ecx;" \
|
||||||
|
GST_ATOMIC_LOCK "cmpxchg8b %1;" \
|
||||||
|
" jz 20f;" \
|
||||||
|
" testl %%eax, %%eax;" \
|
||||||
|
" jnz 10b;" \
|
||||||
|
"20:\t" \
|
||||||
|
: "=a" (*res) \
|
||||||
|
: "m" (*(swap)), \
|
||||||
|
"a" (val), \
|
||||||
|
"d" ((swap)->cnt) \
|
||||||
|
: "ecx", "ebx"); \
|
||||||
|
} G_STMT_END
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define _GST_ATOMIC_SWAP_INIT(swap,val) \
|
||||||
|
G_STMT_START { \
|
||||||
|
(swap)->lock = g_mutex_new(); \
|
||||||
|
(swap)->value = (gpointer)val; \
|
||||||
|
} G_STMT_END
|
||||||
|
|
||||||
|
#define _GST_ATOMIC_SWAP(swap, val) \
|
||||||
|
G_STMT_START { \
|
||||||
|
gpointer tmp; \
|
||||||
|
g_mutex_lock ((swap)->lock); \
|
||||||
|
tmp = (swap)->value; \
|
||||||
|
(swap)->value = val; \
|
||||||
|
((gpointer)*val) = tmp; \
|
||||||
|
g_mutex_unlock ((swap)->lock); \
|
||||||
|
} G_STMT_END
|
||||||
|
|
||||||
|
#define _GST_ATOMIC_SWAP_GET(swap, val, res) \
|
||||||
|
G_STMT_START { \
|
||||||
|
if (val) { \
|
||||||
|
gpointer tmp; \
|
||||||
|
gint *tmp2; /* this is pretty EVIL */ \
|
||||||
|
g_mutex_lock ((swap)->lock); \
|
||||||
|
tmp = (swap)->value; \
|
||||||
|
tmp2 = val; \
|
||||||
|
(swap)->value = (gpointer)*tmp2; \
|
||||||
|
(*res) = (gpointer)*tmp2 = tmp; \
|
||||||
|
g_mutex_unlock ((swap)->lock); \
|
||||||
|
} \
|
||||||
|
} G_STMT_END
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* initialize the swap structure with an initial value */
|
||||||
|
#define GST_ATOMIC_SWAP_INIT(swap,val) _GST_ATOMIC_SWAP_INIT(swap, val)
|
||||||
|
|
||||||
|
/* atomically swap the contents the swap value with the value pointed to
|
||||||
|
* by val. */
|
||||||
|
#define GST_ATOMIC_SWAP(swap, val) _GST_ATOMIC_SWAP(swap, val)
|
||||||
|
|
||||||
|
/* atomically swap the contents the swap value with the value pointed to
|
||||||
|
* by val. The new value of the swap value is returned in the memory pointed
|
||||||
|
* to by res */
|
||||||
|
#define GST_ATOMIC_SWAP_GET(swap,val,res) _GST_ATOMIC_SWAP_GET(swap, val, res)
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GST_ATOMIC_H__ */
|
165
gst/gstdata.c
Normal file
165
gst/gstdata.c
Normal file
|
@ -0,0 +1,165 @@
|
||||||
|
/* GStreamer
|
||||||
|
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
|
||||||
|
* 2000 Wim Taymans <wtay@chello.be>
|
||||||
|
*
|
||||||
|
* gstdata.c: Data operations
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* this file makes too much noise for most debugging sessions */
|
||||||
|
#define GST_DEBUG_FORCE_DISABLE
|
||||||
|
#include "gst_private.h"
|
||||||
|
|
||||||
|
#include "gstdata.h"
|
||||||
|
#include "gstdata_private.h"
|
||||||
|
#include "gstlog.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
_gst_data_init (GstData *data, GType type, guint16 flags, GstDataFreeFunction free, GstDataCopyFunction copy)
|
||||||
|
{
|
||||||
|
_GST_DATA_INIT (data, type, flags, free, copy);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_gst_data_free (GstData *data)
|
||||||
|
{
|
||||||
|
_GST_DATA_DISPOSE (data);
|
||||||
|
g_free (data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_data_copy:
|
||||||
|
* @data: a #GstData to copy
|
||||||
|
*
|
||||||
|
* Copies the given #GstData
|
||||||
|
*
|
||||||
|
* Returns: a copy of the data or NULL if the data cannot be copied.
|
||||||
|
*/
|
||||||
|
GstData*
|
||||||
|
gst_data_copy (const GstData *data)
|
||||||
|
{
|
||||||
|
if (data->copy)
|
||||||
|
return data->copy (data);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_data_copy_on_write:
|
||||||
|
* @data: a #GstData to copy
|
||||||
|
*
|
||||||
|
* Copies the given #GstData if the refcount is greater than 1 so that the
|
||||||
|
* #GstData object can be written to safely.
|
||||||
|
*
|
||||||
|
* Returns: a copy of the data if the refcount is > 1, data if the refcount == 1
|
||||||
|
* or NULL if the data could not be copied.
|
||||||
|
*/
|
||||||
|
GstData*
|
||||||
|
gst_data_copy_on_write (const GstData *data)
|
||||||
|
{
|
||||||
|
gint refcount;
|
||||||
|
|
||||||
|
GST_ATOMIC_INT_READ (&data->refcount, &refcount);
|
||||||
|
|
||||||
|
if (refcount == 1)
|
||||||
|
return GST_DATA (data);
|
||||||
|
|
||||||
|
if (data->copy)
|
||||||
|
return data->copy (data);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_data_free:
|
||||||
|
* @data: a #GstData to free
|
||||||
|
*
|
||||||
|
* Frees the given #GstData
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
gst_data_free (GstData *data)
|
||||||
|
{
|
||||||
|
if (data->free)
|
||||||
|
data->free (data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_data_ref:
|
||||||
|
* @data: a #GstData to reference
|
||||||
|
*
|
||||||
|
* Increments the reference count of this data.
|
||||||
|
*
|
||||||
|
* Returns: the data
|
||||||
|
*/
|
||||||
|
GstData*
|
||||||
|
gst_data_ref (GstData *data)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (data != NULL, NULL);
|
||||||
|
g_return_val_if_fail (GST_DATA_REFCOUNT_VALUE(data) > 0, NULL);
|
||||||
|
|
||||||
|
GST_ATOMIC_INT_INC (&data->refcount);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_data_ref_by_count:
|
||||||
|
* @data: a #GstData to reference
|
||||||
|
* @count: the number to increment the reference count by
|
||||||
|
*
|
||||||
|
* Increments the reference count of this data by the given number.
|
||||||
|
*
|
||||||
|
* Returns: the data
|
||||||
|
*/
|
||||||
|
GstData*
|
||||||
|
gst_data_ref_by_count (GstData *data, gint count)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (data != NULL, NULL);
|
||||||
|
g_return_val_if_fail (count >= 0, NULL);
|
||||||
|
g_return_val_if_fail (GST_DATA_REFCOUNT_VALUE(data) > 0, NULL);
|
||||||
|
|
||||||
|
GST_ATOMIC_INT_ADD (&data->refcount, count);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_data_unref:
|
||||||
|
* @data: a #GstData to unreference
|
||||||
|
*
|
||||||
|
* Decrements the refcount of this data. If the refcount is
|
||||||
|
* zero, the data will be freeed.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
gst_data_unref (GstData *data)
|
||||||
|
{
|
||||||
|
gint zero;
|
||||||
|
|
||||||
|
g_return_if_fail (data != NULL);
|
||||||
|
|
||||||
|
GST_INFO (GST_CAT_BUFFER, "unref data %p, current count is %d", data,GST_DATA_REFCOUNT_VALUE(data));
|
||||||
|
g_return_if_fail (GST_DATA_REFCOUNT_VALUE(data) > 0);
|
||||||
|
|
||||||
|
GST_ATOMIC_INT_DEC_AND_TEST (&data->refcount, &zero);
|
||||||
|
|
||||||
|
/* if we ended up with the refcount at zero, free the data */
|
||||||
|
if (zero) {
|
||||||
|
if (data->free)
|
||||||
|
data->free (data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
36
gst/gstdata_private.h
Normal file
36
gst/gstdata_private.h
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
/* GStreamer
|
||||||
|
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
|
||||||
|
* 2000 Wim Taymans <wtay@chello.be>
|
||||||
|
*
|
||||||
|
* gstdata.c: Data operations
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define _GST_DATA_INIT(data, ptype, pflags, pfree, pcopy) \
|
||||||
|
G_STMT_START { \
|
||||||
|
GST_ATOMIC_INT_INIT (&(data)->refcount, 1); \
|
||||||
|
(data)->type = ptype; \
|
||||||
|
(data)->flags = pflags; \
|
||||||
|
(data)->free = pfree; \
|
||||||
|
(data)->copy = pcopy; \
|
||||||
|
} G_STMT_END;
|
||||||
|
|
||||||
|
#define _GST_DATA_DISPOSE(data) \
|
||||||
|
G_STMT_START { \
|
||||||
|
GST_ATOMIC_INT_FREE (&(data)->refcount); \
|
||||||
|
} G_STMT_END;
|
||||||
|
|
159
gst/gstmemchunk.c
Normal file
159
gst/gstmemchunk.c
Normal file
|
@ -0,0 +1,159 @@
|
||||||
|
/* GStreamer
|
||||||
|
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h> /* memset */
|
||||||
|
|
||||||
|
#include "gstlog.h"
|
||||||
|
#include "gstmemchunk.h"
|
||||||
|
#include "gstutils.h"
|
||||||
|
|
||||||
|
#define GST_MEM_CHUNK_AREA(chunk) (((GstMemChunkElement*)(chunk))->area)
|
||||||
|
#define GST_MEM_CHUNK_DATA(chunk) ((gpointer)(((GstMemChunkElement*)(chunk)) + 1))
|
||||||
|
#define GST_MEM_CHUNK_LINK(mem) ((GstMemChunkElement*)((guint8*)(mem) - sizeof (GstMemChunkElement)))
|
||||||
|
|
||||||
|
/*******************************************************
|
||||||
|
* area size
|
||||||
|
* +-----------------------------------------+
|
||||||
|
* chunk size
|
||||||
|
* +------------+
|
||||||
|
*
|
||||||
|
* !next!data... !next!data.... !next!data...
|
||||||
|
* ! ^ ! ^ !
|
||||||
|
* +-------------+ +------------+ +---> NULL
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static gboolean
|
||||||
|
populate (GstMemChunk *mem_chunk)
|
||||||
|
{
|
||||||
|
guint8 *area;
|
||||||
|
gint i;
|
||||||
|
|
||||||
|
if (mem_chunk->cleanup)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
area = (guint8 *) g_malloc0 (mem_chunk->area_size);
|
||||||
|
|
||||||
|
for (i=0; i < mem_chunk->area_size; i += mem_chunk->chunk_size) {
|
||||||
|
GST_MEM_CHUNK_AREA (area + i) = (GstMemChunkElement *)area;
|
||||||
|
gst_mem_chunk_free (mem_chunk, GST_MEM_CHUNK_DATA (area + i));
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GstMemChunk*
|
||||||
|
gst_mem_chunk_new (gchar* name, gint atom_size, gulong area_size, gint type)
|
||||||
|
{
|
||||||
|
GstMemChunk *mem_chunk;
|
||||||
|
|
||||||
|
g_return_val_if_fail (atom_size > 0, NULL);
|
||||||
|
g_return_val_if_fail (area_size >= atom_size, NULL);
|
||||||
|
|
||||||
|
mem_chunk = g_malloc (sizeof (GstMemChunk));
|
||||||
|
|
||||||
|
mem_chunk->chunk_size = atom_size + sizeof (GstMemChunkElement);
|
||||||
|
area_size = (area_size/atom_size) * mem_chunk->chunk_size;
|
||||||
|
|
||||||
|
mem_chunk->name = g_strdup (name);
|
||||||
|
mem_chunk->atom_size = atom_size;
|
||||||
|
mem_chunk->area_size = area_size;
|
||||||
|
mem_chunk->cleanup = FALSE;
|
||||||
|
GST_ATOMIC_SWAP_INIT (&mem_chunk->swap, NULL);
|
||||||
|
|
||||||
|
populate (mem_chunk);
|
||||||
|
|
||||||
|
return mem_chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
free_area (gpointer key, gpointer value, gpointer user_data)
|
||||||
|
{
|
||||||
|
g_free (key);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gst_mem_chunk_destroy (GstMemChunk *mem_chunk)
|
||||||
|
{
|
||||||
|
GHashTable *elements = g_hash_table_new (NULL, NULL);
|
||||||
|
gpointer data;
|
||||||
|
|
||||||
|
mem_chunk->cleanup = TRUE;
|
||||||
|
|
||||||
|
data = gst_mem_chunk_alloc (mem_chunk);
|
||||||
|
while (data) {
|
||||||
|
GstMemChunkElement *elem = GST_MEM_CHUNK_LINK (data);
|
||||||
|
|
||||||
|
g_hash_table_insert (elements, GST_MEM_CHUNK_AREA (elem), NULL);
|
||||||
|
|
||||||
|
data = gst_mem_chunk_alloc (mem_chunk);
|
||||||
|
}
|
||||||
|
g_hash_table_foreach_remove (elements, free_area, NULL);
|
||||||
|
|
||||||
|
g_hash_table_destroy (elements);
|
||||||
|
g_free (mem_chunk->name);
|
||||||
|
g_free (mem_chunk);
|
||||||
|
}
|
||||||
|
|
||||||
|
gpointer
|
||||||
|
gst_mem_chunk_alloc (GstMemChunk *mem_chunk)
|
||||||
|
{
|
||||||
|
GstMemChunkElement *chunk = NULL;
|
||||||
|
|
||||||
|
g_return_val_if_fail (mem_chunk != NULL, NULL);
|
||||||
|
|
||||||
|
again:
|
||||||
|
GST_ATOMIC_SWAP_GET (&mem_chunk->swap,
|
||||||
|
GST_ATOMIC_SWAP_VALUE (&mem_chunk->swap),
|
||||||
|
&chunk);
|
||||||
|
|
||||||
|
if (!chunk) {
|
||||||
|
if (populate (mem_chunk))
|
||||||
|
goto again;
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return GST_MEM_CHUNK_DATA (chunk);
|
||||||
|
}
|
||||||
|
|
||||||
|
gpointer
|
||||||
|
gst_mem_chunk_alloc0 (GstMemChunk *mem_chunk)
|
||||||
|
{
|
||||||
|
gpointer mem = gst_mem_chunk_alloc (mem_chunk);
|
||||||
|
|
||||||
|
if (mem)
|
||||||
|
memset (mem, 0, mem_chunk->atom_size);
|
||||||
|
|
||||||
|
return mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gst_mem_chunk_free (GstMemChunk *mem_chunk, gpointer mem)
|
||||||
|
{
|
||||||
|
GstMemChunkElement *chunk;
|
||||||
|
|
||||||
|
g_return_if_fail (mem_chunk != NULL);
|
||||||
|
g_return_if_fail (mem != NULL);
|
||||||
|
|
||||||
|
chunk = GST_MEM_CHUNK_LINK (mem);
|
||||||
|
|
||||||
|
GST_ATOMIC_SWAP (&mem_chunk->swap, &chunk->link);
|
||||||
|
}
|
67
gst/gstmemchunk.h
Normal file
67
gst/gstmemchunk.h
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
/* GStreamer
|
||||||
|
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GST_MEM_CHUNK_H__
|
||||||
|
#define __GST_MEM_CHUNK_H__
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <gst/gstatomic.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
typedef struct _GstMemChunk GstMemChunk;
|
||||||
|
typedef struct _GstMemChunkElement GstMemChunkElement;
|
||||||
|
|
||||||
|
struct _GstMemChunkElement
|
||||||
|
{
|
||||||
|
GstMemChunkElement *link; /* next cell in the lifo */
|
||||||
|
GstMemChunkElement *area;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GstMemChunk
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
volatile GstMemChunkElement *free; /* the first free element */
|
||||||
|
volatile gulong cnt; /* used to avoid ABA problem */
|
||||||
|
#endif
|
||||||
|
GstAtomicSwap swap;
|
||||||
|
|
||||||
|
gchar *name;
|
||||||
|
gulong area_size;
|
||||||
|
gulong chunk_size;
|
||||||
|
gulong atom_size;
|
||||||
|
gboolean cleanup;
|
||||||
|
GMutex *lock;
|
||||||
|
};
|
||||||
|
|
||||||
|
GstMemChunk* gst_mem_chunk_new (gchar *name,
|
||||||
|
gint atom_size,
|
||||||
|
gulong area_size,
|
||||||
|
gint type);
|
||||||
|
|
||||||
|
void gst_mem_chunk_destroy (GstMemChunk *mem_chunk);
|
||||||
|
|
||||||
|
gpointer gst_mem_chunk_alloc (GstMemChunk *mem_chunk);
|
||||||
|
gpointer gst_mem_chunk_alloc0 (GstMemChunk *mem_chunk);
|
||||||
|
void gst_mem_chunk_free (GstMemChunk *mem_chunk,
|
||||||
|
gpointer mem);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GST_MEM_CHUNK_H__ */
|
Loading…
Reference in a new issue