glib/tests/slice-threadinit.c
changeset 18 47c74d1534e1
equal deleted inserted replaced
0:e4d67989cc36 18:47c74d1534e1
       
     1 /* slice-threadinit.c - test GSlice across g_thread_init
       
     2  * Copyright (C) 2007 Tim Janik
       
     3  * Portions copyright (c) 2009 Nokia Corporation.  All rights reserved.
       
     4  * This work is provided "as is"; redistribution and modification
       
     5  * in whole or in part, in any medium, physical or electronic is
       
     6  * permitted without restriction.
       
     7  *
       
     8  * This work is distributed in the hope that it will be useful,
       
     9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
       
    11  *
       
    12  * In no event shall the authors or contributors be liable for any
       
    13  * direct, indirect, incidental, special, exemplary, or consequential
       
    14  * damages (including, but not limited to, procurement of substitute
       
    15  * goods or services; loss of use, data, or profits; or business
       
    16  * interruption) however caused and on any theory of liability, whether
       
    17  * in contract, strict liability, or tort (including negligence or
       
    18  * otherwise) arising in any way out of the use of this software, even
       
    19  * if advised of the possibility of such damage.
       
    20  */
       
    21 #include <glib.h>
       
    22 #ifdef __SYMBIAN32__
       
    23 #include "mrt2_glib2_test.h"
       
    24 #endif /*__SYMBIAN32__*/
       
    25 #define N_PAGES                 (101)                   /* number of pages to sample */
       
    26 #define SAMPLE_SIZE             (7)
       
    27 #define PAGE_SIZE               (128)                   /* must be <= minimum GSlice alignment block */
       
    28 #define MAGAZINE_PROBES         { 81, 265, 347 }        /* block sizes hopefully unused by g_thread_init */
       
    29 #define MAX_PROBE_TRIALS        (1031)                  /* must be >= maximum magazine size */
       
    30 
       
    31 #define ALIGN(size, base)       ((base) * (gsize) (((size) + (base) - 1) / (base)))
       
    32 
       
    33 static struct {
       
    34   void *page;
       
    35   void *sample;
       
    36 } pages[N_PAGES] = { { NULL, }, };
       
    37 
       
    38 static const guint magazine_probes[] = MAGAZINE_PROBES;
       
    39 #define N_MAGAZINE_PROBES       G_N_ELEMENTS (magazine_probes)
       
    40 
       
    41 static void
       
    42 release_trash_list (GSList **trash_list,
       
    43                     gsize    block_size)
       
    44 {
       
    45   while (*trash_list)
       
    46     {
       
    47       g_slice_free1 (block_size, (*trash_list)->data);
       
    48       *trash_list = g_slist_delete_link (*trash_list, *trash_list);
       
    49     }
       
    50 }
       
    51 
       
    52 static GSList *free_list = NULL;
       
    53 
       
    54 static gboolean
       
    55 allocate_from_known_page (void)
       
    56 {
       
    57   guint i, j, n_trials = N_PAGES * PAGE_SIZE / SAMPLE_SIZE; /* upper bound */
       
    58   for (i = 0; i < n_trials; i++)
       
    59     {
       
    60       void *b = g_slice_alloc (SAMPLE_SIZE);
       
    61       void *p = (void*) (PAGE_SIZE * ((gsize) b / PAGE_SIZE));
       
    62       free_list = g_slist_prepend (free_list, b);
       
    63       /* find page */
       
    64       for (j = 0; j < N_PAGES; j++)
       
    65         if (pages[j].page == p)
       
    66           return TRUE;
       
    67     }
       
    68   return FALSE;
       
    69 }
       
    70 
       
    71 int
       
    72 main (int   argc,
       
    73       char *argv[])
       
    74 {
       
    75   int j, n_pages = 0;
       
    76   void *mps[N_MAGAZINE_PROBES];
       
    77 #ifdef __SYMBIAN32__
       
    78   g_log_set_handler (NULL,  G_LOG_FLAG_FATAL| G_LOG_FLAG_RECURSION | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING | G_LOG_LEVEL_MESSAGE | G_LOG_LEVEL_INFO | G_LOG_LEVEL_DEBUG, &mrtLogHandler, NULL);
       
    79   g_set_print_handler(mrtPrintHandler);
       
    80   #endif /*__SYMBIAN32__*/
       
    81   /* probe some magazine sizes */
       
    82   for (j = 0; j < N_MAGAZINE_PROBES; j++)
       
    83     mps[j] = g_slice_alloc (magazine_probes[j]);
       
    84   /* mps[*] now contains pointers to allocated slices */
       
    85 
       
    86   /* allocate blocks from N_PAGES different pages */
       
    87   while (n_pages < N_PAGES)
       
    88     {
       
    89       void *b = g_slice_alloc (SAMPLE_SIZE);
       
    90       void *p = (void*) (PAGE_SIZE * ((gsize) b / PAGE_SIZE));
       
    91       for (j = 0; j < N_PAGES; j++)
       
    92         if (pages[j].page == p)
       
    93           break;
       
    94       if (j < N_PAGES)  /* known page */
       
    95         free_list = g_slist_prepend (free_list, b);
       
    96       else              /* new page */
       
    97         {
       
    98           j = n_pages++;
       
    99           pages[j].page = p;
       
   100           pages[j].sample = b;
       
   101         }
       
   102     }
       
   103   /* release intermediate allocations */
       
   104   release_trash_list (&free_list, SAMPLE_SIZE);
       
   105 
       
   106   /* ensure that we can allocate from known pages */
       
   107   if (!allocate_from_known_page())
       
   108     g_error ("failed to allocate from magazine/page cache (before g_thread_init)");
       
   109   /* release intermediate allocations */
       
   110   release_trash_list (&free_list, SAMPLE_SIZE);
       
   111 
       
   112   /* release magazine probes to be retained */
       
   113   for (j = 0; j < N_MAGAZINE_PROBES; j++)
       
   114     g_slice_free1 (magazine_probes[j], mps[j]);
       
   115   /* mps[*] now contains pointers to releaed slices */
       
   116 
       
   117   /* ensure probes were retained */
       
   118   for (j = 0; j < N_MAGAZINE_PROBES; j++)
       
   119     {
       
   120       GSList *trash = NULL;
       
   121       guint k;
       
   122       for (k = 0; k < MAX_PROBE_TRIALS; k++)
       
   123         {
       
   124           void *mem = g_slice_alloc (magazine_probes[j]);
       
   125           if (mem == mps[j])
       
   126             break;      /* reallocated previously freed slice */
       
   127           trash = g_slist_prepend (trash, mem);
       
   128         }
       
   129       release_trash_list (&trash, magazine_probes[j]);
       
   130       if (k >= MAX_PROBE_TRIALS)        /* failed to reallocate slice */
       
   131         g_error ("failed to reallocate slice from magazine (before g_thread_init): size=%d", magazine_probes[j]);
       
   132     }
       
   133   /* mps[*] now contains pointers to reallocated slices */
       
   134 
       
   135   /* release magazine probes to be retained across g_thread_init */
       
   136   for (j = 0; j < N_MAGAZINE_PROBES; j++)
       
   137     g_slice_free1 (magazine_probes[j], mps[j]);
       
   138   /* mps[*] now contains pointers to released slices */
       
   139 
       
   140   /* initialize threading (should retain allocator state) */
       
   141   g_thread_init (NULL);
       
   142 
       
   143   /* ensure probes were retained */
       
   144   for (j = 0; j < N_MAGAZINE_PROBES; j++)
       
   145     {
       
   146       GSList *trash = NULL;
       
   147       guint k;
       
   148       for (k = 0; k < MAX_PROBE_TRIALS; k++)
       
   149         {
       
   150           void *mem = g_slice_alloc (magazine_probes[j]);
       
   151           if (mem == mps[j])
       
   152             break;      /* reallocated previously freed slice */
       
   153           trash = g_slist_prepend (trash, mem);
       
   154         }
       
   155       release_trash_list (&trash, magazine_probes[j]);
       
   156       if (k >= MAX_PROBE_TRIALS)        /* failed to reallocate slice */
       
   157         g_error ("failed to reallocate slice from magazine (after g_thread_init): size=%d", magazine_probes[j]);
       
   158     }
       
   159   /* mps[*] now contains pointers to reallocated slices */
       
   160 
       
   161   /* ensure that we can allocate from known pages */
       
   162   if (!allocate_from_known_page())
       
   163     g_error ("failed to allocate from magazine/page cache (after g_thread_init)");
       
   164 
       
   165   /* some cleanups */
       
   166   for (j = 0; j < N_MAGAZINE_PROBES; j++)
       
   167     g_slice_free1 (magazine_probes[j], mps[j]);
       
   168   release_trash_list (&free_list, SAMPLE_SIZE);
       
   169 #if __SYMBIAN32__
       
   170   testResultXml("slice-threadinit");
       
   171   #endif /* EMULATOR */
       
   172   return 0;
       
   173 }