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