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