From 223754f6277032b0b149da29e7e937915ebd913d Mon Sep 17 00:00:00 2001 From: Tim Janik Date: Thu, 12 Jul 2007 15:26:47 +0000 Subject: [PATCH] added GSLice test from Stefan Westerfeld, bug #433314. Thu Jul 12 17:26:05 2007 Tim Janik * tests/slice-concurrent.c: added GSLice test from Stefan Westerfeld, bug #433314. svn path=/trunk/; revision=5630 --- ChangeLog | 5 +++ tests/Makefile.am | 3 ++ tests/slice-concurrent.c | 108 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 116 insertions(+) create mode 100644 tests/slice-concurrent.c diff --git a/ChangeLog b/ChangeLog index ee2e81c..2355e2c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Thu Jul 12 17:26:05 2007 Tim Janik + + * tests/slice-concurrent.c: added GSLice test from Stefan Westerfeld, + bug #433314. + Thu Jul 12 15:46:40 2007 Tim Janik * glib/gslice.c: migrate per-thread magazine caches from single-thread diff --git a/tests/Makefile.am b/tests/Makefile.am index 8919399..9088136 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -104,6 +104,7 @@ test_programs = \ slist-test \ slice-test \ slice-color \ + slice-concurrent \ slice-threadinit \ spawn-test \ $(spawn_test_win32_gui) \ @@ -176,6 +177,8 @@ slice_test_SOURCES = slice-test.c memchunks.c slice_test_LDADD = $(thread_ldadd) slice_color_SOURCES = slice-color.c memchunks.c slice_color_LDADD = $(thread_ldadd) +slice_concurrent_SOURCES = slice-concurrent.c +slice_concurrent_LDADD = $(thread_ldadd) slice_threadinit_SOURCES = slice-threadinit.c slice_threadinit_LDADD = $(thread_ldadd) spawn_test_LDADD = $(progs_ldadd) diff --git a/tests/slice-concurrent.c b/tests/slice-concurrent.c new file mode 100644 index 0000000..3e9f77f --- /dev/null +++ b/tests/slice-concurrent.c @@ -0,0 +1,108 @@ +/* test for gslice cross thread allocation/free + * Copyright (C) 2006 Stefan Westerfeld + * + * This library 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 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 +#include +#include + +#define N_THREADS 8 +#define N_ALLOCS 50000 +#define MAX_BLOCK_SIZE 32 + +struct ThreadData +{ + int thread_id; + GThread* gthread; + + GMutex* to_free_mutex; + void* to_free [N_THREADS * N_ALLOCS]; + int bytes_to_free [N_THREADS * N_ALLOCS]; + int n_to_free; + int n_freed; +} tdata[N_THREADS]; + +void* +thread_func (void *arg) +{ + struct ThreadData *td = arg; + int i; + g_print ("Thread %d starting\n", td->thread_id); + for (i = 0; i < N_ALLOCS; i++) + { + if (rand() % (N_ALLOCS / 20) == 0) + g_print ("%d", td->thread_id); + + int bytes = rand() % MAX_BLOCK_SIZE + 1; + char *mem = g_slice_alloc (bytes); + + int f; + for (f = 0; f < bytes; f++) + mem[f] = rand(); + + int t = rand() % N_THREADS; + g_mutex_lock (tdata[t].to_free_mutex); + tdata[t].to_free[tdata[t].n_to_free] = mem; + tdata[t].bytes_to_free[tdata[t].n_to_free] = bytes; + tdata[t].n_to_free++; + g_mutex_unlock (tdata[t].to_free_mutex); + + usleep (rand() % 1000); + + g_mutex_lock (td->to_free_mutex); + if (td->n_to_free > 0) + { + td->n_to_free--; + g_slice_free1 (td->bytes_to_free[td->n_to_free], td->to_free[td->n_to_free]); + td->n_freed++; + } + g_mutex_unlock (td->to_free_mutex); + } + + return NULL; +} + +int +main() +{ + int t; + g_thread_init (NULL); + + for (t = 0; t < N_THREADS; t++) + { + tdata[t].thread_id = t + 1; + tdata[t].n_to_free = 0; + tdata[t].n_freed = 0; + tdata[t].to_free_mutex = g_mutex_new(); + } + for (t = 0; t < N_THREADS; t++) + { + tdata[t].gthread = g_thread_create (thread_func, &tdata[t], TRUE, NULL); + g_assert (tdata[t].gthread != NULL); + } + for (t = 0; t < N_THREADS; t++) + { + g_thread_join (tdata[t].gthread); + } + g_print ("\n"); + for (t = 0; t < N_THREADS; t++) + { + g_print ("Thread %d: %d blocks freed, %d blocks not freed\n", + tdata[t].thread_id, tdata[t].n_freed, tdata[t].n_to_free); + } + return 0; +} -- 2.7.4