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