implemented Setup.hs to build boehm cpp libs and install them;
[hs-boehmgc.git] / gc-7.2 / 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
25 #ifndef MAX_NTHREADS
26 # define MAX_NTHREADS 100
27 #endif
28
29 #ifndef DEFAULT_NTHREADS
30 # ifdef HAVE_MMAP
31 #   define DEFAULT_NTHREADS 10
32 # else
33 #   define DEFAULT_NTHREADS 3
34 # endif
35 #endif
36
37 #ifndef N_REVERSALS
38 # define N_REVERSALS 1000 /* must be even */
39 #endif
40
41 #ifndef LIST_LENGTH
42 # ifdef HAVE_MMAP
43 #   define LIST_LENGTH 1000
44 # else
45 #   define LIST_LENGTH 100
46 # endif
47 #endif
48
49 #ifndef LARGE_OBJ_SIZE
50 # ifdef HAVE_MMAP
51 #   define LARGE_OBJ_SIZE 200000
52 # else
53 #   define LARGE_OBJ_SIZE 20000
54 # endif
55 #endif
56
57 #ifdef USE_STANDARD_MALLOC
58 # define AO_malloc(n) malloc(n)
59 # define AO_free(p) free(p)
60 # define AO_malloc_enable_mmap()
61 #endif
62
63 typedef struct list_node {
64         struct list_node *next;
65         int data;
66 } ln;
67
68 ln *cons(int d, ln *tail)
69 {
70   static size_t extra = 0;
71   size_t my_extra = extra;
72   ln *result;
73   int * extras;
74   int i;
75
76   if (my_extra > 100)
77     extra = my_extra = 0;
78   else
79     ++extra;
80   result = AO_malloc(sizeof(ln) + sizeof(int)*my_extra);
81   if (result == 0)
82     {
83       fprintf(stderr, "Out of memory\n");
84         /* Normal for more than about 10 threads without mmap? */
85       exit(2);
86     }
87
88   result -> data = d;
89   result -> next = tail;
90   extras = (int *)(result+1);
91   for (i = 0; i < my_extra; ++i) extras[i] = 42;
92   return result;
93 }
94
95 void print_list(ln *l)
96 {
97   ln *p;
98
99   for (p = l; p != 0; p = p -> next)
100     {
101       fprintf(stderr, "%d, ", p -> data);
102     }
103   fprintf(stderr, "\n");
104 }
105
106 /* Check that l contains numbers from m to n inclusive in ascending order */
107 void check_list(ln *l, int m, int n)
108 {
109   ln *p;
110   int i;
111
112   for (p = l, i = m; p != 0; p = p -> next, ++i)
113     {
114       if (i != p -> data)
115         {
116           fprintf(stderr, "Found %d, expected %d\n", p -> data, i);
117           abort();
118         }
119     }
120 }
121
122 /* Create a list of integers from m to n */
123 ln *
124 make_list(int m, int n)
125 {
126   if (m > n) return 0;
127   return cons(m, make_list(m+1, n));
128 }
129
130 /* Reverse list x, and concatenate it to y, deallocating no longer needed */
131 /* nodes in x.                                                            */
132 ln *
133 reverse(ln *x, ln *y)
134 {
135   ln * result;
136
137   if (x == 0) return y;
138   result = reverse(x -> next, cons(x -> data, y));
139   AO_free(x);
140   return result;
141 }
142
143 int dummy_test(void) { return 1; }
144
145 void * run_one_test(void * arg) {
146   ln * x = make_list(1, LIST_LENGTH);
147   int i;
148   char *p = AO_malloc(LARGE_OBJ_SIZE);
149   char *q;
150
151   if (0 == p) {
152 #   ifdef HAVE_MMAP
153       fprintf(stderr, "AO_malloc(%d) failed\n", LARGE_OBJ_SIZE);
154 #   else
155       fprintf(stderr, "AO_malloc(%d) failed: This is normal without mmap\n",
156               LARGE_OBJ_SIZE);
157 #   endif
158   } else {
159     p[0] = p[LARGE_OBJ_SIZE/2] = p[LARGE_OBJ_SIZE-1] = 'a';
160     q = AO_malloc(LARGE_OBJ_SIZE);
161     if (q == 0)
162       {
163         fprintf(stderr, "Out of memory\n");
164           /* Normal for more than about 10 threads without mmap? */
165         exit(2);
166       }
167     q[0] = q[LARGE_OBJ_SIZE/2] = q[LARGE_OBJ_SIZE-1] = 'b';
168     if (p[0] != 'a' || p[LARGE_OBJ_SIZE/2] != 'a'
169         || p[LARGE_OBJ_SIZE-1] != 'a') {
170       fprintf(stderr, "First large allocation smashed\n");
171       abort();
172     }
173     AO_free(p);
174     if (q[0] != 'b' || q[LARGE_OBJ_SIZE/2] != 'b'
175         || q[LARGE_OBJ_SIZE-1] != 'b') {
176       fprintf(stderr, "Second large allocation smashed\n");
177       abort();
178     }
179     AO_free(q);
180   }
181 # ifdef DEBUG_RUN_ONE_TEST
182     x = reverse(x, 0);
183     print_list(x);
184     x = reverse(x, 0);
185     print_list(x);
186 # endif
187   for (i = 0; i < N_REVERSALS; ++i) {
188     x = reverse(x, 0);
189   }
190   check_list(x, 1, LIST_LENGTH);
191   return 0;
192 }
193
194 int main(int argc, char **argv) {
195     int nthreads;
196
197     if (1 == argc) {
198       nthreads = DEFAULT_NTHREADS;
199     } else if (2 == argc) {
200       nthreads = atoi(argv[1]);
201       if (nthreads < 1 || nthreads > MAX_NTHREADS) {
202         fprintf(stderr, "Invalid # of threads argument\n");
203         exit(1);
204       }
205     } else {
206       fprintf(stderr, "Usage: %s [# of threads]\n", argv[0]);
207       exit(1);
208     }
209     printf("Performing %d reversals of %d element lists in %d threads\n",
210            N_REVERSALS, LIST_LENGTH, nthreads);
211     AO_malloc_enable_mmap();
212     run_parallel(nthreads, run_one_test, dummy_test, "AO_malloc/AO_free");
213     return 0;
214 }