1964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik/* slice-threadinit.c - test GSlice across g_thread_init
2964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik * Copyright (C) 2007 Tim Janik
3964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik *
4964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik * This work is provided "as is"; redistribution and modification
5964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik * in whole or in part, in any medium, physical or electronic is
6964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik * permitted without restriction.
7964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik *
8964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik * This work is distributed in the hope that it will be useful,
9964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik * but WITHOUT ANY WARRANTY; without even the implied warranty of
10964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik *
12964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik * In no event shall the authors or contributors be liable for any
13964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik * direct, indirect, incidental, special, exemplary, or consequential
14964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik * damages (including, but not limited to, procurement of substitute
15964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik * goods or services; loss of use, data, or profits; or business
16964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik * interruption) however caused and on any theory of liability, whether
17964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik * in contract, strict liability, or tort (including negligence or
18964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik * otherwise) arising in any way out of the use of this software, even
19964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik * if advised of the possibility of such damage.
20964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik */
21964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik#include <glib.h>
22964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik
23964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik#define N_PAGES                 (101)                   /* number of pages to sample */
24964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik#define SAMPLE_SIZE             (7)
25964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik#define PAGE_SIZE               (128)                   /* must be <= minimum GSlice alignment block */
2684fdf0d00eb3b615ca4cbef8ce54881c14745264Matthias Clasen#define MAGAZINE_PROBES         { 81, 265, 347 }        /* block sizes hopefully unused by g_thread_init */
27964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik#define MAX_PROBE_TRIALS        (1031)                  /* must be >= maximum magazine size */
28964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik
29964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik#define ALIGN(size, base)       ((base) * (gsize) (((size) + (base) - 1) / (base)))
30964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik
31964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janikstatic struct {
32964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik  void *page;
33964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik  void *sample;
34964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik} pages[N_PAGES] = { { NULL, }, };
35964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik
36964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janikstatic const guint magazine_probes[] = MAGAZINE_PROBES;
37964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik#define N_MAGAZINE_PROBES       G_N_ELEMENTS (magazine_probes)
38964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik
39964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janikstatic void
40964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janikrelease_trash_list (GSList **trash_list,
41964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik                    gsize    block_size)
42964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik{
43964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik  while (*trash_list)
44964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik    {
45964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik      g_slice_free1 (block_size, (*trash_list)->data);
46964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik      *trash_list = g_slist_delete_link (*trash_list, *trash_list);
47964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik    }
48964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik}
49964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik
50964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janikstatic GSList *free_list = NULL;
51964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik
52964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janikstatic gboolean
53964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janikallocate_from_known_page (void)
54964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik{
55964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik  guint i, j, n_trials = N_PAGES * PAGE_SIZE / SAMPLE_SIZE; /* upper bound */
56964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik  for (i = 0; i < n_trials; i++)
57964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik    {
58964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik      void *b = g_slice_alloc (SAMPLE_SIZE);
59964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik      void *p = (void*) (PAGE_SIZE * ((gsize) b / PAGE_SIZE));
60964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik      free_list = g_slist_prepend (free_list, b);
61964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik      /* find page */
62964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik      for (j = 0; j < N_PAGES; j++)
63964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik        if (pages[j].page == p)
64964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik          return TRUE;
65964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik    }
66964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik  return FALSE;
67964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik}
68964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik
69964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janikint
70964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janikmain (int   argc,
71964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik      char *argv[])
72964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik{
73964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik  int j, n_pages = 0;
74964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik  void *mps[N_MAGAZINE_PROBES];
75964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik
76964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik  /* probe some magazine sizes */
77964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik  for (j = 0; j < N_MAGAZINE_PROBES; j++)
78964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik    mps[j] = g_slice_alloc (magazine_probes[j]);
79964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik  /* mps[*] now contains pointers to allocated slices */
80964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik
81964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik  /* allocate blocks from N_PAGES different pages */
82964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik  while (n_pages < N_PAGES)
83964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik    {
84964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik      void *b = g_slice_alloc (SAMPLE_SIZE);
85964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik      void *p = (void*) (PAGE_SIZE * ((gsize) b / PAGE_SIZE));
86964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik      for (j = 0; j < N_PAGES; j++)
87964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik        if (pages[j].page == p)
88964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik          break;
89964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik      if (j < N_PAGES)  /* known page */
90964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik        free_list = g_slist_prepend (free_list, b);
91964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik      else              /* new page */
92964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik        {
93964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik          j = n_pages++;
94964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik          pages[j].page = p;
95964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik          pages[j].sample = b;
96964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik        }
97964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik    }
98964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik  /* release intermediate allocations */
99964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik  release_trash_list (&free_list, SAMPLE_SIZE);
100964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik
101964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik  /* ensure that we can allocate from known pages */
102964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik  if (!allocate_from_known_page())
103964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik    g_error ("failed to allocate from magazine/page cache (before g_thread_init)");
104964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik  /* release intermediate allocations */
105964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik  release_trash_list (&free_list, SAMPLE_SIZE);
106964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik
107964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik  /* release magazine probes to be retained */
108964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik  for (j = 0; j < N_MAGAZINE_PROBES; j++)
109964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik    g_slice_free1 (magazine_probes[j], mps[j]);
110964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik  /* mps[*] now contains pointers to releaed slices */
111964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik
112964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik  /* ensure probes were retained */
113964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik  for (j = 0; j < N_MAGAZINE_PROBES; j++)
114964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik    {
115964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik      GSList *trash = NULL;
116964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik      guint k;
117964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik      for (k = 0; k < MAX_PROBE_TRIALS; k++)
118964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik        {
119964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik          void *mem = g_slice_alloc (magazine_probes[j]);
120964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik          if (mem == mps[j])
121964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik            break;      /* reallocated previously freed slice */
122964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik          trash = g_slist_prepend (trash, mem);
123964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik        }
124964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik      release_trash_list (&trash, magazine_probes[j]);
125964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik      if (k >= MAX_PROBE_TRIALS)        /* failed to reallocate slice */
126964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik        g_error ("failed to reallocate slice from magazine (before g_thread_init): size=%d", magazine_probes[j]);
127964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik    }
128964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik  /* mps[*] now contains pointers to reallocated slices */
129964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik
130964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik  /* release magazine probes to be retained across g_thread_init */
131964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik  for (j = 0; j < N_MAGAZINE_PROBES; j++)
132964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik    g_slice_free1 (magazine_probes[j], mps[j]);
13384fdf0d00eb3b615ca4cbef8ce54881c14745264Matthias Clasen  /* mps[*] now contains pointers to released slices */
134964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik
135964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik  /* initialize threading (should retain allocator state) */
136964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik  g_thread_init (NULL);
137964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik
138964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik  /* ensure probes were retained */
139964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik  for (j = 0; j < N_MAGAZINE_PROBES; j++)
140964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik    {
141964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik      GSList *trash = NULL;
142964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik      guint k;
143964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik      for (k = 0; k < MAX_PROBE_TRIALS; k++)
144964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik        {
145964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik          void *mem = g_slice_alloc (magazine_probes[j]);
146964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik          if (mem == mps[j])
147964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik            break;      /* reallocated previously freed slice */
148964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik          trash = g_slist_prepend (trash, mem);
149964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik        }
150964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik      release_trash_list (&trash, magazine_probes[j]);
151964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik      if (k >= MAX_PROBE_TRIALS)        /* failed to reallocate slice */
152964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik        g_error ("failed to reallocate slice from magazine (after g_thread_init): size=%d", magazine_probes[j]);
153964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik    }
154964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik  /* mps[*] now contains pointers to reallocated slices */
155964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik
156964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik  /* ensure that we can allocate from known pages */
157964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik  if (!allocate_from_known_page())
158964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik    g_error ("failed to allocate from magazine/page cache (after g_thread_init)");
159964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik
160964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik  /* some cleanups */
161964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik  for (j = 0; j < N_MAGAZINE_PROBES; j++)
162964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik    g_slice_free1 (magazine_probes[j], mps[j]);
163964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik  release_trash_list (&free_list, SAMPLE_SIZE);
164964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik
165964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik  return 0;
166964d75ebe37ba879d05fa1b27f06aed63e7106dbTim Janik}
167