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