From 1058e3cf9057e9f344e62508fcc85b2d86492673 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Sun, 30 Sep 2001 21:37:36 +0000 Subject: [PATCH] Added automatic growing of the memchunk. Original commit message from CVS: Added automatic growing of the memchunk. Added cleanup. --- test/memchunk/Makefile.am | 2 +- test/memchunk/gstmemchunk.c | 129 ++++++++++++++++++++++---------- test/memchunk/gstmemchunk.h | 8 +- test/memchunk/gstmemchunktest.c | 10 ++- 4 files changed, 106 insertions(+), 43 deletions(-) diff --git a/test/memchunk/Makefile.am b/test/memchunk/Makefile.am index 3c8e0231f1..e3198c289e 100644 --- a/test/memchunk/Makefile.am +++ b/test/memchunk/Makefile.am @@ -4,4 +4,4 @@ gmemchunktest_SOURCES = gmemchunktest.c gstmemchunktest_SOURCES = gstmemchunktest.c gstmemchunk.c gstmemchunk.h LIBS += $(GST_LIBS) -CFLAGS += $(GST_CFLAGS) +CFLAGS += $(GST_CFLAGS) diff --git a/test/memchunk/gstmemchunk.c b/test/memchunk/gstmemchunk.c index 81f21a64f8..be99be5a79 100644 --- a/test/memchunk/gstmemchunk.c +++ b/test/memchunk/gstmemchunk.c @@ -6,6 +6,10 @@ #define CHUNK_LOCK "" #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 * +-----------------------------------------+ @@ -17,93 +21,142 @@ * +-------------+ +------------+ +---> NULL * */ -static void +static gboolean populate (GstMemChunk *mem_chunk) { guint8 *area; 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) { - gst_mem_chunk_free (mem_chunk, area + sizeof (gpointer)); - area += mem_chunk->chunk_size; + area = (guint8 *) g_malloc (mem_chunk->area_size); + g_print ("alloc %p\n", area); + + 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* +gst_mem_chunk_new (gchar* name, gint atom_size, gulong area_size, gint type) { GstMemChunk *mem_chunk; - gint chunk_size; - //g_print ("create: atom size %d, area_size %lu\n", atom_size, area_size); - - 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); + 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->free = NULL; mem_chunk->cnt = 0; mem_chunk->atom_size = atom_size; - mem_chunk->chunk_size = chunk_size; mem_chunk->area_size = area_size; + mem_chunk->cleanup = FALSE; populate (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 gst_mem_chunk_alloc (GstMemChunk *mem_chunk) { - guint8 *chunk = NULL; + GstMemChunkElement *chunk = NULL; g_return_val_if_fail (mem_chunk != NULL, NULL); again: - __asm__ __volatile__ ("testl %%eax, %%eax \n\t" - "jz 20f \n" - "10:\t" - "movl (%%eax), %%ebx \n\t" - "movl %%edx, %%ecx \n\t" - "incl %%ecx \n\t" - CHUNK_LOCK "cmpxchg8b %1 \n\t" - "jz 20f \n\t" - "testl %%eax, %%eax \n\t" - "jnz 10b \n" + __asm__ __volatile__ (" testl %%eax, %%eax \n\t" + " jz 20f \n" + "10: \t" + " movl (%%eax), %%ebx \n\t" + " movl %%edx, %%ecx \n\t" + " incl %%ecx \n\t" + CHUNK_LOCK "cmpxchg8b %1 \n\t" + " jz 20f \n\t" + " testl %%eax, %%eax \n\t" + " jnz 10b \n" "20:\t" :"=a" (chunk) :"m" (*mem_chunk), "a" (mem_chunk->free), "d" (mem_chunk->cnt) :"ecx", "ebx"); - if (chunk) - chunk += sizeof (gpointer); - else { + if (!chunk) { //g_print ("extending\n"); - populate (mem_chunk); - goto again; + if (populate (mem_chunk)) + 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 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 != NULL); - __asm__ __volatile__ ( "1:\t" - "movl %2, (%1) \n" - CHUNK_LOCK "cmpxchg %1, %0 \n\t" - "jnz 1b \n\t" + chunk = GST_MEM_CHUNK_LINK (mem); + + __asm__ __volatile__ ( "1: \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)); } diff --git a/test/memchunk/gstmemchunk.h b/test/memchunk/gstmemchunk.h index 49fd0c67b9..c71660a567 100644 --- a/test/memchunk/gstmemchunk.h +++ b/test/memchunk/gstmemchunk.h @@ -7,17 +7,19 @@ typedef struct _GstMemChunkElement GstMemChunkElement; struct _GstMemChunkElement { GstMemChunkElement *link; /* next cell in the lifo */ - // data is here + GstMemChunkElement *area; }; struct _GstMemChunk { 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 chunk_size; gulong atom_size; + gboolean cleanup; }; GstMemChunk* gst_mem_chunk_new (gchar *name, @@ -25,6 +27,8 @@ GstMemChunk* gst_mem_chunk_new (gchar *name, gulong area_size, gint type); +void gst_mem_chunk_destroy (GstMemChunk *mem_chunk); + gpointer gst_mem_chunk_alloc (GstMemChunk *mem_chunk); void gst_mem_chunk_free (GstMemChunk *mem_chunk, gpointer mem); diff --git a/test/memchunk/gstmemchunktest.c b/test/memchunk/gstmemchunktest.c index 18f26d7d19..05acccb104 100644 --- a/test/memchunk/gstmemchunktest.c +++ b/test/memchunk/gstmemchunktest.c @@ -56,7 +56,7 @@ main (gint argc, gchar *argv[]) num_threads = atoi (argv[1]); 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++) { 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); - pthread_exit (NULL); + for(t=0; t < num_threads; t++) { + pthread_join (threads[t], NULL); + } g_mem_chunk_info(); + + gst_mem_chunk_destroy (_chunks); + + return 0; }