summaryrefslogtreecommitdiff
path: root/src/Alloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/Alloc.c')
-rw-r--r--src/Alloc.c496
1 files changed, 496 insertions, 0 deletions
diff --git a/src/Alloc.c b/src/Alloc.c
new file mode 100644
index 0000000..16d922d
--- /dev/null
+++ b/src/Alloc.c
@@ -0,0 +1,496 @@
+/* $Xorg: Alloc.c,v 1.4 2001/02/09 02:03:53 xorgcvs Exp $ */
+
+/***********************************************************
+Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts,
+Copyright 1993 by Sun Microsystems, Inc. Mountain View, CA.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Digital or Sun not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+SUN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT-
+NESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SUN BE LI-
+ABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
+THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/*
+
+Copyright 1987, 1988, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+
+/*
+ * X Toolkit Memory Allocation Routines
+ *
+ * Uses Xlib memory management, which is spec'd to be re-entrant.
+ */
+
+#include "IntrinsicI.h"
+#undef _XBCOPYFUNC
+
+#ifndef X_NOT_STDC_ENV
+#include <stdlib.h>
+#else
+char *malloc(), *realloc(), *calloc();
+#endif
+
+#define Xmalloc(size) malloc((size))
+#define Xrealloc(ptr, size) realloc((ptr), (size))
+#define Xcalloc(nelem, elsize) calloc((nelem), (elsize))
+#define Xfree(ptr) free(ptr)
+
+#ifdef _XNEEDBCOPYFUNC
+void _XtBcopy(src, dst, length)
+ char *src, *dst;
+ int length;
+{
+ if (src < dst) {
+ dst += length;
+ src += length;
+ while (length--)
+ *--dst = *--src;
+ } else {
+ while (length--)
+ *dst++ = *src++;
+ }
+}
+#endif
+
+void _XtAllocError(type)
+ String type;
+{
+ Cardinal num_params = 1;
+ if (type == NULL) type = "local memory allocation";
+ XtErrorMsg("allocError", type, XtCXtToolkitError,
+ "Cannot perform %s", &type, &num_params);
+}
+
+void _XtHeapInit(heap)
+ Heap* heap;
+{
+ heap->start = NULL;
+ heap->bytes_remaining = 0;
+}
+
+#ifndef XTTRACEMEMORY
+
+char *XtMalloc(size)
+ unsigned size;
+{
+ char *ptr;
+
+#if defined (MALLOC_0_RETURNS_NULL) && defined(XTMALLOC_BC)
+ /* preserve this (broken) behavior until everyone fixes their apps */
+ if (!size) size = 1;
+#endif
+ if ((ptr = Xmalloc(size)) == NULL)
+ _XtAllocError("malloc");
+
+ return(ptr);
+}
+
+char *XtRealloc(ptr, size)
+ char *ptr;
+ unsigned size;
+{
+ if (ptr == NULL) {
+#if MALLOC_0_RETURNS_NULL
+ if (!size) size = 1;
+#endif
+ return(XtMalloc(size));
+ } else if ((ptr = Xrealloc(ptr, size)) == NULL
+#if MALLOC_0_RETURNS_NULL
+ && size
+#endif
+ )
+ _XtAllocError("realloc");
+
+ return(ptr);
+}
+
+char *XtCalloc(num, size)
+ unsigned num, size;
+{
+ char *ptr;
+
+#if defined (MALLOC_0_RETURNS_NULL) && defined(XTMALLOC_BC)
+ /* preserve this (broken) behavior until everyone fixes their apps */
+ if (!size) num = size = 1;
+#endif
+ if ((ptr = Xcalloc(num, size)) == NULL)
+ _XtAllocError("calloc");
+
+ return(ptr);
+}
+
+void XtFree(ptr)
+ char *ptr;
+{
+ if (ptr != NULL) Xfree(ptr);
+}
+
+char* __XtMalloc(size)
+ unsigned size;
+{
+#ifdef MALLOC_0_RETURNS_NULL
+ if (!size) size = 1;
+#endif
+ return XtMalloc (size);
+}
+
+char* __XtCalloc(num, size)
+ unsigned num, size;
+{
+#ifdef MALLOC_0_RETURNS_NULL
+ if (!size) num = size = 1;
+#endif
+ return XtCalloc(num, size);
+}
+
+#ifndef HEAP_SEGMENT_SIZE
+#define HEAP_SEGMENT_SIZE 1492
+#endif
+
+char* _XtHeapAlloc(heap, bytes)
+ Heap* heap;
+ Cardinal bytes;
+{
+ register char* heap_loc;
+ if (heap == NULL) return XtMalloc(bytes);
+ if (heap->bytes_remaining < (int)bytes) {
+ if ((bytes + sizeof(char*)) >= (HEAP_SEGMENT_SIZE>>1)) {
+ /* preserve current segment; insert this one in front */
+#ifdef _TRACE_HEAP
+ printf( "allocating large segment (%d bytes) on heap %#x\n",
+ bytes, heap );
+#endif
+ heap_loc = XtMalloc(bytes + sizeof(char*));
+ if (heap->start) {
+ *(char**)heap_loc = *(char**)heap->start;
+ *(char**)heap->start = heap_loc;
+ }
+ else {
+ *(char**)heap_loc = NULL;
+ heap->start = heap_loc;
+ }
+ return heap_loc + sizeof(char*);
+ }
+ /* else discard remainder of this segment */
+#ifdef _TRACE_HEAP
+ printf( "allocating new segment on heap %#x\n", heap );
+#endif
+ heap_loc = XtMalloc((unsigned)HEAP_SEGMENT_SIZE);
+ *(char**)heap_loc = heap->start;
+ heap->start = heap_loc;
+ heap->current = heap_loc + sizeof(char*);
+ heap->bytes_remaining = HEAP_SEGMENT_SIZE - sizeof(char*);
+ }
+ bytes = (bytes + (sizeof(long) - 1)) & (~(sizeof(long) - 1));
+ heap_loc = heap->current;
+ heap->current += bytes;
+ heap->bytes_remaining -= bytes; /* can be negative, if rounded */
+ return heap_loc;
+}
+
+void _XtHeapFree(heap)
+ Heap* heap;
+{
+ char* segment = heap->start;
+ while (segment != NULL) {
+ char* next_segment = *(char**)segment;
+ XtFree(segment);
+ segment = next_segment;
+ }
+ heap->start = NULL;
+ heap->bytes_remaining = 0;
+}
+
+#else
+
+/*
+ * X Toolkit Memory Trace Allocation Routines
+ */
+
+#undef XtMalloc
+#undef XtRealloc
+#undef XtCalloc
+#undef XtFree
+
+typedef struct _Stats *StatsPtr;
+typedef struct _Stats {
+ StatsPtr prev, next;
+ char *file;
+ int line;
+ unsigned size;
+ unsigned long seq;
+ XtPointer heap;
+} Stats;
+
+static StatsPtr XtMemory = (StatsPtr)NULL;
+static unsigned long ActiveXtMemory = 0;
+static unsigned long XtSeqId = 0;
+static unsigned long XtSeqBreakpoint = ~0;
+
+#define StatsSize(n) ((((n) + (sizeof(long) - 1)) & ~(sizeof(long) - 1)) + sizeof(Stats))
+#define ToStats(ptr) ((StatsPtr)(ptr - sizeof(Stats)))
+#define ToMem(ptr) (((char *)ptr) + sizeof(Stats))
+
+#define CHAIN(ptr,len,hp) \
+ ptr->next = XtMemory; \
+ if (XtMemory) \
+ XtMemory->prev = ptr; \
+ XtMemory = ptr; \
+ ptr->prev = (StatsPtr)NULL; \
+ ptr->file = file; \
+ ptr->line = line; \
+ ptr->size = len; \
+ ptr->heap = hp; \
+ if (file) \
+ ActiveXtMemory += len; \
+ ptr->seq = XtSeqId; \
+ if (XtSeqId == XtSeqBreakpoint) \
+ _XtBreakpoint(ptr); \
+ XtSeqId++
+
+/*ARGUSED*/
+static void _XtBreakpoint(mem)
+ StatsPtr mem;
+{
+ mem->seq = XtSeqId; /* avoid being optimized out of existence */
+}
+
+char *_XtMalloc(size, file, line)
+ unsigned size;
+ char *file;
+ int line;
+{
+ StatsPtr ptr;
+ unsigned newsize;
+ char* retval = NULL;
+
+ LOCK_PROCESS;
+ newsize = StatsSize(size);
+ if ((ptr = (StatsPtr)Xmalloc(newsize)) == NULL)
+ _XtAllocError("malloc");
+ CHAIN(ptr, size, NULL);
+ retval = (ToMem(ptr));
+ UNLOCK_PROCESS;
+ return retval;
+}
+
+char *XtMalloc(size)
+ unsigned size;
+{
+ return _XtMalloc(size, (char *)NULL, 0);
+}
+
+char *_XtRealloc(ptr, size, file, line)
+ char *ptr;
+ unsigned size;
+ char *file;
+ int line;
+{
+ char *newptr;
+
+ LOCK_PROCESS;
+ newptr = _XtMalloc(size, file, line);
+ if (ptr) {
+ unsigned copysize = ToStats(ptr)->size;
+ if (copysize > size) copysize = size;
+ memmove(newptr, ptr, copysize);
+ _XtFree(ptr);
+ }
+ UNLOCK_PROCESS;
+ return(newptr);
+}
+
+char *XtRealloc(ptr, size)
+ char *ptr;
+ unsigned size;
+{
+ return _XtRealloc(ptr, size, (char *)NULL, 0);
+}
+
+char *_XtCalloc(num, size, file, line)
+ unsigned num, size;
+ char *file;
+ int line;
+{
+ StatsPtr ptr;
+ unsigned total, newsize;
+ char* retval = NULL;
+
+ LOCK_PROCESS;
+ total = num * size;
+ newsize = StatsSize(total);
+ if ((ptr = (StatsPtr)Xcalloc(newsize, 1)) == NULL)
+ _XtAllocError("calloc");
+ CHAIN(ptr, total, NULL);
+ retval = (ToMem(ptr));
+ UNLOCK_PROCESS;
+ return retval;
+}
+
+char *XtCalloc(num, size)
+ unsigned num, size;
+{
+ return _XtCalloc(num, size, (char *)NULL, 0);
+}
+
+Boolean _XtIsValidPointer(ptr)
+ char *ptr;
+{
+ register StatsPtr mem;
+ register StatsPtr stp = ToStats(ptr);
+
+ LOCK_PROCESS;
+ for (mem = XtMemory; mem; mem = mem->next) {
+ if (mem == stp) {
+ UNLOCK_PROCESS;
+ return True;
+ }
+ }
+ UNLOCK_PROCESS;
+ return False;
+}
+
+Boolean _XtValidateMemory = False;
+
+void _XtFree(ptr)
+ char *ptr;
+{
+ register StatsPtr stp;
+
+ LOCK_PROCESS;
+ if (ptr) {
+ if (_XtValidateMemory && !_XtIsValidPointer(ptr))
+ abort();
+ stp = ToStats(ptr);
+ if (stp->file)
+ ActiveXtMemory -= stp->size;
+ if (stp->prev)
+ stp->prev->next = stp->next;
+ else
+ XtMemory = stp->next;
+ if (stp->next)
+ stp->next->prev = stp->prev;
+ Xfree((char *)stp);
+ }
+ UNLOCK_PROCESS;
+}
+
+void XtFree(ptr)
+ char *ptr;
+{
+ _XtFree(ptr);
+}
+
+char *_XtHeapMalloc(heap, size, file, line)
+ Heap *heap;
+ Cardinal size;
+ char *file;
+ int line;
+{
+ StatsPtr ptr;
+ unsigned newsize;
+ XtPointer hp = (XtPointer) heap;
+ char* retval = NULL;
+
+ LOCK_PROCESS;
+ newsize = StatsSize(size);
+ if ((ptr = (StatsPtr)Xmalloc(newsize)) == NULL)
+ _XtAllocError("malloc");
+ CHAIN(ptr, size, hp);
+ retval = (ToMem(ptr));
+ UNLOCK_PROCESS;
+ return retval;
+}
+
+void _XtHeapFree(heap)
+ register XtPointer heap;
+{
+ register StatsPtr mem, next;
+
+ LOCK_PROCESS;
+ for (mem = XtMemory; mem; mem = next) {
+ next = mem->next;
+ if (mem->heap == heap) {
+ if (mem->file)
+ ActiveXtMemory -= mem->size;
+ if (mem->prev)
+ mem->prev->next = next;
+ else
+ XtMemory = next;
+ if (next)
+ next->prev = mem->prev;
+ Xfree((char *)mem);
+ }
+ }
+ UNLOCK_PROCESS;
+}
+
+#include <stdio.h>
+
+void _XtPrintMemory(filename)
+char * filename;
+{
+ register StatsPtr mem;
+ FILE *f;
+
+ if (filename == NULL)
+ f = stderr;
+ else
+ f = fopen(filename, "w");
+ LOCK_PROCESS;
+ fprintf(f, "total size: %d\n", ActiveXtMemory);
+ for (mem = XtMemory; mem; mem = mem->next) {
+ if (mem->file)
+ fprintf(f, "size: %6d seq: %5d %12s(%4d) %s\n",
+ mem->size, mem->seq,
+ mem->file, mem->line, mem->heap ? "heap" : "");
+ }
+ UNLOCK_PROCESS;
+ if (filename) fclose(f);
+}
+
+#endif /* XTTRACEMEMORY */