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