make xhash request for less allocated space
[archipelago] / xseg / xtypes / xheap_test.c
1 #include <stdlib.h>
2 #include "xheap.h"
3 #include <stdint.h>
4 #include <pthread.h>
5
6 struct xheap heap;
7 uint32_t al_unit = 12;
8 unsigned long size = 1048576;
9 unsigned long chunk = 4096;
10 unsigned long nr_threads = 4;
11 unsigned long nr_frees;
12 void *mem;
13
14 #define full_size(_x_) ((_x_) + sizeof(struct xheap_header))
15 void print_ptr(void *ptr)
16 {
17         uint64_t size = xheap_get_chunk_size(ptr);
18         printf("ptr: %lx, bytes: %llu (actual: %llu)\n", 
19                         (unsigned long) ptr, 
20                         (unsigned long long) size, 
21                         (unsigned long long) full_size(size));
22 }
23
24 unsigned long test(struct xheap *heap)
25 {
26         int r = xheap_init(heap, size, al_unit, mem);
27         if (r < 0){
28                 printf("xheap init error\n");
29                 return -1;
30         }
31         unsigned long i = 0;
32         uint64_t alloc_size = 0, start = heap->cur;
33         printf("heap starts with %llu\n", start);
34         void *ptr;
35         do {
36                 ptr = xheap_allocate(heap, chunk);
37                 if (ptr != NULL){
38                         i++;
39                         if ((unsigned long) ptr & ((1 << al_unit) -1)) {
40                                 printf("ptr %x not aligned with al_unit %lu\n",
41                                                 ptr, al_unit);
42                                 return -1;
43                         }
44                         alloc_size += xheap_get_chunk_size(ptr);
45                 }
46         }while (ptr != NULL);
47         printf("Allocated %lu chunks of size %lu with allocation unit %lu (%lu bytes)\n",
48                         i, chunk, al_unit, (1<<al_unit));
49         printf("Total allocated space: %llu\n", (unsigned long long) alloc_size);
50         alloc_size += i*sizeof(struct xheap_header);
51         printf("Total allocated space plus headers: %llu\n", 
52                         (unsigned long long) alloc_size);
53         alloc_size += start + 2 * sizeof(struct xheap_header);
54         printf("Total allocated space plus headers and start/end padding: %llu\n", 
55                         (unsigned long long) alloc_size);
56         printf("Lost space: %llu\n", (unsigned long long) (heap->size - alloc_size));
57         return i;
58 }
59
60 int test_align(struct xheap *heap)
61 {
62         uint64_t bytes = heap->size;
63         int m = sizeof(bytes)*8 - __builtin_clzl(bytes -1);
64         unsigned long i;
65         void *ptr;
66         for (i = 5; i < m; i++){
67                 int r = xheap_init(heap, size, i, mem);
68                 if (r < 0){
69                         printf("align: xheap init error\n");
70                         return -1;
71                 }
72                 do {
73                         ptr = xheap_allocate(heap, chunk);
74                         if (ptr != NULL){
75                                 if ((unsigned long) ptr & ((1 << i) -1)) {
76                                         printf("ptr %x not aligned with al_unit %lu\n",
77                                                         ptr, i);
78                                         return -1;
79                                 }
80                         }
81                 }while (ptr != NULL);
82         }
83         return 0;
84 }
85
86 int test_reuse(struct xheap *heap)
87 {
88         int r = xheap_init(heap, size, al_unit, mem);
89         if (r < 0){
90                 printf("xheap init error\n");
91                 return -1;
92         }
93         void *ptr1, *ptr2;
94         ptr1 = xheap_allocate(heap, chunk);
95         if (ptr1 == NULL) {
96                 printf("couldn't allocate\n");
97                 return -1;
98         }
99         xheap_free(ptr1);
100         ptr2 = xheap_allocate(heap, chunk);
101         if (ptr2 == NULL) {
102                 printf("couldn't allocate\n");
103                 return -1;
104         }
105         if (ptr1 != ptr2) {
106                 printf("alloc-free-alloc return diffrent ptr\n");
107                 return -1;
108         }
109         return 0;
110 }
111
112 struct thread_arg{
113         int id;
114         struct xheap *heap;
115         unsigned long c;
116         unsigned long allocations;
117         unsigned long frees;
118 };
119
120 void *thread_test(void *arg)
121 {
122         struct thread_arg *targ = (struct thread_arg *) arg;
123         struct xheap *heap = targ->heap;
124         int id = targ->id;
125         unsigned long c = targ->c;
126         void *ptr;
127         unsigned long i = 0;
128         do {
129                 ptr = xheap_allocate(heap, chunk);
130                 if (ptr != NULL){
131                         i++;
132                         memset(ptr, 1, xheap_get_chunk_size(ptr));
133                         if (c) {
134                                 xheap_free(ptr);
135                                 c--;
136                         }
137                 }
138         }while (ptr != NULL);
139
140         targ->allocations = i;
141         targ->frees = targ->c - c;
142         return NULL;
143 }
144
145 unsigned long test_threads(struct xheap *heap)
146 {
147         int i;
148         unsigned long allocations = 0;
149         nr_frees = 0;
150
151         int r = xheap_init(heap, size, al_unit, mem);
152         if (r < 0){
153                 printf("threads: xheap init error\n");
154                 return -1;
155         }
156
157         struct thread_arg *targs = malloc(sizeof(struct thread_arg) * nr_threads);
158         if (!targs) {
159                 printf("error malloc\n");
160                 return -1;
161         }
162
163         pthread_t *threads = malloc(sizeof(pthread_t) * nr_threads);
164         if (!threads){
165                 printf("error malloc\n");
166                 return -1;
167         }
168
169         for (i = 0; i < nr_threads; i++) {
170                 targs[i].id = i;
171                 targs[i].heap = heap;
172                 targs[i].c = 256;
173         }
174
175         for (i = 0; i < nr_threads; i++) {
176                 r = pthread_create(&threads[i], NULL, thread_test, &targs[i]);
177                 if (r) {
178                         printf("error pthread_create\n");
179                         return -1;
180                 }
181         }
182
183         for (i = 0; i < nr_threads; i++) {
184                 pthread_join(threads[i], NULL);
185                 allocations +=  targs[i].allocations;
186                 nr_frees += targs[i].frees;
187         }
188         return allocations;
189 }
190
191 int main(int argc, const char *argv[])
192 {
193         unsigned long alloc, expected, i =0;
194         int r;
195         if (argc < 5){
196                 printf("Usage: %s al_unit size chunk_size nr_threads\n", argv[0]);
197                 return -1;
198         }
199         al_unit = atol(argv[1]); 
200         size = atol(argv[2]); 
201         chunk = atol(argv[3]);
202         nr_threads = atol(argv[4]);
203         mem = malloc(size);
204         r = test(&heap);
205         alloc = r;
206         
207         printf("Testing align: ");
208         r = test_align(&heap);
209         if (r < 0) 
210                 printf("Failed\n");
211         else
212                 printf("Success\n");
213         
214         printf("Testing reuse: ");
215         r= test_reuse(&heap);
216         if (r < 0) 
217                 printf("Failed\n");
218         else
219                 printf("Success\n");
220         expected = alloc + nr_frees;
221         r = expected;
222         while(r == expected && i < 100) {
223                 r = test_threads(&heap);
224                 expected = alloc + nr_frees;
225                 if (r != expected)
226                         printf("test_threads failed r: %lu vs expected %lu\n", r, expected);
227                 i++;
228         }
229         return 0;
230 }