Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / openhackware / src / libc / src / malloc.c
1 /*
2  * <malloc.c>
3  *
4  * Open Hack'Ware BIOS: memory management
5  * 
6  * Copyright (c) 2004-2005 Jocelyn Mayer
7  * 
8  *   This program is free software; you can redistribute it and/or
9  *   modify it under the terms of the GNU General Public License V2
10  *   as published by the Free Software Foundation
11  *
12  *   This program is distributed in the hope that it will be useful,
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *   GNU General Public License for more details.
16  *
17  *   You should have received a copy of the GNU General Public License
18  *   along with this program; if not, write to the Free Software
19  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 /* functions prototypes are here */
23 /* NULL is declared here */
24 #include <stdlib.h>
25 /* memcpy is defined here */
26 #include <string.h>
27 /* set_errno is defined here */
28 #include <errno.h>
29
30 //#define DEBUG_MEMOPS
31 #if defined (DEBUG_MEMOPS)
32 #define MEMOPS_PRINTF(fmt, args...) do { dprintf(fmt , ##args); } while (0)
33 #else
34 #define MEMOPS_PRINTF(fmt, args...) do { } while (0)
35 #endif
36
37 #define unused __attribute__ (( unused ))
38
39 /* XXX: TODO: put this elsewhere */
40 void *page_get (int nb_pages);
41 void page_put (void *addr, int nb_pages);
42
43 /* XXX: TOTO: put this elsewhere */
44 #if defined (__i386__)
45 #define NATURAL_ALIGN_BITS 2
46 #define PAGE_BITS 12
47 #define __32_BITS 1
48 #elif defined (__powerpc__) || defined (_ARCH_PPC)
49 #define NATURAL_ALIGN_BITS 2
50 #define PAGE_BITS 12
51 #define __32_BITS 1
52 #elif defined (__x86_64__)
53 #define NATURAL_ALIGN_BITS 3
54 #define PAGE_BITS 12
55 #else
56 #error "Unsupported architecture"
57 #endif
58 #define PAGE_SIZE (1 << PAGE_BITS)
59 #define PAGE(addr) ((void *)((unsigned long)(addr) & ~(PAGE_SIZE - 1)))
60
61
62 #define MIN_ELEM_BITS (NATURAL_ALIGN_BITS + 1)
63 #define MIN_ELEM_SIZE (1 << (MIN_ELEM_BITS))
64 #define MAX_ELEM_BITS (PAGE_BITS)
65 #define MAX_ELEM_SIZE (1 << (MAX_ELEM_BITS - 1))
66 #define POOL_MAX ((MAX_ELEM_BITS) - (MIN_ELEM_BITS))
67 #define CACHE_MAX 16
68
69 typedef struct free_slot_t free_slot_t;
70 struct free_slot_t {
71     struct free_slot_t *next;
72 };
73
74 typedef struct page_descr_t page_descr_t;
75 struct page_descr_t {
76     struct page_descr_t *next;
77     struct page_descr_t *prev;
78     void *addr;
79     unsigned long nb;
80 };
81
82 /*
83  * This points to the first descriptor page where stand:
84  * - 1 descriptor for this page.
85  * - 1 decriptor pages list head.
86  * - POOL_MAX pool descriptors list heads.
87  * - CACHE_MAX page cache entries list heads.
88  */
89 static void *malloc_base;
90
91 /* Shared functions */
92 static inline page_descr_t *main_descr_get (void)
93 {
94     return (page_descr_t *)malloc_base + 1;
95 }
96
97 static inline page_descr_t *pool_head_get (int pool_idx)
98 {
99     return main_descr_get() + 1 + pool_idx;
100 }
101
102 static inline page_descr_t *cache_head_get (int cache_idx)
103 {
104     return pool_head_get(POOL_MAX) + 1 + cache_idx;
105 }
106
107 static void free_slots_init (void *page, int incr, int size)
108 {
109     free_slot_t *slot, *next;
110     
111     for (slot = page;
112          slot < (free_slot_t *)((char *)page + size); slot = next) {
113         next = (void *)((char *)slot + incr);
114         slot->next = next;
115     }
116     slot = (void *)((char *)slot - incr);
117     slot->next = NULL;
118 }
119
120 static page_descr_t *descr_find_free (page_descr_t *head_descr,
121                                       page_descr_t *skip_descr)
122 {
123     page_descr_t *cur_descr, *best;
124     unsigned long max_used;
125
126     /* Try to always return the page with the less free slots to reduce
127      * memory fragmentation.
128      */
129     max_used = 0;
130     best = NULL;
131     for (cur_descr = head_descr->next;
132          cur_descr != head_descr; cur_descr = cur_descr->next) {
133         if (cur_descr != skip_descr && cur_descr->addr != NULL &&
134             cur_descr->nb >= max_used) {
135             max_used = cur_descr->nb;
136             best = cur_descr;
137         }
138     }
139
140     return best;
141 }
142
143 /* Page descriptors management */
144 static void page_descr_free (page_descr_t *head_descr)
145 {
146     head_descr->next->prev = head_descr->prev;
147     head_descr->prev->next = head_descr->next;
148     page_put(head_descr, 1);
149 }
150
151 static page_descr_t *page_descr_get (void)
152 {
153     page_descr_t *main_descr, *head_descr, *page_descr;
154     free_slot_t *first_free;
155
156     main_descr = main_descr_get();
157     head_descr = main_descr->addr;
158     first_free = head_descr->addr;
159     if (first_free == NULL) {
160         /* Find a page with free descriptors */
161         head_descr = descr_find_free(main_descr, NULL);
162         if (head_descr != NULL) {
163             /* Get the first free slot */
164             first_free = head_descr->addr;
165         } else {
166             /* Allocate a new page */
167             head_descr = page_get(1);
168             if (head_descr == NULL) {
169                 MEMOPS_PRINTF("%s: cannot get new head descriptor\n",
170                               __func__);
171                 return NULL;
172             }
173             /* Initialise free slots */
174             free_slots_init(head_descr, sizeof(page_descr_t), PAGE_SIZE);
175             /* Initialise page head descriptor */
176             head_descr->addr = head_descr + 1;
177             head_descr->nb = 0;
178             head_descr->next = main_descr;
179             head_descr->prev = main_descr->prev;
180             /* Update main descriptor */
181             main_descr->prev->next = head_descr;
182             main_descr->prev = head_descr;
183             main_descr->nb++;
184             first_free = head_descr->addr;
185         }
186         main_descr->addr = head_descr;
187     }
188     head_descr->addr = first_free->next;
189     if (head_descr->nb == 0)
190         main_descr->nb--;
191     head_descr->nb++;
192     page_descr = (page_descr_t *)first_free;
193     page_descr->prev = NULL;
194     page_descr->next = NULL;
195     page_descr->addr = NULL;
196     page_descr->nb = 0;
197     
198     return page_descr;
199 }
200
201 static void page_descr_put (page_descr_t *page_descr)
202 {
203     page_descr_t *main_descr, *head_descr, *next_descr, *free_descr;
204     free_slot_t *first_free, *next_free;
205     
206     head_descr = PAGE(page_descr);
207     /* Mark this descriptor as free */
208     next_free = head_descr->addr;
209     first_free = (free_slot_t *)page_descr;
210     first_free->next = next_free;
211     /* Update page descriptor */
212     head_descr->addr = first_free;
213     head_descr->nb--;
214     main_descr = main_descr_get();
215     if (head_descr->nb == 0) {
216         /* Try to free this page */
217         if (main_descr->addr == head_descr ||
218             main_descr->addr == NULL ||
219             main_descr->nb > 0)
220             free_descr = descr_find_free(main_descr, head_descr);
221         else
222             free_descr = main_descr->addr;
223         if (free_descr != NULL) {
224             /* Update main descriptor */
225             page_descr_free(head_descr);
226             main_descr->addr = free_descr;
227         } else {
228             main_descr->addr = head_descr;
229             main_descr->nb++;
230         }
231     } else if (next_free == NULL) {
232         free_descr = head_descr;
233         for (head_descr = main_descr->next;
234              main_descr->nb > 0 && head_descr != main_descr;
235              head_descr = next_descr) {
236             next_descr = head_descr->next;
237             if (head_descr->nb == 0) {
238                 if (main_descr->addr == head_descr)
239                     main_descr->addr = NULL;
240                 page_descr_free(head_descr);
241                 main_descr->nb--;
242             }
243         }
244         if (main_descr->addr == NULL)
245             main_descr->addr = free_descr;
246     }
247 }
248
249 /* Page cache management */
250 static inline unsigned long cache_idx (void *addr)
251 {
252     return ((unsigned long)addr >> PAGE_BITS) & (CACHE_MAX - 1);
253 }
254
255 static inline unsigned long page_cache_pool_idx (page_descr_t *cache_descr)
256 {
257     return (cache_descr->nb & 0xF);
258 }
259
260 static inline page_descr_t *page_cache_page_descr (page_descr_t *cache_descr)
261 {
262     return (page_descr_t *)(cache_descr->nb & ~0xF);
263 }
264
265 static int page_cache_add_page (page_descr_t *page_descr, int pool_idx)
266 {
267     page_descr_t *main_descr, *cache_head, *cache_descr;
268
269     main_descr = main_descr_get();
270     cache_head = cache_head_get(cache_idx(page_descr->addr));
271     cache_descr = page_descr_get();
272     if (cache_descr == NULL) {
273         MEMOPS_PRINTF("%s: cannot get cache page\n", __func__);
274         return -1;
275     }
276     cache_descr->nb = pool_idx | (unsigned long)page_descr;
277     cache_descr->prev = cache_head;
278     cache_descr->next = cache_head->next;
279     cache_descr->addr = page_descr->addr;
280     cache_head->next->prev = cache_descr;
281     cache_head->next = cache_descr;
282
283     return 0;
284 }
285
286 static page_descr_t *page_cache_get_descr (void *addr)
287 {
288     page_descr_t *main_descr, *cache_head, *cache_descr;
289
290     main_descr = main_descr_get();
291     cache_head = cache_head_get(cache_idx(addr));
292     for (cache_descr = cache_head->next;
293          cache_descr != cache_head; cache_descr = cache_descr->next) {
294         if (cache_descr->addr == addr) {
295             return cache_descr;
296         }
297     }
298     MEMOPS_PRINTF("%s: cannot get cache page descr\n", __func__);
299
300     return NULL;
301 }
302
303 static void page_cache_remove_descr (page_descr_t *cache_descr)
304 {
305     cache_descr->next->prev = cache_descr->prev;
306     cache_descr->prev->next = cache_descr->next;
307     page_descr_put(cache_descr);
308 }
309
310 /* Allocation by pool (size <= PAGE_SIZE / 2) */
311 static void pool_descr_free (page_descr_t *cache_descr,
312                              page_descr_t *pool_descr)
313 {
314     page_put(PAGE(pool_descr->addr), 1);
315     page_cache_remove_descr(cache_descr);
316     pool_descr->next->prev = pool_descr->prev;
317     pool_descr->prev->next = pool_descr->next;
318     page_descr_put(pool_descr);
319 }
320
321 static void *pool_malloc (int pool_idx)
322 {
323     page_descr_t *main_descr, *pool_head, *pool_descr;
324     free_slot_t *first_free, *next_free;
325
326     main_descr = main_descr_get();
327     pool_head = pool_head_get(pool_idx);
328     pool_descr = pool_head->addr;
329     if (pool_descr == NULL || pool_descr->addr == NULL) {
330         pool_descr = descr_find_free(pool_head, NULL);
331         if (pool_descr == NULL) {
332             pool_descr = page_descr_get();
333             if (pool_descr == NULL) {
334                 MEMOPS_PRINTF("%s: cannot get pool descr\n", __func__);
335                 return NULL;
336             }
337             pool_descr->addr = page_get(1);
338             if (pool_descr->addr == NULL) {
339                 MEMOPS_PRINTF("%s: cannot allocate new page\n", __func__);
340                 page_descr_put(pool_descr);
341                 return NULL;
342             }
343             if (page_cache_add_page(pool_descr, pool_idx) < 0) {
344                 MEMOPS_PRINTF("%s: cannot add new page to cache\n", __func__);
345                 page_put(pool_descr->addr, 1);
346                 page_descr_put(pool_descr);
347                 return NULL;
348             }
349             free_slots_init(pool_descr->addr,
350                             1 << (MIN_ELEM_BITS + pool_idx), PAGE_SIZE);
351             pool_descr->nb = 0;
352             pool_descr->prev = pool_head->prev;
353             pool_descr->next = pool_head;
354             pool_head->prev->next = pool_descr;
355             pool_head->prev = pool_descr;
356             pool_head->nb++;
357         }
358         pool_head->addr = pool_descr;
359     }
360     first_free = pool_descr->addr;
361     next_free = first_free->next;
362     //    memset(first_free, 0, 1 << (MIN_ELEM_BITS + pool_idx));
363     pool_descr->addr = next_free;
364     if (pool_descr->nb == 0)
365         pool_head->nb--;
366     pool_descr->nb++;
367
368     return first_free;
369 }
370
371 unused static void pool_free (page_descr_t *cache_descr, void *area)
372 {
373     page_descr_t *pool_head, *pool_descr, *pool_next, *free_pool;
374     free_slot_t *first_free, *next_free;
375     unsigned long size, pool_idx;
376     
377     pool_descr = page_cache_page_descr(cache_descr);
378     first_free = area;
379     next_free = pool_descr->addr;
380     pool_idx = page_cache_pool_idx(cache_descr);
381     size = 1 << (MIN_ELEM_BITS + pool_idx);
382     first_free->next = next_free;
383     pool_descr->addr = first_free;
384     pool_descr->nb--;
385     pool_head = pool_head_get(pool_idx);
386     if (pool_descr->nb == 0) {
387         if (pool_head->addr == pool_descr ||
388             pool_head->addr == NULL ||
389             pool_head->nb > 0)
390             free_pool = descr_find_free(pool_head, pool_descr);
391         else
392             free_pool = pool_head->addr;
393         if (free_pool != NULL) {
394             /* Free page & descriptor */
395             pool_descr_free(cache_descr, pool_descr);
396             pool_head->addr = free_pool;
397         } else {
398             pool_head->addr = pool_descr;
399             pool_head->nb++;
400         }
401     } else if (next_free == NULL) {
402         free_pool = pool_descr;
403         for (pool_descr = pool_head->next;
404              pool_head->nb > 0 && pool_descr != pool_head;
405              pool_descr = pool_next) {
406             pool_next = pool_descr->next;
407             if (pool_descr->nb == 0) {
408                 if (pool_head->addr == pool_descr)
409                     pool_head->addr = NULL;
410                 cache_descr = page_cache_get_descr(PAGE(pool_descr->addr));
411                 if (cache_descr != NULL) {
412                     pool_descr_free(cache_descr, pool_descr);
413                     pool_head->nb--;
414                 } else {
415                     /* Incoherency: what to do ? */
416                 }
417             }
418         }
419         if (pool_head->addr == NULL)
420             pool_head->addr = free_pool;
421     }
422 }
423
424 /* Big area management (size > PAGE_SIZE / 2) */
425 static void *big_malloc (int nb_pages)
426 {
427     page_descr_t *main_descr, *pool_head, *pool_descr;
428
429     main_descr = main_descr_get();
430     pool_head = pool_head_get(POOL_MAX);
431     pool_descr = page_descr_get();
432     if (pool_descr == NULL) {
433         MEMOPS_PRINTF("%s: cannot get pool descr\n", __func__);
434         return NULL;
435     }
436     pool_descr->addr = page_get(nb_pages);
437     if (pool_descr->addr == NULL) {
438         page_descr_put(pool_descr);
439         MEMOPS_PRINTF("%s: cannot get page\n", __func__);
440         return NULL;
441     }
442     if (page_cache_add_page(pool_descr, POOL_MAX) < 0) {
443         page_put(pool_descr->addr, nb_pages);
444         page_descr_put(pool_descr);
445         MEMOPS_PRINTF("%s: cannot get add page to cache\n", __func__);
446         return NULL;
447     }
448     pool_descr->prev = pool_head->prev;
449     pool_descr->next = pool_head;
450     pool_descr->nb = nb_pages;
451     pool_head->prev->next = pool_descr;
452     pool_head->prev = pool_descr;
453
454     return pool_descr->addr;
455 }
456
457 static void big_free (page_descr_t *cache_descr)
458 {
459     page_descr_t *pool_descr;
460
461     pool_descr = page_cache_page_descr(cache_descr);
462     if (pool_descr->addr != NULL && pool_descr->nb != 0) {
463         page_put(pool_descr->addr, pool_descr->nb);
464         pool_descr->next->prev = pool_descr->prev;
465         pool_descr->prev->next = pool_descr->next;
466         page_descr_put(pool_descr);
467         page_cache_remove_descr(cache_descr);
468     } else {
469         MEMOPS_PRINTF("%s: ERROR %p %d\n",
470                       __func__, pool_descr->addr, (int)pool_descr->nb);
471     }
472 }
473
474 unused static void *big_realloc (page_descr_t *cache_descr, int new_size)
475 {
476     void *new_area;
477     page_descr_t *pool_descr;
478     unsigned long new_nb;
479
480     pool_descr = page_cache_page_descr(cache_descr);
481     new_nb = (new_size + PAGE_SIZE - 1) / PAGE_SIZE;
482     if (new_nb == pool_descr->nb) {
483         new_area = cache_descr->addr;
484     } else {
485         new_area = big_malloc(new_size);
486         memcpy(new_area, cache_descr->addr, pool_descr->nb * PAGE_SIZE);
487         big_free(cache_descr);
488     }
489
490     return new_area;
491 }
492
493 /* Global entry points */
494 int page_descrs_init (void)
495 {
496     page_descr_t *main_descr, *page_descr, *pool_head, *cache_head;
497     int i;
498
499     /* Allocate first descriptor page */
500     malloc_base = page_get(1);
501     if (malloc_base == NULL) {
502         set_errno(ENOMEM);
503         MEMOPS_PRINTF("%s: cannot get main descriptor\n", __func__);
504         return -1;
505     }
506     /* Init free slots in this page */
507     free_slots_init(malloc_base, sizeof(page_descr_t), PAGE_SIZE);
508     /* Init main descriptor */
509     page_descr = malloc_base;
510     main_descr = main_descr_get();
511     main_descr->addr = page_descr;
512     main_descr->nb = 0;
513     main_descr->next = page_descr;
514     main_descr->prev = page_descr;
515     page_descr->nb = 1;
516     page_descr->addr = page_descr + 2;
517     page_descr->next = main_descr;
518     page_descr->prev = main_descr;
519     /* Init pool lists heads */
520     for (i = 0; i <= POOL_MAX; i++) {
521         pool_head = page_descr_get();
522         if (pool_head == NULL) {
523             page_put(malloc_base, 1);
524             malloc_base = NULL;
525             MEMOPS_PRINTF("%s: cannot get pool descriptor %d\n", __func__, i);
526             return -1;
527         }
528         pool_head->prev = pool_head;
529         pool_head->next = pool_head;
530         pool_head->addr = NULL;
531     }
532     /* Init page caches lists heads */
533     for (i = 0; i < CACHE_MAX; i++) {
534         cache_head = page_descr_get();
535         if (cache_head == NULL) {
536             page_put(malloc_base, 1);
537             malloc_base = NULL;
538             MEMOPS_PRINTF("%s: cannot get page cache descriptor %d\n",
539                           __func__, i);
540             return -1;
541         }
542         cache_head->prev = cache_head;
543         cache_head->next = cache_head;
544     }
545
546     return 0;
547 }
548
549 static inline int get_pool_idx (size_t size)
550 {
551     int pool_idx;
552     
553     pool_idx = 0;
554     for (size /= MIN_ELEM_SIZE; size != 0; size = size / 2)
555         pool_idx++;
556
557     return pool_idx;
558 }
559
560 #if 1
561 void *malloc (size_t size)
562 {
563     void *ret;
564     int pool_idx;
565     
566     if (malloc_base == NULL || size == 0) {
567         ret = NULL;
568     } else if (size >= MAX_ELEM_SIZE) {
569         ret = big_malloc((size + PAGE_SIZE - 1) / PAGE_SIZE);
570     } else {
571         if (size <= MIN_ELEM_SIZE)
572             pool_idx = 0;
573         else {
574             pool_idx = get_pool_idx(size);
575         }
576         ret = pool_malloc(pool_idx);
577     }
578     if (ret != NULL)
579         memset(ret, 0, size);
580 #if 0
581     memory_dump();
582     printf("%s(%d) => %p\n", __func__, size, ret);
583 #endif
584
585     return ret;
586 }
587 #endif
588
589 #if 0
590 void free (void *area)
591 {
592     page_descr_t *cache_descr;
593     int pool_idx;
594
595     if (malloc_base == NULL || area == NULL)
596         return;
597     cache_descr = page_cache_get_descr(PAGE(area));
598     if (cache_descr != NULL) {
599         pool_idx = page_cache_pool_idx(cache_descr);
600         if (pool_idx == POOL_MAX) {
601             big_free(cache_descr);
602         } else {
603             pool_free(cache_descr, area);
604         }
605     } else {
606         /* Given area is not valid */
607         MEMOPS_PRINTF("ERROR: area to free not found: %p\n", area);
608     }
609 }
610 #endif
611
612 #if 0
613 void *realloc (void *area, size_t new_size)
614 {
615     void *new_area;
616     page_descr_t *pool_descr, *cache_descr;
617     size_t size;
618     int pool_idx, new_pool_idx;
619
620     if (malloc_base == NULL || new_size == 0) {
621         free(area);
622         return NULL;
623     }
624     if (area == NULL)
625         return malloc(new_size);
626     cache_descr = page_cache_get_descr(PAGE(area));
627     if (cache_descr == NULL) {
628         /* Given area is not valid */
629         return NULL;
630     }
631     pool_idx = page_cache_pool_idx(cache_descr);
632     if (new_size >= MAX_ELEM_SIZE) {
633         new_pool_idx = POOL_MAX;
634         if (pool_idx == POOL_MAX)
635             return big_realloc(cache_descr, new_size);
636     } else {
637         if (new_size <= MIN_ELEM_SIZE)
638             new_pool_idx = 0;
639         else
640             new_pool_idx = get_pool_idx(size);
641         if (pool_idx == new_pool_idx)
642             return area;
643     }
644     /* Common case: alloc, copy & free */
645     if (new_pool_idx == POOL_MAX)
646         new_area = big_malloc((new_size + PAGE_SIZE - 1) / PAGE_SIZE);
647     else
648         new_area = pool_malloc(new_pool_idx);
649     if (new_area == NULL)
650         return NULL;
651     if (pool_idx == POOL_MAX) {
652         pool_descr = page_cache_page_descr(cache_descr);
653         size = pool_descr->nb * PAGE_SIZE;
654     } else {
655         size = MIN_ELEM_SIZE << pool_idx;
656     }
657     memcpy(new_area, area, size);
658     if (pool_idx == POOL_MAX)
659         big_free(cache_descr);
660     else
661         pool_free(cache_descr, area);
662     
663     return new_area;
664 }
665 #endif
666
667 void memory_dump (void)
668 {
669 #if defined (DEBUG_MEMOPS)
670     page_descr_t *main_descr, *page_descr;
671     page_descr_t *pool_head, *pool_descr, *cache_head, *cache_descr;
672     int i, n;
673
674     main_descr = main_descr_get();
675     /* Dump descriptor pages */
676     printf("Descriptor pages dump: %p max=%d %d pages with no alloc descrs\n",
677            main_descr, (int)(PAGE_SIZE / sizeof(page_descr_t)), (int)main_descr->nb);
678     n = 0;
679     for (page_descr = main_descr->next;
680          page_descr != main_descr; page_descr = page_descr->next) {
681         printf("Descr %d : %p %p used: %d\n",
682                n, page_descr, page_descr->addr, (int)page_descr->nb);
683         n++;
684     }
685     /* Dump pool areas pages */
686     for (i = 0; i < POOL_MAX; i++) {
687         n = 0;
688         pool_head = pool_head_get(i);
689         printf("Pool %d %p\n", i, pool_head);
690         for (pool_descr = pool_head->next;
691              pool_descr != pool_head; pool_descr = pool_descr->next) {
692             printf("Pool %d descr %d : %p %p used: %d size %d free: %p %p\n",
693                    i, n, pool_descr, PAGE(pool_descr->addr), (int)pool_descr->nb,
694                    1 << (MIN_ELEM_BITS + i), pool_descr->addr,
695                    ((free_slot_t *)pool_descr->addr)->next);
696             n++;
697         }
698         printf(" => %d pages allocated\n", n);
699     }
700 #if 0
701     /* Dump big area pages */
702     printf("Pool %d\n", POOL_MAX);
703     n = 0;
704     pool_head = pool_head_get(POOL_MAX);
705     for (pool_descr = pool_head->next;
706          pool_descr != pool_head; pool_descr = pool_descr->next) {
707         printf("Pool %d descr %d : %p nb pages: %d\n",
708                POOL_MAX, n, pool_descr->addr, (int)pool_descr->nb);
709         n++;
710     }
711     printf(" => %d pages allocated\n", n);
712     /* Dump page cache */
713     for (i = 0; i < CACHE_MAX; i++) {
714         printf("Page cache 0x____%x___\n", i);
715         n = 0;
716         cache_head = cache_head_get(i);
717         for (cache_descr = cache_head->next;
718              cache_descr != cache_head; cache_descr = cache_descr->next) {
719             pool_descr = page_cache_page_descr(cache_descr);
720             printf("Cache %d descr %d : %p pool: %d descr: %p %p %d\n",
721                    i, n, cache_descr->addr,
722                    (int)page_cache_pool_idx(cache_descr),
723                    pool_descr, pool_descr->addr, (int)pool_descr->nb);
724             n++;
725         }
726         printf(" => %d pages allocated\n", n);
727     }
728 #endif
729 #endif
730 }