📄 dlmalloc.cxx
字号:
//==========================================================================
//
// dlmalloc.cxx
//
// Port of Doug Lea's malloc implementation
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos 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 General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): Doug Lea (dl at g.oswego.edu), jlarmour
// Contributors:
// Date: 2000-06-18
// Purpose: Doug Lea's malloc implementation
// Description: Doug Lea's malloc has been ported to eCos. This file
// provides the implementation in a way acceptable to eCos.
// Substantial amounts of unnecessary bits (to eCos) of the
// original implementation have been removed to make the
// code more tractable. Note this may make a number of the
// comments appear to make little sense, or no longer apply!
// In particular, mmap support is removed entirely.
// Also the memory is "sbrked" all at once at the
// beginning, covering the entire memory region given at
// construction, and there can be no more afterwards.
// Usage: #include <cyg/memalloc/dlmalloc.hxx>
//
//
//####DESCRIPTIONEND####
//
//==========================================================================
// DOCUMENTATION FROM ORIGINAL FILE:
// (some now irrelevant parts elided)
//----------------------------------------------------------------------------
/*
A version of malloc/free/realloc written by Doug Lea and released to the
public domain. Send questions/comments/complaints/performance data
to dl at cs.oswego.edu
* VERSION 2.6.6 Sun Mar 5 19:10:03 2000 Doug Lea (dl at gee)
Note: There may be an updated version of this malloc obtainable at
ftp://g.oswego.edu/pub/misc/malloc.c
Check before installing!
* 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
* Synopsis of public routines
(Much fuller descriptions are contained in the program documentation below.)
[ these have of course been renamed in the eCos port ]a
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. realloc of
zero bytes calls free(p)
* 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 when the request
size is treaded as a long will return null.
Maximum overhead wastage per allocated chunk: normally 15 bytes
Alignnment 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
one exception: because requests for zero bytes allocate non-zero space,
the worst case wastage for a request of zero bytes is 24 bytes.
* Limitations
Here are some features that are NOT currently supported
* No user-definable hooks for callbacks and the like.
* 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. It is also reported to work on WIN32 platforms.
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.
CYGDBG_MEMALLOC_ALLOCATOR_DLMALLOC_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_LOCK (default: NOT defined)
MALLOC_UNLOCK (default: NOT defined)
Define these to C expressions which are run to lock and unlock
the malloc data structures. Calls may be nested; that is,
MALLOC_LOCK may be called more than once before the corresponding
MALLOC_UNLOCK calls. MALLOC_LOCK must avoid waiting for a lock
that it already holds.
MALLOC_ALIGNMENT (default: NOT defined)
Define this to 16 if you need 16 byte alignment instead of 8 byte alignment
which is the normal default.
SIZE_T_SMALLER_THAN_LONG (default: NOT defined)
Define this when the platform you are compiling has
sizeof(long) > sizeof(size_t).
The option causes some extra code to be generated to handle operations
that use size_t operands and have long results.
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.
*/
//----------------------------------------------------------------------------
/* Preliminaries */
#include <pkgconf/memalloc.h> // configuration header
#include <pkgconf/infra.h> // CYGDBG_USE_ASSERTS
#include <cyg/infra/cyg_type.h> // types
#include <cyg/infra/cyg_ass.h> // assertions
#include <stddef.h> // for size_t
#include <cyg/memalloc/dlmalloc.hxx>
//#include <cyg/infra/diag.h>
/*
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 CYGDBG_MEMALLOC_ALLOCATOR_DLMALLOC_DEBUG enabled, 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 get_status() with DEBUG set will
attempt to check every allocated and free chunk in the
course of computing the summmaries.
Setting CYGDBG_MEMALLOC_ALLOCATOR_DLMALLOC_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.
*/
#ifdef CYGDBG_MEMALLOC_ALLOCATOR_DLMALLOC_DEBUG
# define ASSERT(x) CYG_ASSERTC( x )
#else
# define ASSERT(x) ((void)0)
#endif
/*
Define MALLOC_LOCK and MALLOC_UNLOCK to C expressions to run to
lock and unlock the malloc data structures. MALLOC_LOCK may be
called recursively.
*/
#ifndef MALLOC_LOCK
#define MALLOC_LOCK
#endif
#ifndef MALLOC_UNLOCK
#define MALLOC_UNLOCK
#endif
/*
INTERNAL_SIZE_T is the word-size used for internal bookkeeping
of chunk sizes. On a 64-bit machine, you can reduce malloc
overhead by defining INTERNAL_SIZE_T to be a 32 bit `unsigned int'
at the expense of not being able to handle requests greater than
2^31. This limitation is hardly ever a concern; you are encouraged
to set this. However, the default version is the same as size_t.
*/
#ifndef INTERNAL_SIZE_T
#define INTERNAL_SIZE_T Cyg_Mempool_dlmalloc_Implementation::Cyg_dlmalloc_size_t
#endif
/*
Following is needed on implementations whereby long > size_t.
The problem is caused because the code performs subtractions of
size_t values and stores the result in long values. In the case
where long > size_t and the first value is actually less than
the second value, the resultant value is positive. For example,
(long)(x - y) where x = 0 and y is 1 ends up being 0x00000000FFFFFFFF
which is 2*31 - 1 instead of 0xFFFFFFFFFFFFFFFF. This is due to the
fact that assignment from unsigned to signed won't sign extend.
*/
#ifdef SIZE_T_SMALLER_THAN_LONG
#define long_sub_size_t(x, y) ( (x < y) ? -((long)(y - x)) : (x - y) );
#else
#define long_sub_size_t(x, y) ( (long)(x - y) )
#endif
#ifdef CYGIMP_MEMALLOC_ALLOCATOR_DLMALLOC_USE_MEMCPY
#include <string.h> // memcpy, memset
/* The following macros are only invoked with (2n+1)-multiples of
INTERNAL_SIZE_T units, with a positive integer n. This is exploited
for fast inline execution when n is small. */
#define MALLOC_ZERO(charp, nbytes) \do { \ INTERNAL_SIZE_T mzsz = (nbytes); \ if(mzsz <= 9*sizeof(mzsz)) { \ INTERNAL_SIZE_T* mz = (INTERNAL_SIZE_T*) (charp); \ if(mzsz >= 5*sizeof(mzsz)) { *mz++ = 0; \ *mz++ = 0; \ if(mzsz >= 7*sizeof(mzsz)) { *mz++ = 0; \ *mz++ = 0; \ if(mzsz >= 9*sizeof(mzsz)) { *mz++ = 0; \ *mz++ = 0; }}} \ *mz++ = 0; \ *mz++ = 0; \ *mz = 0; \ } else memset((charp), 0, mzsz); \} while(0)
#define MALLOC_COPY(dest,src,nbytes) \do { \ INTERNAL_SIZE_T mcsz = (nbytes); \ if(mcsz <= 9*sizeof(mcsz)) { \ INTERNAL_SIZE_T* mcsrc = (INTERNAL_SIZE_T*) (src); \ INTERNAL_SIZE_T* mcdst = (INTERNAL_SIZE_T*) (dest); \ if(mcsz >= 5*sizeof(mcsz)) { *mcdst++ = *mcsrc++; \ *mcdst++ = *mcsrc++; \ if(mcsz >= 7*sizeof(mcsz)) { *mcdst++ = *mcsrc++; \ *mcdst++ = *mcsrc++; \ if(mcsz >= 9*sizeof(mcsz)) { *mcdst++ = *mcsrc++; \ *mcdst++ = *mcsrc++; }}} \
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -