Alloc.c revision bdf0f55d
1/*********************************************************** 2Copyright (c) 1993, 2011, 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#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 94void _XtBcopy( 95 char *src, char *dst, 96 int length) 97{ 98 if (src < dst) { 99 dst += length; 100 src += length; 101 while (length--) 102 *--dst = *--src; 103 } else { 104 while (length--) 105 *dst++ = *src++; 106 } 107} 108#endif 109 110void _XtAllocError( 111 String type) 112{ 113 Cardinal num_params = 1; 114 if (type == NULL) type = "local memory allocation"; 115 XtErrorMsg("allocError", type, XtCXtToolkitError, 116 "Cannot perform %s", &type, &num_params); 117} 118 119void _XtHeapInit( 120 Heap* heap) 121{ 122 heap->start = NULL; 123 heap->bytes_remaining = 0; 124} 125 126/* Version of asprintf() using XtMalloc 127 * Not currently available in XTTRACEMEMORY version, since that would 128 * require varargs macros everywhere, which are only standard in C99 & later. 129 */ 130Cardinal XtAsprintf( 131 String *new_string, 132 _Xconst char * _X_RESTRICT_KYWD format, 133 ...) 134{ 135 char buf[256]; 136 Cardinal 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(len + 1); /* snprintf doesn't count trailing '\0' */ 147 if (len < sizeof(buf)) 148 { 149 strncpy(*new_string, buf, len); 150 (*new_string)[len] = '\0'; 151 } 152 else 153 { 154 va_start(ap, format); 155 if (vsnprintf(*new_string, len + 1, format, ap) < 0) 156 _XtAllocError("vsnprintf"); 157 va_end(ap); 158 } 159 return len; 160} 161 162 163#ifndef XTTRACEMEMORY 164 165char *XtMalloc( 166 unsigned size) 167{ 168 char *ptr; 169 170#if defined(MALLOC_0_RETURNS_NULL) && defined(XTMALLOC_BC) 171 /* preserve this (broken) behavior until everyone fixes their apps */ 172 if (!size) size = 1; 173#endif 174 if ((ptr = Xmalloc(size)) == NULL) 175 _XtAllocError("malloc"); 176 177 return(ptr); 178} 179 180char *XtRealloc( 181 char *ptr, 182 unsigned size) 183{ 184 if (ptr == NULL) { 185#ifdef MALLOC_0_RETURNS_NULL 186 if (!size) size = 1; 187#endif 188 return(XtMalloc(size)); 189 } else if ((ptr = Xrealloc(ptr, size)) == NULL 190#ifdef MALLOC_0_RETURNS_NULL 191 && size 192#endif 193 ) 194 _XtAllocError("realloc"); 195 196 return(ptr); 197} 198 199char *XtCalloc( 200 unsigned num, unsigned size) 201{ 202 char *ptr; 203 204#if defined(MALLOC_0_RETURNS_NULL) && defined(XTMALLOC_BC) 205 /* preserve this (broken) behavior until everyone fixes their apps */ 206 if (!size) num = size = 1; 207#endif 208 if ((ptr = Xcalloc(num, size)) == NULL) 209 _XtAllocError("calloc"); 210 211 return(ptr); 212} 213 214void XtFree( 215 char *ptr) 216{ 217 if (ptr != NULL) Xfree(ptr); 218} 219 220char* __XtMalloc( 221 unsigned size) 222{ 223#ifdef MALLOC_0_RETURNS_NULL 224 if (!size) size = 1; 225#endif 226 return XtMalloc (size); 227} 228 229char* __XtCalloc( 230 unsigned num, unsigned size) 231{ 232#ifdef MALLOC_0_RETURNS_NULL 233 if (!size) num = size = 1; 234#endif 235 return XtCalloc(num, size); 236} 237 238#ifndef HEAP_SEGMENT_SIZE 239#define HEAP_SEGMENT_SIZE 1492 240#endif 241 242char* _XtHeapAlloc( 243 Heap* heap, 244 Cardinal bytes) 245{ 246 register char* heap_loc; 247 if (heap == NULL) return XtMalloc(bytes); 248 if (heap->bytes_remaining < (int)bytes) { 249 if ((bytes + sizeof(char*)) >= (HEAP_SEGMENT_SIZE>>1)) { 250 /* preserve current segment; insert this one in front */ 251#ifdef _TRACE_HEAP 252 printf( "allocating large segment (%d bytes) on heap %#x\n", 253 bytes, heap ); 254#endif 255 heap_loc = XtMalloc(bytes + sizeof(char*)); 256 if (heap->start) { 257 *(char**)heap_loc = *(char**)heap->start; 258 *(char**)heap->start = heap_loc; 259 } 260 else { 261 *(char**)heap_loc = NULL; 262 heap->start = heap_loc; 263 } 264 return heap_loc + sizeof(char*); 265 } 266 /* else discard remainder of this segment */ 267#ifdef _TRACE_HEAP 268 printf( "allocating new segment on heap %#x\n", heap ); 269#endif 270 heap_loc = XtMalloc((unsigned)HEAP_SEGMENT_SIZE); 271 *(char**)heap_loc = heap->start; 272 heap->start = heap_loc; 273 heap->current = heap_loc + sizeof(char*); 274 heap->bytes_remaining = HEAP_SEGMENT_SIZE - sizeof(char*); 275 } 276 bytes = (bytes + (sizeof(long) - 1)) & (~(sizeof(long) - 1)); 277 heap_loc = heap->current; 278 heap->current += bytes; 279 heap->bytes_remaining -= bytes; /* can be negative, if rounded */ 280 return heap_loc; 281} 282 283void _XtHeapFree( 284 Heap* heap) 285{ 286 char* segment = heap->start; 287 while (segment != NULL) { 288 char* next_segment = *(char**)segment; 289 XtFree(segment); 290 segment = next_segment; 291 } 292 heap->start = NULL; 293 heap->bytes_remaining = 0; 294} 295 296#else 297 298/* 299 * X Toolkit Memory Trace Allocation Routines 300 */ 301 302#undef XtMalloc 303#undef XtRealloc 304#undef XtCalloc 305#undef XtFree 306 307typedef struct _Stats *StatsPtr; 308typedef struct _Stats { 309 StatsPtr prev, next; 310 char *file; 311 int line; 312 unsigned size; 313 unsigned long seq; 314 XtPointer heap; 315} Stats; 316 317static StatsPtr XtMemory = (StatsPtr)NULL; 318static unsigned long ActiveXtMemory = 0; 319static unsigned long XtSeqId = 0; 320static unsigned long XtSeqBreakpoint = ~0; 321 322#define StatsSize(n) ((((n) + (sizeof(long) - 1)) & ~(sizeof(long) - 1)) + sizeof(Stats)) 323#define ToStats(ptr) ((StatsPtr)(ptr - sizeof(Stats))) 324#define ToMem(ptr) (((char *)ptr) + sizeof(Stats)) 325 326#define CHAIN(ptr,len,hp) \ 327 ptr->next = XtMemory; \ 328 if (XtMemory) \ 329 XtMemory->prev = ptr; \ 330 XtMemory = ptr; \ 331 ptr->prev = (StatsPtr)NULL; \ 332 ptr->file = file; \ 333 ptr->line = line; \ 334 ptr->size = len; \ 335 ptr->heap = hp; \ 336 if (file) \ 337 ActiveXtMemory += len; \ 338 ptr->seq = XtSeqId; \ 339 if (XtSeqId == XtSeqBreakpoint) \ 340 _XtBreakpoint(ptr); \ 341 XtSeqId++ 342 343/*ARGUSED*/ 344static void _XtBreakpoint( 345 StatsPtr mem) 346{ 347 mem->seq = XtSeqId; /* avoid being optimized out of existence */ 348} 349 350char *_XtMalloc( 351 unsigned size, 352 char *file, 353 int line) 354{ 355 StatsPtr ptr; 356 unsigned newsize; 357 char* retval = NULL; 358 359 LOCK_PROCESS; 360 newsize = StatsSize(size); 361 if ((ptr = (StatsPtr)Xmalloc(newsize)) == NULL) 362 _XtAllocError("malloc"); 363 CHAIN(ptr, size, NULL); 364 retval = (ToMem(ptr)); 365 UNLOCK_PROCESS; 366 return retval; 367} 368 369char *XtMalloc( 370 unsigned size) 371{ 372 return _XtMalloc(size, (char *)NULL, 0); 373} 374 375char *_XtRealloc( 376 char *ptr, 377 unsigned size, 378 char *file, 379 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 if (copysize > size) copysize = size; 388 memmove(newptr, ptr, copysize); 389 _XtFree(ptr); 390 } 391 UNLOCK_PROCESS; 392 return(newptr); 393} 394 395char *XtRealloc( 396 char *ptr, 397 unsigned size) 398{ 399 return _XtRealloc(ptr, size, (char *)NULL, 0); 400} 401 402char *_XtCalloc( 403 unsigned num, unsigned size, 404 char *file, 405 int line) 406{ 407 StatsPtr ptr; 408 unsigned total, newsize; 409 char* retval = NULL; 410 411 LOCK_PROCESS; 412 total = num * size; 413 newsize = StatsSize(total); 414 if ((ptr = (StatsPtr)Xcalloc(newsize, 1)) == NULL) 415 _XtAllocError("calloc"); 416 CHAIN(ptr, total, NULL); 417 retval = (ToMem(ptr)); 418 UNLOCK_PROCESS; 419 return retval; 420} 421 422char *XtCalloc( 423 unsigned num, unsigned size) 424{ 425 return _XtCalloc(num, size, (char *)NULL, 0); 426} 427 428Boolean _XtIsValidPointer( 429 char *ptr) 430{ 431 register StatsPtr mem; 432 register StatsPtr stp = ToStats(ptr); 433 434 LOCK_PROCESS; 435 for (mem = XtMemory; mem; mem = mem->next) { 436 if (mem == stp) { 437 UNLOCK_PROCESS; 438 return True; 439 } 440 } 441 UNLOCK_PROCESS; 442 return False; 443} 444 445Boolean _XtValidateMemory = False; 446 447void _XtFree( 448 char *ptr) 449{ 450 register StatsPtr stp; 451 452 LOCK_PROCESS; 453 if (ptr) { 454 if (_XtValidateMemory && !_XtIsValidPointer(ptr)) 455 abort(); 456 stp = ToStats(ptr); 457 if (stp->file) 458 ActiveXtMemory -= stp->size; 459 if (stp->prev) 460 stp->prev->next = stp->next; 461 else 462 XtMemory = stp->next; 463 if (stp->next) 464 stp->next->prev = stp->prev; 465 Xfree((char *)stp); 466 } 467 UNLOCK_PROCESS; 468} 469 470void XtFree(char *ptr) 471{ 472 _XtFree(ptr); 473} 474 475char *_XtHeapMalloc( 476 Heap *heap, 477 Cardinal size, 478 char *file, 479 int line) 480{ 481 StatsPtr ptr; 482 unsigned newsize; 483 XtPointer hp = (XtPointer) heap; 484 char* retval = NULL; 485 486 LOCK_PROCESS; 487 newsize = StatsSize(size); 488 if ((ptr = (StatsPtr)Xmalloc(newsize)) == NULL) 489 _XtAllocError("malloc"); 490 CHAIN(ptr, size, hp); 491 retval = (ToMem(ptr)); 492 UNLOCK_PROCESS; 493 return retval; 494} 495 496void _XtHeapFree(register XtPointer heap) 497{ 498 register StatsPtr mem, next; 499 500 LOCK_PROCESS; 501 for (mem = XtMemory; mem; mem = next) { 502 next = mem->next; 503 if (mem->heap == heap) { 504 if (mem->file) 505 ActiveXtMemory -= mem->size; 506 if (mem->prev) 507 mem->prev->next = next; 508 else 509 XtMemory = next; 510 if (next) 511 next->prev = mem->prev; 512 Xfree((char *)mem); 513 } 514 } 515 UNLOCK_PROCESS; 516} 517 518#include <stdio.h> 519 520void _XtPrintMemory(char * filename) 521{ 522 register StatsPtr mem; 523 FILE *f; 524 525 if (filename == NULL) 526 f = stderr; 527 else 528 f = fopen(filename, "w"); 529 LOCK_PROCESS; 530 fprintf(f, "total size: %d\n", ActiveXtMemory); 531 for (mem = XtMemory; mem; mem = mem->next) { 532 if (mem->file) 533 fprintf(f, "size: %6d seq: %5d %12s(%4d) %s\n", 534 mem->size, mem->seq, 535 mem->file, mem->line, mem->heap ? "heap" : ""); 536 } 537 UNLOCK_PROCESS; 538 if (filename) fclose(f); 539} 540 541#endif /* XTTRACEMEMORY */ 542