|
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 } |