alloca.c revision 1.1.1.2 1 1.1 christos /* alloca.c -- allocate automatically reclaimed memory
2 1.1.1.2 christos This file is in the public domain. */
3 1.1.1.2 christos
4 1.1.1.2 christos /* (Mostly) portable implementation -- D A Gwyn
5 1.1 christos
6 1.1 christos This implementation of the PWB library alloca function,
7 1.1 christos which is used to allocate space off the run-time stack so
8 1.1 christos that it is automatically reclaimed upon procedure exit,
9 1.1 christos was inspired by discussions with J. Q. Johnson of Cornell.
10 1.1 christos J.Otto Tennant <jot (at) cray.com> contributed the Cray support.
11 1.1 christos
12 1.1 christos There are some preprocessor constants that can
13 1.1 christos be defined when compiling for your specific system, for
14 1.1 christos improved efficiency; however, the defaults should be okay.
15 1.1 christos
16 1.1 christos The general concept of this implementation is to keep
17 1.1 christos track of all alloca-allocated blocks, and reclaim any
18 1.1 christos that are found to be deeper in the stack than the current
19 1.1 christos invocation. This heuristic does not reclaim storage as
20 1.1 christos soon as it becomes invalid, but it will do so eventually.
21 1.1 christos
22 1.1 christos As a special case, alloca(0) reclaims storage without
23 1.1 christos allocating any. It is a good idea to use alloca(0) in
24 1.1 christos your main control loop, etc. to force garbage collection. */
25 1.1 christos
26 1.1 christos #include <config.h>
27 1.1 christos
28 1.1 christos #include <alloca.h>
29 1.1 christos
30 1.1 christos #include <string.h>
31 1.1 christos #include <stdlib.h>
32 1.1 christos
33 1.1 christos #ifdef emacs
34 1.1 christos # include "lisp.h"
35 1.1 christos # include "blockinput.h"
36 1.1 christos # ifdef EMACS_FREE
37 1.1 christos # undef free
38 1.1 christos # define free EMACS_FREE
39 1.1 christos # endif
40 1.1 christos #else
41 1.1 christos # define memory_full() abort ()
42 1.1 christos #endif
43 1.1 christos
44 1.1.1.2 christos /* If compiling with GCC or clang, this file is not needed. */
45 1.1.1.2 christos #if !(defined __GNUC__ || defined __clang__)
46 1.1 christos
47 1.1 christos /* If someone has defined alloca as a macro,
48 1.1 christos there must be some other way alloca is supposed to work. */
49 1.1 christos # ifndef alloca
50 1.1 christos
51 1.1 christos # ifdef emacs
52 1.1 christos # ifdef static
53 1.1 christos /* actually, only want this if static is defined as ""
54 1.1 christos -- this is for usg, in which emacs must undefine static
55 1.1 christos in order to make unexec workable
56 1.1 christos */
57 1.1 christos # ifndef STACK_DIRECTION
58 1.1 christos you
59 1.1 christos lose
60 1.1 christos -- must know STACK_DIRECTION at compile-time
61 1.1 christos /* Using #error here is not wise since this file should work for
62 1.1 christos old and obscure compilers. */
63 1.1 christos # endif /* STACK_DIRECTION undefined */
64 1.1 christos # endif /* static */
65 1.1 christos # endif /* emacs */
66 1.1 christos
67 1.1 christos /* Define STACK_DIRECTION if you know the direction of stack
68 1.1 christos growth for your system; otherwise it will be automatically
69 1.1 christos deduced at run-time.
70 1.1 christos
71 1.1 christos STACK_DIRECTION > 0 => grows toward higher addresses
72 1.1 christos STACK_DIRECTION < 0 => grows toward lower addresses
73 1.1 christos STACK_DIRECTION = 0 => direction of growth unknown */
74 1.1 christos
75 1.1 christos # ifndef STACK_DIRECTION
76 1.1 christos # define STACK_DIRECTION 0 /* Direction unknown. */
77 1.1 christos # endif
78 1.1 christos
79 1.1 christos # if STACK_DIRECTION != 0
80 1.1 christos
81 1.1 christos # define STACK_DIR STACK_DIRECTION /* Known at compile-time. */
82 1.1 christos
83 1.1 christos # else /* STACK_DIRECTION == 0; need run-time code. */
84 1.1 christos
85 1.1 christos static int stack_dir; /* 1 or -1 once known. */
86 1.1 christos # define STACK_DIR stack_dir
87 1.1 christos
88 1.1 christos static int
89 1.1 christos find_stack_direction (int *addr, int depth)
90 1.1 christos {
91 1.1 christos int dir, dummy = 0;
92 1.1 christos if (! addr)
93 1.1 christos addr = &dummy;
94 1.1 christos *addr = addr < &dummy ? 1 : addr == &dummy ? 0 : -1;
95 1.1 christos dir = depth ? find_stack_direction (addr, depth - 1) : 0;
96 1.1 christos return dir + dummy;
97 1.1 christos }
98 1.1 christos
99 1.1 christos # endif /* STACK_DIRECTION == 0 */
100 1.1 christos
101 1.1 christos /* An "alloca header" is used to:
102 1.1 christos (a) chain together all alloca'ed blocks;
103 1.1 christos (b) keep track of stack depth.
104 1.1 christos
105 1.1 christos It is very important that sizeof(header) agree with malloc
106 1.1 christos alignment chunk size. The following default should work okay. */
107 1.1 christos
108 1.1 christos # ifndef ALIGN_SIZE
109 1.1 christos # define ALIGN_SIZE sizeof(double)
110 1.1 christos # endif
111 1.1 christos
112 1.1 christos typedef union hdr
113 1.1 christos {
114 1.1 christos char align[ALIGN_SIZE]; /* To force sizeof(header). */
115 1.1 christos struct
116 1.1 christos {
117 1.1 christos union hdr *next; /* For chaining headers. */
118 1.1 christos char *deep; /* For stack depth measure. */
119 1.1 christos } h;
120 1.1 christos } header;
121 1.1 christos
122 1.1 christos static header *last_alloca_header = NULL; /* -> last alloca header. */
123 1.1 christos
124 1.1 christos /* Return a pointer to at least SIZE bytes of storage,
125 1.1 christos which will be automatically reclaimed upon exit from
126 1.1 christos the procedure that called alloca. Originally, this space
127 1.1 christos was supposed to be taken from the current stack frame of the
128 1.1 christos caller, but that method cannot be made to work for some
129 1.1 christos implementations of C, for example under Gould's UTX/32. */
130 1.1 christos
131 1.1 christos void *
132 1.1 christos alloca (size_t size)
133 1.1 christos {
134 1.1 christos auto char probe; /* Probes stack depth: */
135 1.1.1.2 christos register char *depth = &probe;
136 1.1 christos
137 1.1 christos # if STACK_DIRECTION == 0
138 1.1 christos if (STACK_DIR == 0) /* Unknown growth direction. */
139 1.1 christos STACK_DIR = find_stack_direction (NULL, (size & 1) + 20);
140 1.1 christos # endif
141 1.1 christos
142 1.1 christos /* Reclaim garbage, defined as all alloca'd storage that
143 1.1 christos was allocated from deeper in the stack than currently. */
144 1.1 christos
145 1.1 christos {
146 1.1 christos register header *hp; /* Traverses linked list. */
147 1.1 christos
148 1.1 christos # ifdef emacs
149 1.1 christos BLOCK_INPUT;
150 1.1 christos # endif
151 1.1 christos
152 1.1 christos for (hp = last_alloca_header; hp != NULL;)
153 1.1 christos if ((STACK_DIR > 0 && hp->h.deep > depth)
154 1.1 christos || (STACK_DIR < 0 && hp->h.deep < depth))
155 1.1 christos {
156 1.1 christos register header *np = hp->h.next;
157 1.1 christos
158 1.1 christos free (hp); /* Collect garbage. */
159 1.1 christos
160 1.1 christos hp = np; /* -> next header. */
161 1.1 christos }
162 1.1 christos else
163 1.1 christos break; /* Rest are not deeper. */
164 1.1 christos
165 1.1 christos last_alloca_header = hp; /* -> last valid storage. */
166 1.1 christos
167 1.1 christos # ifdef emacs
168 1.1 christos UNBLOCK_INPUT;
169 1.1 christos # endif
170 1.1 christos }
171 1.1 christos
172 1.1 christos if (size == 0)
173 1.1 christos return NULL; /* No allocation required. */
174 1.1 christos
175 1.1 christos /* Allocate combined header + user data storage. */
176 1.1 christos
177 1.1 christos {
178 1.1 christos /* Address of header. */
179 1.1 christos register header *new;
180 1.1 christos
181 1.1 christos size_t combined_size = sizeof (header) + size;
182 1.1 christos if (combined_size < sizeof (header))
183 1.1 christos memory_full ();
184 1.1 christos
185 1.1 christos new = malloc (combined_size);
186 1.1 christos
187 1.1 christos if (! new)
188 1.1 christos memory_full ();
189 1.1 christos
190 1.1 christos new->h.next = last_alloca_header;
191 1.1 christos new->h.deep = depth;
192 1.1 christos
193 1.1 christos last_alloca_header = new;
194 1.1 christos
195 1.1 christos /* User storage begins just after header. */
196 1.1 christos
197 1.1 christos return (void *) (new + 1);
198 1.1 christos }
199 1.1 christos }
200 1.1 christos
201 1.1 christos # endif /* no alloca */
202 1.1.1.2 christos #endif /* not GCC || clang */
203