summaryrefslogtreecommitdiff
path: root/dmake/dbug/malloc/malloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'dmake/dbug/malloc/malloc.c')
-rw-r--r--dmake/dbug/malloc/malloc.c627
1 files changed, 627 insertions, 0 deletions
diff --git a/dmake/dbug/malloc/malloc.c b/dmake/dbug/malloc/malloc.c
new file mode 100644
index 000000000000..ff84e3efce9f
--- /dev/null
+++ b/dmake/dbug/malloc/malloc.c
@@ -0,0 +1,627 @@
+/*
+ * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).
+ * You may copy, distribute, and use this software as long as this
+ * copyright statement is not removed.
+ */
+#include <stdio.h>
+#include <fcntl.h>
+#include "malloc.h"
+#include "tostring.h"
+
+/*
+ * Function: malloc()
+ *
+ * Purpose: memory allocator
+ *
+ * Arguments: size - size of data area needed
+ *
+ * Returns: pointer to allocated area, or NULL if unable
+ * to allocate addtional data.
+ *
+ * Narrative:
+ *
+ */
+#ifndef lint
+static
+char rcs_hdr[] = "$Id: malloc.c,v 1.2 2006-07-25 10:08:36 rt Exp $";
+#endif
+
+extern int malloc_checking;
+char * malloc_data_start;
+char * malloc_data_end;
+struct mlist * malloc_end;
+int malloc_errfd = 2;
+int malloc_errno;
+int malloc_fatal_level = M_HANDLE_CORE;
+struct mlist malloc_start;
+int malloc_warn_level;
+void malloc_memset();
+
+char *
+malloc(size)
+ unsigned int size;
+{
+ char * func = "malloc";
+ char * getenv();
+ void malloc_fatal();
+ void malloc_init();
+ void malloc_split();
+ void malloc_warning();
+ unsigned int need;
+ struct mlist * oldptr;
+ struct mlist * ptr;
+ char * sbrk();
+
+ /*
+ * If this is the first call to malloc...
+ */
+ if( malloc_data_start == (char *) 0 )
+ {
+ malloc_init();
+ }
+
+ /*
+ * If malloc chain checking is on, go do it.
+ */
+ if( malloc_checking )
+ {
+ (void) malloc_chain_check(1);
+ }
+
+ /*
+ * always make sure there is at least on extra byte in the malloc
+ * area so that we can verify that the user does not overrun the
+ * data area.
+ */
+ size++;
+
+ /*
+ * Now look for a free area of memory of size bytes...
+ */
+ oldptr = NULL;
+ for(ptr = &malloc_start; ; ptr = ptr->next)
+ {
+ /*
+ * Since the malloc chain is a forward only chain, any
+ * pointer that we get should always be positioned in
+ * memory following the previous pointer. If this is not
+ * so, we must have a corrupted chain.
+ */
+ if( ptr )
+ {
+ if( ptr<oldptr )
+ {
+ malloc_errno = M_CODE_CHAIN_BROKE;
+ malloc_fatal(func);
+ return(NULL);
+ }
+ oldptr = ptr;
+ }
+ else if( oldptr != malloc_end )
+ {
+ /*
+ * This should never happen. If it does, then
+ * we got a real problem.
+ */
+ malloc_errno = M_CODE_NO_END;
+ malloc_fatal(func);
+ return(NULL);
+ }
+
+
+ /*
+ * if this element is already in use...
+ */
+ if( ptr && ((ptr->flag & M_INUSE) != 0) )
+ {
+ continue;
+ }
+
+ /*
+ * if there isn't room for this block..
+ */
+ if( ptr && (ptr->s.size < size) )
+ {
+ continue;
+ }
+
+ /*
+ * If ptr is null, we have run out of memory and must sbrk more
+ */
+ if( ptr == NULL )
+ {
+ need = (size + M_SIZE) * (size > 10*1024 ? 1:2);
+ if( need < M_BLOCKSIZE )
+ {
+ need = M_BLOCKSIZE;
+ }
+ else if( need & (M_BLOCKSIZE-1) )
+ {
+ need &= ~(M_BLOCKSIZE-1);
+ need += M_BLOCKSIZE;
+ }
+ ptr = (struct mlist *) sbrk((int)need);
+ if( ptr == (struct mlist *) -1 )
+ {
+ malloc_errno = M_CODE_NOMORE_MEM;
+ malloc_fatal(func);
+ }
+ malloc_data_end = sbrk((int)0);
+
+ ptr->prev = oldptr;
+ ptr->next = (struct mlist *) 0;
+ ptr->s.size = need - M_SIZE;
+ ptr->flag = M_MAGIC;
+
+ oldptr->next = ptr;
+ malloc_end = ptr;
+
+
+ } /* if( ptr ==... */
+
+ /*
+ * Now ptr points to a memory location that can store
+ * this data, so lets go to work.
+ */
+
+ ptr->r_size = size; /* save requested size */
+ ptr->flag |= M_INUSE;
+
+ /*
+ * split off unneeded data area in this block, if possible...
+ */
+ malloc_split(ptr);
+
+ /*
+ * re-adjust the requested size so that it is what the user
+ * actually requested...
+ */
+
+ ptr->r_size--;
+
+ /*
+ * just to make sure that noone is misusing malloced
+ * memory without initializing it, lets set it to
+ * all '\01's. We call local_memset() because memset()
+ * may be checking for malloc'd ptrs and this isn't
+ * a malloc'd ptr yet.
+ */
+ malloc_memset(ptr->data,M_FILL,(int)ptr->s.size);
+
+ return( ptr->data);
+
+ } /* for(... */
+
+} /* malloc(... */
+
+/*
+ * Function: malloc_split()
+ *
+ * Purpose: to split a malloc segment if there is enough room at the
+ * end of the segment that isn't being used
+ *
+ * Arguments: ptr - pointer to segment to split
+ *
+ * Returns: nothing of any use.
+ *
+ * Narrative:
+ * get the needed size of the module
+ * round the size up to appropriat boundry
+ * calculate amount of left over space
+ * if there is enough left over space
+ * create new malloc block out of remainder
+ * if next block is free
+ * join the two blocks together
+ * fill new empty block with free space filler
+ * re-adjust pointers and size of current malloc block
+ *
+ *
+ *
+ * Mod History:
+ * 90/01/27 cpcahil Initial revision.
+ */
+void
+malloc_split(ptr)
+ struct mlist * ptr;
+{
+ extern struct mlist * malloc_end;
+ void malloc_join();
+ int rest;
+ int size;
+ struct mlist * tptr;
+
+ size = ptr->r_size;
+
+ /*
+ * roundup size to the appropriate boundry
+ */
+
+ M_ROUNDUP(size);
+
+ /*
+ * figure out how much room is left in the array.
+ * if there is enough room, create a new mlist
+ * structure there.
+ */
+
+ if( ptr->s.size > size )
+ {
+ rest = ptr->s.size - size;
+ }
+ else
+ {
+ rest = 0;
+ }
+
+ if( rest > (M_SIZE+M_RND) )
+ {
+ tptr = (struct mlist *) (ptr->data+size);
+ tptr->prev = ptr;
+ tptr->next = ptr->next;
+ tptr->flag = M_MAGIC;
+ tptr->s.size = rest - M_SIZE;
+
+ /*
+ * If possible, join this segment with the next one
+ */
+
+ malloc_join(tptr, tptr->next,0,0);
+
+ if( tptr->next )
+ {
+ tptr->next->prev = tptr;
+ }
+
+ malloc_memset(tptr->data,M_FREE_FILL, (int)tptr->s.size);
+
+ ptr->next = tptr;
+ ptr->s.size = size;
+
+ if( malloc_end == ptr )
+ {
+ malloc_end = tptr;
+ }
+ }
+
+} /* malloc_split(... */
+
+/*
+ * Function: malloc_join()
+ *
+ * Purpose: to join two malloc segments together (if possible)
+ *
+ * Arguments: ptr - pointer to segment to join to.
+ * nextptr - pointer to next segment to join to ptr.
+ *
+ * Returns: nothing of any values.
+ *
+ * Narrative:
+ *
+ * Mod History:
+ * 90/01/27 cpcahil Initial revision.
+ */
+void
+malloc_join(ptr,nextptr, inuse_override, fill_flag)
+ struct mlist * ptr;
+ struct mlist * nextptr;
+ int inuse_override;
+ int fill_flag;
+{
+ unsigned int newsize;
+
+ if( ptr && ! (inuse_override || (ptr->flag & M_INUSE)) &&
+ nextptr && ! (nextptr->flag & M_INUSE) &&
+ ((ptr->data+ptr->s.size) == (char *) nextptr) )
+ {
+ if( malloc_end == nextptr )
+ {
+ malloc_end = ptr;
+ }
+ ptr->next = nextptr->next;
+ newsize = nextptr->s.size + M_SIZE;
+
+ /*
+ * if we are to fill and this segment is in use,
+ * fill in with M_FILL newly added space...
+ */
+
+ if(fill_flag && (ptr->flag & M_INUSE) )
+ {
+ malloc_memset(ptr->data+ptr->s.size,
+ M_FILL, (int)(nextptr->s.size + M_SIZE));
+ }
+
+ ptr->s.size += newsize;
+ if( ptr->next )
+ {
+ ptr->next->prev = ptr;
+ }
+ }
+
+} /* malloc_join(... */
+
+
+/*
+ * The following mess is just to ensure that the versions of these functions in
+ * the current library are included (to make sure that we don't accidentaly get
+ * the libc versions. (This is the lazy man's -u ld directive)
+ */
+
+void free();
+int strcmp();
+int memcmp();
+char * realloc();
+
+void (*malloc_void_funcs[])() =
+{
+ free,
+};
+
+int (*malloc_int_funcs[])() =
+{
+ strcmp,
+ memcmp,
+};
+
+char * (*malloc_char_star_funcs[])() =
+{
+ realloc,
+};
+
+/*
+ * This is malloc's own memset which is used without checking the parameters.
+ */
+
+void
+malloc_memset(ptr,byte,len)
+ char * ptr;
+ char byte;
+ int len;
+{
+
+ while(len-- > 0)
+ {
+ *ptr++ = byte;
+ }
+
+} /* malloc_memset(... */
+
+/*
+ * Function: malloc_fatal()
+ *
+ * Purpose: to display fatal error message and take approrpriate action
+ *
+ * Arguments: funcname - name of function calling this routine
+ *
+ * Returns: nothing of any value
+ *
+ * Narrative:
+ *
+ * Notes: This routine does not make use of any libc functions to build
+ * and/or disply the error message. This is due to the fact that
+ * we are probably at a point where malloc is having a real problem
+ * and we don't want to call any function that may use malloc.
+ */
+void
+malloc_fatal(funcname)
+ char * funcname;
+{
+ char errbuf[128];
+ void exit();
+ void malloc_err_handler();
+ extern char * malloc_err_strings[];
+ extern int malloc_errno;
+ extern int malloc_fatal_level;
+ char * s;
+ char * t;
+
+ s = errbuf;
+ t = "Fatal error: ";
+ while( *s = *t++)
+ {
+ s++;
+ }
+ t = funcname;
+ while( *s = *t++)
+ {
+ s++;
+ }
+
+ t = "(): ";
+ while( *s = *t++)
+ {
+ s++;
+ }
+
+ t = malloc_err_strings[malloc_errno];
+ while( *s = *t++)
+ {
+ s++;
+ }
+
+ *(s++) = '\n';
+
+ if( write(malloc_errfd,errbuf,(unsigned)(s-errbuf)) != (s-errbuf))
+ {
+ (void) write(2,"I/O error to error file\n",(unsigned)24);
+ exit(110);
+ }
+ malloc_err_handler(malloc_fatal_level);
+
+} /* malloc_fatal(... */
+
+/*
+ * Function: malloc_warning()
+ *
+ * Purpose: to display warning error message and take approrpriate action
+ *
+ * Arguments: funcname - name of function calling this routine
+ *
+ * Returns: nothing of any value
+ *
+ * Narrative:
+ *
+ * Notes: This routine does not make use of any libc functions to build
+ * and/or disply the error message. This is due to the fact that
+ * we are probably at a point where malloc is having a real problem
+ * and we don't want to call any function that may use malloc.
+ */
+void
+malloc_warning(funcname)
+ char * funcname;
+{
+ char errbuf[128];
+ void exit();
+ void malloc_err_handler();
+ extern char * malloc_err_strings[];
+ extern int malloc_errno;
+ extern int malloc_warn_level;
+ char * s;
+ char * t;
+
+ s = errbuf;
+ t = "Warning: ";
+ while( *s = *t++)
+ {
+ s++;
+ }
+ t = funcname;
+ while( *s = *t++)
+ {
+ s++;
+ }
+
+ t = "(): ";
+ while( *s = *t++)
+ {
+ s++;
+ }
+
+ t = malloc_err_strings[malloc_errno];
+ while( *s = *t++)
+ {
+ s++;
+ }
+
+ *(s++) = '\n';
+
+ if( write(malloc_errfd,errbuf,(unsigned)(s-errbuf)) != (s-errbuf))
+ {
+ (void) write(2,"I/O error to error file\n",(unsigned)24);
+ exit(110);
+ }
+
+ malloc_err_handler(malloc_warn_level);
+
+} /* malloc_warning(... */
+
+/*
+ * Function: malloc_err_handler()
+ *
+ * Purpose: to take the appropriate action for warning and/or fatal
+ * error conditions.
+ *
+ * Arguments: level - error handling level
+ *
+ * Returns: nothing of any value
+ *
+ * Narrative:
+ *
+ * Notes: This routine does not make use of any libc functions to build
+ * and/or disply the error message. This is due to the fact that
+ * we are probably at a point where malloc is having a real problem
+ * and we don't want to call any function that may use malloc.
+ */
+void
+malloc_err_handler(level)
+{
+ void exit();
+ void malloc_dump();
+ extern int malloc_errfd;
+
+ if( level & M_HANDLE_DUMP )
+ {
+ malloc_dump(malloc_errfd);
+ }
+
+ switch( level & ~M_HANDLE_DUMP )
+ {
+ /*
+ * If we are to drop a core file and exit
+ */
+ case M_HANDLE_ABORT:
+ (void) abort();
+ break;
+
+ /*
+ * If we are to exit..
+ */
+ case M_HANDLE_EXIT:
+ exit(200);
+ break;
+
+#ifndef __MSDOS__
+ /*
+ * If we are to dump a core, but keep going on our merry way
+ */
+ case M_HANDLE_CORE:
+ {
+ int pid;
+
+ /*
+ * fork so child can abort (and dump core)
+ */
+ if( (pid = fork()) == 0 )
+ {
+ (void) write(2,"Child dumping core\n",
+ (unsigned)9);
+ (void) abort();
+ }
+
+ /*
+ * wait for child to finish dumping core
+ */
+ while( wait((int *)0) != pid)
+ {
+ }
+
+ /*
+ * Move core file to core.pid.cnt so
+ * multiple cores don't overwrite each
+ * other.
+ */
+ if( access("core",0) == 0 )
+ {
+ static int corecnt;
+ char filenam[32];
+ filenam[0] = 'c';
+ filenam[1] = 'o';
+ filenam[2] = 'r';
+ filenam[3] = 'e';
+ filenam[4] = '.';
+ (void)tostring(filenam+5,getpid(),
+ 5, B_DEC, '0');
+ filenam[10] = '.';
+ (void)tostring(filenam+11,corecnt++,
+ 3, B_DEC, '0');
+ filenam[14] = '\0';
+ (void) unlink(filenam);
+ if( link("core",filenam) == 0)
+ {
+ (void) unlink("core");
+ }
+ }
+ }
+#endif
+
+
+ /*
+ * If we are to just ignore the error and keep on processing
+ */
+ case M_HANDLE_IGNORE:
+ break;
+
+ } /* switch(... */
+
+} /* malloc_err_handler(... */
+