xcache: Explicitly set flag to use rm tables
[archipelago] / xseg / xtypes / xheap_test.c
1 /*
2  * Copyright 2012 GRNET S.A. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or
5  * without modification, are permitted provided that the following
6  * conditions are met:
7  *
8  *   1. Redistributions of source code must retain the above
9  *      copyright notice, this list of conditions and the following
10  *      disclaimer.
11  *   2. Redistributions in binary form must reproduce the above
12  *      copyright notice, this list of conditions and the following
13  *      disclaimer in the documentation and/or other materials
14  *      provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  *
29  * The views and conclusions contained in the software and
30  * documentation are those of the authors and should not be
31  * interpreted as representing official policies, either expressed
32  * or implied, of GRNET S.A.
33  */
34
35 #include <stdlib.h>
36 #include "xheap.h"
37 #include <stdint.h>
38 #include <pthread.h>
39
40 struct xheap heap;
41 uint32_t al_unit = 12;
42 unsigned long size = 1048576;
43 unsigned long chunk = 4096;
44 unsigned long nr_threads = 4;
45 unsigned long nr_frees;
46 void *mem;
47
48 #define full_size(_x_) ((_x_) + sizeof(struct xheap_header))
49 void print_ptr(void *ptr)
50 {
51         uint64_t size = xheap_get_chunk_size(ptr);
52         printf("ptr: %lx, bytes: %llu (actual: %llu)\n", 
53                         (unsigned long) ptr, 
54                         (unsigned long long) size, 
55                         (unsigned long long) full_size(size));
56 }
57
58 unsigned long test(struct xheap *heap)
59 {
60         int r = xheap_init(heap, size, al_unit, mem);
61         if (r < 0){
62                 printf("xheap init error\n");
63                 return -1;
64         }
65         unsigned long i = 0;
66         uint64_t alloc_size = 0, start = heap->cur;
67         printf("heap starts with %llu\n", start);
68         void *ptr;
69         do {
70                 ptr = xheap_allocate(heap, chunk);
71                 if (ptr != NULL){
72                         i++;
73                         if ((unsigned long) ptr & ((1 << al_unit) -1)) {
74                                 printf("ptr %x not aligned with al_unit %lu\n",
75                                                 ptr, al_unit);
76                                 return -1;
77                         }
78                         alloc_size += xheap_get_chunk_size(ptr);
79                 }
80         }while (ptr != NULL);
81         printf("Allocated %lu chunks of size %lu with allocation unit %lu (%lu bytes)\n",
82                         i, chunk, al_unit, (1<<al_unit));
83         printf("Total allocated space: %llu\n", (unsigned long long) alloc_size);
84         alloc_size += i*sizeof(struct xheap_header);
85         printf("Total allocated space plus headers: %llu\n", 
86                         (unsigned long long) alloc_size);
87         alloc_size += start + 2 * sizeof(struct xheap_header);
88         printf("Total allocated space plus headers and start/end padding: %llu\n", 
89                         (unsigned long long) alloc_size);
90         printf("Lost space: %llu\n", (unsigned long long) (heap->size - alloc_size));
91         return i;
92 }
93
94 int test_align(struct xheap *heap)
95 {
96         uint64_t bytes = heap->size;
97         int m = sizeof(bytes)*8 - __builtin_clzl(bytes -1);
98         unsigned long i;
99         void *ptr;
100         for (i = 5; i < m; i++){
101                 int r = xheap_init(heap, size, i, mem);
102                 if (r < 0){
103                         printf("align: xheap init error\n");
104                         return -1;
105                 }
106                 do {
107                         ptr = xheap_allocate(heap, chunk);
108                         if (ptr != NULL){
109                                 if ((unsigned long) ptr & ((1 << i) -1)) {
110                                         printf("ptr %x not aligned with al_unit %lu\n",
111                                                         ptr, i);
112                                         return -1;
113                                 }
114                         }
115                 }while (ptr != NULL);
116         }
117         return 0;
118 }
119
120 int test_reuse(struct xheap *heap)
121 {
122         int r = xheap_init(heap, size, al_unit, mem);
123         if (r < 0){
124                 printf("xheap init error\n");
125                 return -1;
126         }
127         void *ptr1, *ptr2;
128         ptr1 = xheap_allocate(heap, chunk);
129         if (ptr1 == NULL) {
130                 printf("couldn't allocate\n");
131                 return -1;
132         }
133         xheap_free(ptr1);
134         ptr2 = xheap_allocate(heap, chunk);
135         if (ptr2 == NULL) {
136                 printf("couldn't allocate\n");
137                 return -1;
138         }
139         if (ptr1 != ptr2) {
140                 printf("alloc-free-alloc return diffrent ptr\n");
141                 return -1;
142         }
143         return 0;
144 }
145
146 struct thread_arg{
147         int id;
148         struct xheap *heap;
149         unsigned long c;
150         unsigned long allocations;
151         unsigned long frees;
152 };
153
154 void *thread_test(void *arg)
155 {
156         struct thread_arg *targ = (struct thread_arg *) arg;
157         struct xheap *heap = targ->heap;
158         int id = targ->id;
159         unsigned long c = targ->c;
160         void *ptr;
161         unsigned long i = 0;
162         do {
163                 ptr = xheap_allocate(heap, chunk);
164                 if (ptr != NULL){
165                         i++;
166                         memset(ptr, 1, xheap_get_chunk_size(ptr));
167                         if (c) {
168                                 xheap_free(ptr);
169                                 c--;
170                         }
171                 }
172         }while (ptr != NULL);
173
174         targ->allocations = i;
175         targ->frees = targ->c - c;
176         return NULL;
177 }
178
179 unsigned long test_threads(struct xheap *heap)
180 {
181         int i;
182         unsigned long allocations = 0;
183         nr_frees = 0;
184
185         int r = xheap_init(heap, size, al_unit, mem);
186         if (r < 0){
187                 printf("threads: xheap init error\n");
188                 return -1;
189         }
190
191         struct thread_arg *targs = malloc(sizeof(struct thread_arg) * nr_threads);
192         if (!targs) {
193                 printf("error malloc\n");
194                 return -1;
195         }
196
197         pthread_t *threads = malloc(sizeof(pthread_t) * nr_threads);
198         if (!threads){
199                 printf("error malloc\n");
200                 return -1;
201         }
202
203         for (i = 0; i < nr_threads; i++) {
204                 targs[i].id = i;
205                 targs[i].heap = heap;
206                 targs[i].c = 256;
207         }
208
209         for (i = 0; i < nr_threads; i++) {
210                 r = pthread_create(&threads[i], NULL, thread_test, &targs[i]);
211                 if (r) {
212                         printf("error pthread_create\n");
213                         return -1;
214                 }
215         }
216
217         for (i = 0; i < nr_threads; i++) {
218                 pthread_join(threads[i], NULL);
219                 allocations +=  targs[i].allocations;
220                 nr_frees += targs[i].frees;
221         }
222         return allocations;
223 }
224
225 int main(int argc, const char *argv[])
226 {
227         unsigned long alloc, expected, i =0;
228         int r;
229         if (argc < 5){
230                 printf("Usage: %s al_unit size chunk_size nr_threads\n", argv[0]);
231                 return -1;
232         }
233         al_unit = atol(argv[1]); 
234         size = atol(argv[2]); 
235         chunk = atol(argv[3]);
236         nr_threads = atol(argv[4]);
237         mem = malloc(size);
238         r = test(&heap);
239         alloc = r;
240         
241         printf("Testing align: ");
242         r = test_align(&heap);
243         if (r < 0) 
244                 printf("Failed\n");
245         else
246                 printf("Success\n");
247         
248         printf("Testing reuse: ");
249         r= test_reuse(&heap);
250         if (r < 0) 
251                 printf("Failed\n");
252         else
253                 printf("Success\n");
254         expected = alloc + nr_frees;
255         r = expected;
256         while(r == expected && i < 100) {
257                 r = test_threads(&heap);
258                 expected = alloc + nr_frees;
259                 if (r != expected)
260                         printf("test_threads failed r: %lu vs expected %lu\n", r, expected);
261                 i++;
262         }
263         return 0;
264 }