Alloc.c revision 1477040f
1/* $Xorg: Alloc.c,v 1.4 2001/02/09 02:03:53 xorgcvs Exp $ */
2
3/***********************************************************
4Copyright 1993 Sun Microsystems, Inc.  All rights reserved.
5
6Permission is hereby granted, free of charge, to any person obtaining a
7copy of this software and associated documentation files (the "Software"),
8to deal in the Software without restriction, including without limitation
9the rights to use, copy, modify, merge, publish, distribute, sublicense,
10and/or sell copies of the Software, and to permit persons to whom the
11Software is furnished to do so, subject to the following conditions:
12
13The above copyright notice and this permission notice (including the next
14paragraph) shall be included in all copies or substantial portions of the
15Software.
16
17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23DEALINGS IN THE SOFTWARE.
24
25Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
26
27                        All Rights Reserved
28
29Permission to use, copy, modify, and distribute this software and its
30documentation for any purpose and without fee is hereby granted,
31provided that the above copyright notice appear in all copies and that
32both that copyright notice and this permission notice appear in
33supporting documentation, and that the name of Digital not be
34used in advertising or publicity pertaining to distribution of the
35software without specific, written prior permission.
36
37DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
38ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
39DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
40ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
41WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
42ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
43SOFTWARE.
44
45******************************************************************/
46
47/*
48
49Copyright 1987, 1988, 1998  The Open Group
50
51Permission to use, copy, modify, distribute, and sell this software and its
52documentation for any purpose is hereby granted without fee, provided that
53the above copyright notice appear in all copies and that both that
54copyright notice and this permission notice appear in supporting
55documentation.
56
57The above copyright notice and this permission notice shall be included in
58all copies or substantial portions of the Software.
59
60THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
61IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
62FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
63OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
64AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
65CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
66
67Except as contained in this notice, the name of The Open Group shall not be
68used in advertising or otherwise to promote the sale, use or other dealings
69in this Software without prior written authorization from The Open Group.
70
71*/
72/* $XFree86: xc/lib/Xt/Alloc.c,v 1.9 2001/12/14 19:56:07 dawes Exp $ */
73
74/*
75 * X Toolkit Memory Allocation Routines
76 *
77 * Uses Xlib memory management, which is spec'd to be re-entrant.
78 */
79
80#ifdef HAVE_CONFIG_H
81#include <config.h>
82#endif
83#include "IntrinsicI.h"
84#include "InitialI.h"
85#undef _XBCOPYFUNC
86
87#include <stdlib.h>
88
89#define Xmalloc(size) malloc((size))
90#define Xrealloc(ptr, size) realloc((ptr), (size))
91#define Xcalloc(nelem, elsize) calloc((nelem), (elsize))
92#define Xfree(ptr) free(ptr)
93
94#ifdef _XNEEDBCOPYFUNC
95void _XtBcopy(
96    char *src, char *dst,
97    int length)
98{
99    if (src < dst) {
100	dst += length;
101	src += length;
102	while (length--)
103	    *--dst = *--src;
104    } else {
105	while (length--)
106	    *dst++ = *src++;
107    }
108}
109#endif
110
111void _XtAllocError(
112    String type)
113{
114    Cardinal num_params = 1;
115    if (type == NULL) type = "local memory allocation";
116    XtErrorMsg("allocError", type, XtCXtToolkitError,
117	       "Cannot perform %s", &type, &num_params);
118}
119
120void _XtHeapInit(
121    Heap*	heap)
122{
123    heap->start = NULL;
124    heap->bytes_remaining = 0;
125}
126
127#ifndef XTTRACEMEMORY
128
129char *XtMalloc(
130    unsigned size)
131{
132    char *ptr;
133
134#if defined(MALLOC_0_RETURNS_NULL) && defined(XTMALLOC_BC)
135    /* preserve this (broken) behavior until everyone fixes their apps */
136    if (!size) size = 1;
137#endif
138    if ((ptr = Xmalloc(size)) == NULL)
139        _XtAllocError("malloc");
140
141    return(ptr);
142}
143
144char *XtRealloc(
145    char     *ptr,
146    unsigned size)
147{
148   if (ptr == NULL) {
149#ifdef MALLOC_0_RETURNS_NULL
150	if (!size) size = 1;
151#endif
152	return(XtMalloc(size));
153   } else if ((ptr = Xrealloc(ptr, size)) == NULL
154#ifdef MALLOC_0_RETURNS_NULL
155		&& size
156#endif
157	)
158	_XtAllocError("realloc");
159
160   return(ptr);
161}
162
163char *XtCalloc(
164    unsigned num, unsigned size)
165{
166    char *ptr;
167
168#if defined(MALLOC_0_RETURNS_NULL) && defined(XTMALLOC_BC)
169    /* preserve this (broken) behavior until everyone fixes their apps */
170    if (!size) num = size = 1;
171#endif
172    if ((ptr = Xcalloc(num, size)) == NULL)
173	_XtAllocError("calloc");
174
175    return(ptr);
176}
177
178void XtFree(
179    char *ptr)
180{
181    if (ptr != NULL) Xfree(ptr);
182}
183
184char* __XtMalloc(
185    unsigned size)
186{
187#ifdef MALLOC_0_RETURNS_NULL
188    if (!size) size = 1;
189#endif
190    return XtMalloc (size);
191}
192
193char* __XtCalloc(
194    unsigned num, unsigned size)
195{
196#ifdef MALLOC_0_RETURNS_NULL
197    if (!size) num = size = 1;
198#endif
199    return XtCalloc(num, size);
200}
201
202#ifndef HEAP_SEGMENT_SIZE
203#define HEAP_SEGMENT_SIZE 1492
204#endif
205
206char* _XtHeapAlloc(
207    Heap*	heap,
208    Cardinal	bytes)
209{
210    register char* heap_loc;
211    if (heap == NULL) return XtMalloc(bytes);
212    if (heap->bytes_remaining < (int)bytes) {
213	if ((bytes + sizeof(char*)) >= (HEAP_SEGMENT_SIZE>>1)) {
214	    /* preserve current segment; insert this one in front */
215#ifdef _TRACE_HEAP
216	    printf( "allocating large segment (%d bytes) on heap %#x\n",
217		    bytes, heap );
218#endif
219	    heap_loc = XtMalloc(bytes + sizeof(char*));
220	    if (heap->start) {
221		*(char**)heap_loc = *(char**)heap->start;
222		*(char**)heap->start = heap_loc;
223	    }
224	    else {
225		*(char**)heap_loc = NULL;
226		heap->start = heap_loc;
227	    }
228	    return heap_loc + sizeof(char*);
229	}
230	/* else discard remainder of this segment */
231#ifdef _TRACE_HEAP
232	printf( "allocating new segment on heap %#x\n", heap );
233#endif
234	heap_loc = XtMalloc((unsigned)HEAP_SEGMENT_SIZE);
235	*(char**)heap_loc = heap->start;
236	heap->start = heap_loc;
237	heap->current = heap_loc + sizeof(char*);
238	heap->bytes_remaining = HEAP_SEGMENT_SIZE - sizeof(char*);
239    }
240    bytes = (bytes + (sizeof(long) - 1)) & (~(sizeof(long) - 1));
241    heap_loc = heap->current;
242    heap->current += bytes;
243    heap->bytes_remaining -= bytes; /* can be negative, if rounded */
244    return heap_loc;
245}
246
247void _XtHeapFree(
248    Heap*	heap)
249{
250    char* segment = heap->start;
251    while (segment != NULL) {
252	char* next_segment = *(char**)segment;
253	XtFree(segment);
254	segment = next_segment;
255    }
256    heap->start = NULL;
257    heap->bytes_remaining = 0;
258}
259
260#else
261
262/*
263 * X Toolkit Memory Trace Allocation Routines
264 */
265
266#undef XtMalloc
267#undef XtRealloc
268#undef XtCalloc
269#undef XtFree
270
271typedef struct _Stats *StatsPtr;
272typedef struct _Stats {
273    StatsPtr prev, next;
274    char *file;
275    int line;
276    unsigned size;
277    unsigned long seq;
278    XtPointer heap;
279} Stats;
280
281static StatsPtr XtMemory = (StatsPtr)NULL;
282static unsigned long ActiveXtMemory = 0;
283static unsigned long XtSeqId = 0;
284static unsigned long XtSeqBreakpoint = ~0;
285
286#define StatsSize(n) ((((n) + (sizeof(long) - 1)) & ~(sizeof(long) - 1)) + sizeof(Stats))
287#define ToStats(ptr) ((StatsPtr)(ptr - sizeof(Stats)))
288#define ToMem(ptr) (((char *)ptr) + sizeof(Stats))
289
290#define CHAIN(ptr,len,hp) \
291    ptr->next = XtMemory; \
292    if (XtMemory) \
293        XtMemory->prev = ptr; \
294    XtMemory = ptr; \
295    ptr->prev = (StatsPtr)NULL; \
296    ptr->file = file; \
297    ptr->line = line; \
298    ptr->size = len; \
299    ptr->heap = hp; \
300    if (file) \
301	ActiveXtMemory += len; \
302    ptr->seq = XtSeqId; \
303    if (XtSeqId == XtSeqBreakpoint) \
304	_XtBreakpoint(ptr); \
305    XtSeqId++
306
307/*ARGUSED*/
308static void _XtBreakpoint(
309    StatsPtr mem)
310{
311    mem->seq = XtSeqId; /* avoid being optimized out of existence */
312}
313
314char *_XtMalloc(
315    unsigned size,
316    char *file,
317    int line)
318{
319    StatsPtr ptr;
320    unsigned newsize;
321    char* retval = NULL;
322
323    LOCK_PROCESS;
324    newsize = StatsSize(size);
325    if ((ptr = (StatsPtr)Xmalloc(newsize)) == NULL)
326        _XtAllocError("malloc");
327    CHAIN(ptr, size, NULL);
328    retval = (ToMem(ptr));
329    UNLOCK_PROCESS;
330    return retval;
331}
332
333char *XtMalloc(
334    unsigned size)
335{
336    return _XtMalloc(size, (char *)NULL, 0);
337}
338
339char *_XtRealloc(
340    char     *ptr,
341    unsigned size,
342    char *file,
343    int line)
344{
345   char *newptr;
346
347   LOCK_PROCESS;
348   newptr = _XtMalloc(size, file, line);
349   if (ptr) {
350       unsigned copysize = ToStats(ptr)->size;
351       if (copysize > size) copysize = size;
352       memmove(newptr, ptr, copysize);
353       _XtFree(ptr);
354   }
355   UNLOCK_PROCESS;
356   return(newptr);
357}
358
359char *XtRealloc(
360    char     *ptr,
361    unsigned size)
362{
363    return _XtRealloc(ptr, size, (char *)NULL, 0);
364}
365
366char *_XtCalloc(
367    unsigned num, unsigned size,
368    char *file,
369    int line)
370{
371    StatsPtr ptr;
372    unsigned total, newsize;
373    char* retval = NULL;
374
375    LOCK_PROCESS;
376    total = num * size;
377    newsize = StatsSize(total);
378    if ((ptr = (StatsPtr)Xcalloc(newsize, 1)) == NULL)
379        _XtAllocError("calloc");
380    CHAIN(ptr, total, NULL);
381    retval = (ToMem(ptr));
382    UNLOCK_PROCESS;
383    return retval;
384}
385
386char *XtCalloc(
387    unsigned num, unsigned size)
388{
389    return _XtCalloc(num, size, (char *)NULL, 0);
390}
391
392Boolean _XtIsValidPointer(
393    char *ptr)
394{
395    register StatsPtr mem;
396    register StatsPtr stp = ToStats(ptr);
397
398    LOCK_PROCESS;
399    for (mem = XtMemory; mem; mem = mem->next) {
400	if (mem == stp) {
401	    UNLOCK_PROCESS;
402	    return True;
403	}
404    }
405    UNLOCK_PROCESS;
406    return False;
407}
408
409Boolean _XtValidateMemory = False;
410
411void _XtFree(
412    char *ptr)
413{
414   register StatsPtr stp;
415
416   LOCK_PROCESS;
417   if (ptr) {
418       if (_XtValidateMemory && !_XtIsValidPointer(ptr))
419	   abort();
420       stp = ToStats(ptr);
421       if (stp->file)
422	   ActiveXtMemory -= stp->size;
423       if (stp->prev)
424	   stp->prev->next = stp->next;
425       else
426	   XtMemory = stp->next;
427       if (stp->next)
428	   stp->next->prev = stp->prev;
429       Xfree((char *)stp);
430   }
431   UNLOCK_PROCESS;
432}
433
434void XtFree(char *ptr)
435{
436   _XtFree(ptr);
437}
438
439char *_XtHeapMalloc(
440    Heap *heap,
441    Cardinal size,
442    char *file,
443    int line)
444{
445    StatsPtr ptr;
446    unsigned newsize;
447    XtPointer hp = (XtPointer) heap;
448    char* retval = NULL;
449
450    LOCK_PROCESS;
451    newsize = StatsSize(size);
452    if ((ptr = (StatsPtr)Xmalloc(newsize)) == NULL)
453        _XtAllocError("malloc");
454    CHAIN(ptr, size, hp);
455    retval = (ToMem(ptr));
456    UNLOCK_PROCESS;
457    return retval;
458}
459
460void _XtHeapFree(register XtPointer heap)
461{
462    register StatsPtr mem, next;
463
464    LOCK_PROCESS;
465    for (mem = XtMemory; mem; mem = next) {
466	next = mem->next;
467	if (mem->heap == heap) {
468	    if (mem->file)
469		ActiveXtMemory -= mem->size;
470	    if (mem->prev)
471		mem->prev->next = next;
472	    else
473		XtMemory = next;
474	    if (next)
475		next->prev = mem->prev;
476	    Xfree((char *)mem);
477	}
478    }
479    UNLOCK_PROCESS;
480}
481
482#include <stdio.h>
483
484void _XtPrintMemory(char * filename)
485{
486    register StatsPtr mem;
487    FILE *f;
488
489    if (filename == NULL)
490	f = stderr;
491    else
492	f = fopen(filename, "w");
493    LOCK_PROCESS;
494    fprintf(f, "total size: %d\n", ActiveXtMemory);
495    for (mem = XtMemory; mem; mem = mem->next) {
496	if (mem->file)
497	    fprintf(f, "size: %6d  seq: %5d  %12s(%4d)  %s\n",
498		    mem->size, mem->seq,
499		    mem->file, mem->line, mem->heap ? "heap" : "");
500    }
501    UNLOCK_PROCESS;
502    if (filename) fclose(f);
503}
504
505#endif  /* XTTRACEMEMORY */
506