mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-04 23:46:43 +00:00
Added automatic growing of the memchunk.
Original commit message from CVS: Added automatic growing of the memchunk. Added cleanup.
This commit is contained in:
parent
4389c3a5c9
commit
1058e3cf90
4 changed files with 106 additions and 43 deletions
|
@ -4,4 +4,4 @@ gmemchunktest_SOURCES = gmemchunktest.c
|
||||||
gstmemchunktest_SOURCES = gstmemchunktest.c gstmemchunk.c gstmemchunk.h
|
gstmemchunktest_SOURCES = gstmemchunktest.c gstmemchunk.c gstmemchunk.h
|
||||||
|
|
||||||
LIBS += $(GST_LIBS)
|
LIBS += $(GST_LIBS)
|
||||||
CFLAGS += $(GST_CFLAGS)
|
CFLAGS += $(GST_CFLAGS)
|
||||||
|
|
|
@ -6,6 +6,10 @@
|
||||||
#define CHUNK_LOCK ""
|
#define CHUNK_LOCK ""
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#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
|
* area size
|
||||||
* +-----------------------------------------+
|
* +-----------------------------------------+
|
||||||
|
@ -17,93 +21,142 @@
|
||||||
* +-------------+ +------------+ +---> NULL
|
* +-------------+ +------------+ +---> NULL
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static void
|
static gboolean
|
||||||
populate (GstMemChunk *mem_chunk)
|
populate (GstMemChunk *mem_chunk)
|
||||||
{
|
{
|
||||||
guint8 *area;
|
guint8 *area;
|
||||||
gint i;
|
gint i;
|
||||||
|
|
||||||
area = (guint8 *)g_malloc0 (mem_chunk->area_size);
|
if (mem_chunk->cleanup)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
for (i = 0; i < mem_chunk->area_size; i += mem_chunk->chunk_size) {
|
area = (guint8 *) g_malloc (mem_chunk->area_size);
|
||||||
gst_mem_chunk_free (mem_chunk, area + sizeof (gpointer));
|
g_print ("alloc %p\n", area);
|
||||||
area += mem_chunk->chunk_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 *
|
GstMemChunk*
|
||||||
gst_mem_chunk_new (gchar * name, gint atom_size, gulong area_size, gint type)
|
gst_mem_chunk_new (gchar* name, gint atom_size, gulong area_size, gint type)
|
||||||
{
|
{
|
||||||
GstMemChunk *mem_chunk;
|
GstMemChunk *mem_chunk;
|
||||||
gint chunk_size;
|
|
||||||
|
|
||||||
//g_print ("create: atom size %d, area_size %lu\n", atom_size, area_size);
|
g_return_val_if_fail (atom_size > 0, NULL);
|
||||||
|
g_return_val_if_fail (area_size >= atom_size, NULL);
|
||||||
chunk_size = atom_size + sizeof (gpointer);
|
|
||||||
area_size = (area_size/atom_size) * chunk_size;
|
|
||||||
|
|
||||||
//g_print ("chunk size %d, real area_size %lu\n", chunk_size, area_size);
|
|
||||||
|
|
||||||
mem_chunk = g_malloc (sizeof (GstMemChunk));
|
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->free = NULL;
|
mem_chunk->free = NULL;
|
||||||
mem_chunk->cnt = 0;
|
mem_chunk->cnt = 0;
|
||||||
mem_chunk->atom_size = atom_size;
|
mem_chunk->atom_size = atom_size;
|
||||||
mem_chunk->chunk_size = chunk_size;
|
|
||||||
mem_chunk->area_size = area_size;
|
mem_chunk->area_size = area_size;
|
||||||
|
mem_chunk->cleanup = FALSE;
|
||||||
|
|
||||||
populate (mem_chunk);
|
populate (mem_chunk);
|
||||||
|
|
||||||
return mem_chunk;
|
return mem_chunk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
free_area (gpointer key, gpointer value, gpointer user_data)
|
||||||
|
{
|
||||||
|
g_print ("free %p\n", key);
|
||||||
|
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
|
gpointer
|
||||||
gst_mem_chunk_alloc (GstMemChunk *mem_chunk)
|
gst_mem_chunk_alloc (GstMemChunk *mem_chunk)
|
||||||
{
|
{
|
||||||
guint8 *chunk = NULL;
|
GstMemChunkElement *chunk = NULL;
|
||||||
|
|
||||||
g_return_val_if_fail (mem_chunk != NULL, NULL);
|
g_return_val_if_fail (mem_chunk != NULL, NULL);
|
||||||
|
|
||||||
again:
|
again:
|
||||||
__asm__ __volatile__ ("testl %%eax, %%eax \n\t"
|
__asm__ __volatile__ (" testl %%eax, %%eax \n\t"
|
||||||
"jz 20f \n"
|
" jz 20f \n"
|
||||||
"10:\t"
|
"10: \t"
|
||||||
"movl (%%eax), %%ebx \n\t"
|
" movl (%%eax), %%ebx \n\t"
|
||||||
"movl %%edx, %%ecx \n\t"
|
" movl %%edx, %%ecx \n\t"
|
||||||
"incl %%ecx \n\t"
|
" incl %%ecx \n\t"
|
||||||
CHUNK_LOCK "cmpxchg8b %1 \n\t"
|
CHUNK_LOCK "cmpxchg8b %1 \n\t"
|
||||||
"jz 20f \n\t"
|
" jz 20f \n\t"
|
||||||
"testl %%eax, %%eax \n\t"
|
" testl %%eax, %%eax \n\t"
|
||||||
"jnz 10b \n"
|
" jnz 10b \n"
|
||||||
"20:\t"
|
"20:\t"
|
||||||
:"=a" (chunk)
|
:"=a" (chunk)
|
||||||
:"m" (*mem_chunk), "a" (mem_chunk->free), "d" (mem_chunk->cnt)
|
:"m" (*mem_chunk), "a" (mem_chunk->free), "d" (mem_chunk->cnt)
|
||||||
:"ecx", "ebx");
|
:"ecx", "ebx");
|
||||||
|
|
||||||
if (chunk)
|
if (!chunk) {
|
||||||
chunk += sizeof (gpointer);
|
|
||||||
else {
|
|
||||||
//g_print ("extending\n");
|
//g_print ("extending\n");
|
||||||
populate (mem_chunk);
|
if (populate (mem_chunk))
|
||||||
goto again;
|
goto again;
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
return GST_MEM_CHUNK_DATA (chunk);
|
||||||
|
}
|
||||||
|
|
||||||
return (gpointer) 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
|
void
|
||||||
gst_mem_chunk_free (GstMemChunk *mem_chunk, gpointer mem)
|
gst_mem_chunk_free (GstMemChunk *mem_chunk, gpointer mem)
|
||||||
{
|
{
|
||||||
guint8 *chunk = ((guint8 *)mem) - sizeof (gpointer);
|
GstMemChunkElement *chunk;
|
||||||
|
|
||||||
g_return_if_fail (mem_chunk != NULL);
|
g_return_if_fail (mem_chunk != NULL);
|
||||||
g_return_if_fail (mem != NULL);
|
g_return_if_fail (mem != NULL);
|
||||||
|
|
||||||
__asm__ __volatile__ ( "1:\t"
|
chunk = GST_MEM_CHUNK_LINK (mem);
|
||||||
"movl %2, (%1) \n"
|
|
||||||
CHUNK_LOCK "cmpxchg %1, %0 \n\t"
|
__asm__ __volatile__ ( "1: \t"
|
||||||
"jnz 1b \n\t"
|
" movl %2, (%1) \n"
|
||||||
|
CHUNK_LOCK "cmpxchg %1, %0 \n\t"
|
||||||
|
" jnz 1b \n\t"
|
||||||
:
|
:
|
||||||
:"m" (*mem_chunk), "r" (chunk), "a" (mem_chunk->free));
|
:"m" (*mem_chunk), "r" (chunk), "a" (mem_chunk->free));
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,17 +7,19 @@ typedef struct _GstMemChunkElement GstMemChunkElement;
|
||||||
struct _GstMemChunkElement
|
struct _GstMemChunkElement
|
||||||
{
|
{
|
||||||
GstMemChunkElement *link; /* next cell in the lifo */
|
GstMemChunkElement *link; /* next cell in the lifo */
|
||||||
// data is here
|
GstMemChunkElement *area;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstMemChunk
|
struct _GstMemChunk
|
||||||
{
|
{
|
||||||
volatile GstMemChunkElement *free; /* the first free element */
|
volatile GstMemChunkElement *free; /* the first free element */
|
||||||
volatile unsigned long cnt; /* used to avoid ABA problem */
|
volatile gulong cnt; /* used to avoid ABA problem */
|
||||||
|
|
||||||
|
gchar *name;
|
||||||
gulong area_size;
|
gulong area_size;
|
||||||
gulong chunk_size;
|
gulong chunk_size;
|
||||||
gulong atom_size;
|
gulong atom_size;
|
||||||
|
gboolean cleanup;
|
||||||
};
|
};
|
||||||
|
|
||||||
GstMemChunk* gst_mem_chunk_new (gchar *name,
|
GstMemChunk* gst_mem_chunk_new (gchar *name,
|
||||||
|
@ -25,6 +27,8 @@ GstMemChunk* gst_mem_chunk_new (gchar *name,
|
||||||
gulong area_size,
|
gulong area_size,
|
||||||
gint type);
|
gint type);
|
||||||
|
|
||||||
|
void gst_mem_chunk_destroy (GstMemChunk *mem_chunk);
|
||||||
|
|
||||||
gpointer gst_mem_chunk_alloc (GstMemChunk *mem_chunk);
|
gpointer gst_mem_chunk_alloc (GstMemChunk *mem_chunk);
|
||||||
void gst_mem_chunk_free (GstMemChunk *mem_chunk,
|
void gst_mem_chunk_free (GstMemChunk *mem_chunk,
|
||||||
gpointer mem);
|
gpointer mem);
|
||||||
|
|
|
@ -56,7 +56,7 @@ main (gint argc, gchar *argv[])
|
||||||
num_threads = atoi (argv[1]);
|
num_threads = atoi (argv[1]);
|
||||||
num_allocs = atoi (argv[2]);
|
num_allocs = atoi (argv[2]);
|
||||||
|
|
||||||
_chunks = gst_mem_chunk_new ("test", 32, 32 * 4, G_ALLOC_AND_FREE);
|
_chunks = gst_mem_chunk_new ("test", 32, 32 * 16, G_ALLOC_AND_FREE);
|
||||||
|
|
||||||
for(t=0; t < num_threads; t++) {
|
for(t=0; t < num_threads; t++) {
|
||||||
rc = pthread_create (&threads[t], NULL, run_test, (void *)t);
|
rc = pthread_create (&threads[t], NULL, run_test, (void *)t);
|
||||||
|
@ -68,6 +68,12 @@ main (gint argc, gchar *argv[])
|
||||||
}
|
}
|
||||||
printf ("main(): Created %d threads.\n", t);
|
printf ("main(): Created %d threads.\n", t);
|
||||||
|
|
||||||
pthread_exit (NULL);
|
for(t=0; t < num_threads; t++) {
|
||||||
|
pthread_join (threads[t], NULL);
|
||||||
|
}
|
||||||
g_mem_chunk_info();
|
g_mem_chunk_info();
|
||||||
|
|
||||||
|
gst_mem_chunk_destroy (_chunks);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue