📄 malloc.c
字号:
/* Malloc implementation for multiple threads without lock contention. Copyright (C) 1996-2001, 2002 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Wolfram Gloger <wmglo@dent.med.uni-muenchen.de> and Doug Lea <dl@cs.oswego.edu>, 1996. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *//* $Id: malloc.c,v 1.1.1.1 2003/08/19 22:29:46 craigv Exp $ This work is mainly derived from malloc-2.6.4 by Doug Lea <dl@cs.oswego.edu>, which is available from: ftp://g.oswego.edu/pub/misc/malloc.c Most of the original comments are reproduced in the code below.* Why use this malloc? This is not the fastest, most space-conserving, most portable, or most tunable malloc ever written. However it is among the fastest while also being among the most space-conserving, portable and tunable. Consistent balance across these factors results in a good general-purpose allocator. For a high-level description, see http://g.oswego.edu/dl/html/malloc.html On many systems, the standard malloc implementation is by itself not thread-safe, and therefore wrapped with a single global lock around all malloc-related functions. In some applications, especially with multiple available processors, this can lead to contention problems and bad performance. This malloc version was designed with the goal to avoid waiting for locks as much as possible. Statistics indicate that this goal is achieved in many cases.* Synopsis of public routines (Much fuller descriptions are contained in the program documentation below.) ptmalloc_init(); Initialize global configuration. When compiled for multiple threads, this function must be called once before any other function in the package. It is not required otherwise. It is called automatically in the Linux/GNU C libray or when compiling with MALLOC_HOOKS. malloc(size_t n); Return a pointer to a newly allocated chunk of at least n bytes, or null if no space is available. free(Void_t* p); Release the chunk of memory pointed to by p, or no effect if p is null. realloc(Void_t* p, size_t n); Return a pointer to a chunk of size n that contains the same data as does chunk p up to the minimum of (n, p's size) bytes, or null if no space is available. The returned pointer may or may not be the same as p. If p is null, equivalent to malloc. Unless the #define REALLOC_ZERO_BYTES_FREES below is set, realloc with a size argument of zero (re)allocates a minimum-sized chunk. memalign(size_t alignment, size_t n); Return a pointer to a newly allocated chunk of n bytes, aligned in accord with the alignment argument, which must be a power of two. valloc(size_t n); Equivalent to memalign(pagesize, n), where pagesize is the page size of the system (or as near to this as can be figured out from all the includes/defines below.) pvalloc(size_t n); Equivalent to valloc(minimum-page-that-holds(n)), that is, round up n to nearest pagesize. calloc(size_t unit, size_t quantity); Returns a pointer to quantity * unit bytes, with all locations set to zero. cfree(Void_t* p); Equivalent to free(p). malloc_trim(size_t pad); Release all but pad bytes of freed top-most memory back to the system. Return 1 if successful, else 0. malloc_usable_size(Void_t* p); Report the number usable allocated bytes associated with allocated chunk p. This may or may not report more bytes than were requested, due to alignment and minimum size constraints. malloc_stats(); Prints brief summary statistics on stderr. mallinfo() Returns (by copy) a struct containing various summary statistics. mallopt(int parameter_number, int parameter_value) Changes one of the tunable parameters described below. Returns 1 if successful in changing the parameter, else 0.* Vital statistics: Alignment: 8-byte 8 byte alignment is currently hardwired into the design. This seems to suffice for all current machines and C compilers. Assumed pointer representation: 4 or 8 bytes Code for 8-byte pointers is untested by me but has worked reliably by Wolfram Gloger, who contributed most of the changes supporting this. Assumed size_t representation: 4 or 8 bytes Note that size_t is allowed to be 4 bytes even if pointers are 8. Minimum overhead per allocated chunk: 4 or 8 bytes Each malloced chunk has a hidden overhead of 4 bytes holding size and status information. Minimum allocated size: 4-byte ptrs: 16 bytes (including 4 overhead) 8-byte ptrs: 24/32 bytes (including, 4/8 overhead) When a chunk is freed, 12 (for 4byte ptrs) or 20 (for 8 byte ptrs but 4 byte size) or 24 (for 8/8) additional bytes are needed; 4 (8) for a trailing size field and 8 (16) bytes for free list pointers. Thus, the minimum allocatable size is 16/24/32 bytes. Even a request for zero bytes (i.e., malloc(0)) returns a pointer to something of the minimum allocatable size. Maximum allocated size: 4-byte size_t: 2^31 - 8 bytes 8-byte size_t: 2^63 - 16 bytes It is assumed that (possibly signed) size_t bit values suffice to represent chunk sizes. `Possibly signed' is due to the fact that `size_t' may be defined on a system as either a signed or an unsigned type. To be conservative, values that would appear as negative numbers are avoided. Requests for sizes with a negative sign bit will return a minimum-sized chunk. Maximum overhead wastage per allocated chunk: normally 15 bytes Alignment demands, plus the minimum allocatable size restriction make the normal worst-case wastage 15 bytes (i.e., up to 15 more bytes will be allocated than were requested in malloc), with two exceptions: 1. Because requests for zero bytes allocate non-zero space, the worst case wastage for a request of zero bytes is 24 bytes. 2. For requests >= mmap_threshold that are serviced via mmap(), the worst case wastage is 8 bytes plus the remainder from a system page (the minimal mmap unit); typically 4096 bytes.* Limitations Here are some features that are NOT currently supported * No automated mechanism for fully checking that all accesses to malloced memory stay within their bounds. * No support for compaction.* Synopsis of compile-time options: People have reported using previous versions of this malloc on all versions of Unix, sometimes by tweaking some of the defines below. It has been tested most extensively on Solaris and Linux. People have also reported adapting this malloc for use in stand-alone embedded systems. The implementation is in straight, hand-tuned ANSI C. Among other consequences, it uses a lot of macros. Because of this, to be at all usable, this code should be compiled using an optimizing compiler (for example gcc -O2) that can simplify expressions and control paths. __STD_C (default: derived from C compiler defines) Nonzero if using ANSI-standard C compiler, a C++ compiler, or a C compiler sufficiently close to ANSI to get away with it. MALLOC_DEBUG (default: NOT defined) Define to enable debugging. Adds fairly extensive assertion-based checking to help track down memory errors, but noticeably slows down execution. MALLOC_HOOKS (default: NOT defined) Define to enable support run-time replacement of the allocation functions through user-defined `hooks'. REALLOC_ZERO_BYTES_FREES (default: defined) Define this if you think that realloc(p, 0) should be equivalent to free(p). (The C standard requires this behaviour, therefore it is the default.) Otherwise, since malloc returns a unique pointer for malloc(0), so does realloc(p, 0). HAVE_MEMCPY (default: defined) Define if you are not otherwise using ANSI STD C, but still have memcpy and memset in your C library and want to use them. Otherwise, simple internal versions are supplied. USE_MEMCPY (default: 1 if HAVE_MEMCPY is defined, 0 otherwise) Define as 1 if you want the C library versions of memset and memcpy called in realloc and calloc (otherwise macro versions are used). At least on some platforms, the simple macro versions usually outperform libc versions. HAVE_MMAP (default: defined as 1) Define to non-zero to optionally make malloc() use mmap() to allocate very large blocks. HAVE_MREMAP (default: defined as 0 unless Linux libc set) Define to non-zero to optionally make realloc() use mremap() to reallocate very large blocks. USE_ARENAS (default: the same as HAVE_MMAP) Enable support for multiple arenas, allocated using mmap(). malloc_getpagesize (default: derived from system #includes) Either a constant or routine call returning the system page size. HAVE_USR_INCLUDE_MALLOC_H (default: NOT defined) Optionally define if you are on a system with a /usr/include/malloc.h that declares struct mallinfo. It is not at all necessary to define this even if you do, but will ensure consistency. INTERNAL_SIZE_T (default: size_t) Define to a 32-bit type (probably `unsigned int') if you are on a 64-bit machine, yet do not want or need to allow malloc requests of greater than 2^31 to be handled. This saves space, especially for very small chunks. _LIBC (default: NOT defined) Defined only when compiled as part of the Linux libc/glibc. Also note that there is some odd internal name-mangling via defines (for example, internally, `malloc' is named `mALLOc') needed when compiling in this case. These look funny but don't otherwise affect anything. LACKS_UNISTD_H (default: undefined) Define this if your system does not have a <unistd.h>. MORECORE (default: sbrk) The name of the routine to call to obtain more memory from the system. MORECORE_FAILURE (default: -1) The value returned upon failure of MORECORE. MORECORE_CLEARS (default 1) The degree to which the routine mapped to MORECORE zeroes out memory: never (0), only for newly allocated space (1) or always (2). The distinction between (1) and (2) is necessary because on some systems, if the application first decrements and then increments the break value, the contents of the reallocated space are unspecified. DEFAULT_TRIM_THRESHOLD DEFAULT_TOP_PAD DEFAULT_MMAP_THRESHOLD DEFAULT_MMAP_MAX Default values of tunable parameters (described in detail below) controlling interaction with host system routines (sbrk, mmap, etc). These values may also be changed dynamically via mallopt(). The preset defaults are those that give best performance for typical programs/systems. DEFAULT_CHECK_ACTION When the standard debugging hooks are in place, and a pointer is detected as corrupt, do nothing (0), print an error message (1), or call abort() (2).*//** Compile-time options for multiple threads: USE_PTHREADS, USE_THR, USE_SPROC Define one of these as 1 to select the thread interface: POSIX threads, Solaris threads or SGI sproc's, respectively. If none of these is defined as non-zero, you get a `normal' malloc implementation which is not thread-safe. Support for multiple threads requires HAVE_MMAP=1. As an exception, when compiling for GNU libc, i.e. when _LIBC is defined, then none of the USE_... symbols have to be defined. HEAP_MIN_SIZE HEAP_MAX_SIZE When thread support is enabled, additional `heap's are created with mmap calls. These are limited in size; HEAP_MIN_SIZE should be a multiple of the page size, while HEAP_MAX_SIZE must be a power of two for alignment reasons. HEAP_MAX_SIZE should be at least twice as large as the mmap threshold. THREAD_STATS When this is defined as non-zero, some statistics on mutex locking are computed.*//* Preliminaries */#ifndef __STD_C#if defined (__STDC__)#define __STD_C 1#else#if __cplusplus#define __STD_C 1#else#define __STD_C 0#endif /*__cplusplus*/#endif /*__STDC__*/#endif /*__STD_C*/#ifndef Void_t#if __STD_C#define Void_t void#else#define Void_t char#endif#endif /*Void_t*/#if __STD_C# include <stddef.h> /* for size_t */# if defined _LIBC || defined MALLOC_HOOKS# include <stdlib.h> /* for getenv(), abort() */# endif#else# include <sys/types.h># if defined _LIBC || defined MALLOC_HOOKSextern char* getenv();# endif#endif/* newlib modifications */#include <libc-symbols.h>#include <sys/types.h>extern void __pthread_initialize (void) __attribute__((weak));extern void *__mmap (void *__addr, size_t __len, int __prot, int __flags, int __fd, off_t __offset);extern int __munmap (void *__addr, size_t __len);extern void *__mremap (void *__addr, size_t __old_len, size_t __new_len, int __may_move);extern int __getpagesize (void);#define __libc_enable_secure 1/* Macros for handling mutexes and thread-specific data. This is included early, because some thread-related header files (such as pthread.h) should be included before any others. */#include <bits/libc-lock.h>#include "thread-m.h"void *(*__malloc_internal_tsd_get) (enum __libc_tsd_key_t) = NULL;int (*__malloc_internal_tsd_set) (enum __libc_tsd_key_t, __const void *) = NULL;weak_alias(__malloc_internal_tsd_get, __libc_internal_tsd_get)weak_alias(__malloc_internal_tsd_set, __libc_internal_tsd_set)#ifdef __cplusplusextern "C" {#endif#include <errno.h>#include <stdio.h> /* needed for malloc_stats *//* Compile-time options*//* Debugging: Because freed chunks may be overwritten with link fields, this malloc will often die when freed memory is overwritten by user programs. This can be very effective (albeit in an annoying way) in helping track down dangling pointers. If you compile with -DMALLOC_DEBUG, a number of assertion checks are enabled that will catch more memory errors. You probably won't be able to make much sense of the actual assertion errors, but they should help you locate incorrectly overwritten memory. The checking is fairly extensive, and will slow down execution noticeably. Calling malloc_stats or mallinfo with MALLOC_DEBUG set will attempt to check every non-mmapped allocated and free chunk in the course of computing the summaries. (By nature, mmapped regions cannot be checked very much automatically.) Setting MALLOC_DEBUG may also be helpful if you are trying to modify this code. The assertions in the check routines spell out in more detail the assumptions and invariants underlying the algorithms.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -