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