comparison src/alloca.c @ 2746:e4595f258ddd

Initial revision
author Jim Meyering <jim@meyering.net>
date Tue, 11 May 1993 23:23:34 +0000
parents
children 59bbdf423db8
comparison
equal deleted inserted replaced
2745:adf91f018312 2746:e4595f258ddd
1 /* alloca.c -- allocate automatically reclaimed memory
2 (Mostly) portable public-domain implementation -- D A Gwyn
3
4 This implementation of the PWB library alloca function,
5 which is used to allocate space off the run-time stack so
6 that it is automatically reclaimed upon procedure exit,
7 was inspired by discussions with J. Q. Johnson of Cornell.
8 J.Otto Tennant <jot@cray.com> contributed the Cray support.
9
10 There are some preprocessor constants that can
11 be defined when compiling for your specific system, for
12 improved efficiency; however, the defaults should be okay.
13
14 The general concept of this implementation is to keep
15 track of all alloca-allocated blocks, and reclaim any
16 that are found to be deeper in the stack than the current
17 invocation. This heuristic does not reclaim storage as
18 soon as it becomes invalid, but it will do so eventually.
19
20 As a special case, alloca(0) reclaims storage without
21 allocating any. It is a good idea to use alloca(0) in
22 your main control loop, etc. to force garbage collection. */
23
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27
28 /* If compiling with GCC, this file's not needed. */
29 #ifndef alloca
30
31 #ifdef emacs
32 #ifdef static
33 /* actually, only want this if static is defined as ""
34 -- this is for usg, in which emacs must undefine static
35 in order to make unexec workable
36 */
37 #ifndef STACK_DIRECTION
38 you
39 lose
40 -- must know STACK_DIRECTION at compile-time
41 #endif /* STACK_DIRECTION undefined */
42 #endif /* static */
43 #endif /* emacs */
44
45 #ifdef emacs
46 #define free xfree
47 #endif
48
49 /* If your stack is a linked list of frames, you have to
50 provide an "address metric" ADDRESS_FUNCTION macro. */
51
52 #ifdef CRAY
53 long i00afunc ();
54 #define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg))
55 #else
56 #define ADDRESS_FUNCTION(arg) &(arg)
57 #endif
58
59 #if __STDC__
60 typedef void *pointer;
61 #else
62 typedef char *pointer;
63 #endif
64
65 #define NULL 0
66
67 extern pointer xmalloc ();
68
69 /* Define STACK_DIRECTION if you know the direction of stack
70 growth for your system; otherwise it will be automatically
71 deduced at run-time.
72
73 STACK_DIRECTION > 0 => grows toward higher addresses
74 STACK_DIRECTION < 0 => grows toward lower addresses
75 STACK_DIRECTION = 0 => direction of growth unknown */
76
77 #ifndef STACK_DIRECTION
78 #define STACK_DIRECTION 0 /* Direction unknown. */
79 #endif
80
81 #if STACK_DIRECTION != 0
82
83 #define STACK_DIR STACK_DIRECTION /* Known at compile-time. */
84
85 #else /* STACK_DIRECTION == 0; need run-time code. */
86
87 static int stack_dir; /* 1 or -1 once known. */
88 #define STACK_DIR stack_dir
89
90 static void
91 find_stack_direction ()
92 {
93 static char *addr = NULL; /* Address of first `dummy', once known. */
94 auto char dummy; /* To get stack address. */
95
96 if (addr == NULL)
97 { /* Initial entry. */
98 addr = ADDRESS_FUNCTION (dummy);
99
100 find_stack_direction (); /* Recurse once. */
101 }
102 else
103 {
104 /* Second entry. */
105 if (ADDRESS_FUNCTION (dummy) > addr)
106 stack_dir = 1; /* Stack grew upward. */
107 else
108 stack_dir = -1; /* Stack grew downward. */
109 }
110 }
111
112 #endif /* STACK_DIRECTION == 0 */
113
114 /* An "alloca header" is used to:
115 (a) chain together all alloca'ed blocks;
116 (b) keep track of stack depth.
117
118 It is very important that sizeof(header) agree with malloc
119 alignment chunk size. The following default should work okay. */
120
121 #ifndef ALIGN_SIZE
122 #define ALIGN_SIZE sizeof(double)
123 #endif
124
125 typedef union hdr
126 {
127 char align[ALIGN_SIZE]; /* To force sizeof(header). */
128 struct
129 {
130 union hdr *next; /* For chaining headers. */
131 char *deep; /* For stack depth measure. */
132 } h;
133 } header;
134
135 static header *last_alloca_header = NULL; /* -> last alloca header. */
136
137 /* Return a pointer to at least SIZE bytes of storage,
138 which will be automatically reclaimed upon exit from
139 the procedure that called alloca. Originally, this space
140 was supposed to be taken from the current stack frame of the
141 caller, but that method cannot be made to work for some
142 implementations of C, for example under Gould's UTX/32. */
143
144 pointer
145 alloca (size)
146 unsigned size;
147 {
148 auto char probe; /* Probes stack depth: */
149 register char *depth = ADDRESS_FUNCTION (probe);
150
151 #if STACK_DIRECTION == 0
152 if (STACK_DIR == 0) /* Unknown growth direction. */
153 find_stack_direction ();
154 #endif
155
156 /* Reclaim garbage, defined as all alloca'd storage that
157 was allocated from deeper in the stack than currently. */
158
159 {
160 register header *hp; /* Traverses linked list. */
161
162 for (hp = last_alloca_header; hp != NULL;)
163 if ((STACK_DIR > 0 && hp->h.deep > depth)
164 || (STACK_DIR < 0 && hp->h.deep < depth))
165 {
166 register header *np = hp->h.next;
167
168 free ((pointer) hp); /* Collect garbage. */
169
170 hp = np; /* -> next header. */
171 }
172 else
173 break; /* Rest are not deeper. */
174
175 last_alloca_header = hp; /* -> last valid storage. */
176 }
177
178 if (size == 0)
179 return NULL; /* No allocation required. */
180
181 /* Allocate combined header + user data storage. */
182
183 {
184 register pointer new = xmalloc (sizeof (header) + size);
185 /* Address of header. */
186
187 ((header *) new)->h.next = last_alloca_header;
188 ((header *) new)->h.deep = depth;
189
190 last_alloca_header = (header *) new;
191
192 /* User storage begins just after header. */
193
194 return (pointer) ((char *) new + sizeof (header));
195 }
196 }
197
198 #ifdef CRAY
199
200 #ifdef DEBUG_I00AFUNC
201 #include <stdio.h>
202 #endif
203
204 #ifndef CRAY_STACK
205 #define CRAY_STACK
206 #ifndef CRAY2
207 /* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */
208 struct stack_control_header
209 {
210 long shgrow:32; /* Number of times stack has grown. */
211 long shaseg:32; /* Size of increments to stack. */
212 long shhwm:32; /* High water mark of stack. */
213 long shsize:32; /* Current size of stack (all segments). */
214 };
215
216 /* The stack segment linkage control information occurs at
217 the high-address end of a stack segment. (The stack
218 grows from low addresses to high addresses.) The initial
219 part of the stack segment linkage control information is
220 0200 (octal) words. This provides for register storage
221 for the routine which overflows the stack. */
222
223 struct stack_segment_linkage
224 {
225 long ss[0200]; /* 0200 overflow words. */
226 long sssize:32; /* Number of words in this segment. */
227 long ssbase:32; /* Offset to stack base. */
228 long:32;
229 long sspseg:32; /* Offset to linkage control of previous
230 segment of stack. */
231 long:32;
232 long sstcpt:32; /* Pointer to task common address block. */
233 long sscsnm; /* Private control structure number for
234 microtasking. */
235 long ssusr1; /* Reserved for user. */
236 long ssusr2; /* Reserved for user. */
237 long sstpid; /* Process ID for pid based multi-tasking. */
238 long ssgvup; /* Pointer to multitasking thread giveup. */
239 long sscray[7]; /* Reserved for Cray Research. */
240 long ssa0;
241 long ssa1;
242 long ssa2;
243 long ssa3;
244 long ssa4;
245 long ssa5;
246 long ssa6;
247 long ssa7;
248 long sss0;
249 long sss1;
250 long sss2;
251 long sss3;
252 long sss4;
253 long sss5;
254 long sss6;
255 long sss7;
256 };
257
258 #else /* CRAY2 */
259 /* The following structure defines the vector of words
260 returned by the STKSTAT library routine. */
261 struct stk_stat
262 {
263 long now; /* Current total stack size. */
264 long maxc; /* Amount of contiguous space which would
265 be required to satisfy the maximum
266 stack demand to date. */
267 long high_water; /* Stack high-water mark. */
268 long overflows; /* Number of stack overflow ($STKOFEN) calls. */
269 long hits; /* Number of internal buffer hits. */
270 long extends; /* Number of block extensions. */
271 long stko_mallocs; /* Block allocations by $STKOFEN. */
272 long underflows; /* Number of stack underflow calls ($STKRETN). */
273 long stko_free; /* Number of deallocations by $STKRETN. */
274 long stkm_free; /* Number of deallocations by $STKMRET. */
275 long segments; /* Current number of stack segments. */
276 long maxs; /* Maximum number of stack segments so far. */
277 long pad_size; /* Stack pad size. */
278 long current_address; /* Current stack segment address. */
279 long current_size; /* Current stack segment size. This
280 number is actually corrupted by STKSTAT to
281 include the fifteen word trailer area. */
282 long initial_address; /* Address of initial segment. */
283 long initial_size; /* Size of initial segment. */
284 };
285
286 /* The following structure describes the data structure which trails
287 any stack segment. I think that the description in 'asdef' is
288 out of date. I only describe the parts that I am sure about. */
289
290 struct stk_trailer
291 {
292 long this_address; /* Address of this block. */
293 long this_size; /* Size of this block (does not include
294 this trailer). */
295 long unknown2;
296 long unknown3;
297 long link; /* Address of trailer block of previous
298 segment. */
299 long unknown5;
300 long unknown6;
301 long unknown7;
302 long unknown8;
303 long unknown9;
304 long unknown10;
305 long unknown11;
306 long unknown12;
307 long unknown13;
308 long unknown14;
309 };
310
311 #endif /* CRAY2 */
312 #endif /* not CRAY_STACK */
313
314 #ifdef CRAY2
315 /* Determine a "stack measure" for an arbitrary ADDRESS.
316 I doubt that "lint" will like this much. */
317
318 static long
319 i00afunc (long *address)
320 {
321 struct stk_stat status;
322 struct stk_trailer *trailer;
323 long *block, size;
324 long result = 0;
325
326 /* We want to iterate through all of the segments. The first
327 step is to get the stack status structure. We could do this
328 more quickly and more directly, perhaps, by referencing the
329 $LM00 common block, but I know that this works. */
330
331 STKSTAT (&status);
332
333 /* Set up the iteration. */
334
335 trailer = (struct stk_trailer *) (status.current_address
336 + status.current_size
337 - 15);
338
339 /* There must be at least one stack segment. Therefore it is
340 a fatal error if "trailer" is null. */
341
342 if (trailer == 0)
343 abort ();
344
345 /* Discard segments that do not contain our argument address. */
346
347 while (trailer != 0)
348 {
349 block = (long *) trailer->this_address;
350 size = trailer->this_size;
351 if (block == 0 || size == 0)
352 abort ();
353 trailer = (struct stk_trailer *) trailer->link;
354 if ((block <= address) && (address < (block + size)))
355 break;
356 }
357
358 /* Set the result to the offset in this segment and add the sizes
359 of all predecessor segments. */
360
361 result = address - block;
362
363 if (trailer == 0)
364 {
365 return result;
366 }
367
368 do
369 {
370 if (trailer->this_size <= 0)
371 abort ();
372 result += trailer->this_size;
373 trailer = (struct stk_trailer *) trailer->link;
374 }
375 while (trailer != 0);
376
377 /* We are done. Note that if you present a bogus address (one
378 not in any segment), you will get a different number back, formed
379 from subtracting the address of the first block. This is probably
380 not what you want. */
381
382 return (result);
383 }
384
385 #else /* not CRAY2 */
386 /* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP.
387 Determine the number of the cell within the stack,
388 given the address of the cell. The purpose of this
389 routine is to linearize, in some sense, stack addresses
390 for alloca. */
391
392 static long
393 i00afunc (long address)
394 {
395 long stkl = 0;
396
397 long size, pseg, this_segment, stack;
398 long result = 0;
399
400 struct stack_segment_linkage *ssptr;
401
402 /* Register B67 contains the address of the end of the
403 current stack segment. If you (as a subprogram) store
404 your registers on the stack and find that you are past
405 the contents of B67, you have overflowed the segment.
406
407 B67 also points to the stack segment linkage control
408 area, which is what we are really interested in. */
409
410 stkl = CRAY_STACKSEG_END ();
411 ssptr = (struct stack_segment_linkage *) stkl;
412
413 /* If one subtracts 'size' from the end of the segment,
414 one has the address of the first word of the segment.
415
416 If this is not the first segment, 'pseg' will be
417 nonzero. */
418
419 pseg = ssptr->sspseg;
420 size = ssptr->sssize;
421
422 this_segment = stkl - size;
423
424 /* It is possible that calling this routine itself caused
425 a stack overflow. Discard stack segments which do not
426 contain the target address. */
427
428 while (!(this_segment <= address && address <= stkl))
429 {
430 #ifdef DEBUG_I00AFUNC
431 fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl);
432 #endif
433 if (pseg == 0)
434 break;
435 stkl = stkl - pseg;
436 ssptr = (struct stack_segment_linkage *) stkl;
437 size = ssptr->sssize;
438 pseg = ssptr->sspseg;
439 this_segment = stkl - size;
440 }
441
442 result = address - this_segment;
443
444 /* If you subtract pseg from the current end of the stack,
445 you get the address of the previous stack segment's end.
446 This seems a little convoluted to me, but I'll bet you save
447 a cycle somewhere. */
448
449 while (pseg != 0)
450 {
451 #ifdef DEBUG_I00AFUNC
452 fprintf (stderr, "%011o %011o\n", pseg, size);
453 #endif
454 stkl = stkl - pseg;
455 ssptr = (struct stack_segment_linkage *) stkl;
456 size = ssptr->sssize;
457 pseg = ssptr->sspseg;
458 result += size;
459 }
460 return (result);
461 }
462
463 #endif /* not CRAY2 */
464 #endif /* CRAY */
465
466 #endif /* no alloca */