added GSLice test from Stefan Westerfeld, bug #433314.
[platform/upstream/glib.git] / tests / slice-concurrent.c
1 /* test for gslice cross thread allocation/free
2  * Copyright (C) 2006 Stefan Westerfeld
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19 #include <glib.h>
20 #include <stdlib.h>
21 #include <unistd.h>
22
23 #define N_THREADS       8
24 #define N_ALLOCS        50000
25 #define MAX_BLOCK_SIZE  32
26
27 struct ThreadData
28 {
29   int      thread_id;
30   GThread* gthread;
31
32   GMutex*  to_free_mutex;
33   void*    to_free [N_THREADS * N_ALLOCS];
34   int      bytes_to_free [N_THREADS * N_ALLOCS];
35   int      n_to_free;
36   int      n_freed;
37 } tdata[N_THREADS];
38
39 void*
40 thread_func (void *arg)
41 {
42   struct ThreadData *td = arg;
43   int i;
44   g_print ("Thread %d starting\n", td->thread_id);
45   for (i = 0; i < N_ALLOCS; i++)
46     {
47       if (rand() % (N_ALLOCS / 20) == 0)
48         g_print ("%d", td->thread_id);
49
50       int   bytes = rand() % MAX_BLOCK_SIZE + 1;
51       char *mem = g_slice_alloc (bytes);
52       
53       int f;
54       for (f = 0; f < bytes; f++)
55         mem[f] = rand();
56
57       int t = rand() % N_THREADS;
58       g_mutex_lock (tdata[t].to_free_mutex);
59       tdata[t].to_free[tdata[t].n_to_free] = mem;
60       tdata[t].bytes_to_free[tdata[t].n_to_free] = bytes;
61       tdata[t].n_to_free++;
62       g_mutex_unlock (tdata[t].to_free_mutex);
63
64       usleep (rand() % 1000);
65
66       g_mutex_lock (td->to_free_mutex);
67       if (td->n_to_free > 0)
68         {
69           td->n_to_free--;
70           g_slice_free1 (td->bytes_to_free[td->n_to_free], td->to_free[td->n_to_free]);
71           td->n_freed++;
72         }
73       g_mutex_unlock (td->to_free_mutex);
74     }
75
76   return NULL;
77 }
78
79 int
80 main()
81 {
82   int t;
83   g_thread_init (NULL);
84   
85   for (t = 0; t < N_THREADS; t++)
86     {
87       tdata[t].thread_id = t + 1;
88       tdata[t].n_to_free = 0;
89       tdata[t].n_freed = 0;
90       tdata[t].to_free_mutex = g_mutex_new();
91     }
92   for (t = 0; t < N_THREADS; t++)
93     {
94       tdata[t].gthread   = g_thread_create (thread_func, &tdata[t], TRUE, NULL);
95       g_assert (tdata[t].gthread != NULL);
96     }
97   for (t = 0; t < N_THREADS; t++)
98     {
99       g_thread_join (tdata[t].gthread);
100     }
101   g_print ("\n");
102   for (t = 0; t < N_THREADS; t++)
103     {
104       g_print ("Thread %d: %d blocks freed, %d blocks not freed\n",
105                     tdata[t].thread_id, tdata[t].n_freed, tdata[t].n_to_free);
106     }
107   return 0;
108 }