implemented static debugging hash-tree to validate slice adresses and

Thu Dec 28 12:50:31 2006  Tim Janik  <timj@imendio.com>

        * glib/gslice.h, glib/gslice.c: implemented static debugging
        hash-tree to validate slice adresses and sizes with G_SLICE=debug-blocks.
        use abort() to exit in mem_error() to allow catching of these in gdb.
        abort programs with a descriptive error message if g_thread_init() is
        called after GSlice was in use. previously this just silently corrupted
        the magazines.

        * glib/ghash.c (struct _GHashNode): reordered fields to keep 8-byte
        pointer alignment on 64bit systems and request smaller slice sizes
        on 32bit systems.

        * tests/slice-test.c: support '~' option flag to introduce slice
        allocation/release corruption with a significant probability. this
        allowes testing of G_SLICE=debug-blocks.
This commit is contained in:
Tim Janik
2006-12-28 11:50:43 +00:00
committed by Tim Janik
parent 636dae32c3
commit 1bd8993451
6 changed files with 360 additions and 15 deletions

View File

@@ -26,6 +26,7 @@ static guint prime_size = 1021; // 769; // 509
static gboolean clean_memchunks = FALSE;
static guint number_of_blocks = 10000; /* total number of blocks allocated */
static guint number_of_repetitions = 10000; /* number of alloc+free repetitions */
static gboolean want_corruption = FALSE;
/* --- old memchunk prototypes (memchunks.c) --- */
void old_mem_chunks_init (void);
@@ -47,6 +48,18 @@ void old_mem_chunk_info (void);
#endif
/* --- functions --- */
static inline int
corruption (void)
{
if (G_UNLIKELY (want_corruption))
{
/* corruption per call likelyness is about 1:4000000 */
guint32 r = g_random_int() % 8000009;
return r == 277 ? +1 : r == 281 ? -1 : 0;
}
return 0;
}
static inline gpointer
memchunk_alloc (GMemChunk **memchunkp,
guint size)
@@ -153,31 +166,31 @@ test_sliced_mem_thread (gpointer data)
ss[i] = quick_rand32() % prime_size;
/* allocate number_of_blocks blocks */
for (i = 0; i < number_of_blocks; i++)
ps[i] = g_slice_alloc (ss[i]);
ps[i] = g_slice_alloc (ss[i] + corruption());
for (j = 0; j < number_of_repetitions; j++)
{
/* free number_of_blocks/2 blocks */
for (i = 0; i < number_of_blocks; i += 2)
g_slice_free1 (ss[i], ps[i]);
g_slice_free1 (ss[i] + corruption(), ps[i] + corruption());
/* allocate number_of_blocks/2 blocks with new sizes */
for (i = 0; i < number_of_blocks; i += 2)
{
ss[i] = quick_rand32() % prime_size;
ps[i] = g_slice_alloc (ss[i]);
ps[i] = g_slice_alloc (ss[i] + corruption());
}
}
/* free number_of_blocks blocks */
for (i = 0; i < number_of_blocks; i++)
g_slice_free1 (ss[i], ps[i]);
g_slice_free1 (ss[i] + corruption(), ps[i] + corruption());
/* alloc and free many equally sized chunks in a row */
for (i = 0; i < number_of_repetitions; i++)
{
guint sz = quick_rand32() % prime_size;
guint k = number_of_blocks / 100;
for (j = 0; j < k; j++)
ps[j] = g_slice_alloc (sz);
ps[j] = g_slice_alloc (sz + corruption());
for (j = 0; j < k; j++)
g_slice_free1 (sz, ps[j]);
g_slice_free1 (sz + corruption(), ps[j] + corruption());
}
g_free (ps);
g_free (ss);
@@ -188,7 +201,7 @@ test_sliced_mem_thread (gpointer data)
static void
usage (void)
{
g_print ("Usage: slice-test [n_threads] [G|S|M|O][f][c] [maxblocksize] [seed]\n");
g_print ("Usage: slice-test [n_threads] [G|S|M|O][f][c][~] [maxblocksize] [seed]\n");
}
int
@@ -233,6 +246,9 @@ main (int argc,
case 'c': /* print contention counters */
ccounters = TRUE;
break;
case '~':
want_corruption = TRUE; /* force occasional corruption */
break;
default:
usage();
return 1;