Tizen 2.1 base
[external/gmp.git] / tests / memory.c
1 /* Memory allocation used during tests.
2
3 Copyright 2001, 2002, 2007 Free Software Foundation, Inc.
4
5 This file is part of the GNU MP Library.
6
7 The GNU MP Library is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11
12 The GNU MP Library is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
15 License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with the GNU MP Library.  If not, see http://www.gnu.org/licenses/.  */
19
20 #include <stdio.h>
21 #include <stdlib.h>             /* for abort */
22 #include <string.h>             /* for memcpy, memcmp */
23 #include "gmp.h"
24 #include "gmp-impl.h"
25
26 #if GMP_LIMB_BITS == 64
27 #define PATTERN1 CNST_LIMB(0xcafebabedeadbeef)
28 #define PATTERN2 CNST_LIMB(0xabacadabaedeedab)
29 #else
30 #define PATTERN1 CNST_LIMB(0xcafebabe)
31 #define PATTERN2 CNST_LIMB(0xdeadbeef)
32 #endif
33
34 /* Each block allocated is a separate malloc, for the benefit of a redzoning
35    malloc debugger during development or when bug hunting.
36
37    Sizes passed when reallocating or freeing are checked (the default
38    routines don't care about these).
39
40    Memory leaks are checked by requiring that all blocks have been freed
41    when tests_memory_end() is called.  Test programs must be sure to have
42    "clear"s for all temporary variables used.  */
43
44
45 struct header {
46   void           *ptr;
47   size_t         size;
48   struct header  *next;
49 };
50
51 struct header  *tests_memory_list = NULL;
52
53 /* Return a pointer to a pointer to the found block (so it can be updated
54    when unlinking). */
55 struct header **
56 tests_memory_find (void *ptr)
57 {
58   struct header  **hp;
59
60   for (hp = &tests_memory_list; *hp != NULL; hp = &((*hp)->next))
61     if ((*hp)->ptr == ptr)
62       return hp;
63
64   return NULL;
65 }
66
67 int
68 tests_memory_valid (void *ptr)
69 {
70   return (tests_memory_find (ptr) != NULL);
71 }
72
73 void *
74 tests_allocate (size_t size)
75 {
76   struct header  *h;
77   void *rptr, *ptr;
78   mp_limb_t PATTERN2_var;
79
80   if (size == 0)
81     {
82       fprintf (stderr, "tests_allocate(): attempt to allocate 0 bytes\n");
83       abort ();
84     }
85
86   h = (struct header *) __gmp_default_allocate (sizeof (*h));
87   h->next = tests_memory_list;
88   tests_memory_list = h;
89
90   rptr = __gmp_default_allocate (size + 2 * sizeof (mp_limb_t));
91   ptr = (void *) ((gmp_intptr_t) rptr + sizeof (mp_limb_t));
92
93   *((mp_limb_t *) ((gmp_intptr_t) ptr - sizeof (mp_limb_t)))
94     = PATTERN1 - ((mp_limb_t) ptr);
95   PATTERN2_var = PATTERN2 - ((mp_limb_t) ptr);
96   memcpy ((void *) ((gmp_intptr_t) ptr + size), &PATTERN2_var, sizeof (mp_limb_t));
97
98   h->size = size;
99   h->ptr = ptr;
100   return h->ptr;
101 }
102
103 void *
104 tests_reallocate (void *ptr, size_t old_size, size_t new_size)
105 {
106   struct header  **hp, *h;
107   void *rptr;
108   mp_limb_t PATTERN2_var;
109
110   if (new_size == 0)
111     {
112       fprintf (stderr, "tests_reallocate(): attempt to reallocate %p to 0 bytes\n",
113                ptr);
114       abort ();
115     }
116
117   hp = tests_memory_find (ptr);
118   if (hp == NULL)
119     {
120       fprintf (stderr, "tests_reallocate(): attempt to reallocate bad pointer %p\n",
121                ptr);
122       abort ();
123     }
124   h = *hp;
125
126   if (h->size != old_size)
127     {
128       fprintf (stderr, "tests_reallocate(): bad old size %lu, should be %lu\n",
129                (unsigned long) old_size, (unsigned long) h->size);
130       abort ();
131     }
132
133   if (*((mp_limb_t *) ((gmp_intptr_t) ptr - sizeof (mp_limb_t)))
134       != PATTERN1 - ((mp_limb_t) ptr))
135     {
136       fprintf (stderr, "in realloc: redzone clobbered before block\n");
137       abort ();
138     }
139   PATTERN2_var = PATTERN2 - ((mp_limb_t) ptr);
140   if (memcmp ((void *) ((gmp_intptr_t) ptr + h->size), &PATTERN2_var, sizeof (mp_limb_t)))
141     {
142       fprintf (stderr, "in realloc: redzone clobbered after block\n");
143       abort ();
144     }
145
146   rptr = __gmp_default_reallocate ((void *) ((gmp_intptr_t) ptr - sizeof (mp_limb_t)),
147                                  old_size + 2 * sizeof (mp_limb_t),
148                                  new_size + 2 * sizeof (mp_limb_t));
149   ptr = (void *) ((gmp_intptr_t) rptr + sizeof (mp_limb_t));
150
151   *((mp_limb_t *) ((gmp_intptr_t) ptr - sizeof (mp_limb_t)))
152     = PATTERN1 - ((mp_limb_t) ptr);
153   PATTERN2_var = PATTERN2 - ((mp_limb_t) ptr);
154   memcpy ((void *) ((gmp_intptr_t) ptr + new_size), &PATTERN2_var, sizeof (mp_limb_t));
155
156   h->size = new_size;
157   h->ptr = ptr;
158   return h->ptr;
159 }
160
161 struct header **
162 tests_free_find (void *ptr)
163 {
164   struct header  **hp = tests_memory_find (ptr);
165   if (hp == NULL)
166     {
167       fprintf (stderr, "tests_free(): attempt to free bad pointer %p\n",
168                ptr);
169       abort ();
170     }
171   return hp;
172 }
173
174 void
175 tests_free_nosize (void *ptr)
176 {
177   struct header  **hp = tests_free_find (ptr);
178   struct header  *h = *hp;
179   mp_limb_t PATTERN2_var;
180
181   *hp = h->next;  /* unlink */
182
183   if (*((mp_limb_t *) ((gmp_intptr_t) ptr - sizeof (mp_limb_t)))
184       != PATTERN1 - ((mp_limb_t) ptr))
185     {
186       fprintf (stderr, "in free: redzone clobbered before block\n");
187       abort ();
188     }
189   PATTERN2_var = PATTERN2 - ((mp_limb_t) ptr);
190   if (memcmp ((void *) ((gmp_intptr_t) ptr + h->size), &PATTERN2_var, sizeof (mp_limb_t)))
191     {
192       fprintf (stderr, "in free: redzone clobbered after block\n");
193       abort ();
194     }
195
196   __gmp_default_free ((void *) ((gmp_intptr_t) ptr - sizeof(mp_limb_t)),
197                       h->size + 2 * sizeof (mp_limb_t));
198   __gmp_default_free (h, sizeof (*h));
199 }
200
201 void
202 tests_free (void *ptr, size_t size)
203 {
204   struct header  **hp = tests_free_find (ptr);
205   struct header  *h = *hp;
206
207   if (h->size != size)
208     {
209       fprintf (stderr, "tests_free(): bad size %lu, should be %lu\n",
210                (unsigned long) size, (unsigned long) h->size);
211       abort ();
212     }
213
214   tests_free_nosize (ptr);
215 }
216
217 void
218 tests_memory_start (void)
219 {
220   mp_set_memory_functions (tests_allocate, tests_reallocate, tests_free);
221 }
222
223 void
224 tests_memory_end (void)
225 {
226   if (tests_memory_list != NULL)
227     {
228       struct header  *h;
229       unsigned  count;
230
231       fprintf (stderr, "tests_memory_end(): not all memory freed\n");
232
233       count = 0;
234       for (h = tests_memory_list; h != NULL; h = h->next)
235         count++;
236
237       fprintf (stderr, "    %u blocks remaining\n", count);
238       abort ();
239     }
240 }