Added automatic growing of the memchunk.

Original commit message from CVS:
Added automatic growing of the memchunk.
Added cleanup.
This commit is contained in:
Wim Taymans 2001-09-30 21:37:36 +00:00
parent 4389c3a5c9
commit 1058e3cf90
4 changed files with 106 additions and 43 deletions

View file

@ -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,18 +21,24 @@
* +-------------+ +------------+ +---> 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;
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) { for (i=0; i < mem_chunk->area_size; i += mem_chunk->chunk_size) {
gst_mem_chunk_free (mem_chunk, area + sizeof (gpointer)); GST_MEM_CHUNK_AREA (area + i) = (GstMemChunkElement *)area;
area += mem_chunk->chunk_size; gst_mem_chunk_free (mem_chunk, GST_MEM_CHUNK_DATA (area + i));
} }
return TRUE;
} }
@ -36,32 +46,63 @@ 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);
@ -81,25 +122,37 @@ again:
:"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);
chunk = GST_MEM_CHUNK_LINK (mem);
__asm__ __volatile__ ( "1: \t" __asm__ __volatile__ ( "1: \t"
" movl %2, (%1) \n" " movl %2, (%1) \n"
CHUNK_LOCK "cmpxchg %1, %0 \n\t" CHUNK_LOCK "cmpxchg %1, %0 \n\t"

View file

@ -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);

View file

@ -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++) {
g_mem_chunk_info(); pthread_join (threads[t], NULL);
}
g_mem_chunk_info();
gst_mem_chunk_destroy (_chunks);
return 0;
} }