Upgrade Boehm GC to 7.2alpha4.
[cacao.git] / src / mm / boehm-gc / libatomic_ops / tests / test_malloc.c
1 /*  
2  * Copyright (c) 2005 Hewlett-Packard Development Company, L.P.
3  * Original Author: Hans Boehm
4  *
5  * This file may be redistributed and/or modified under the
6  * terms of the GNU General Public License as published by the Free Software
7  * Foundation; either version 2, or (at your option) any later version.
8  * 
9  * It is distributed in the hope that it will be useful, but WITHOUT ANY
10  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License in the
12  * file doc/COPYING for more details.
13  */
14
15 #if defined(HAVE_CONFIG_H)
16 # include "config.h"
17 #endif
18
19 #include "run_parallel.inc"
20
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include "atomic_ops_malloc.h"
24 #define MAX_NTHREADS 100
25 #define N_REVERSALS 1000 /* must be even */
26 #define LENGTH 1000
27
28 #ifdef USE_STANDARD_MALLOC
29 # define AO_malloc(n) malloc(n)
30 # define AO_free(p) free(p)
31 # define AO_malloc_enable_mmap() 
32 #endif
33
34 typedef struct list_node {
35         struct list_node *next;
36         int data;
37 } ln;
38
39 ln *cons(int d, ln *tail)
40 {
41   static size_t extra = 0;
42   size_t my_extra = extra;
43   ln *result;
44   int * extras;
45   int i;
46
47   if (my_extra > 100) 
48     extra = my_extra = 0;
49   else
50     ++extra;
51   result = AO_malloc(sizeof(ln) + sizeof(int)*my_extra);
52   if (result == 0)
53     {
54       fprintf(stderr, "Out of memory\n");
55         /* Normal for more than about 10 threads without mmap? */
56       abort();
57     }
58
59   result -> data = d;
60   result -> next = tail;
61   extras = (int *)(result+1);
62   for (i = 0; i < my_extra; ++i) extras[i] = 42;
63   return result;
64 }
65
66 void print_list(ln *l)
67 {
68   ln *p;
69
70   for (p = l; p != 0; p = p -> next)
71     {
72       fprintf(stderr, "%d, ", p -> data);
73     }
74   fprintf(stderr, "\n");
75 }
76
77 /* Check that l contains numbers from m to n inclusive in ascending order */
78 void check_list(ln *l, int m, int n)
79 {
80   ln *p;
81   int i;
82
83   for (p = l, i = m; p != 0; p = p -> next, ++i)
84     {
85       if (i != p -> data)
86         {
87           fprintf(stderr, "Found %d, expected %d\n", p -> data, i);
88           abort();
89         }
90     }
91 }
92
93 /* Create a list of integers from m to n */
94 ln *
95 make_list(int m, int n)
96 {
97   if (m > n) return 0;
98   return cons(m, make_list(m+1, n));
99 }
100
101 /* Reverse list x, and concatenate it to y, deallocating no longer needed */
102 /* nodes in x.                                                            */
103 ln *
104 reverse(ln *x, ln *y)
105 {
106   ln * result;
107
108   if (x == 0) return y;
109   result = reverse(x -> next, cons(x -> data, y));
110   AO_free(x);
111   return result;
112 }
113
114 int dummy_test(void) { return 1; }
115
116 #define LARGE 200000
117
118 void * run_one_test(void * arg) {
119   ln * x = make_list(1, LENGTH);
120   int i;
121   char *p = AO_malloc(LARGE);
122   char *q;
123
124   if (0 == p) {
125     fprintf(stderr, "AO_malloc(%d) failed: This is normal without mmap\n",
126             LARGE);
127     AO_free(p);
128   } else {
129     p[0] = p[LARGE/2] = p[LARGE-1] = 'a';
130     q = AO_malloc(LARGE);
131     q[0] = q[LARGE/2] = q[LARGE-1] = 'b';
132     if (p[0] != 'a' || p[LARGE/2] != 'a' || p[LARGE-1] != 'a') {
133       fprintf(stderr, "First large allocation smashed\n");
134       abort();
135     }
136     AO_free(p);
137     if (q[0] != 'b' || q[LARGE/2] != 'b' || q[LARGE-1] != 'b') {
138       fprintf(stderr, "Second large allocation smashed\n");
139       abort();
140     }
141     AO_free(q);
142   }
143 # if 0 /* enable for debugging */
144     x = reverse(x, 0);
145     print_list(x);
146     x = reverse(x, 0);
147     print_list(x);
148 # endif
149   for (i = 0; i < N_REVERSALS; ++i) {
150     x = reverse(x, 0);
151   }
152   check_list(x, 1, LENGTH);
153   return 0;
154 }
155
156 int main(int argc, char **argv) {
157     int nthreads;
158     int exper_n;
159
160     if (1 == argc) {
161 #     if !defined(HAVE_MMAP)
162         nthreads = 3;
163 #     else
164         nthreads = 10;
165 #     endif
166     } else if (2 == argc) {
167       nthreads = atoi(argv[1]);
168       if (nthreads < 1 || nthreads > MAX_NTHREADS) {
169         fprintf(stderr, "Invalid # of threads argument\n");
170         exit(1);
171       }
172     } else {
173       fprintf(stderr, "Usage: %s [# of threads]\n", argv[0]);
174       exit(1);
175     }
176     printf("Performing %d reversals of %d element lists in %d threads\n",
177            N_REVERSALS, LENGTH, nthreads);
178     AO_malloc_enable_mmap();
179     run_parallel(nthreads, run_one_test, dummy_test, "AO_malloc/AO_free");
180     return 0;
181 }
182