malloc.c
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:10k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* ==== malloc.c ============================================================
  2.  * Copyright (c) 1983 Regents of the University of California.
  3.  * Copyright (c) 1993, 1994 by Chris Provenzano, proven@mit.edu
  4.  * All rights reserved.
  5.  *
  6.  * Redistribution and use in source and binary forms, with or without
  7.  * modification, are permitted provided that the following conditions
  8.  * are met:
  9.  * 1. Redistributions of source code must retain the above copyright
  10.  *    notice, this list of conditions and the following disclaimer.
  11.  * 2. Redistributions in binary form must reproduce the above copyright
  12.  *    notice, this list of conditions and the following disclaimer in the
  13.  *    documentation and/or other materials provided with the distribution.
  14.  * 3. All advertising materials mentioning features or use of this software
  15.  *    must display the following acknowledgement:
  16.  * This product includes software developed by the University of
  17.  * California, Berkeley and its contributors.
  18.  * 4. Neither the name of the University nor the names of its contributors
  19.  *    may be used to endorse or promote products derived from this software
  20.  *    without specific prior written permission.
  21.  *
  22.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  23.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  24.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  25.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  26.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  27.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  28.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  29.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  31.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  32.  * SUCH DAMAGE.
  33.  *
  34.  *  Description : Malloc functions.
  35.  *  This is a very fast storage allocator.  It allocates blocks of a small 
  36.  *  number of different sizes, and keeps free lists of each size.  Blocks that
  37.  *  don't exactly fit are passed up to the next larger size.  In this 
  38.  *  implementation, the available sizes are 2^n-4 (or 2^n-10) bytes long.
  39.  *  This is designed for use in a virtual memory environment.
  40.  *
  41.  *  0.00 82/02/21 Chris Kingsley kingsley@cit-20 
  42.  *
  43.  *  1.00 93/11/06 proven
  44.  *      -Modified BSD libc malloc to be threadsafe.
  45.  *
  46.  */
  47. #ifndef lint
  48. static const char rcsid[] = "$Id$";
  49. #endif
  50. #include <pthread.h>
  51. #include <sys/types.h>
  52. #include <string.h>
  53. #include <pthread/posix.h>
  54. /*
  55.  * The overhead on a block is at least 4 bytes.  When free, this space
  56.  * contains a pointer to the next free block, and the bottom two bits must
  57.  * be zero.  When in use, the first byte is set to MAGIC, and the second
  58.  * byte is the size index.  The remaining bytes are for alignment.
  59.  * If range checking is enabled then a second word holds the size of the
  60.  * requested block, less 1, rounded up to a multiple of sizeof(RMAGIC).
  61.  * The order of elements is critical: ov_magic must overlay the low order
  62.  * bits of ov_next, and ov_magic can not be a valid ov_next bit pattern.
  63.  */
  64. #ifdef __alpha
  65. #define _MOST_RESTRICTIVE_ALIGNMENT_TYPE char*
  66. #else
  67. #define _MOST_RESTRICTIVE_ALIGNMENT_TYPE double
  68. #endif /* __alpha */
  69. union overhead {
  70. _MOST_RESTRICTIVE_ALIGNMENT_TYPE __alignment_pad0;
  71. union overhead *ov_next; /* when free */
  72. struct {
  73. u_char ovu_magic; /* magic number */
  74. u_char ovu_index; /* bucket # */
  75. #ifdef RCHECK
  76. u_short ovu_rmagic; /* range magic number */
  77. size_t ovu_size; /* actual block size */
  78. #endif
  79. } ovu;
  80. #define ov_magic ovu.ovu_magic
  81. #define ov_index ovu.ovu_index
  82. #define ov_rmagic ovu.ovu_rmagic
  83. #define ov_size ovu.ovu_size
  84. };
  85. #define MAGIC 0xef /* magic # on accounting info */
  86. #define RMAGIC 0x5555 /* magic # on range info */
  87. #ifdef RCHECK
  88. #define RSLOP sizeof (u_short)
  89. #else
  90. #define RSLOP 0
  91. #endif
  92. /*
  93.  * nextf[i] is the pointer to the next free block of size 2^(i+3).  The
  94.  * smallest allocatable block is 8 bytes.  The overhead information
  95.  * precedes the data area returned to the user.
  96.  */
  97. #define NBUCKETS 30
  98. static union overhead *nextf[NBUCKETS];
  99. #ifndef hpux
  100. extern char *sbrk();
  101. #endif
  102. static size_t pagesz; /* page size */
  103. static int pagebucket; /* page size bucket */
  104. static  pthread_mutex_t malloc_mutex = PTHREAD_MUTEX_INITIALIZER;
  105. #if defined(DEBUG) || defined(RCHECK)
  106. #define ASSERT(p)   if (!(p)) botch("p")
  107. #include <stdio.h>
  108. static
  109. botch(s)
  110. char *s;
  111. {
  112. fprintf(stderr, "rnassertion botched: %srn", s);
  113.   (void) fflush(stderr); /* just in case user buffered it */
  114. abort();
  115. }
  116. #else
  117. #define ASSERT(p)
  118. #endif
  119. /* ==========================================================================
  120.  * morecore()
  121.  *
  122.  * Allocate more memory to the indicated bucket
  123.  */
  124. static inline void morecore(int bucket)
  125. {
  126.    register union overhead *op;
  127. register size_t sz; /* size of desired block */
  128.    size_t amt; /* amount to allocate */
  129.    size_t nblks; /* how many blocks we get */
  130. /*
  131.  * sbrk_size <= 0 only for big, FLUFFY, requests (about
  132.  * 2^30 bytes on a VAX, I think) or for a negative arg.
  133.  */
  134. sz = 1L << (bucket + 3);
  135. #ifdef DEBUG
  136. ASSERT(sz > 0);
  137. #else
  138. if (sz <= 0)
  139. return;
  140. #endif
  141. if (sz < pagesz) {
  142. amt = pagesz;
  143.    nblks = amt / sz;
  144. } else {
  145. amt = sz + pagesz;
  146. nblks = 1;
  147. }
  148. op = (union overhead *)sbrk(amt);
  149. /* no more room! */
  150. if (op == (union overhead *) -1)
  151. return;
  152. /*
  153.  * Add new memory allocated to that on
  154.  * free list for this hash bucket.
  155.  */
  156.    nextf[bucket] = op;
  157.    while (--nblks > 0) {
  158. op->ov_next = (union overhead *)((caddr_t)op + sz);
  159. op = (union overhead *)((caddr_t)op + sz);
  160.    }
  161. }
  162. /* ==========================================================================
  163.  * malloc()
  164.  */
  165. void *malloc(size_t nbytes)
  166. {
  167. pthread_mutex_t *mutex;
  168.    union overhead *op;
  169. size_t amt;
  170. size_t bucket, n;
  171. mutex = &malloc_mutex;
  172. pthread_mutex_lock(mutex);
  173. /*
  174.  * First time malloc is called, setup page size and
  175.  * align break pointer so all data will be page aligned.
  176.  */
  177. if (pagesz == 0) {
  178. size_t x;
  179. pagesz = n = getpagesize();
  180. op = (union overhead *)sbrk(0);
  181. x = sizeof (*op) - ((long)op & (n - 1));
  182. if (n < x)
  183. n = n + pagesz - x;
  184. else
  185. n = n - x;
  186.    if (n) {
  187.   if (sbrk(n) == (char *)-1) {
  188.     /* Unlock before returning (mevans) */
  189.     pthread_mutex_unlock(mutex);
  190.     return (NULL);
  191.   }
  192. }
  193. bucket = 0;
  194. amt = 8;
  195. while (pagesz > amt) {
  196. amt <<= 1;
  197. bucket++;
  198. }
  199. pagebucket = bucket;
  200. }
  201. /*
  202.  * Convert amount of memory requested into closest block size
  203.  * stored in hash buckets which satisfies request.
  204.  * Account for space used per block for accounting.
  205.  */
  206. if (nbytes <= (n = pagesz - sizeof (*op) - RSLOP)) {
  207. #ifndef RCHECK
  208. amt = 8; /* size of first bucket */
  209. bucket = 0;
  210. #else
  211. amt = 16; /* size of first bucket */
  212. bucket = 1;
  213. #endif
  214. n = -(sizeof (*op) + RSLOP);
  215. } else {
  216. amt = pagesz;
  217. bucket = pagebucket;
  218. }
  219. while (nbytes > amt + n) {
  220. amt <<= 1;
  221. if (amt == 0) {
  222. pthread_mutex_unlock(mutex);
  223. return (NULL);
  224. }
  225. bucket++;
  226. }
  227. ASSERT (bucket < NBUCKETS);
  228. /*
  229.  * If nothing in hash bucket right now,
  230.  * request more memory from the system.
  231.  */
  232.    if ((op = nextf[bucket]) == NULL) {
  233.    morecore(bucket);
  234.    if ((op = nextf[bucket]) == NULL) {
  235. pthread_mutex_unlock(mutex);
  236.    return (NULL);
  237. }
  238. }
  239. /* remove from linked list */
  240.    nextf[bucket] = op->ov_next;
  241. op->ov_magic = MAGIC;
  242. op->ov_index = bucket;
  243. #ifdef RCHECK
  244. /*
  245.  * Record allocated size of block and
  246.  * bound space with magic numbers.
  247.  */
  248. op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1);
  249. op->ov_rmagic = RMAGIC;
  250.    *(u_short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC;
  251. #endif
  252. pthread_mutex_unlock(mutex);
  253.    return ((char *)(op + 1));
  254. }
  255. /* ==========================================================================
  256.  * free()
  257.  */
  258. void free(void *cp)
  259. {   
  260. pthread_mutex_t *mutex;
  261. union overhead *op;
  262. int size;
  263. mutex = &malloc_mutex;
  264. pthread_mutex_lock(mutex);
  265.    if (cp == NULL) {
  266. pthread_mutex_unlock(mutex);
  267.    return;
  268. }
  269. op = (union overhead *)((caddr_t)cp - sizeof (union overhead));
  270. #ifdef DEBUG
  271.    ASSERT(op->ov_magic == MAGIC); /* make sure it was in use */
  272. #else
  273. if (op->ov_magic != MAGIC) {
  274. pthread_mutex_unlock(mutex);
  275. return; /* sanity */
  276. }
  277. #endif
  278. #ifdef RCHECK
  279.    ASSERT(op->ov_rmagic == RMAGIC);
  280. ASSERT(*(u_short *)((caddr_t)(op + 1) + op->ov_size) == RMAGIC);
  281. #endif
  282.    size = op->ov_index;
  283.    ASSERT(size < NBUCKETS);
  284. op->ov_next = nextf[size]; /* also clobbers ov_magic */
  285.    nextf[size] = op;
  286. pthread_mutex_unlock(mutex);
  287. }
  288. /* ==========================================================================
  289.  * realloc()
  290.  *
  291.  * Storage compaction is no longer supported, fix program and try again.
  292.  */
  293. void *realloc(void *cp, size_t nbytes)
  294. {   
  295. pthread_mutex_t *mutex;
  296.    size_t onb;
  297. size_t i;
  298. union overhead *op;
  299.    char *res;
  300.    if (cp == NULL)
  301.    return (malloc(nbytes));
  302. op = (union overhead *)((caddr_t)cp - sizeof (union overhead));
  303. if (op->ov_magic == MAGIC) {
  304. i = op->ov_index;
  305. } else {
  306. /*
  307.  * This will cause old programs using storage compaction feature of
  308.  * realloc to break in a pseudo resonable way that is easy to debug.
  309.  * Returning a malloced buffer without the copy may cause
  310.  * indeterministic behavior.
  311.  */
  312.     return(NULL);
  313. }
  314. mutex = &malloc_mutex;
  315. pthread_mutex_lock(mutex);
  316. onb = 1L << (i + 3);
  317. if (onb < pagesz)
  318. onb -= sizeof (*op) + RSLOP;
  319. else
  320. onb += pagesz - sizeof (*op) - RSLOP;
  321. /* avoid the copy if same size block */
  322. if (i) {
  323. i = 1L << (i + 2);
  324. if (i < pagesz)
  325. i -= sizeof (*op) + RSLOP;
  326. else
  327. i += pagesz - sizeof (*op) - RSLOP;
  328. }
  329. if (nbytes <= onb && nbytes > i) {
  330. #ifdef RCHECK
  331. op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1);
  332. *(u_short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC;
  333. #endif
  334. pthread_mutex_unlock(mutex);
  335. return(cp);
  336. }
  337. pthread_mutex_unlock(mutex);
  338.    if ((res = malloc(nbytes)) == NULL) {
  339. free(cp);
  340.    return (NULL);
  341. }
  342. memcpy(res, cp, (nbytes < onb) ? nbytes : onb);
  343. free(cp);
  344.    return (res);
  345. }
  346. /* ==========================================================================
  347.  * calloc()
  348.  *
  349.  * Added to ensure pthread's allocation is used (mevans).
  350.  */
  351. void *calloc(size_t nmemb, size_t size)
  352. {
  353.   void *p;
  354.   size *= nmemb;
  355.   p = malloc(size);
  356.   if (p) memset(p, 0, size);
  357.   return (p);
  358. }