diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libc/arch/alpha/gen/Makefile.inc | 6 | ||||
-rw-r--r-- | lib/libc/arch/hppa/gen/Makefile.inc | 3 | ||||
-rw-r--r-- | lib/libc/arch/m88k/gen/Makefile.inc | 3 | ||||
-rw-r--r-- | lib/libc/arch/mips/gen/Makefile.inc | 3 | ||||
-rw-r--r-- | lib/libc/arch/powerpc/gen/Makefile.inc | 1 | ||||
-rw-r--r-- | lib/libc/arch/sparc/gen/Makefile.inc | 3 | ||||
-rw-r--r-- | lib/libc/arch/sparc64/gen/Makefile.inc | 3 | ||||
-rw-r--r-- | lib/libc/gen/alloca.c | 133 |
8 files changed, 147 insertions, 8 deletions
diff --git a/lib/libc/arch/alpha/gen/Makefile.inc b/lib/libc/arch/alpha/gen/Makefile.inc index b9df181ef49..67af127a822 100644 --- a/lib/libc/arch/alpha/gen/Makefile.inc +++ b/lib/libc/arch/alpha/gen/Makefile.inc @@ -1,8 +1,8 @@ -# $OpenBSD: Makefile.inc,v 1.4 2001/09/10 22:38:11 millert Exp $ +# $OpenBSD: Makefile.inc,v 1.5 2003/05/02 19:20:26 millert Exp $ # $NetBSD: Makefile.inc,v 1.3 1995/04/29 05:09:14 cgd Exp $ -SRCS+= _setjmp.S fabs.S frexp.c infinity.c isinf.c isnan.c ldexp.c modf.c \ - setjmp.S +SRCS+= _setjmp.S alloca.c fabs.S frexp.c infinity.c isinf.c isnan.c ldexp.c \ + modf.c setjmp.S SRCS+= flt_rounds.c fpgetmask.c fpgetround.c fpgetsticky.c fpsetmask.c \ fpsetround.c fpsetsticky.c SRCS+= sigsetjmp.S diff --git a/lib/libc/arch/hppa/gen/Makefile.inc b/lib/libc/arch/hppa/gen/Makefile.inc index 26a255cdba7..e59f0cd20ff 100644 --- a/lib/libc/arch/hppa/gen/Makefile.inc +++ b/lib/libc/arch/hppa/gen/Makefile.inc @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile.inc,v 1.5 2002/05/17 18:41:02 mickey Exp $ +# $OpenBSD: Makefile.inc,v 1.6 2003/05/02 19:20:26 millert Exp $ SRCS+= setjmp.S SRCS+= fabs.c frexp.c ldexp.c @@ -6,3 +6,4 @@ SRCS+= isnan.c isinf.c infinity.c setjmp.S SRCS+= flt_rounds.c fpgetmask.c fpgetround.c fpgetsticky.c fpsetmask.c \ fpsetround.c fpsetsticky.c SRCS+= modf.c +SRCS+= alloca.c diff --git a/lib/libc/arch/m88k/gen/Makefile.inc b/lib/libc/arch/m88k/gen/Makefile.inc index c89d6e16a5a..a21dd5d2966 100644 --- a/lib/libc/arch/m88k/gen/Makefile.inc +++ b/lib/libc/arch/m88k/gen/Makefile.inc @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile.inc,v 1.2 2001/09/21 14:49:15 miod Exp $ +# $OpenBSD: Makefile.inc,v 1.3 2003/05/02 19:20:26 millert Exp $ # $NetBSD: Makefile.inc,v 1.3 1995/04/10 21:09:06 jtc Exp $ #SRCS+= _setjmp.S fabs.S frexp.c infinity.c isinf.c isnan.c ldexp.c modf.S @@ -11,3 +11,4 @@ SRCS+= flt_rounds.c fpgetmask.c fpgetround.c fpgetsticky.c fpsetmask.c \ fpsetround.c fpsetsticky.c SRCS+= setjmp.S sigsetjmp.S SRCS+= modf.c +SRCS+= alloca.c diff --git a/lib/libc/arch/mips/gen/Makefile.inc b/lib/libc/arch/mips/gen/Makefile.inc index d2afa4040a2..27d23fc3e9b 100644 --- a/lib/libc/arch/mips/gen/Makefile.inc +++ b/lib/libc/arch/mips/gen/Makefile.inc @@ -1,6 +1,7 @@ -# $OpenBSD: Makefile.inc,v 1.3 1996/08/19 08:15:50 tholo Exp $ +# $OpenBSD: Makefile.inc,v 1.4 2003/05/02 19:20:26 millert Exp $ SRCS+= _setjmp.S fabs.S frexp.c infinity.c isinf.S ldexp.S modf.S SRCS+= flt_rounds.c fpgetmask.c fpgetround.c fpgetsticky.c fpsetmask.c \ fpsetround.c fpsetsticky.c SRCS+= setjmp.S sigsetjmp.S +SRCS+= alloca.c diff --git a/lib/libc/arch/powerpc/gen/Makefile.inc b/lib/libc/arch/powerpc/gen/Makefile.inc index 3e0e5091c31..7f9092c3dc4 100644 --- a/lib/libc/arch/powerpc/gen/Makefile.inc +++ b/lib/libc/arch/powerpc/gen/Makefile.inc @@ -3,3 +3,4 @@ SRCS+= ldexp.c fabs.c frexp.c SRCS+= fpgetmask.c fpsetmask.c SRCS+= fpgetround.c fpsetround.c SRCS+= fpgetsticky.c fpsetsticky.c +SRCS+= alloca.c diff --git a/lib/libc/arch/sparc/gen/Makefile.inc b/lib/libc/arch/sparc/gen/Makefile.inc index d0fa7366173..95e1b4011ef 100644 --- a/lib/libc/arch/sparc/gen/Makefile.inc +++ b/lib/libc/arch/sparc/gen/Makefile.inc @@ -1,6 +1,7 @@ -# $OpenBSD: Makefile.inc,v 1.2 1996/08/19 08:17:24 tholo Exp $ +# $OpenBSD: Makefile.inc,v 1.3 2003/05/02 19:20:26 millert Exp $ SRCS+= _setjmp.S fabs.S frexp.c infinity.c isinf.c isnan.c ldexp.c modf.S SRCS+= flt_rounds.c fpgetmask.c fpgetround.c fpgetsticky.c fpsetmask.c \ fpsetround.c fpsetsticky.c SRCS+= fixunsdfsi.S mul.S umul.S saveregs.S setjmp.S sigsetjmp.S +SRCS+= alloca.c diff --git a/lib/libc/arch/sparc64/gen/Makefile.inc b/lib/libc/arch/sparc64/gen/Makefile.inc index fc594a5525e..227469f6920 100644 --- a/lib/libc/arch/sparc64/gen/Makefile.inc +++ b/lib/libc/arch/sparc64/gen/Makefile.inc @@ -1,6 +1,7 @@ -# $OpenBSD: Makefile.inc,v 1.1 2001/08/29 01:48:12 art Exp $ +# $OpenBSD: Makefile.inc,v 1.2 2003/05/02 19:20:26 millert Exp $ SRCS+= _setjmp.S fabs.S frexp.c infinity.c isinf.c isnan.c ldexp.c modf.S SRCS+= flt_rounds.c fpgetmask.c fpgetround.c fpgetsticky.c fpsetmask.c \ fpsetround.c fpsetsticky.c SRCS+= fixunsdfsi.S mul.S umul.S saveregs.S setjmp.S sigsetjmp.S +SRCS+= alloca.c diff --git a/lib/libc/gen/alloca.c b/lib/libc/gen/alloca.c new file mode 100644 index 00000000000..0855700596a --- /dev/null +++ b/lib/libc/gen/alloca.c @@ -0,0 +1,133 @@ +/* alloca.c -- allocate automatically reclaimed memory + (Mostly) portable public-domain implementation -- D A Gwyn + + This implementation of the PWB library alloca function, + which is used to allocate space off the run-time stack so + that it is automatically reclaimed upon procedure exit, + was inspired by discussions with J. Q. Johnson of Cornell. + + There are some preprocessor constants that can + be defined when compiling for your specific system, for + improved efficiency; however, the defaults should be okay. + + The general concept of this implementation is to keep + track of all alloca-allocated blocks, and reclaim any + that are found to be deeper in the stack than the current + invocation. This heuristic does not reclaim storage as + soon as it becomes invalid, but it will do so eventually. + + As a special case, alloca(0) reclaims storage without + allocating any. It is a good idea to use alloca(0) in + your main control loop, etc. to force garbage collection. */ + +/* If someone has defined alloca as a macro, + there must be some other way alloca is supposed to work. */ +#ifndef alloca + +#include <string.h> +#include <stdlib.h> + +/* If your stack is a linked list of frames, you have to + provide an "address metric" ADDRESS_FUNCTION macro. */ + +#define ADDRESS_FUNCTION(arg) &(arg) + +typedef void *pointer; + +/* Define STACK_DIRECTION for your cpu: + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses */ + +#if defined(__alpha__) || defined(__m68k__) || defined(__i386__) || \ + defined(__m88k__) || defined(__mips__) || defined(__powerpc__) || \ + defined(__sparc__) || defined(__sparc64__) || defined(__vax__) +# define STACK_DIRECTION -1 +#elif defined(__hppa__) +# define STACK_DIRECTION 1 +#else +# error must specify stack direction +#endif + +/* An "alloca header" is used to: + (a) chain together all alloca'ed blocks; + (b) keep track of stack depth. + + It is very important that sizeof(header) agree with malloc + alignment chunk size. The following default should work okay. */ + +#ifndef ALIGN_SIZE +#define ALIGN_SIZE sizeof(double) +#endif + +typedef union hdr +{ + char align[ALIGN_SIZE]; /* To force sizeof(header). */ + struct + { + union hdr *next; /* For chaining headers. */ + char *deep; /* For stack depth measure. */ + } h; +} header; + +static header *last_alloca_header = NULL; /* -> last alloca header. */ + +/* Return a pointer to at least SIZE bytes of storage, + which will be automatically reclaimed upon exit from + the procedure that called alloca. Originally, this space + was supposed to be taken from the current stack frame of the + caller, but that method cannot be made to work for some + implementations of C, for example under Gould's UTX/32. */ + +pointer +alloca (size) + unsigned size; +{ + auto char probe; /* Probes stack depth: */ + register char *depth = ADDRESS_FUNCTION (probe); + + /* Reclaim garbage, defined as all alloca'd storage that + was allocated from deeper in the stack than currently. */ + + { + register header *hp; /* Traverses linked list. */ + + for (hp = last_alloca_header; hp != NULL;) + if ((STACK_DIRECTION > 0 && hp->h.deep > depth) + || (STACK_DIRECTION < 0 && hp->h.deep < depth)) + { + register header *np = hp->h.next; + + free ((pointer) hp); /* Collect garbage. */ + + hp = np; /* -> next header. */ + } + else + break; /* Rest are not deeper. */ + + last_alloca_header = hp; /* -> last valid storage. */ + } + + if (size == 0) + return NULL; /* No allocation required. */ + + /* Allocate combined header + user data storage. */ + + { + register pointer new = malloc (sizeof (header) + size); + /* Address of header. */ + + if (new == 0) + abort(); + + ((header *) new)->h.next = last_alloca_header; + ((header *) new)->h.deep = depth; + + last_alloca_header = (header *) new; + + /* User storage begins just after header. */ + + return (pointer) ((char *) new + sizeof (header)); + } +} + +#endif /* no alloca */ |