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