18dffb485Schristos /* alloca.c -- allocate automatically reclaimed memory
2*4b169a6bSchristos This file is in the public domain. */
3*4b169a6bSchristos
4*4b169a6bSchristos /* (Mostly) portable implementation -- D A Gwyn
58dffb485Schristos
68dffb485Schristos This implementation of the PWB library alloca function,
78dffb485Schristos which is used to allocate space off the run-time stack so
88dffb485Schristos that it is automatically reclaimed upon procedure exit,
98dffb485Schristos was inspired by discussions with J. Q. Johnson of Cornell.
108dffb485Schristos J.Otto Tennant <jot@cray.com> contributed the Cray support.
118dffb485Schristos
128dffb485Schristos There are some preprocessor constants that can
138dffb485Schristos be defined when compiling for your specific system, for
148dffb485Schristos improved efficiency; however, the defaults should be okay.
158dffb485Schristos
168dffb485Schristos The general concept of this implementation is to keep
178dffb485Schristos track of all alloca-allocated blocks, and reclaim any
188dffb485Schristos that are found to be deeper in the stack than the current
198dffb485Schristos invocation. This heuristic does not reclaim storage as
208dffb485Schristos soon as it becomes invalid, but it will do so eventually.
218dffb485Schristos
228dffb485Schristos As a special case, alloca(0) reclaims storage without
238dffb485Schristos allocating any. It is a good idea to use alloca(0) in
248dffb485Schristos your main control loop, etc. to force garbage collection. */
258dffb485Schristos
268dffb485Schristos #include <config.h>
278dffb485Schristos
288dffb485Schristos #include <alloca.h>
298dffb485Schristos
308dffb485Schristos #include <string.h>
318dffb485Schristos #include <stdlib.h>
328dffb485Schristos
338dffb485Schristos #ifdef emacs
348dffb485Schristos # include "lisp.h"
358dffb485Schristos # include "blockinput.h"
368dffb485Schristos # ifdef EMACS_FREE
378dffb485Schristos # undef free
388dffb485Schristos # define free EMACS_FREE
398dffb485Schristos # endif
408dffb485Schristos #else
418dffb485Schristos # define memory_full() abort ()
428dffb485Schristos #endif
438dffb485Schristos
44*4b169a6bSchristos /* If compiling with GCC or clang, this file is not needed. */
45*4b169a6bSchristos #if !(defined __GNUC__ || defined __clang__)
468dffb485Schristos
478dffb485Schristos /* If someone has defined alloca as a macro,
488dffb485Schristos there must be some other way alloca is supposed to work. */
498dffb485Schristos # ifndef alloca
508dffb485Schristos
518dffb485Schristos # ifdef emacs
528dffb485Schristos # ifdef static
538dffb485Schristos /* actually, only want this if static is defined as ""
548dffb485Schristos -- this is for usg, in which emacs must undefine static
558dffb485Schristos in order to make unexec workable
568dffb485Schristos */
578dffb485Schristos # ifndef STACK_DIRECTION
588dffb485Schristos you
598dffb485Schristos lose
608dffb485Schristos -- must know STACK_DIRECTION at compile-time
618dffb485Schristos /* Using #error here is not wise since this file should work for
628dffb485Schristos old and obscure compilers. */
638dffb485Schristos # endif /* STACK_DIRECTION undefined */
648dffb485Schristos # endif /* static */
658dffb485Schristos # endif /* emacs */
668dffb485Schristos
678dffb485Schristos /* Define STACK_DIRECTION if you know the direction of stack
688dffb485Schristos growth for your system; otherwise it will be automatically
698dffb485Schristos deduced at run-time.
708dffb485Schristos
718dffb485Schristos STACK_DIRECTION > 0 => grows toward higher addresses
728dffb485Schristos STACK_DIRECTION < 0 => grows toward lower addresses
738dffb485Schristos STACK_DIRECTION = 0 => direction of growth unknown */
748dffb485Schristos
758dffb485Schristos # ifndef STACK_DIRECTION
768dffb485Schristos # define STACK_DIRECTION 0 /* Direction unknown. */
778dffb485Schristos # endif
788dffb485Schristos
798dffb485Schristos # if STACK_DIRECTION != 0
808dffb485Schristos
818dffb485Schristos # define STACK_DIR STACK_DIRECTION /* Known at compile-time. */
828dffb485Schristos
838dffb485Schristos # else /* STACK_DIRECTION == 0; need run-time code. */
848dffb485Schristos
858dffb485Schristos static int stack_dir; /* 1 or -1 once known. */
868dffb485Schristos # define STACK_DIR stack_dir
878dffb485Schristos
888dffb485Schristos static int
898dffb485Schristos find_stack_direction (int *addr, int depth)
908dffb485Schristos {
918dffb485Schristos int dir, dummy = 0;
928dffb485Schristos if (! addr)
938dffb485Schristos addr = &dummy;
948dffb485Schristos *addr = addr < &dummy ? 1 : addr == &dummy ? 0 : -1;
958dffb485Schristos dir = depth ? find_stack_direction (addr, depth - 1) : 0;
968dffb485Schristos return dir + dummy;
978dffb485Schristos }
988dffb485Schristos
998dffb485Schristos # endif /* STACK_DIRECTION == 0 */
1008dffb485Schristos
1018dffb485Schristos /* An "alloca header" is used to:
1028dffb485Schristos (a) chain together all alloca'ed blocks;
1038dffb485Schristos (b) keep track of stack depth.
1048dffb485Schristos
1058dffb485Schristos It is very important that sizeof(header) agree with malloc
1068dffb485Schristos alignment chunk size. The following default should work okay. */
1078dffb485Schristos
1088dffb485Schristos # ifndef ALIGN_SIZE
1098dffb485Schristos # define ALIGN_SIZE sizeof(double)
1108dffb485Schristos # endif
1118dffb485Schristos
1128dffb485Schristos typedef union hdr
1138dffb485Schristos {
1148dffb485Schristos char align[ALIGN_SIZE]; /* To force sizeof(header). */
1158dffb485Schristos struct
1168dffb485Schristos {
1178dffb485Schristos union hdr *next; /* For chaining headers. */
1188dffb485Schristos char *deep; /* For stack depth measure. */
1198dffb485Schristos } h;
1208dffb485Schristos } header;
1218dffb485Schristos
1228dffb485Schristos static header *last_alloca_header = NULL; /* -> last alloca header. */
1238dffb485Schristos
1248dffb485Schristos /* Return a pointer to at least SIZE bytes of storage,
1258dffb485Schristos which will be automatically reclaimed upon exit from
1268dffb485Schristos the procedure that called alloca. Originally, this space
1278dffb485Schristos was supposed to be taken from the current stack frame of the
1288dffb485Schristos caller, but that method cannot be made to work for some
1298dffb485Schristos implementations of C, for example under Gould's UTX/32. */
1308dffb485Schristos
1318dffb485Schristos void *
alloca(size_t size)1328dffb485Schristos alloca (size_t size)
1338dffb485Schristos {
1348dffb485Schristos auto char probe; /* Probes stack depth: */
135*4b169a6bSchristos register char *depth = &probe;
1368dffb485Schristos
1378dffb485Schristos # if STACK_DIRECTION == 0
1388dffb485Schristos if (STACK_DIR == 0) /* Unknown growth direction. */
1398dffb485Schristos STACK_DIR = find_stack_direction (NULL, (size & 1) + 20);
1408dffb485Schristos # endif
1418dffb485Schristos
1428dffb485Schristos /* Reclaim garbage, defined as all alloca'd storage that
1438dffb485Schristos was allocated from deeper in the stack than currently. */
1448dffb485Schristos
1458dffb485Schristos {
1468dffb485Schristos register header *hp; /* Traverses linked list. */
1478dffb485Schristos
1488dffb485Schristos # ifdef emacs
1498dffb485Schristos BLOCK_INPUT;
1508dffb485Schristos # endif
1518dffb485Schristos
1528dffb485Schristos for (hp = last_alloca_header; hp != NULL;)
1538dffb485Schristos if ((STACK_DIR > 0 && hp->h.deep > depth)
1548dffb485Schristos || (STACK_DIR < 0 && hp->h.deep < depth))
1558dffb485Schristos {
1568dffb485Schristos register header *np = hp->h.next;
1578dffb485Schristos
1588dffb485Schristos free (hp); /* Collect garbage. */
1598dffb485Schristos
1608dffb485Schristos hp = np; /* -> next header. */
1618dffb485Schristos }
1628dffb485Schristos else
1638dffb485Schristos break; /* Rest are not deeper. */
1648dffb485Schristos
1658dffb485Schristos last_alloca_header = hp; /* -> last valid storage. */
1668dffb485Schristos
1678dffb485Schristos # ifdef emacs
1688dffb485Schristos UNBLOCK_INPUT;
1698dffb485Schristos # endif
1708dffb485Schristos }
1718dffb485Schristos
1728dffb485Schristos if (size == 0)
1738dffb485Schristos return NULL; /* No allocation required. */
1748dffb485Schristos
1758dffb485Schristos /* Allocate combined header + user data storage. */
1768dffb485Schristos
1778dffb485Schristos {
1788dffb485Schristos /* Address of header. */
1798dffb485Schristos register header *new;
1808dffb485Schristos
1818dffb485Schristos size_t combined_size = sizeof (header) + size;
1828dffb485Schristos if (combined_size < sizeof (header))
1838dffb485Schristos memory_full ();
1848dffb485Schristos
1858dffb485Schristos new = malloc (combined_size);
1868dffb485Schristos
1878dffb485Schristos if (! new)
1888dffb485Schristos memory_full ();
1898dffb485Schristos
1908dffb485Schristos new->h.next = last_alloca_header;
1918dffb485Schristos new->h.deep = depth;
1928dffb485Schristos
1938dffb485Schristos last_alloca_header = new;
1948dffb485Schristos
1958dffb485Schristos /* User storage begins just after header. */
1968dffb485Schristos
1978dffb485Schristos return (void *) (new + 1);
1988dffb485Schristos }
1998dffb485Schristos }
2008dffb485Schristos
2018dffb485Schristos # endif /* no alloca */
202*4b169a6bSchristos #endif /* not GCC || clang */
203