os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/generic/tclAlloc.c
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/generic/tclAlloc.c Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,731 @@
1.4 +/*
1.5 + * tclAlloc.c --
1.6 + *
1.7 + * This is a very fast storage allocator. It allocates blocks of a
1.8 + * small number of different sizes, and keeps free lists of each size.
1.9 + * Blocks that don't exactly fit are passed up to the next larger size.
1.10 + * Blocks over a certain size are directly allocated from the system.
1.11 + *
1.12 + * Copyright (c) 1983 Regents of the University of California.
1.13 + * Copyright (c) 1996-1997 Sun Microsystems, Inc.
1.14 + * Copyright (c) 1998-1999 by Scriptics Corporation.
1.15 + *
1.16 + * Portions contributed by Chris Kingsley, Jack Jansen and Ray Johnson.
1.17 + *
1.18 + * See the file "license.terms" for information on usage and redistribution
1.19 + * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
1.20 + *
1.21 + * RCS: @(#) $Id: tclAlloc.c,v 1.16.2.1 2004/10/28 21:12:37 andreas_kupries Exp $
1.22 + */
1.23 +
1.24 +/*
1.25 + * Windows and Unix use an alternative allocator when building with threads
1.26 + * that has significantly reduced lock contention.
1.27 + */
1.28 +
1.29 +#if !defined(TCL_THREADS) || !defined(USE_THREAD_ALLOC) || defined(TCL_MEM_DEBUG)
1.30 +
1.31 +#include "tclInt.h"
1.32 +#include "tclPort.h"
1.33 +
1.34 +#if USE_TCLALLOC
1.35 +
1.36 +#ifdef TCL_DEBUG
1.37 +# define DEBUG
1.38 +/* #define MSTATS */
1.39 +# define RCHECK
1.40 +#endif
1.41 +
1.42 +/*
1.43 + * We should really make use of AC_CHECK_TYPE(caddr_t)
1.44 + * here, but it can wait until Tcl uses config.h properly.
1.45 + */
1.46 +#if defined(MAC_TCL) || defined(_MSC_VER) || defined(__MINGW32__) || defined(__BORLANDC__)
1.47 +typedef unsigned long caddr_t;
1.48 +#endif
1.49 +
1.50 +/*
1.51 + * The overhead on a block is at least 8 bytes. When free, this space
1.52 + * contains a pointer to the next free block, and the bottom two bits must
1.53 + * be zero. When in use, the first byte is set to MAGIC, and the second
1.54 + * byte is the size index. The remaining bytes are for alignment.
1.55 + * If range checking is enabled then a second word holds the size of the
1.56 + * requested block, less 1, rounded up to a multiple of sizeof(RMAGIC).
1.57 + * The order of elements is critical: ov_magic must overlay the low order
1.58 + * bits of ov_next, and ov_magic can not be a valid ov_next bit pattern.
1.59 + */
1.60 +
1.61 +union overhead {
1.62 + union overhead *ov_next; /* when free */
1.63 + unsigned char ov_padding[8]; /* Ensure the structure is 8-byte aligned. */
1.64 + struct {
1.65 + unsigned char ovu_magic0; /* magic number */
1.66 + unsigned char ovu_index; /* bucket # */
1.67 + unsigned char ovu_unused; /* unused */
1.68 + unsigned char ovu_magic1; /* other magic number */
1.69 +#ifdef RCHECK
1.70 + unsigned short ovu_rmagic; /* range magic number */
1.71 + unsigned long ovu_size; /* actual block size */
1.72 + unsigned short ovu_unused2; /* padding to 8-byte align */
1.73 +#endif
1.74 + } ovu;
1.75 +#define ov_magic0 ovu.ovu_magic0
1.76 +#define ov_magic1 ovu.ovu_magic1
1.77 +#define ov_index ovu.ovu_index
1.78 +#define ov_rmagic ovu.ovu_rmagic
1.79 +#define ov_size ovu.ovu_size
1.80 +};
1.81 +
1.82 +
1.83 +#define MAGIC 0xef /* magic # on accounting info */
1.84 +#define RMAGIC 0x5555 /* magic # on range info */
1.85 +
1.86 +#ifdef RCHECK
1.87 +#define RSLOP sizeof (unsigned short)
1.88 +#else
1.89 +#define RSLOP 0
1.90 +#endif
1.91 +
1.92 +#define OVERHEAD (sizeof(union overhead) + RSLOP)
1.93 +
1.94 +/*
1.95 + * nextf[i] is the pointer to the next free block of size 2^(i+3). The
1.96 + * smallest allocatable block is 8 bytes. The overhead information
1.97 + * precedes the data area returned to the user.
1.98 + */
1.99 +
1.100 +#define NBUCKETS 13
1.101 +#define MAXMALLOC (1<<(NBUCKETS+2))
1.102 +static union overhead *nextf[NBUCKETS];
1.103 +
1.104 +/*
1.105 + * The following structure is used to keep track of all system memory
1.106 + * currently owned by Tcl. When finalizing, all this memory will
1.107 + * be returned to the system.
1.108 + */
1.109 +
1.110 +struct block {
1.111 + struct block *nextPtr; /* Linked list. */
1.112 + struct block *prevPtr; /* Linked list for big blocks, ensures 8-byte
1.113 + * alignment for suballocated blocks. */
1.114 +};
1.115 +
1.116 +static struct block *blockList; /* Tracks the suballocated blocks. */
1.117 +static struct block bigBlocks = { /* Big blocks aren't suballocated. */
1.118 + &bigBlocks, &bigBlocks
1.119 +};
1.120 +
1.121 +/*
1.122 + * The allocator is protected by a special mutex that must be
1.123 + * explicitly initialized. Futhermore, because Tcl_Alloc may be
1.124 + * used before anything else in Tcl, we make this module self-initializing
1.125 + * after all with the allocInit variable.
1.126 + */
1.127 +
1.128 +#ifdef TCL_THREADS
1.129 +static Tcl_Mutex *allocMutexPtr;
1.130 +#endif
1.131 +static int allocInit = 0;
1.132 +
1.133 +
1.134 +#ifdef MSTATS
1.135 +
1.136 +/*
1.137 + * nmalloc[i] is the difference between the number of mallocs and frees
1.138 + * for a given block size.
1.139 + */
1.140 +
1.141 +static unsigned int nmalloc[NBUCKETS+1];
1.142 +#include <stdio.h>
1.143 +#endif
1.144 +
1.145 +#if defined(DEBUG) || defined(RCHECK)
1.146 +#define ASSERT(p) if (!(p)) panic(# p)
1.147 +#define RANGE_ASSERT(p) if (!(p)) panic(# p)
1.148 +#else
1.149 +#define ASSERT(p)
1.150 +#define RANGE_ASSERT(p)
1.151 +#endif
1.152 +
1.153 +/*
1.154 + * Prototypes for functions used only in this file.
1.155 + */
1.156 +
1.157 +static void MoreCore _ANSI_ARGS_((int bucket));
1.158 +
1.159 +
1.160 +/*
1.161 + *-------------------------------------------------------------------------
1.162 + *
1.163 + * TclInitAlloc --
1.164 + *
1.165 + * Initialize the memory system.
1.166 + *
1.167 + * Results:
1.168 + * None.
1.169 + *
1.170 + * Side effects:
1.171 + * Initialize the mutex used to serialize allocations.
1.172 + *
1.173 + *-------------------------------------------------------------------------
1.174 + */
1.175 +
1.176 +void
1.177 +TclInitAlloc()
1.178 +{
1.179 + if (!allocInit) {
1.180 + allocInit = 1;
1.181 +#ifdef TCL_THREADS
1.182 + allocMutexPtr = Tcl_GetAllocMutex();
1.183 +#endif
1.184 + }
1.185 +}
1.186 +
1.187 +/*
1.188 + *-------------------------------------------------------------------------
1.189 + *
1.190 + * TclFinalizeAllocSubsystem --
1.191 + *
1.192 + * Release all resources being used by this subsystem, including
1.193 + * aggressively freeing all memory allocated by TclpAlloc() that
1.194 + * has not yet been released with TclpFree().
1.195 + *
1.196 + * After this function is called, all memory allocated with
1.197 + * TclpAlloc() should be considered unusable.
1.198 + *
1.199 + * Results:
1.200 + * None.
1.201 + *
1.202 + * Side effects:
1.203 + * This subsystem is self-initializing, since memory can be
1.204 + * allocated before Tcl is formally initialized. After this call,
1.205 + * this subsystem has been reset to its initial state and is
1.206 + * usable again.
1.207 + *
1.208 + *-------------------------------------------------------------------------
1.209 + */
1.210 +
1.211 +void
1.212 +TclFinalizeAllocSubsystem()
1.213 +{
1.214 + int i;
1.215 + struct block *blockPtr, *nextPtr;
1.216 +
1.217 + Tcl_MutexLock(allocMutexPtr);
1.218 + for (blockPtr = blockList; blockPtr != NULL; blockPtr = nextPtr) {
1.219 + nextPtr = blockPtr->nextPtr;
1.220 + TclpSysFree(blockPtr);
1.221 + }
1.222 + blockList = NULL;
1.223 +
1.224 + for (blockPtr = bigBlocks.nextPtr; blockPtr != &bigBlocks; ) {
1.225 + nextPtr = blockPtr->nextPtr;
1.226 + TclpSysFree(blockPtr);
1.227 + blockPtr = nextPtr;
1.228 + }
1.229 + bigBlocks.nextPtr = &bigBlocks;
1.230 + bigBlocks.prevPtr = &bigBlocks;
1.231 +
1.232 + for (i = 0; i < NBUCKETS; i++) {
1.233 + nextf[i] = NULL;
1.234 +#ifdef MSTATS
1.235 + nmalloc[i] = 0;
1.236 +#endif
1.237 + }
1.238 +#ifdef MSTATS
1.239 + nmalloc[i] = 0;
1.240 +#endif
1.241 + Tcl_MutexUnlock(allocMutexPtr);
1.242 +}
1.243 +
1.244 +/*
1.245 + *----------------------------------------------------------------------
1.246 + *
1.247 + * TclpAlloc --
1.248 + *
1.249 + * Allocate more memory.
1.250 + *
1.251 + * Results:
1.252 + * None.
1.253 + *
1.254 + * Side effects:
1.255 + * None.
1.256 + *
1.257 + *----------------------------------------------------------------------
1.258 + */
1.259 +
1.260 +char *
1.261 +TclpAlloc(nbytes)
1.262 + unsigned int nbytes; /* Number of bytes to allocate. */
1.263 +{
1.264 + register union overhead *op;
1.265 + register long bucket;
1.266 + register unsigned amt;
1.267 + struct block *bigBlockPtr;
1.268 +
1.269 + if (!allocInit) {
1.270 + /*
1.271 + * We have to make the "self initializing" because Tcl_Alloc
1.272 + * may be used before any other part of Tcl. E.g., see
1.273 + * main() for tclsh!
1.274 + */
1.275 + TclInitAlloc();
1.276 + }
1.277 + Tcl_MutexLock(allocMutexPtr);
1.278 + /*
1.279 + * First the simple case: we simple allocate big blocks directly
1.280 + */
1.281 + if (nbytes + OVERHEAD >= MAXMALLOC) {
1.282 + bigBlockPtr = (struct block *) TclpSysAlloc((unsigned)
1.283 + (sizeof(struct block) + OVERHEAD + nbytes), 0);
1.284 + if (bigBlockPtr == NULL) {
1.285 + Tcl_MutexUnlock(allocMutexPtr);
1.286 + return NULL;
1.287 + }
1.288 + bigBlockPtr->nextPtr = bigBlocks.nextPtr;
1.289 + bigBlocks.nextPtr = bigBlockPtr;
1.290 + bigBlockPtr->prevPtr = &bigBlocks;
1.291 + bigBlockPtr->nextPtr->prevPtr = bigBlockPtr;
1.292 +
1.293 + op = (union overhead *) (bigBlockPtr + 1);
1.294 + op->ov_magic0 = op->ov_magic1 = MAGIC;
1.295 + op->ov_index = 0xff;
1.296 +#ifdef MSTATS
1.297 + nmalloc[NBUCKETS]++;
1.298 +#endif
1.299 +#ifdef RCHECK
1.300 + /*
1.301 + * Record allocated size of block and
1.302 + * bound space with magic numbers.
1.303 + */
1.304 + op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1);
1.305 + op->ov_rmagic = RMAGIC;
1.306 + *(unsigned short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC;
1.307 +#endif
1.308 + Tcl_MutexUnlock(allocMutexPtr);
1.309 + return (void *)(op+1);
1.310 + }
1.311 + /*
1.312 + * Convert amount of memory requested into closest block size
1.313 + * stored in hash buckets which satisfies request.
1.314 + * Account for space used per block for accounting.
1.315 + */
1.316 +#ifndef RCHECK
1.317 + amt = 8; /* size of first bucket */
1.318 + bucket = 0;
1.319 +#else
1.320 + amt = 16; /* size of first bucket */
1.321 + bucket = 1;
1.322 +#endif
1.323 + while (nbytes + OVERHEAD > amt) {
1.324 + amt <<= 1;
1.325 + if (amt == 0) {
1.326 + Tcl_MutexUnlock(allocMutexPtr);
1.327 + return (NULL);
1.328 + }
1.329 + bucket++;
1.330 + }
1.331 + ASSERT( bucket < NBUCKETS );
1.332 +
1.333 + /*
1.334 + * If nothing in hash bucket right now,
1.335 + * request more memory from the system.
1.336 + */
1.337 + if ((op = nextf[bucket]) == NULL) {
1.338 + MoreCore(bucket);
1.339 + if ((op = nextf[bucket]) == NULL) {
1.340 + Tcl_MutexUnlock(allocMutexPtr);
1.341 + return (NULL);
1.342 + }
1.343 + }
1.344 + /*
1.345 + * Remove from linked list
1.346 + */
1.347 + nextf[bucket] = op->ov_next;
1.348 + op->ov_magic0 = op->ov_magic1 = MAGIC;
1.349 + op->ov_index = (unsigned char) bucket;
1.350 +#ifdef MSTATS
1.351 + nmalloc[bucket]++;
1.352 +#endif
1.353 +#ifdef RCHECK
1.354 + /*
1.355 + * Record allocated size of block and
1.356 + * bound space with magic numbers.
1.357 + */
1.358 + op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1);
1.359 + op->ov_rmagic = RMAGIC;
1.360 + *(unsigned short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC;
1.361 +#endif
1.362 + Tcl_MutexUnlock(allocMutexPtr);
1.363 + return ((char *)(op + 1));
1.364 +}
1.365 +
1.366 +/*
1.367 + *----------------------------------------------------------------------
1.368 + *
1.369 + * MoreCore --
1.370 + *
1.371 + * Allocate more memory to the indicated bucket.
1.372 + *
1.373 + * Assumes Mutex is already held.
1.374 + *
1.375 + * Results:
1.376 + * None.
1.377 + *
1.378 + * Side effects:
1.379 + * Attempts to get more memory from the system.
1.380 + *
1.381 + *----------------------------------------------------------------------
1.382 + */
1.383 +
1.384 +static void
1.385 +MoreCore(bucket)
1.386 + int bucket; /* What bucket to allocat to. */
1.387 +{
1.388 + register union overhead *op;
1.389 + register long sz; /* size of desired block */
1.390 + long amt; /* amount to allocate */
1.391 + int nblks; /* how many blocks we get */
1.392 + struct block *blockPtr;
1.393 +
1.394 + /*
1.395 + * sbrk_size <= 0 only for big, FLUFFY, requests (about
1.396 + * 2^30 bytes on a VAX, I think) or for a negative arg.
1.397 + */
1.398 + sz = 1 << (bucket + 3);
1.399 + ASSERT(sz > 0);
1.400 +
1.401 + amt = MAXMALLOC;
1.402 + nblks = amt / sz;
1.403 + ASSERT(nblks*sz == amt);
1.404 +
1.405 + blockPtr = (struct block *) TclpSysAlloc((unsigned)
1.406 + (sizeof(struct block) + amt), 1);
1.407 + /* no more room! */
1.408 + if (blockPtr == NULL) {
1.409 + return;
1.410 + }
1.411 + blockPtr->nextPtr = blockList;
1.412 + blockList = blockPtr;
1.413 +
1.414 + op = (union overhead *) (blockPtr + 1);
1.415 +
1.416 + /*
1.417 + * Add new memory allocated to that on
1.418 + * free list for this hash bucket.
1.419 + */
1.420 + nextf[bucket] = op;
1.421 + while (--nblks > 0) {
1.422 + op->ov_next = (union overhead *)((caddr_t)op + sz);
1.423 + op = (union overhead *)((caddr_t)op + sz);
1.424 + }
1.425 + op->ov_next = (union overhead *)NULL;
1.426 +}
1.427 +
1.428 +/*
1.429 + *----------------------------------------------------------------------
1.430 + *
1.431 + * TclpFree --
1.432 + *
1.433 + * Free memory.
1.434 + *
1.435 + * Results:
1.436 + * None.
1.437 + *
1.438 + * Side effects:
1.439 + * None.
1.440 + *
1.441 + *----------------------------------------------------------------------
1.442 + */
1.443 +
1.444 +void
1.445 +TclpFree(cp)
1.446 + char *cp; /* Pointer to memory to free. */
1.447 +{
1.448 + register long size;
1.449 + register union overhead *op;
1.450 + struct block *bigBlockPtr;
1.451 +
1.452 + if (cp == NULL) {
1.453 + return;
1.454 + }
1.455 +
1.456 + Tcl_MutexLock(allocMutexPtr);
1.457 + op = (union overhead *)((caddr_t)cp - sizeof (union overhead));
1.458 +
1.459 + ASSERT(op->ov_magic0 == MAGIC); /* make sure it was in use */
1.460 + ASSERT(op->ov_magic1 == MAGIC);
1.461 + if (op->ov_magic0 != MAGIC || op->ov_magic1 != MAGIC) {
1.462 + Tcl_MutexUnlock(allocMutexPtr);
1.463 + return;
1.464 + }
1.465 +
1.466 + RANGE_ASSERT(op->ov_rmagic == RMAGIC);
1.467 + RANGE_ASSERT(*(unsigned short *)((caddr_t)(op + 1) + op->ov_size) == RMAGIC);
1.468 + size = op->ov_index;
1.469 + if ( size == 0xff ) {
1.470 +#ifdef MSTATS
1.471 + nmalloc[NBUCKETS]--;
1.472 +#endif
1.473 + bigBlockPtr = (struct block *) op - 1;
1.474 + bigBlockPtr->prevPtr->nextPtr = bigBlockPtr->nextPtr;
1.475 + bigBlockPtr->nextPtr->prevPtr = bigBlockPtr->prevPtr;
1.476 + TclpSysFree(bigBlockPtr);
1.477 + Tcl_MutexUnlock(allocMutexPtr);
1.478 + return;
1.479 + }
1.480 + ASSERT(size < NBUCKETS);
1.481 + op->ov_next = nextf[size]; /* also clobbers ov_magic */
1.482 + nextf[size] = op;
1.483 +#ifdef MSTATS
1.484 + nmalloc[size]--;
1.485 +#endif
1.486 + Tcl_MutexUnlock(allocMutexPtr);
1.487 +}
1.488 +
1.489 +/*
1.490 + *----------------------------------------------------------------------
1.491 + *
1.492 + * TclpRealloc --
1.493 + *
1.494 + * Reallocate memory.
1.495 + *
1.496 + * Results:
1.497 + * None.
1.498 + *
1.499 + * Side effects:
1.500 + * None.
1.501 + *
1.502 + *----------------------------------------------------------------------
1.503 + */
1.504 +
1.505 +char *
1.506 +TclpRealloc(cp, nbytes)
1.507 + char *cp; /* Pointer to alloced block. */
1.508 + unsigned int nbytes; /* New size of memory. */
1.509 +{
1.510 + int i;
1.511 + union overhead *op;
1.512 + struct block *bigBlockPtr;
1.513 + int expensive;
1.514 + unsigned long maxsize;
1.515 +
1.516 + if (cp == NULL) {
1.517 + return (TclpAlloc(nbytes));
1.518 + }
1.519 +
1.520 + Tcl_MutexLock(allocMutexPtr);
1.521 +
1.522 + op = (union overhead *)((caddr_t)cp - sizeof (union overhead));
1.523 +
1.524 + ASSERT(op->ov_magic0 == MAGIC); /* make sure it was in use */
1.525 + ASSERT(op->ov_magic1 == MAGIC);
1.526 + if (op->ov_magic0 != MAGIC || op->ov_magic1 != MAGIC) {
1.527 + Tcl_MutexUnlock(allocMutexPtr);
1.528 + return NULL;
1.529 + }
1.530 +
1.531 + RANGE_ASSERT(op->ov_rmagic == RMAGIC);
1.532 + RANGE_ASSERT(*(unsigned short *)((caddr_t)(op + 1) + op->ov_size) == RMAGIC);
1.533 + i = op->ov_index;
1.534 +
1.535 + /*
1.536 + * If the block isn't in a bin, just realloc it.
1.537 + */
1.538 +
1.539 + if (i == 0xff) {
1.540 + struct block *prevPtr, *nextPtr;
1.541 + bigBlockPtr = (struct block *) op - 1;
1.542 + prevPtr = bigBlockPtr->prevPtr;
1.543 + nextPtr = bigBlockPtr->nextPtr;
1.544 + bigBlockPtr = (struct block *) TclpSysRealloc(bigBlockPtr,
1.545 + sizeof(struct block) + OVERHEAD + nbytes);
1.546 + if (bigBlockPtr == NULL) {
1.547 + Tcl_MutexUnlock(allocMutexPtr);
1.548 + return NULL;
1.549 + }
1.550 +
1.551 + if (prevPtr->nextPtr != bigBlockPtr) {
1.552 + /*
1.553 + * If the block has moved, splice the new block into the list where
1.554 + * the old block used to be.
1.555 + */
1.556 +
1.557 + prevPtr->nextPtr = bigBlockPtr;
1.558 + nextPtr->prevPtr = bigBlockPtr;
1.559 + }
1.560 +
1.561 + op = (union overhead *) (bigBlockPtr + 1);
1.562 +#ifdef MSTATS
1.563 + nmalloc[NBUCKETS]++;
1.564 +#endif
1.565 +#ifdef RCHECK
1.566 + /*
1.567 + * Record allocated size of block and update magic number bounds.
1.568 + */
1.569 +
1.570 + op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1);
1.571 + *(unsigned short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC;
1.572 +#endif
1.573 + Tcl_MutexUnlock(allocMutexPtr);
1.574 + return (char *)(op+1);
1.575 + }
1.576 + maxsize = 1 << (i+3);
1.577 + expensive = 0;
1.578 + if ( nbytes + OVERHEAD > maxsize ) {
1.579 + expensive = 1;
1.580 + } else if ( i > 0 && nbytes + OVERHEAD < (maxsize/2) ) {
1.581 + expensive = 1;
1.582 + }
1.583 +
1.584 + if (expensive) {
1.585 + void *newp;
1.586 +
1.587 + Tcl_MutexUnlock(allocMutexPtr);
1.588 +
1.589 + newp = TclpAlloc(nbytes);
1.590 + if ( newp == NULL ) {
1.591 + return NULL;
1.592 + }
1.593 + maxsize -= OVERHEAD;
1.594 + if ( maxsize < nbytes )
1.595 + nbytes = maxsize;
1.596 + memcpy((VOID *) newp, (VOID *) cp, (size_t) nbytes);
1.597 + TclpFree(cp);
1.598 + return newp;
1.599 + }
1.600 +
1.601 + /*
1.602 + * Ok, we don't have to copy, it fits as-is
1.603 + */
1.604 +#ifdef RCHECK
1.605 + op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1);
1.606 + *(unsigned short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC;
1.607 +#endif
1.608 + Tcl_MutexUnlock(allocMutexPtr);
1.609 + return(cp);
1.610 +}
1.611 +
1.612 +/*
1.613 + *----------------------------------------------------------------------
1.614 + *
1.615 + * mstats --
1.616 + *
1.617 + * Prints two lines of numbers, one showing the length of the
1.618 + * free list for each size category, the second showing the
1.619 + * number of mallocs - frees for each size category.
1.620 + *
1.621 + * Results:
1.622 + * None.
1.623 + *
1.624 + * Side effects:
1.625 + * None.
1.626 + *
1.627 + *----------------------------------------------------------------------
1.628 + */
1.629 +
1.630 +#ifdef MSTATS
1.631 +void
1.632 +mstats(s)
1.633 + char *s; /* Where to write info. */
1.634 +{
1.635 + register int i, j;
1.636 + register union overhead *p;
1.637 + int totfree = 0,
1.638 + totused = 0;
1.639 +
1.640 + Tcl_MutexLock(allocMutexPtr);
1.641 + fprintf(stderr, "Memory allocation statistics %s\nTclpFree:\t", s);
1.642 + for (i = 0; i < NBUCKETS; i++) {
1.643 + for (j = 0, p = nextf[i]; p; p = p->ov_next, j++)
1.644 + fprintf(stderr, " %d", j);
1.645 + totfree += j * (1 << (i + 3));
1.646 + }
1.647 + fprintf(stderr, "\nused:\t");
1.648 + for (i = 0; i < NBUCKETS; i++) {
1.649 + fprintf(stderr, " %d", nmalloc[i]);
1.650 + totused += nmalloc[i] * (1 << (i + 3));
1.651 + }
1.652 + fprintf(stderr, "\n\tTotal small in use: %d, total free: %d\n",
1.653 + totused, totfree);
1.654 + fprintf(stderr, "\n\tNumber of big (>%d) blocks in use: %d\n",
1.655 + MAXMALLOC, nmalloc[NBUCKETS]);
1.656 + Tcl_MutexUnlock(allocMutexPtr);
1.657 +}
1.658 +#endif
1.659 +
1.660 +#else /* !USE_TCLALLOC */
1.661 +
1.662 +/*
1.663 + *----------------------------------------------------------------------
1.664 + *
1.665 + * TclpAlloc --
1.666 + *
1.667 + * Allocate more memory.
1.668 + *
1.669 + * Results:
1.670 + * None.
1.671 + *
1.672 + * Side effects:
1.673 + * None.
1.674 + *
1.675 + *----------------------------------------------------------------------
1.676 + */
1.677 +
1.678 +char *
1.679 +TclpAlloc(nbytes)
1.680 + unsigned int nbytes; /* Number of bytes to allocate. */
1.681 +{
1.682 + return (char*) malloc(nbytes);
1.683 +}
1.684 +
1.685 +/*
1.686 + *----------------------------------------------------------------------
1.687 + *
1.688 + * TclpFree --
1.689 + *
1.690 + * Free memory.
1.691 + *
1.692 + * Results:
1.693 + * None.
1.694 + *
1.695 + * Side effects:
1.696 + * None.
1.697 + *
1.698 + *----------------------------------------------------------------------
1.699 + */
1.700 +
1.701 +void
1.702 +TclpFree(cp)
1.703 + char *cp; /* Pointer to memory to free. */
1.704 +{
1.705 + free(cp);
1.706 + return;
1.707 +}
1.708 +
1.709 +/*
1.710 + *----------------------------------------------------------------------
1.711 + *
1.712 + * TclpRealloc --
1.713 + *
1.714 + * Reallocate memory.
1.715 + *
1.716 + * Results:
1.717 + * None.
1.718 + *
1.719 + * Side effects:
1.720 + * None.
1.721 + *
1.722 + *----------------------------------------------------------------------
1.723 + */
1.724 +
1.725 +char *
1.726 +TclpRealloc(cp, nbytes)
1.727 + char *cp; /* Pointer to alloced block. */
1.728 + unsigned int nbytes; /* New size of memory. */
1.729 +{
1.730 + return (char*) realloc(cp, nbytes);
1.731 +}
1.732 +
1.733 +#endif /* !USE_TCLALLOC */
1.734 +#endif /* !TCL_THREADS */