added GSLice test from Stefan Westerfeld, bug #433314.
authorTim Janik <timj@imendio.com>
Thu, 12 Jul 2007 15:26:47 +0000 (15:26 +0000)
committerTim Janik <timj@src.gnome.org>
Thu, 12 Jul 2007 15:26:47 +0000 (15:26 +0000)
Thu Jul 12 17:26:05 2007  Tim Janik  <timj@imendio.com>

        * tests/slice-concurrent.c: added GSLice test from Stefan Westerfeld,
        bug #433314.

svn path=/trunk/; revision=5630

ChangeLog
tests/Makefile.am
tests/slice-concurrent.c [new file with mode: 0644]

index ee2e81c..2355e2c 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Thu Jul 12 17:26:05 2007  Tim Janik  <timj@imendio.com>
+
+       * tests/slice-concurrent.c: added GSLice test from Stefan Westerfeld,
+       bug #433314.
+
 Thu Jul 12 15:46:40 2007  Tim Janik  <timj@imendio.com>
 
        * glib/gslice.c: migrate per-thread magazine caches from single-thread
index 8919399..9088136 100644 (file)
@@ -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 (file)
index 0000000..3e9f77f
--- /dev/null
@@ -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 <glib.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#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;
+}