tclAlloc.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:17k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /* 
  2.  * tclAlloc.c --
  3.  *
  4.  * This is a very fast storage allocator.  It allocates blocks of a
  5.  * small number of different sizes, and keeps free lists of each size.
  6.  * Blocks that don't exactly fit are passed up to the next larger size.
  7.  * Blocks over a certain size are directly allocated from the system.
  8.  *
  9.  * Copyright (c) 1983 Regents of the University of California.
  10.  * Copyright (c) 1996-1997 Sun Microsystems, Inc.
  11.  * Copyright (c) 1998-1999 by Scriptics Corporation.
  12.  *
  13.  * Portions contributed by Chris Kingsley, Jack Jansen and Ray Johnson.
  14.  *
  15.  * See the file "license.terms" for information on usage and redistribution
  16.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  17.  *
  18.  * RCS: @(#) $Id: tclAlloc.c,v 1.16.2.3 2007/09/22 15:46:45 das Exp $
  19.  */
  20. /*
  21.  * Windows and Unix use an alternative allocator when building with threads
  22.  * that has significantly reduced lock contention.
  23.  */
  24. #if !defined(TCL_THREADS) || !defined(USE_THREAD_ALLOC) || defined(TCL_MEM_DEBUG)
  25. #include "tclInt.h"
  26. #include "tclPort.h"
  27. #if USE_TCLALLOC
  28. #ifdef TCL_DEBUG
  29. #   define DEBUG
  30. /* #define MSTATS */
  31. #   define RCHECK
  32. #endif
  33. /*
  34.  * We should really make use of AC_CHECK_TYPE(caddr_t)
  35.  * here, but it can wait until Tcl uses config.h properly.
  36.  */
  37. #if defined(MAC_TCL) || defined(_MSC_VER) || defined(__MINGW32__) || defined(__BORLANDC__)
  38. typedef unsigned long caddr_t;
  39. #endif
  40. /*
  41.  * Alignment for allocated memory.
  42.  */
  43. #if defined(__APPLE__)
  44. #define ALLOCALIGN 16
  45. #else
  46. #define ALLOCALIGN 8
  47. #endif
  48. /*
  49.  * The overhead on a block is at least 8 bytes.  When free, this space
  50.  * contains a pointer to the next free block, and the bottom two bits must
  51.  * be zero.  When in use, the first byte is set to MAGIC, and the second
  52.  * byte is the size index.  The remaining bytes are for alignment.
  53.  * If range checking is enabled then a second word holds the size of the
  54.  * requested block, less 1, rounded up to a multiple of sizeof(RMAGIC).
  55.  * The order of elements is critical: ov_magic must overlay the low order
  56.  * bits of ov_next, and ov_magic can not be a valid ov_next bit pattern.
  57.  */
  58. union overhead {
  59.     union overhead *ov_next; /* when free */
  60.     unsigned char ov_padding[ALLOCALIGN];/* align struct to ALLOCALIGN bytes */
  61.     struct {
  62. unsigned char ovu_magic0; /* magic number */
  63. unsigned char ovu_index; /* bucket # */
  64. unsigned char ovu_unused; /* unused */
  65. unsigned char ovu_magic1; /* other magic number */
  66. #ifdef RCHECK
  67. unsigned short ovu_rmagic; /* range magic number */
  68. unsigned long ovu_size; /* actual block size */
  69. unsigned short  ovu_unused2;    /* padding to 8-byte align */
  70. #endif
  71.     } ovu;
  72. #define ov_magic0 ovu.ovu_magic0
  73. #define ov_magic1 ovu.ovu_magic1
  74. #define ov_index ovu.ovu_index
  75. #define ov_rmagic ovu.ovu_rmagic
  76. #define ov_size ovu.ovu_size
  77. };
  78. #define MAGIC 0xef /* magic # on accounting info */
  79. #define RMAGIC 0x5555 /* magic # on range info */
  80. #ifdef RCHECK
  81. #define RSLOP sizeof (unsigned short)
  82. #else
  83. #define RSLOP 0
  84. #endif
  85. #define OVERHEAD (sizeof(union overhead) + RSLOP)
  86. /*
  87.  * nextf[i] is the pointer to the next free block of size 2^(i+3).  The
  88.  * smallest allocatable block is MINBLOCK bytes. The overhead information
  89.  * precedes the data area returned to the user.
  90.  */
  91. #define MINBLOCK ((sizeof(union overhead) + (ALLOCALIGN-1)) & ~(ALLOCALIGN-1))
  92. #define NBUCKETS (13 - (MINBLOCK >> 4))
  93. #define MAXMALLOC (1<<(NBUCKETS+2))
  94. static union overhead *nextf[NBUCKETS];
  95. /* 
  96.  * The following structure is used to keep track of all system memory 
  97.  * currently owned by Tcl.  When finalizing, all this memory will
  98.  * be returned to the system.
  99.  */
  100. struct block {
  101.     struct block *nextPtr; /* Linked list. */
  102.     struct block *prevPtr; /* Linked list for big blocks, ensures 8-byte 
  103.  * alignment for suballocated blocks. */
  104. };
  105. static struct block *blockList; /* Tracks the suballocated blocks. */
  106. static struct block bigBlocks = { /* Big blocks aren't suballocated. */
  107.     &bigBlocks, &bigBlocks
  108. };
  109. /*
  110.  * The allocator is protected by a special mutex that must be
  111.  * explicitly initialized.  Futhermore, because Tcl_Alloc may be
  112.  * used before anything else in Tcl, we make this module self-initializing
  113.  * after all with the allocInit variable.
  114.  */
  115. #ifdef TCL_THREADS
  116. static Tcl_Mutex *allocMutexPtr;
  117. #endif
  118. static int allocInit = 0;
  119. #ifdef MSTATS
  120. /*
  121.  * nmalloc[i] is the difference between the number of mallocs and frees
  122.  * for a given block size.
  123.  */
  124. static unsigned int nmalloc[NBUCKETS+1];
  125. #include <stdio.h>
  126. #endif
  127. #if defined(DEBUG) || defined(RCHECK)
  128. #define ASSERT(p)   if (!(p)) panic(# p)
  129. #define RANGE_ASSERT(p) if (!(p)) panic(# p)
  130. #else
  131. #define ASSERT(p)
  132. #define RANGE_ASSERT(p)
  133. #endif
  134. /*
  135.  * Prototypes for functions used only in this file.
  136.  */
  137. static void  MoreCore _ANSI_ARGS_((int bucket));
  138. /*
  139.  *-------------------------------------------------------------------------
  140.  *
  141.  * TclInitAlloc --
  142.  *
  143.  * Initialize the memory system.
  144.  *
  145.  * Results:
  146.  * None.
  147.  *
  148.  * Side effects:
  149.  * Initialize the mutex used to serialize allocations.
  150.  *
  151.  *-------------------------------------------------------------------------
  152.  */
  153. void
  154. TclInitAlloc()
  155. {
  156.     if (!allocInit) {
  157. allocInit = 1;
  158. #ifdef TCL_THREADS
  159. allocMutexPtr = Tcl_GetAllocMutex();
  160. #endif
  161.     }
  162. }
  163. /*
  164.  *-------------------------------------------------------------------------
  165.  *
  166.  * TclFinalizeAllocSubsystem --
  167.  *
  168.  * Release all resources being used by this subsystem, including 
  169.  * aggressively freeing all memory allocated by TclpAlloc() that 
  170.  * has not yet been released with TclpFree().
  171.  *
  172.  * After this function is called, all memory allocated with 
  173.  * TclpAlloc() should be considered unusable.
  174.  *
  175.  * Results:
  176.  * None.
  177.  *
  178.  * Side effects:
  179.  * This subsystem is self-initializing, since memory can be 
  180.  * allocated before Tcl is formally initialized.  After this call,
  181.  * this subsystem has been reset to its initial state and is 
  182.  * usable again.
  183.  *
  184.  *-------------------------------------------------------------------------
  185.  */
  186. void
  187. TclFinalizeAllocSubsystem()
  188. {
  189.     unsigned int i;
  190.     struct block *blockPtr, *nextPtr;
  191.     Tcl_MutexLock(allocMutexPtr);
  192.     for (blockPtr = blockList; blockPtr != NULL; blockPtr = nextPtr) {
  193. nextPtr = blockPtr->nextPtr;
  194. TclpSysFree(blockPtr);
  195.     }
  196.     blockList = NULL;
  197.     for (blockPtr = bigBlocks.nextPtr; blockPtr != &bigBlocks; ) {
  198. nextPtr = blockPtr->nextPtr;
  199. TclpSysFree(blockPtr);
  200. blockPtr = nextPtr;
  201.     }
  202.     bigBlocks.nextPtr = &bigBlocks;
  203.     bigBlocks.prevPtr = &bigBlocks;
  204.     for (i = 0; i < NBUCKETS; i++) {
  205. nextf[i] = NULL;
  206. #ifdef MSTATS
  207. nmalloc[i] = 0;
  208. #endif
  209.     }
  210. #ifdef MSTATS
  211.     nmalloc[i] = 0;
  212. #endif
  213.     Tcl_MutexUnlock(allocMutexPtr);
  214. }
  215. /*
  216.  *----------------------------------------------------------------------
  217.  *
  218.  * TclpAlloc --
  219.  *
  220.  * Allocate more memory.
  221.  *
  222.  * Results:
  223.  * None.
  224.  *
  225.  * Side effects:
  226.  * None.
  227.  *
  228.  *----------------------------------------------------------------------
  229.  */
  230. char *
  231. TclpAlloc(nbytes)
  232.     unsigned int nbytes; /* Number of bytes to allocate. */
  233. {
  234.     register union overhead *op;
  235.     register long bucket;
  236.     register unsigned amt;
  237.     struct block *bigBlockPtr;
  238.     if (!allocInit) {
  239. /*
  240.  * We have to make the "self initializing" because Tcl_Alloc
  241.  * may be used before any other part of Tcl.  E.g., see
  242.  * main() for tclsh!
  243.  */
  244. TclInitAlloc();
  245.     }
  246.     Tcl_MutexLock(allocMutexPtr);
  247.     /*
  248.      * First the simple case: we simple allocate big blocks directly
  249.      */
  250.     if (nbytes + OVERHEAD >= MAXMALLOC) {
  251. bigBlockPtr = (struct block *) TclpSysAlloc((unsigned) 
  252. (sizeof(struct block) + OVERHEAD + nbytes), 0);
  253. if (bigBlockPtr == NULL) {
  254.     Tcl_MutexUnlock(allocMutexPtr);
  255.     return NULL;
  256. }
  257. bigBlockPtr->nextPtr = bigBlocks.nextPtr;
  258. bigBlocks.nextPtr = bigBlockPtr;
  259. bigBlockPtr->prevPtr = &bigBlocks;
  260. bigBlockPtr->nextPtr->prevPtr = bigBlockPtr;
  261. op = (union overhead *) (bigBlockPtr + 1);
  262. op->ov_magic0 = op->ov_magic1 = MAGIC;
  263. op->ov_index = 0xff;
  264. #ifdef MSTATS
  265. nmalloc[NBUCKETS]++;
  266. #endif
  267. #ifdef RCHECK
  268. /*
  269.  * Record allocated size of block and
  270.  * bound space with magic numbers.
  271.  */
  272. op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1);
  273. op->ov_rmagic = RMAGIC;
  274. *(unsigned short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC;
  275. #endif
  276. Tcl_MutexUnlock(allocMutexPtr);
  277. return (void *)(op+1);
  278.     }
  279.     /*
  280.      * Convert amount of memory requested into closest block size
  281.      * stored in hash buckets which satisfies request.
  282.      * Account for space used per block for accounting.
  283.      */
  284.     amt = MINBLOCK; /* size of first bucket */
  285.     bucket = MINBLOCK >> 4;
  286.     while (nbytes + OVERHEAD > amt) {
  287. amt <<= 1;
  288. if (amt == 0) {
  289.     Tcl_MutexUnlock(allocMutexPtr);
  290.     return (NULL);
  291. }
  292. bucket++;
  293.     }
  294.     ASSERT( bucket < NBUCKETS );
  295.     /*
  296.      * If nothing in hash bucket right now,
  297.      * request more memory from the system.
  298.      */
  299.     if ((op = nextf[bucket]) == NULL) {
  300. MoreCore(bucket);
  301. if ((op = nextf[bucket]) == NULL) {
  302.     Tcl_MutexUnlock(allocMutexPtr);
  303.     return (NULL);
  304. }
  305.     }
  306.     /*
  307.      * Remove from linked list
  308.      */
  309.     nextf[bucket] = op->ov_next;
  310.     op->ov_magic0 = op->ov_magic1 = MAGIC;
  311.     op->ov_index = (unsigned char) bucket;
  312. #ifdef MSTATS
  313.     nmalloc[bucket]++;
  314. #endif
  315. #ifdef RCHECK
  316.     /*
  317.      * Record allocated size of block and
  318.      * bound space with magic numbers.
  319.      */
  320.     op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1);
  321.     op->ov_rmagic = RMAGIC;
  322.     *(unsigned short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC;
  323. #endif
  324.     Tcl_MutexUnlock(allocMutexPtr);
  325.     return ((char *)(op + 1));
  326. }
  327. /*
  328.  *----------------------------------------------------------------------
  329.  *
  330.  * MoreCore --
  331.  *
  332.  * Allocate more memory to the indicated bucket.
  333.  *
  334.  * Assumes Mutex is already held.
  335.  *
  336.  * Results:
  337.  * None.
  338.  *
  339.  * Side effects:
  340.  * Attempts to get more memory from the system.
  341.  *
  342.  *----------------------------------------------------------------------
  343.  */
  344. static void
  345. MoreCore(bucket)
  346.     int bucket; /* What bucket to allocat to. */
  347. {
  348.     register union overhead *op;
  349.     register long sz; /* size of desired block */
  350.     long amt; /* amount to allocate */
  351.     int nblks; /* how many blocks we get */
  352.     struct block *blockPtr;
  353.     /*
  354.      * sbrk_size <= 0 only for big, FLUFFY, requests (about
  355.      * 2^30 bytes on a VAX, I think) or for a negative arg.
  356.      */
  357.     sz = 1 << (bucket + 3);
  358.     ASSERT(sz > 0);
  359.     amt = MAXMALLOC;
  360.     nblks = amt / sz;
  361.     ASSERT(nblks*sz == amt);
  362.     blockPtr = (struct block *) TclpSysAlloc((unsigned) 
  363.     (sizeof(struct block) + amt), 1);
  364.     /* no more room! */
  365.     if (blockPtr == NULL) {
  366. return;
  367.     }
  368.     blockPtr->nextPtr = blockList;
  369.     blockList = blockPtr;
  370.     op = (union overhead *) (blockPtr + 1);
  371.     
  372.     /*
  373.      * Add new memory allocated to that on
  374.      * free list for this hash bucket.
  375.      */
  376.     nextf[bucket] = op;
  377.     while (--nblks > 0) {
  378. op->ov_next = (union overhead *)((caddr_t)op + sz);
  379. op = (union overhead *)((caddr_t)op + sz);
  380.     }
  381.     op->ov_next = (union overhead *)NULL;
  382. }
  383. /*
  384.  *----------------------------------------------------------------------
  385.  *
  386.  * TclpFree --
  387.  *
  388.  * Free memory.
  389.  *
  390.  * Results:
  391.  * None.
  392.  *
  393.  * Side effects:
  394.  * None.
  395.  *
  396.  *----------------------------------------------------------------------
  397.  */
  398. void
  399. TclpFree(cp)
  400.     char *cp; /* Pointer to memory to free. */
  401. {   
  402.     register long size;
  403.     register union overhead *op;
  404.     struct block *bigBlockPtr;
  405.     if (cp == NULL) {
  406. return;
  407.     }
  408.     Tcl_MutexLock(allocMutexPtr);
  409.     op = (union overhead *)((caddr_t)cp - sizeof (union overhead));
  410.     ASSERT(op->ov_magic0 == MAGIC); /* make sure it was in use */
  411.     ASSERT(op->ov_magic1 == MAGIC);
  412.     if (op->ov_magic0 != MAGIC || op->ov_magic1 != MAGIC) {
  413. Tcl_MutexUnlock(allocMutexPtr);
  414. return;
  415.     }
  416.     RANGE_ASSERT(op->ov_rmagic == RMAGIC);
  417.     RANGE_ASSERT(*(unsigned short *)((caddr_t)(op + 1) + op->ov_size) == RMAGIC);
  418.     size = op->ov_index;
  419.     if ( size == 0xff ) {
  420. #ifdef MSTATS
  421. nmalloc[NBUCKETS]--;
  422. #endif
  423. bigBlockPtr = (struct block *) op - 1;
  424. bigBlockPtr->prevPtr->nextPtr = bigBlockPtr->nextPtr;
  425. bigBlockPtr->nextPtr->prevPtr = bigBlockPtr->prevPtr;
  426. TclpSysFree(bigBlockPtr);
  427. Tcl_MutexUnlock(allocMutexPtr);
  428. return;
  429.     }
  430.     ASSERT(size < NBUCKETS);
  431.     op->ov_next = nextf[size]; /* also clobbers ov_magic */
  432.     nextf[size] = op;
  433. #ifdef MSTATS
  434.     nmalloc[size]--;
  435. #endif
  436.     Tcl_MutexUnlock(allocMutexPtr);
  437. }
  438. /*
  439.  *----------------------------------------------------------------------
  440.  *
  441.  * TclpRealloc --
  442.  *
  443.  * Reallocate memory.
  444.  *
  445.  * Results:
  446.  * None.
  447.  *
  448.  * Side effects:
  449.  * None.
  450.  *
  451.  *----------------------------------------------------------------------
  452.  */
  453. char *
  454. TclpRealloc(cp, nbytes)
  455.     char *cp; /* Pointer to alloced block. */
  456.     unsigned int nbytes; /* New size of memory. */
  457. {   
  458.     int i;
  459.     union overhead *op;
  460.     struct block *bigBlockPtr;
  461.     int expensive;
  462.     unsigned long maxsize;
  463.     if (cp == NULL) {
  464. return (TclpAlloc(nbytes));
  465.     }
  466.     Tcl_MutexLock(allocMutexPtr);
  467.     op = (union overhead *)((caddr_t)cp - sizeof (union overhead));
  468.     ASSERT(op->ov_magic0 == MAGIC); /* make sure it was in use */
  469.     ASSERT(op->ov_magic1 == MAGIC);
  470.     if (op->ov_magic0 != MAGIC || op->ov_magic1 != MAGIC) {
  471. Tcl_MutexUnlock(allocMutexPtr);
  472. return NULL;
  473.     }
  474.     RANGE_ASSERT(op->ov_rmagic == RMAGIC);
  475.     RANGE_ASSERT(*(unsigned short *)((caddr_t)(op + 1) + op->ov_size) == RMAGIC);
  476.     i = op->ov_index;
  477.     /*
  478.      * If the block isn't in a bin, just realloc it.
  479.      */
  480.     if (i == 0xff) {
  481. struct block *prevPtr, *nextPtr;
  482. bigBlockPtr = (struct block *) op - 1;
  483. prevPtr = bigBlockPtr->prevPtr;
  484. nextPtr = bigBlockPtr->nextPtr;
  485. bigBlockPtr = (struct block *) TclpSysRealloc(bigBlockPtr, 
  486. sizeof(struct block) + OVERHEAD + nbytes);
  487. if (bigBlockPtr == NULL) {
  488.     Tcl_MutexUnlock(allocMutexPtr);
  489.     return NULL;
  490. }
  491. if (prevPtr->nextPtr != bigBlockPtr) {
  492.     /*
  493.      * If the block has moved, splice the new block into the list where
  494.      * the old block used to be. 
  495.      */
  496.     prevPtr->nextPtr = bigBlockPtr;
  497.     nextPtr->prevPtr = bigBlockPtr;
  498. }
  499. op = (union overhead *) (bigBlockPtr + 1);
  500. #ifdef MSTATS
  501. nmalloc[NBUCKETS]++;
  502. #endif
  503. #ifdef RCHECK
  504. /*
  505.  * Record allocated size of block and update magic number bounds.
  506.  */
  507. op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1);
  508. *(unsigned short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC;
  509. #endif
  510. Tcl_MutexUnlock(allocMutexPtr);
  511. return (char *)(op+1);
  512.     }
  513.     maxsize = 1 << (i+3);
  514.     expensive = 0;
  515.     if ( nbytes + OVERHEAD > maxsize ) {
  516. expensive = 1;
  517.     } else if ( i > 0 && nbytes + OVERHEAD < (maxsize/2) ) {
  518. expensive = 1;
  519.     }
  520.     if (expensive) {
  521. void *newp;
  522. Tcl_MutexUnlock(allocMutexPtr);
  523. newp = TclpAlloc(nbytes);
  524. if ( newp == NULL ) {
  525.     return NULL;
  526. }
  527. maxsize -= OVERHEAD;
  528. if ( maxsize < nbytes )
  529.     nbytes = maxsize;
  530. memcpy((VOID *) newp, (VOID *) cp, (size_t) nbytes);
  531. TclpFree(cp);
  532. return newp;
  533.     }
  534.     
  535.     /*
  536.      * Ok, we don't have to copy, it fits as-is
  537.      */
  538. #ifdef RCHECK
  539.     op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1);
  540.     *(unsigned short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC;
  541. #endif
  542.     Tcl_MutexUnlock(allocMutexPtr);
  543.     return(cp);
  544. }
  545. /*
  546.  *----------------------------------------------------------------------
  547.  *
  548.  * mstats --
  549.  *
  550.  * Prints two lines of numbers, one showing the length of the 
  551.  * free list for each size category, the second showing the 
  552.  * number of mallocs - frees for each size category.
  553.  *
  554.  * Results:
  555.  * None.
  556.  *
  557.  * Side effects:
  558.  * None.
  559.  *
  560.  *----------------------------------------------------------------------
  561.  */
  562. #ifdef MSTATS
  563. void
  564. mstats(s)
  565.     char *s; /* Where to write info. */
  566. {
  567.     register int i, j;
  568.     register union overhead *p;
  569.     int totfree = 0,
  570. totused = 0;
  571.     Tcl_MutexLock(allocMutexPtr);
  572.     fprintf(stderr, "Memory allocation statistics %snTclpFree:t", s);
  573.     for (i = 0; i < NBUCKETS; i++) {
  574. for (j = 0, p = nextf[i]; p; p = p->ov_next, j++)
  575.     fprintf(stderr, " %d", j);
  576. totfree += j * (1 << (i + 3));
  577.     }
  578.     fprintf(stderr, "nused:t");
  579.     for (i = 0; i < NBUCKETS; i++) {
  580. fprintf(stderr, " %d", nmalloc[i]);
  581. totused += nmalloc[i] * (1 << (i + 3));
  582.     }
  583.     fprintf(stderr, "ntTotal small in use: %d, total free: %dn",
  584.     totused, totfree);
  585.     fprintf(stderr, "ntNumber of big (>%d) blocks in use: %dn", 
  586.     MAXMALLOC, nmalloc[NBUCKETS]);
  587.     Tcl_MutexUnlock(allocMutexPtr);
  588. }
  589. #endif
  590. #else  /* !USE_TCLALLOC */
  591. /*
  592.  *----------------------------------------------------------------------
  593.  *
  594.  * TclpAlloc --
  595.  *
  596.  * Allocate more memory.
  597.  *
  598.  * Results:
  599.  * None.
  600.  *
  601.  * Side effects:
  602.  * None.
  603.  *
  604.  *----------------------------------------------------------------------
  605.  */
  606. char *
  607. TclpAlloc(nbytes)
  608.     unsigned int nbytes; /* Number of bytes to allocate. */
  609. {
  610.     return (char*) malloc(nbytes);
  611. }
  612. /*
  613.  *----------------------------------------------------------------------
  614.  *
  615.  * TclpFree --
  616.  *
  617.  * Free memory.
  618.  *
  619.  * Results:
  620.  * None.
  621.  *
  622.  * Side effects:
  623.  * None.
  624.  *
  625.  *----------------------------------------------------------------------
  626.  */
  627. void
  628. TclpFree(cp)
  629.     char *cp; /* Pointer to memory to free. */
  630. {   
  631.     free(cp);
  632.     return;
  633. }
  634. /*
  635.  *----------------------------------------------------------------------
  636.  *
  637.  * TclpRealloc --
  638.  *
  639.  * Reallocate memory.
  640.  *
  641.  * Results:
  642.  * None.
  643.  *
  644.  * Side effects:
  645.  * None.
  646.  *
  647.  *----------------------------------------------------------------------
  648.  */
  649. char *
  650. TclpRealloc(cp, nbytes)
  651.     char *cp; /* Pointer to alloced block. */
  652.     unsigned int nbytes; /* New size of memory. */
  653. {   
  654.     return (char*) realloc(cp, nbytes);
  655. }
  656. #endif /* !USE_TCLALLOC */
  657. #endif /* !TCL_THREADS */