1 /*------------------------------------------------------------------------------
2  *
3  * Copyright (c) 2011-2021, EURid vzw. All rights reserved.
4  * The YADIFA TM software product is provided under the BSD 3-clause license:
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  *        * Redistributions of source code must retain the above copyright
11  *          notice, this list of conditions and the following disclaimer.
12  *        * Redistributions in binary form must reproduce the above copyright
13  *          notice, this list of conditions and the following disclaimer in the
14  *          documentation and/or other materials provided with the distribution.
15  *        * Neither the name of EURid nor the names of its contributors may be
16  *          used to endorse or promote products derived from this software
17  *          without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  *
31  *------------------------------------------------------------------------------
32  *
33  */
34 
35 /** @defgroup test
36  *  @ingroup test
37  *  @brief skeleton file
38  *
39  * skeleton test program, will not be installed with a "make install"
40  *
41  * To create a new test based on the skeleton:
42  *
43  * _ copy the folder
44  * _ replace "skeleton" by the name of the test
45  * _ add the test to the top level Makefile.am and configure.ac
46  *
47  */
48 
49 #include <dnscore/dnscore.h>
50 #include <dnscore/format.h>
51 #include <dnscore/shared-heap.h>
52 #include <dnscore/shared-heap-bytearray-output-stream.h>
53 #include <dnscore/random.h>
54 #include <dnscore/process.h>
55 
56 #define MEMORY_HEAP_SIZE 0x40000000
57 #define LOOP_COUNT 4096
58 
59 #define CHILDREN 4
60 
61 #define FORK_LOOPS 64
62 
63 #define L1_SIZE 64
64 #define L1_MASK (L1_SIZE - 1)
65 
66 #define MEMORY_HEAP_L1_SLOTS (MEMORY_HEAP_SIZE / L1_SIZE)
67 #define FORK_LOOP_POINTER_ARRAY_SIZE (MEMORY_HEAP_L1_SLOTS * sizeof(void*))
68 #define FORK_LOOP_COUNT ((((MEMORY_HEAP_SIZE - FORK_LOOP_POINTER_ARRAY_SIZE)) / L1_SIZE) / 2)
69 
70 static u8 *pointers[LOOP_COUNT];
71 
72 static void** shared_blocs;
73 
74 static char one_kb_string[1048] =
75     "BEGIN0123456789ABCDEFGHIJKLMNOPQ"
76     "RSTUVWXYZabcdefghijklmnopqrstuvw"
77     "xyz-j7YZ5sjpN2GPC6B870yZ3HJBIbpk"
78     "7v6hmzxHu6eAomRhAb9ikkfxSP1qy7S6"
79     "Q6cnNREREssBkSv8hlsEoD0GR0Ip1Tu1"
80     "yDQj2LhCpzTJacaJ1qxJ2TjoQxoVi6xe"
81     "m7DHzeUvyJca06wmuZOs0oKGQmJFRu9a"
82     "uz9f8fT8onBFjgBpBcPmzor7rEpqWrcK"
83     "NEtpoueRln6q1qSK6RUkULbYwLShTWgD"
84     "bMstlAEVp5EqUIPhlQXSf4eOpImJM4Yt"
85     "Lu4LFThG5GU8n9zNTk4WlxcGQCj8Emx1"
86     "pqtjHWx55lLiqoJCLgDYPDN99vjB8ukz"
87     "XfaXHQIjq44rnxvwpf7cEpMMxHCp7IOO"
88     "18nJ42O4CmxTfoKtIkJkuA0NczkitEeF"
89     "64Gtj3TubiBLtfRra8zBN8ByqfeeQZG1"
90     "XgHaO6s6covHabtb0gzLVV1GenCPvYfp"
91     "pivvH8lSWvkeH0xJ5zTjG19Voql883Ii"
92     "y28NCXTosBFe81DhvqHQgQ7FU7Njv96o"
93     "kiC9Cr8f6CEXp23qe8fL3A4iaEcMPg4f"
94     "iRZzUAQtblzzf3nryBpe7gHZiIjE1kUG"
95     "eMXJehH0LDFrWR4AmUhZNxR8aK1RSFKZ"
96     "Uy32zPIx6TMrTFncSTBgqluwObbFAk6R"
97     "1G6ToGPL1X75JNpwXhURN752RNQQUCGo"
98     "Vv1SMKBTzpMXH9hfy33wllyiru6ZAciJ"
99     "iAa0KmlE9vfqYIv6hA0PyMqIwP7twDRs"
100     "kuVI4tbBBY5ScHsa42SnsFpYEXBJuKk1"
101     "LFQ4sQED1Stvt5rtf7FDUx316eZ64qVB"
102     "1k1sO9YgNzrrv3gpip3vcHr6SWLybVMa"
103     "yw047f0YZhjfNXg2YOXPJaNmXvKaUiOe"
104     "SyeINNqCIQuDzCUYeLscEEWaoyx5NAyt"
105     "mj9hcK4v3S4zLpB3fs1xa5icmV9uz2SW"
106     "Uk75WhbSnQ3iW8kMcP1TYz9yDIufAz6m"
107     "THE-END";
108 
109 int
main(int argc,char * argv[])110 main(int argc, char *argv[])
111 {
112     (void)argc;
113     (void)argv;
114     /* initializes the core library */
115 
116     ya_result ret;
117 
118     dnscore_init();
119 
120     if(FAIL(ret = shared_heap_init()))
121     {
122         formatln("shared_heap_init() failed: %r", ret);
123         return 1;
124     }
125 
126     if(FAIL(ret = shared_heap_create(MEMORY_HEAP_SIZE))) // 64MB
127     {
128         formatln("shared_heap_create() failed: %r", ret);
129         return 2;
130     }
131 
132     u8 id = (u8)ret;
133 
134     int count = LOOP_COUNT;
135 
136     shared_heap_check(id);
137 
138     for(int j = 11; j < 1023; ++j)
139     {
140         output_stream baos;
141         //output_stream baos2;
142         shared_heap_output_stream_context shos_context;
143         shared_heap_output_stream_init_ex_static(&baos, id, NULL, 48, SHARED_HEAP_DYNAMIC, &shos_context);
144         //shared_heap_output_stream_context shos_context2;
145         //shared_heap_output_stream_init_ex_static(&baos2, id, NULL, 48, SHARED_HEAP_DYNAMIC, &shos_context2);
146 
147         for(int i = 0; i < j; ++i)
148         {
149             output_stream_write(&baos, one_kb_string, i & 1023);
150             //output_stream_write(&baos2, one_kb_string, 1023 - (i & 1023));
151 
152             shared_heap_check(id);
153         }
154 
155         output_stream_close(&baos);
156         //output_stream_close(&baos2);
157 
158         shared_heap_check(id);
159 
160         size_t total;
161         size_t count;
162 
163         shared_heap_count_allocated(id, &total, &count);
164 
165         assert((total == 0) && (count == 0));
166     }
167 
168     for(int i = 0; i < count; ++i)
169     {
170         pointers[i] = (u8*)shared_heap_alloc(id, i);
171         if(pointers[i] == NULL)
172         {
173             formatln("failed to allocate %i bytes", i);
174             return 3;
175         }
176         shared_heap_check_ptr(id, pointers[i]);
177         shared_heap_check(id);
178         memset(pointers[i], i, i);
179         formatln("alloc: @%p: %i bytes", pointers[i], i);
180     }
181 
182     shared_heap_check(id);
183 
184     for(int i = 0; i < count; ++i)
185     {
186         formatln("---->: @%p: %i bytes", pointers[i], i);
187         shared_heap_check_ptr(id, pointers[i]);
188         shared_heap_free(/*id, */pointers[i]);
189         formatln("freed: @%p: %i bytes", pointers[i], i);
190     }
191 
192     shared_heap_check(id);
193 
194     pointers[0] = (u8*)shared_heap_alloc(id, 0);
195     shared_heap_free(/*id, */pointers[0]);
196 
197     for(int i = 0; i < count; ++i)
198     {
199         pointers[i] = (u8*)shared_heap_alloc(id, i);
200         if(pointers[i] == NULL)
201         {
202             formatln("failed to allocate %i bytes", i);
203             return 3;
204         }
205         shared_heap_check_ptr(id, pointers[i]);
206         memset(pointers[i], i, i);
207         formatln("alloc: @%p: %i bytes", pointers[i], i);
208     }
209 
210     shared_heap_check(id);
211 
212     for(int i = count - 1; i >= 0; --i)
213     {
214         formatln("---->: @%p: %i bytes", pointers[i], i);
215         shared_heap_check_ptr(id, pointers[i]);
216         shared_heap_free(/*id, */pointers[i]);
217         formatln("freed: @%p: %i bytes", pointers[i], i);
218     }
219 
220     shared_heap_check(id);
221 
222     random_ctx rndctx = random_init(0);
223 
224     int next_ptr = 0;
225     for(int i = 0; i < 1000000; ++i)
226     {
227         if(next_ptr < LOOP_COUNT)
228         {
229             shared_heap_check(id);
230             pointers[next_ptr] = (u8*)shared_heap_alloc(id, i & 1023);
231             shared_heap_check(id);
232 
233             if(pointers[next_ptr] == NULL)
234             {
235                 --next_ptr;
236                 assert(next_ptr >= 0);
237                 shared_heap_check(id);
238                 shared_heap_free(pointers[next_ptr]);
239                 shared_heap_check(id);
240                 continue;
241             }
242 
243             memset(pointers[next_ptr], i, i & 1023);
244             shared_heap_check(id);
245 
246             ++next_ptr;
247         }
248 
249         if(i & 1)
250         {
251             u32 r = random_next(rndctx);
252             if(r & 1)
253             {
254                 r = random_next(rndctx);
255                 r %= next_ptr;
256                 shared_heap_check(id);
257                 shared_heap_free(pointers[r]);
258                 shared_heap_check(id);
259                 pointers[r] = pointers[--next_ptr];
260             }
261         }
262     }
263 
264     for(int i = 0; i < next_ptr; ++i)
265     {
266         shared_heap_free(pointers[i]);
267         shared_heap_check(id);
268     }
269 
270     next_ptr = 0;
271 
272     for(int i = 0; i < 1000000; ++i)
273     {
274         if(next_ptr < LOOP_COUNT)
275         {
276             shared_heap_check(id);
277             pointers[next_ptr] = (u8*)shared_heap_alloc(id, 48);
278             shared_heap_check(id);
279 
280             if(pointers[next_ptr] == NULL)
281             {
282                 --next_ptr;
283                 assert(next_ptr >= 0);
284                 shared_heap_check(id);
285                 shared_heap_free(pointers[next_ptr]);
286                 shared_heap_check(id);
287                 continue;
288             }
289 
290             memset(pointers[next_ptr], i, 48);
291             shared_heap_check(id);
292 
293             ++next_ptr;
294         }
295 
296         if(i & 1)
297         {
298             u32 r = random_next(rndctx);
299             if(r & 1)
300             {
301                 r = random_next(rndctx);
302                 r %= next_ptr;
303                 shared_heap_check(id);
304                 shared_heap_free(pointers[r]);
305                 shared_heap_check(id);
306                 pointers[r] = pointers[--next_ptr];
307             }
308         }
309     }
310 
311     for(int i = 0; i < next_ptr; ++i)
312     {
313         shared_heap_free(pointers[i]);
314         shared_heap_check(id);
315     }
316 
317     random_finalize(rndctx);
318 
319     pointers[0] = (u8*)shared_heap_alloc(id, 0);
320     shared_heap_free(/*id, */pointers[0]);
321 
322     shared_heap_check(id);
323 
324     shared_blocs = (void**)shared_heap_alloc(id, LOOP_COUNT * sizeof(void*));
325     assert(shared_blocs != NULL);
326 
327     for(int f = 0; f < FORK_LOOPS; ++f)
328     {
329         formatln("fork test %i/%i begin", f, FORK_LOOPS);
330         pid_t child[CHILDREN];
331         for(int i = 0; i < CHILDREN; ++i)
332         {
333             if((child[i] = fork_ex()) == 0)
334             {
335                 formatln("[%5i] working", getpid_ex());
336 
337                 for(int j = 0; j < LOOP_COUNT; j += CHILDREN)
338                 {
339                     shared_blocs[i + j] = shared_heap_alloc(id, j);
340                     //shared_heap_check_ptr(id, shared_blocs[i + j]);
341                     memset(shared_blocs[i + j], 0xff, j);
342                     formatln("[%5i] alloc: @%p: %i bytes", getpid_ex(), shared_blocs[i + j], j);
343                 }
344 
345                 formatln("[%5i] done", getpid_ex());
346 
347                 flushout();
348 
349                 exit(0);
350             }
351             else if(child[i] < 0)
352             {
353                 abort();
354             }
355         }
356 
357         formatln("fork test %i/%i: waiting for children", f, FORK_LOOPS);
358 
359         for(int i = 0; i < CHILDREN; ++i)
360         {
361             waitpid_ex(child[i], NULL, 0);
362         }
363 
364         formatln("fork test %i/%i: integrity check before free", f, FORK_LOOPS);
365 
366         shared_heap_check(id);
367 
368         for(int i = 0; i < LOOP_COUNT; ++i)
369         {
370             formatln("---->: @%p: %i bytes", shared_blocs[i], i / CHILDREN);
371             shared_heap_check_ptr(id, shared_blocs[i]);
372             shared_heap_free(/*id, */shared_blocs[i]);
373             formatln("freed: @%p: %i bytes", shared_blocs[i], i);
374         }
375 
376         formatln("fork test %i/%i: integrity check after free", f, FORK_LOOPS);
377 
378         flushout();
379     }
380 
381     shared_heap_free(/*id, */shared_blocs);
382 
383     shared_heap_check(id);
384 
385     println("and now for a bigger one");
386 
387     pointers[0] = (u8*)shared_heap_alloc(id, 0);
388     shared_heap_free(/*id, */pointers[0]);
389 
390     shared_heap_check(id);
391 
392     shared_blocs = (void**)shared_heap_alloc(id, FORK_LOOP_POINTER_ARRAY_SIZE);
393     assert(shared_blocs != NULL);
394 
395     for(int f = 0; f < FORK_LOOPS; ++f)
396     {
397         formatln("fork test %i/%i begin", f, FORK_LOOPS);
398         pid_t child[CHILDREN];
399         for(int i = 0; i < CHILDREN; ++i)
400         {
401             if((child[i] = fork_ex()) == 0)
402             {
403                 formatln("[%5i] working", getpid_ex());
404 
405                 for(size_t j = 0; j < FORK_LOOP_COUNT; j += CHILDREN)
406                 {
407                     shared_blocs[i + j] = shared_heap_alloc(id, j & L1_MASK);
408                     assert(shared_blocs[i + j] != NULL);
409                     //shared_heap_check_ptr(id, shared_blocs[i + j]);
410                     //formatln("[%5i] alloc: @%p: %i bytes", getpid_ex(), shared_blocs[i + j], j & L1_MASK);
411                 }
412 
413                 formatln("[%5i] done", getpid_ex());
414 
415                 flushout();
416 
417                 exit(0);
418             }
419             else if(child[i] < 0)
420             {
421                 abort();
422             }
423         }
424 
425         formatln("fork test %i/%i: waiting for children", f, FORK_LOOPS);
426 
427         for(int i = 0; i < CHILDREN; ++i)
428         {
429             waitpid_ex(child[i], NULL, 0);
430         }
431 
432         formatln("fork test %i/%i: integrity check before free", f, FORK_LOOPS);
433 
434         shared_heap_check(id);
435 
436         for(size_t i = 0; i < FORK_LOOP_COUNT; ++i)
437         {
438             //formatln("---->: @%p: %i bytes", shared_blocs[i], i);
439             //shared_heap_check_ptr(id, shared_blocs[i]);
440             assert(shared_blocs[i] != NULL);
441             shared_heap_free(/*id, */shared_blocs[i]);
442             //formatln("freed: @%p: %i bytes", shared_blocs[i], i);
443         }
444 
445         formatln("fork test %i/%i: integrity check after free", f, FORK_LOOPS);
446 
447         flushout();
448     }
449 
450     shared_heap_free(/*id, */shared_blocs);
451 
452     shared_heap_check(id);
453 
454     pointers[0] = (u8*)shared_heap_alloc(id, 0);
455     shared_heap_free(/*id, */pointers[0]);
456 
457     flushout();
458     flusherr();
459     fflush(NULL);
460 
461     dnscore_finalize();
462 
463     return EXIT_SUCCESS;
464 }
465