| 
									
										
										
										
											2007-07-12 15:26:47 +00:00
										 |  |  | /* test for gslice cross thread allocation/free
 | 
					
						
							|  |  |  |  * Copyright (C) 2006 Stefan Westerfeld | 
					
						
							| 
									
										
										
										
											2007-07-12 15:35:26 +00:00
										 |  |  |  * Copyright (C) 2007 Tim Janik | 
					
						
							| 
									
										
										
										
											2007-07-12 15:26:47 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * 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 | 
					
						
							| 
									
										
										
										
											2014-01-23 12:58:29 +01:00
										 |  |  |  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
 | 
					
						
							| 
									
										
										
										
											2007-07-12 15:26:47 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | #include <glib.h>
 | 
					
						
							|  |  |  | #include <stdlib.h>
 | 
					
						
							| 
									
										
										
										
											2013-11-05 16:08:45 +08:00
										 |  |  | #ifdef G_OS_UNIX
 | 
					
						
							| 
									
										
										
										
											2007-07-12 15:26:47 +00:00
										 |  |  | #include <unistd.h>
 | 
					
						
							| 
									
										
										
										
											2013-11-05 16:08:45 +08:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2007-07-12 15:26:47 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #define N_THREADS	8
 | 
					
						
							|  |  |  | #define N_ALLOCS	50000
 | 
					
						
							| 
									
										
										
										
											2007-07-12 15:35:26 +00:00
										 |  |  | #define MAX_BLOCK_SIZE  64
 | 
					
						
							| 
									
										
										
										
											2007-07-12 15:26:47 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | struct ThreadData | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   int	   thread_id; | 
					
						
							|  |  |  |   GThread* gthread; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-04 19:04:41 -04:00
										 |  |  |   GMutex   to_free_mutex; | 
					
						
							| 
									
										
										
										
											2007-07-12 15:26:47 +00:00
										 |  |  |   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]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-11-02 15:45:14 +00:00
										 |  |  | static void * | 
					
						
							| 
									
										
										
										
											2007-07-12 15:26:47 +00:00
										 |  |  | thread_func (void *arg) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   struct ThreadData *td = arg; | 
					
						
							|  |  |  |   int i; | 
					
						
							| 
									
										
										
										
											2010-01-20 18:53:08 +01:00
										 |  |  | /*   g_print ("Thread %d starting\n", td->thread_id); */ | 
					
						
							| 
									
										
										
										
											2007-07-12 15:26:47 +00:00
										 |  |  |   for (i = 0; i < N_ALLOCS; i++) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2012-11-02 15:45:14 +00:00
										 |  |  |       int bytes; | 
					
						
							|  |  |  |       char *mem; | 
					
						
							|  |  |  |       int f; | 
					
						
							|  |  |  |       int t; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-07-12 15:26:47 +00:00
										 |  |  |       if (rand() % (N_ALLOCS / 20) == 0) | 
					
						
							| 
									
										
										
										
											2007-07-12 15:35:26 +00:00
										 |  |  | 	g_print ("%c", 'a' - 1 + td->thread_id); | 
					
						
							| 
									
										
										
										
											2007-07-12 15:26:47 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-07-12 15:35:26 +00:00
										 |  |  |       /* allocate block of random size and randomly fill */ | 
					
						
							| 
									
										
										
										
											2012-11-02 15:45:14 +00:00
										 |  |  |       bytes = rand() % MAX_BLOCK_SIZE + 1; | 
					
						
							|  |  |  |       mem = g_slice_alloc (bytes); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-07-12 15:26:47 +00:00
										 |  |  |       for (f = 0; f < bytes; f++) | 
					
						
							|  |  |  | 	mem[f] = rand(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-07-12 15:35:26 +00:00
										 |  |  |       /* associate block with random thread */ | 
					
						
							| 
									
										
										
										
											2012-11-02 15:45:14 +00:00
										 |  |  |       t = rand() % N_THREADS; | 
					
						
							| 
									
										
										
										
											2011-10-04 19:04:41 -04:00
										 |  |  |       g_mutex_lock (&tdata[t].to_free_mutex); | 
					
						
							| 
									
										
										
										
											2007-07-12 15:26:47 +00:00
										 |  |  |       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++; | 
					
						
							| 
									
										
										
										
											2011-10-04 19:04:41 -04:00
										 |  |  |       g_mutex_unlock (&tdata[t].to_free_mutex); | 
					
						
							| 
									
										
										
										
											2007-07-12 15:26:47 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-07-12 15:35:26 +00:00
										 |  |  |       /* shuffle thread execution order every once in a while */ | 
					
						
							|  |  |  |       if (rand() % 97 == 0) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           if (rand() % 2) | 
					
						
							|  |  |  |             g_thread_yield();   /* concurrent shuffling for single core */ | 
					
						
							|  |  |  |           else | 
					
						
							|  |  |  |             g_usleep (1000);    /* concurrent shuffling for multi core */ | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2007-07-12 15:26:47 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-07-12 15:35:26 +00:00
										 |  |  |       /* free a block associated with this thread */ | 
					
						
							| 
									
										
										
										
											2011-10-04 19:04:41 -04:00
										 |  |  |       g_mutex_lock (&td->to_free_mutex); | 
					
						
							| 
									
										
										
										
											2007-07-12 15:26:47 +00:00
										 |  |  |       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++; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-10-04 19:04:41 -04:00
										 |  |  |       g_mutex_unlock (&td->to_free_mutex); | 
					
						
							| 
									
										
										
										
											2007-07-12 15:26:47 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							| 
									
										
										
										
											2012-11-02 15:45:14 +00:00
										 |  |  | main (void) | 
					
						
							| 
									
										
										
										
											2007-07-12 15:26:47 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   int t; | 
					
						
							| 
									
										
										
										
											2007-07-12 15:35:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-07-12 15:26:47 +00:00
										 |  |  |   for (t = 0; t < N_THREADS; t++) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       tdata[t].thread_id = t + 1; | 
					
						
							|  |  |  |       tdata[t].n_to_free = 0; | 
					
						
							|  |  |  |       tdata[t].n_freed = 0; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2007-07-12 15:35:26 +00:00
										 |  |  |   g_print ("Starting %d threads for concurrent GSlice usage...\n", N_THREADS); | 
					
						
							| 
									
										
										
										
											2007-07-12 15:26:47 +00:00
										 |  |  |   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; | 
					
						
							|  |  |  | } |