1 /* Stack allocation routines. This is intended for machines without support
2 for the `alloca' function.
4 Copyright 1996, 1997, 1999, 2000, 2001, 2006 Free Software Foundation, Inc.
6 This file is part of the GNU MP Library.
8 The GNU MP Library is free software; you can redistribute it and/or modify
9 it under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or (at your
11 option) any later version.
13 The GNU MP Library is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16 License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */
29 struct tmp_stack *prev;
31 typedef struct tmp_stack tmp_stack;
34 static unsigned long max_total_allocation = 0;
35 static unsigned long current_total_allocation = 0;
37 static tmp_stack xxx = {&xxx, &xxx, 0};
38 static tmp_stack *current = &xxx;
40 /* The rounded size of the header of each allocation block. */
41 #define HSIZ ROUND_UP_MULTIPLE (sizeof (tmp_stack), __TMP_ALIGN)
44 /* Allocate a block of exactly <size> bytes. This should only be called
45 through the TMP_ALLOC macro, which takes care of rounding/alignment. */
47 __gmp_tmp_alloc (unsigned long size)
51 ASSERT ((size % __TMP_ALIGN) == 0);
52 ASSERT (((unsigned) current->alloc_point % __TMP_ALIGN) == 0);
54 if (size > (char *) current->end - (char *) current->alloc_point)
58 unsigned long chunk_size;
61 /* Allocate a chunk that makes the total current allocation somewhat
62 larger than the maximum allocation ever. If size is very large, we
63 allocate that much. */
65 now = current_total_allocation + size;
66 if (now > max_total_allocation)
68 /* We need more temporary memory than ever before. Increase
70 now = (now * 3 / 2 + __TMP_ALIGN - 1) & -__TMP_ALIGN;
71 chunk_size = now - current_total_allocation + HSIZ;
72 current_total_allocation = now;
73 max_total_allocation = current_total_allocation;
77 chunk_size = max_total_allocation - current_total_allocation + HSIZ;
78 current_total_allocation = max_total_allocation;
81 chunk = (*__gmp_allocate_func) (chunk_size);
82 header = (tmp_stack *) chunk;
83 header->end = (char *) chunk + chunk_size;
84 header->alloc_point = (char *) chunk + HSIZ;
85 header->prev = current;
89 that = current->alloc_point;
90 current->alloc_point = (char *) that + size;
91 ASSERT (((unsigned) that % __TMP_ALIGN) == 0);
95 /* Typically called at function entry. <mark> is assigned so that
96 __gmp_tmp_free can later be used to reclaim all subsequently allocated
99 __gmp_tmp_mark (struct tmp_marker *mark)
101 mark->which_chunk = current;
102 mark->alloc_point = current->alloc_point;
105 /* Free everything allocated since <mark> was assigned by __gmp_tmp_mark */
107 __gmp_tmp_free (struct tmp_marker *mark)
109 while (mark->which_chunk != current)
115 current_total_allocation -= (((char *) (tmp->end) - (char *) tmp) - HSIZ);
116 (*__gmp_free_func) (tmp, (char *) tmp->end - (char *) tmp);
118 current->alloc_point = mark->alloc_point;