First round of hoard changes to change it exactly to what we need.

Removed the arch-specific stuff for all other platforms.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@11326 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2005-02-10 18:47:16 +00:00
parent 577c5fac30
commit 71aa315c95
9 changed files with 194 additions and 888 deletions

View File

@ -1,12 +1,10 @@
SubDir OBOS_TOP src kernel libroot posix malloc ;
KernelMergeObject posix_malloc.o :
<$(SOURCE_GRIST)>arch-specific.cpp
<$(SOURCE_GRIST)>heap.cpp
<$(SOURCE_GRIST)>processheap.cpp
<$(SOURCE_GRIST)>superblock.cpp
<$(SOURCE_GRIST)>threadheap.cpp
<$(SOURCE_GRIST)>wrapper.cpp
:
-DNEWOS=1
arch-specific.cpp
heap.cpp
processheap.cpp
superblock.cpp
threadheap.cpp
wrapper.cpp
;

View File

@ -20,6 +20,7 @@
//#include <assert.h>
#include "arch-specific.h"
#include "heap.h"
// How many iterations we spin waiting for a lock.
enum { SPIN_LIMIT = 100 };
@ -29,51 +30,9 @@ enum { UNLOCKED = 0, LOCKED = 1 };
extern "C" {
#ifdef NEWOS
#include <OS.h>
#include <stdio.h>
#include <syscalls.h>
#include <unistd.h>
sem_id create_sem(int32 count, const char *name);
status_t delete_sem(sem_id id);
status_t acquire_sem(sem_id id);
status_t release_sem(sem_id id);
int hoardGetThreadID (void)
{
return find_thread(NULL);
}
void hoardLockInit (hoardLockType &lock)
{
lock.ben = 0;
lock.sem = create_sem(1, "a hoard lock");
}
void hoardLock (hoardLockType &lock)
{
if((atomic_add(&(lock.ben), 1)) >= 1) acquire_sem(lock.sem);
}
void hoardUnlock (hoardLockType &lock)
{
if((atomic_add(&(lock.ben), -1)) > 1) release_sem(lock.sem);
}
int hoardGetPageSize (void)
{
return 4096;
}
int hoardGetNumProcessors (void)
{
// XXX return the real number of procs here
return 1;
}
static area_id heap_region = -1;
static addr_t brk;
@ -89,561 +48,123 @@ __heap_init()
return 0;
}
class heap_init_hack_t
{
class heap_init_hack_t {
public:
heap_init_hack_t(void) {
heap_init_hack_t(void)
{
__heap_init();
}
} heap_init_hack;
void * hoardSbrk (long size)
void
hoardCreateThread(hoardThreadType &thread,
void *(*function)(void *), void *arg)
{
thread = spawn_thread((int32 (*)(void*))function, "some thread",
B_NORMAL_PRIORITY, arg);
if (thread >= B_OK)
resume_thread(thread);
else
debugger("spawn_thread() failed!");
}
void
hoardJoinThread(hoardThreadType &thread)
{
wait_for_thread(thread, NULL);
}
void
hoardSetConcurrency(int)
{
}
int
hoardGetThreadID(void)
{
return find_thread(NULL);
}
void
hoardLockInit(hoardLockType &lock, const char *name)
{
lock.ben = 0;
lock.sem = create_sem(0, name);
}
void
hoardLock(hoardLockType &lock)
{
if (atomic_add(&(lock.ben), 1) >= 1)
acquire_sem(lock.sem);
}
void
hoardUnlock(hoardLockType &lock)
{
if (atomic_add(&(lock.ben), -1) > 1)
release_sem(lock.sem);
}
int
hoardGetPageSize(void)
{
return B_PAGE_SIZE;
}
int
hoardGetNumProcessors(void)
{
system_info info;
if (get_system_info(&info) != B_OK)
return 1;
return info.cpu_count;
}
void *
hoardSbrk(long size)
{
void *ret = (void *)brk;
brk += size;
brk += size + hoardHeap::ALIGNMENT - 1;
return ret;
// return sbrk(size + hoardHeap::ALIGNMENT - 1);
}
void hoardUnsbrk (void * ptr, long size)
void
hoardUnsbrk(void * ptr, long size)
{
// NOT CURRENTLY IMPLEMENTED!
}
void hoardYield (void)
{
}
#elif defined(WIN32)
unsigned long hoardInterlockedExchange (unsigned long * oldval,
unsigned long newval)
{
return InterlockedExchange (reinterpret_cast<long *>(oldval), newval);
}
void hoardCreateThread (hoardThreadType& t,
void *(*function) (void *),
void * arg)
{
t = CreateThread (0, 0, (LPTHREAD_START_ROUTINE) function, (LPVOID) arg, 0, 0);
}
void hoardJoinThread (hoardThreadType& t)
{
WaitForSingleObject (t, INFINITE);
}
void hoardSetConcurrency (int)
{
}
int hoardGetThreadID (void) {
// Threads from Windows 2000 are 4 apart,
// so we shift them over to get an appropriate thread id.
int tid = GetCurrentThreadId() >> 2;
return tid;
}
void hoardLockInit (hoardLockType& mutex) {
InterlockedExchange (&mutex, 0);
}
void hoardLock (hoardLockType& mutex) {
// A yielding lock (with an initial spin).
int i;
while (1) {
i = 0;
while (i < SPIN_LIMIT) {
if (mutex != LOCKED)
if (InterlockedExchange (&mutex, LOCKED) == UNLOCKED) {
// We got the lock.
return;
}
i++;
}
// Yield to other threads.
Sleep (0);
}
}
void hoardYield (void) {
Sleep (0);
}
void hoardUnlock (hoardLockType& mutex) {
InterlockedExchange (&mutex, UNLOCKED);
}
void * hoardSbrk (long size)
{
void * ptr = HeapAlloc (GetProcessHeap(), 0, size);
return (void *) ptr;
// NOT CURRENTLY IMPLEMENTED!
}
void hoardUnsbrk (void * ptr, long size)
{
HeapFree (GetProcessHeap(), 0, ptr);
}
int hoardGetPageSize (void)
{
SYSTEM_INFO infoReturn[1];
GetSystemInfo (infoReturn);
return (int) (infoReturn -> dwPageSize);
}
int hoardGetNumProcessors (void)
{
static int numProcessors = 0;
if (numProcessors == 0) {
SYSTEM_INFO infoReturn[1];
GetSystemInfo (infoReturn);
numProcessors = (int) (infoReturn -> dwNumberOfProcessors);
}
return numProcessors;
}
#elif defined(__BEOS__)
#include <OS.h>
#include <unistd.h>
void hoardCreateThread (hoardThreadType &t,
void *( *function)( void *),
void *arg)
{
t = spawn_thread((int32 (*)(void*))function, "some thread",
B_NORMAL_PRIORITY, arg);
if (t >= B_OK) resume_thread(t);
else debugger("spawn_thread() failed!");
}
void hoardJoinThread (hoardThreadType &t)
{
status_t dummy;
wait_for_thread(t, &dummy);
}
void hoardSetConcurrency (int)
void
hoardYield(void)
{
}
int hoardGetThreadID (void)
unsigned long
hoardInterlockedExchange(unsigned long *oldval,
unsigned long newval)
{
return find_thread(0);
// This *should* be made atomic. It's never used in the BeOS
// version, so this is included strictly for completeness.
unsigned long o = *oldval;
*oldval = newval;
return o;
}
void hoardLockInit (hoardLockType &lock)
{
lock.ben = 0;
lock.sem = create_sem(0, "a hoard lock");
}
void hoardLock (hoardLockType &lock)
{
if((atomic_add(&(lock.ben), 1)) >= 1) acquire_sem(lock.sem);
}
void hoardUnlock (hoardLockType &lock)
{
if((atomic_add(&(lock.ben), -1)) > 1) release_sem(lock.sem);
}
int hoardGetPageSize (void)
{
return B_PAGE_SIZE;
}
int hoardGetNumProcessors (void)
{
system_info si;
status_t result = get_system_info(&si);
assert (result == B_OK);
return si.cpu_count;
}
void * hoardSbrk (long size)
{
return sbrk(size + hoardHeap::ALIGNMENT - 1);
}
void hoardUnsbrk (void * ptr, long size)
{
// NOT CURRENTLY IMPLEMENTED!
}
void hoardYield (void)
{
}
unsigned long hoardInterlockedExchange (unsigned long * oldval,
unsigned long newval)
{
// This *should* be made atomic. It's never used in the BeOS
// version, so this is included strictly for completeness.
unsigned long o = *oldval;
*oldval = newval;
return o;
}
#else // UNIX
#if USE_SPROC
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <ulocks.h>
#endif
void hoardCreateThread (hoardThreadType& t,
void *(*function) (void *),
void * arg)
{
#if USE_SPROC
typedef void (*sprocFunction) (void *);
t = sproc ((sprocFunction) function, PR_SADDR, arg);
#else
pthread_attr_t attr;
pthread_attr_init (&attr);
#if defined(_AIX)
// Bound (kernel-level) threads.
pthread_attr_setscope (&attr, PTHREAD_SCOPE_SYSTEM);
#endif
pthread_create (&t, &attr, function, arg);
#endif
}
void hoardJoinThread (hoardThreadType& t)
{
#if USE_SPROC
waitpid (t, 0, 0);
#else
pthread_join (t, NULL);
#endif
}
#if defined(__linux)
// This extern declaration is required for Linux.
extern "C" void pthread_setconcurrency (int n);
#endif
void hoardSetConcurrency (int n)
{
#if USE_SPROC
usconfig (CONF_INITUSERS, n);
#elif defined(__SVR4) // Solaris
thr_setconcurrency (n);
#else
pthread_setconcurrency (n);
#endif
}
#if defined(__SVR4) // Solaris
// Solaris's two-level threads model gives us an edge here;
// we can hash on the LWP's id. This helps us in two ways:
// (1) there are likely to be far fewer LWP's than threads,
// (2) if there's a one-to-one correspondence between LWP's
// and the number of processors (usually the case), then
// the number of heaps used will be the same as the number
// of processors (the optimal case).
// Here we rely on an undocumented call in libthread.so, which
// turns out to be MUCH cheaper than the documented _lwp_self(). Go figure.
extern "C" unsigned int lwp_self(void);
#endif
int hoardGetThreadID (void) {
#if USE_SPROC
// This hairiness has the same effect as calling getpid(),
// but it's MUCH faster since it avoids making a system call
// and just accesses the sproc-local data directly.
int pid = (int) PRDA->sys_prda.prda_sys.t_pid;
return pid;
#else
#if defined(__linux)
// Consecutive thread id's in Linux are 1024 apart;
// dividing off the 1024 gives us an appropriate thread id.
return (int) pthread_self() >> 10; // (>> 10 = / 1024)
#endif
#if defined(__AIX)
// Consecutive thread id's in AIX are 257 apart;
// dividing off the 257 gives us an appropriate thread id.
return (int) pthread_self() / 257;
#endif
#if defined(__SVR4)
return (int) lwp_self();
#endif
return (int) pthread_self();
#endif
}
// If we are using either Intel or SPARC,
// we use our own lock implementation
// (spin then yield). This is much cheaper than
// the ordinary mutex, at least on Linux and Solaris.
#if USER_LOCKS && (defined(i386) || defined(sparc) || defined(__sgi) || defined(ppc))
#include <sched.h>
#if defined(__sgi)
#include <mutex.h>
#endif
// Atomically:
// retval = *oldval;
// *oldval = newval;
// return retval;
#if defined(sparc) && !defined(__GNUC__)
extern "C" unsigned long InterlockedExchange (unsigned long * oldval,
unsigned long newval);
#else
unsigned long InterlockedExchange (unsigned long * oldval,
unsigned long newval)
{
#if defined(sparc)
asm volatile ("swap [%1],%0"
:"=r" (newval)
:"r" (oldval), "0" (newval)
: "memory");
#endif
#if defined(i386)
asm volatile ("xchgl %0, %1"
: "=r" (newval)
: "m" (*oldval), "0" (newval)
: "memory");
#endif
#if defined(__sgi)
newval = test_and_set (oldval, newval);
#endif
#if defined(ppc)
int ret;
asm volatile ("sync;"
"0: lwarx %0,0,%1 ;"
" xor. %0,%3,%0;"
" bne 1f;"
" stwcx. %2,0,%1;"
" bne- 0b;"
"1: sync"
: "=&r"(ret)
: "r"(oldval), "r"(newval), "r"(*oldval)
: "cr0", "memory");
#endif
return newval;
}
#endif
unsigned long hoardInterlockedExchange (unsigned long * oldval,
unsigned long newval)
{
return InterlockedExchange (oldval, newval);
}
void hoardLockInit (hoardLockType& mutex) {
InterlockedExchange (&mutex, UNLOCKED);
}
#include <stdio.h>
void hoardLock (hoardLockType& mutex) {
// A yielding lock (with an initial spin).
int i;
while (1) {
i = 0;
while (i < SPIN_LIMIT) {
if (InterlockedExchange (&mutex, LOCKED) == UNLOCKED) {
// We got the lock.
return;
}
i++;
}
// The lock is still being held by someone else.
// Give up our quantum.
sched_yield ();
}
}
void hoardUnlock (hoardLockType& mutex) {
InterlockedExchange (&mutex, UNLOCKED);
}
#else
// use non-user-level locks.
#endif // USER_LOCKS
void hoardYield (void)
{
sched_yield ();
}
#if 1 // !(defined(__sgi))
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#endif
void * hoardSbrk (long size) {
// Use mmap for everything but SGI.
// Apparently sproc's and mmap's don't cooperate.
#if 0 // defined(__sgi)
// Protect calls to sbrk() with a lock.
#if USER_LOCKS
static hoardLockType sbrkLock = 0;
#else
static hoardLockType sbrkLock = PTHREAD_MUTEX_INITIALIZER;
#endif
hoardLock (sbrkLock);
// The "sizeof(double)" should equal hoardHeap::ALIGNMENT.
// This is a workaround (compiler error in g++).
void * moreMemory = sbrk (size + sizeof(double) - 1);
hoardUnlock (sbrkLock);
return moreMemory;
#else
#if defined(linux)
#if USER_LOCKS
static hoardLockType sbrkLock = 0;
#else
static hoardLockType sbrkLock = PTHREAD_MUTEX_INITIALIZER;
#endif
#endif
// Use mmap to get memory from the backing store.
static int fd = ::open ("/dev/zero", O_RDWR);
#if defined(linux)
hoardLock (sbrkLock);
// Map starting at this address to maximize the amount of memory
// available to Hoard. Thanks to Jim Nance for this tip.
char * ptr = (char *) mmap ((void *) 0x10000000, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0);
#else
char * ptr = (char *) mmap (NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0);
#endif
char * retPtr;
if (ptr == (char *) MAP_FAILED) {
retPtr = NULL;
} else {
retPtr = ptr;
}
#if defined(linux)
hoardUnlock (sbrkLock);
#endif
return retPtr;
#endif
}
void hoardUnsbrk (void * ptr, long size)
{
#if defined(linux)
#if USER_LOCKS
static hoardLockType sbrkLock = 0;
#else
static hoardLockType sbrkLock = PTHREAD_MUTEX_INITIALIZER;
#endif
#endif
#if defined(linux)
hoardLock (sbrkLock);
#endif
int result = munmap ((char *) ptr, size);
assert (result == 0);
#if defined(linux)
hoardUnlock (sbrkLock);
#endif
}
int hoardGetPageSize (void)
{
return (int) sysconf(_SC_PAGESIZE);
}
#if defined(linux)
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#endif
#if defined(__sgi)
#include <sys/types.h>
#include <sys/sysmp.h>
#include <sys/sysinfo.h>
#endif
int hoardGetNumProcessors (void)
{
#if !(defined(linux))
#if defined(__sgi)
static int np = (int) sysmp(MP_NAPROCS);
return np;
#else
static int np = (int) sysconf(_SC_NPROCESSORS_ONLN);
return np;
#endif
#else
static int numProcessors = 0;
if (numProcessors == 0) {
// Ugly workaround. Linux's sysconf indirectly calls malloc() (at
// least on multiprocessors). So we just read the info from the
// proc file ourselves and count the occurrences of the word
// "processor".
// We only parse the first 32K of the CPU file. By my estimates,
// that should be more than enough for at least 64 processors.
enum { MAX_PROCFILE_SIZE = 32768 };
char line[MAX_PROCFILE_SIZE];
int fd = open ("/proc/cpuinfo", O_RDONLY);
assert (fd);
read(fd, line, MAX_PROCFILE_SIZE);
char * str = line;
while (str) {
str = strstr(str, "processor");
if (str) {
numProcessors++;
str++;
}
}
close (fd);
assert (numProcessors > 0);
}
return numProcessors;
#endif
}
#endif // UNIX
}

View File

@ -22,92 +22,24 @@
#include "config.h"
#if defined(NEWOS)
#include <syscalls.h>
#include <OS.h>
#include <assert.h>
#else
// Wrap architecture-specific functions.
#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32)
// Windows
#ifndef WIN32
#define WIN32 1
#endif
#include <windows.h>
#include <process.h>
typedef LONG hoardLockType;
typedef HANDLE hoardThreadType;
#elif defined(__BEOS__)
// BeOS
#include <OS.h>
#elif USE_SPROC
// SGI's SPROC library
#include <sys/types.h>
#include <sys/prctl.h>
#else
// Generic UNIX
#if defined(__SVR4) // Solaris
#include <thread.h>
#endif
#include <pthread.h>
#include <unistd.h>
#endif
#endif
#if defined(NEWOS)
typedef struct {
int32 ben;
sem_id sem;
int32 ben;
sem_id sem;
} hoardLockType;
typedef thread_id hoardThreadType;
inline void * operator new(size_t, void *_P)
{return (_P); }
#else
inline void *
operator new(size_t, void *_P)
{
return _P;
}
#ifndef WIN32
#if defined(__BEOS__)
typedef struct {
int32 ben;
sem_id sem;
} hoardLockType;
#elif USER_LOCKS && (defined(i386) || defined(sparc) || defined(__sgi))
typedef unsigned long hoardLockType;
#else
typedef pthread_mutex_t hoardLockType;
#endif
#if USE_SPROC
typedef pid_t hoardThreadType;
#elif defined(__BEOS__)
typedef thread_id hoardThreadType;
#else
typedef pthread_t hoardThreadType;
#endif
#endif
#endif
typedef thread_id hoardThreadType;
extern "C" {
///// Thread-related wrappers.
void hoardCreateThread (hoardThreadType& t,
@ -123,27 +55,9 @@ extern "C" {
///// Lock-related wrappers.
#if !defined(WIN32) && !defined(__BEOS__) && !USER_LOCKS
// Define the lock operations inline to save a little overhead.
inline void hoardLockInit (hoardLockType& lock) {
pthread_mutex_init (&lock, NULL);
}
inline void hoardLock (hoardLockType& lock) {
pthread_mutex_lock (&lock);
}
inline void hoardUnlock (hoardLockType& lock) {
pthread_mutex_unlock (&lock);
}
#else
void hoardLockInit (hoardLockType& lock);
void hoardLock (hoardLockType& lock);
void hoardUnlock (hoardLockType& lock);
#endif
void hoardLockInit(hoardLockType& lock, const char *name);
void hoardLock(hoardLockType& lock);
void hoardUnlock(hoardLockType& lock);
///// Memory-related wrapper.
@ -160,4 +74,3 @@ extern "C" {
}
#endif // _ARCH_SPECIFIC_H_

View File

@ -23,7 +23,7 @@
#include "processheap.h"
#include "superblock.h"
static const char version[] = "The Hoard memory allocator, version 2.0 (http://www.hoard.org). Copyright (C) 1998, 1999, 2000 The University of Texas at Austin. $Id: heap.cpp,v 1.1 2002/10/05 17:13:30 axeld Exp $";
static const char version[] = "The Hoard memory allocator, version 2.0 (http://www.hoard.org). Copyright (C) 1998, 1999, 2000 The University of Texas at Austin. $Id: heap.cpp,v 1.2 2005/02/10 18:47:16 axeld Exp $";
// NB: Use maketable.cpp to update this
// if SIZE_CLASSES, ALIGNMENT, SIZE_CLASS_BASE, MAX_EMPTY_SUPERBLOCKS,
@ -61,7 +61,7 @@ hoardHeap::hoardHeap (void)
#endif
{
// Initialize the per-heap lock.
hoardLockInit (_lock);
hoardLockInit(_lock, "hoard heap");
for (int i = 0; i < SUPERBLOCK_FULLNESS_GROUP; i++) {
for (int j = 0; j < SIZE_CLASSES; j++) {
// Initialize all superblocks lists to empty.

View File

@ -17,27 +17,14 @@
//
//////////////////////////////////////////////////////////////////////////////
/*
heap.h
------------------------------------------------------------------------
hoardHeap, the base class for threadHeap and processHeap.
------------------------------------------------------------------------
@(#) $Id: heap.h,v 1.1 2002/10/05 17:13:30 axeld Exp $
------------------------------------------------------------------------
Emery Berger | <http://www.cs.utexas.edu/users/emery>
Department of Computer Sciences | <http://www.cs.utexas.edu>
University of Texas at Austin | <http://www.utexas.edu>
========================================================================
*/
/* hoardHeap, the base class for threadHeap and processHeap. */
#ifndef _HEAP_H_
#define _HEAP_H_
#include "config.h"
#include <OS.h>
//include <assert.h>
//#include <math.h>
#include "config.h"
#include "arch-specific.h"
#include "superblock.h"
@ -74,7 +61,7 @@ public:
// number of threads -- Hoard imposes no such limit.) This must be
// a power of two! NB: This number is twice the maximum number of
// PROCESSORS supported by Hoard.
enum { MAX_HEAPS = 128 };
enum { MAX_HEAPS = B_MAX_CPU_COUNT };
// ANDing with this rounds to MAX_HEAPS.
enum { MAX_HEAPS_MASK = MAX_HEAPS - 1 };
@ -93,7 +80,7 @@ public:
#elif MAX_INTERNAL_FRAGMENTATION == 10
enum { SIZE_CLASSES = 32 };
#else
#error "Undefined size class base."
# error "Undefined size class base."
#endif
// Every object is aligned so that it can always hold a double.
@ -203,7 +190,7 @@ private:
// For sanity checking.
const unsigned long _magic;
#else
#define _magic HEAP_MAGIC
# define _magic HEAP_MAGIC
#endif
// Heap statistics.

View File

@ -62,9 +62,9 @@ processHeap::processHeap (void)
}
#endif
#if HEAP_FRAG_STATS
hoardLockInit (_statsLock);
hoardLockInit(_statsLock, "hoard stats");
#endif
hoardLockInit (_bufferLock);
hoardLockInit(_bufferLock, "hoard buffer");
}

View File

@ -17,18 +17,7 @@
//
//////////////////////////////////////////////////////////////////////////////
/*
processheap.h
------------------------------------------------------------------------
We use one processHeap for the whole program.
------------------------------------------------------------------------
@(#) $Id: processheap.h,v 1.1 2002/10/05 17:13:30 axeld Exp $
------------------------------------------------------------------------
Emery Berger | <http://www.cs.utexas.edu/users/emery>
Department of Computer Sciences | <http://www.cs.utexas.edu>
University of Texas at Austin | <http://www.utexas.edu>
========================================================================
*/
/* We use one processHeap for the whole program. */
#ifndef _PROCESSHEAP_H_
#define _PROCESSHEAP_H_

View File

@ -22,7 +22,7 @@
The superblock class controls a number of blocks (which are
allocatable units of memory).
------------------------------------------------------------------------
@(#) $Id: superblock.cpp,v 1.1 2002/10/05 17:13:30 axeld Exp $
@(#) $Id: superblock.cpp,v 1.2 2005/02/10 18:47:16 axeld Exp $
------------------------------------------------------------------------
Emery Berger | <http://www.cs.utexas.edu/users/emery>
Department of Computer Sciences | <http://www.cs.utexas.edu>
@ -84,7 +84,7 @@ superblock::superblock (int numBlocks, // The number of blocks in the sb.
computeFullness();
assert ((unsigned long) b <= hoardHeap::align (sizeof(superblock) + blksize * _numBlocks) + (unsigned long) this);
hoardLockInit (_upLock);
hoardLockInit(_upLock, "hoard superblock");
}
superblock * superblock::makeSuperblock (int sizeclass,

View File

@ -17,40 +17,25 @@
//
//////////////////////////////////////////////////////////////////////////////
/*
wrapper.cpp
------------------------------------------------------------------------
Implementations of malloc(), free(), etc. in terms of hoard.
This lets us link in hoard in place of the stock malloc
(useful to test fragmentation).
------------------------------------------------------------------------
@(#) $Id: wrapper.cpp,v 1.1 2002/10/05 17:13:30 axeld Exp $
------------------------------------------------------------------------
Emery Berger | <http://www.cs.utexas.edu/users/emery>
Department of Computer Sciences | <http://www.cs.utexas.edu>
University of Texas at Austin | <http://www.utexas.edu>
========================================================================
*/
/* Implementations of malloc(), free(), etc. in terms of hoard.
* This lets us link in hoard in place of the stock malloc
* (useful to test fragmentation).
*/
#include <string.h>
#include "config.h"
#if USE_PRIVATE_HEAPS
#include "privateheap.h"
#define HEAPTYPE privateHeap
#else
#include "threadheap.h"
#define HEAPTYPE threadHeap
#endif
#include "processheap.h"
#include "arch-specific.h"
inline static processHeap * getAllocator (void) {
static char * buf = (char *) hoardSbrk (sizeof(processHeap));
static processHeap * theAllocator = new (buf) processHeap;
return theAllocator;
inline static processHeap *
getAllocator(void)
{
static char *buffer = (char *)hoardSbrk(sizeof(processHeap));
static processHeap *theAllocator = new (buffer) processHeap;
return theAllocator;
}
#define HOARD_MALLOC(x) malloc(x)
@ -97,173 +82,86 @@ void operator delete[] (void * ptr)
}
extern "C" void * HOARD_MALLOC (size_t sz)
extern "C" void *
malloc(size_t size)
{
static processHeap * pHeap = getAllocator();
void * addr = pHeap->getHeap(pHeap->getHeapIndex()).malloc (sz);
return addr;
static processHeap *pHeap = getAllocator();
void *addr = pHeap->getHeap(pHeap->getHeapIndex()).malloc(size);
return addr;
}
extern "C" void * HOARD_CALLOC (size_t nelem, size_t elsize)
extern "C" void *
calloc(size_t nelem, size_t elsize)
{
static processHeap * pHeap = getAllocator();
void * ptr = pHeap->getHeap(pHeap->getHeapIndex()).malloc (nelem * elsize);
// Zero out the malloc'd block.
memset (ptr, 0, nelem * elsize);
return ptr;
static processHeap *pHeap = getAllocator();
void *ptr = pHeap->getHeap(pHeap->getHeapIndex()).malloc(nelem * elsize);
// Zero out the malloc'd block.
memset(ptr, 0, nelem * elsize);
return ptr;
}
extern "C" void HOARD_FREE (void * ptr)
extern "C" void
free(void *ptr)
{
static processHeap * pHeap = getAllocator();
#if USE_PRIVATE_HEAPS
pHeap->getHeap(pHeap->getHeapIndex()).free(ptr);
#else
pHeap->free (ptr);
#endif
static processHeap *pHeap = getAllocator();
pHeap->free(ptr);
}
extern "C" void * HOARD_MEMALIGN (size_t alignment, size_t size)
extern "C" void *
memalign(size_t alignment, size_t size)
{
static processHeap * pHeap = getAllocator();
void * addr = pHeap->getHeap(pHeap->getHeapIndex()).memalign (alignment, size);
return addr;
static processHeap *pHeap = getAllocator();
void *addr = pHeap->getHeap(pHeap->getHeapIndex()).memalign (alignment, size);
return addr;
}
extern "C" void * HOARD_VALLOC (size_t size)
extern "C" void *
valloc(size_t size)
{
return HOARD_MEMALIGN (hoardGetPageSize(), size);
return memalign(hoardGetPageSize(), size);
}
extern "C" void * HOARD_REALLOC (void * ptr, size_t sz)
extern "C" void *
realloc(void *ptr, size_t sz)
{
if (ptr == NULL) {
return HOARD_MALLOC (sz);
}
if (sz == 0) {
HOARD_FREE (ptr);
return NULL;
}
if (ptr == NULL)
return HOARD_MALLOC (sz);
// If the existing object can hold the new size,
// just return it.
if (sz == 0) {
free(ptr);
return NULL;
}
size_t objSize = HEAPTYPE::objectSize (ptr);
// If the existing object can hold the new size,
// just return it.
if (objSize >= sz) {
return ptr;
}
size_t objSize = threadHeap::objectSize(ptr);
if (objSize >= sz)
return ptr;
// Allocate a new block of size sz.
// Allocate a new block of size sz.
void * buf = HOARD_MALLOC (sz);
void *buffer = malloc(sz);
// Copy the contents of the original object
// up to the size of the new block.
// Copy the contents of the original object
// up to the size of the new block.
size_t minSize = (objSize < sz) ? objSize : sz;
memcpy (buf, ptr, minSize);
size_t minSize = (objSize < sz) ? objSize : sz;
memcpy(buffer, ptr, minSize);
// Free the old block.
// Free the old block.
HOARD_FREE (ptr);
free(ptr);
// Return a pointer to the new one.
return buf;
// Return a pointer to the new one.
return buffer;
}
#ifdef WIN32
// Replace the CRT debugging allocation routines, just to be on the safe side.
// This is not a complete solution, but should avoid inadvertent mixing of allocations.
extern "C" void * _malloc_dbg (size_t sz, int, const char *, int) {
return HOARD_MALLOC (sz);
}
void * operator new(
unsigned int cb,
int nBlockUse,
const char * szFileName,
int nLine
)
{
return HOARD_MALLOC (cb);
}
extern "C" void * _calloc_dbg (size_t num, size_t size, int, const char *, int) {
return HOARD_CALLOC (num, size);
}
extern "C" void * _realloc_dbg (void * ptr, size_t newSize, int, const char *, int) {
return HOARD_REALLOC (ptr, newSize);
}
extern "C" void _free_dbg (void * ptr, int) {
HOARD_FREE (ptr);
}
extern "C" size_t _msize_dbg (void * ptr) {
// Find the block and superblock corresponding to this ptr.
block * b = (block *) ptr - 1;
assert (b->isValid());
// Check to see if this block came from a memalign() call.
if (((unsigned long) b->getNext() & 1) == 1) {
// It did. Set the block to the actual block header.
b = (block *) ((unsigned long) b->getNext() & ~1);
assert (b->isValid());
}
superblock * sb = b->getSuperblock();
assert (sb);
assert (sb->isValid());
const int sizeclass = sb->getBlockSizeClass();
return hoardHeap::sizeFromClass (sizeclass);
}
extern "C" size_t _msize (void * ptr) {
// Find the block and superblock corresponding to this ptr.
block * b = (block *) ptr - 1;
assert (b->isValid());
// Check to see if this block came from a memalign() call.
if (((unsigned long) b->getNext() & 1) == 1) {
// It did. Set the block to the actual block header.
b = (block *) ((unsigned long) b->getNext() & ~1);
assert (b->isValid());
}
superblock * sb = b->getSuperblock();
assert (sb);
assert (sb->isValid());
const int sizeclass = sb->getBlockSizeClass();
return hoardHeap::sizeFromClass (sizeclass);
}
extern "C" void * _nh_malloc_base (size_t sz, int) {
return HOARD_MALLOC (sz);
}
extern "C" void * _nh_malloc_dbg (size_t sz, size_t, int, int, const char *, int) {
return HOARD_MALLOC (sz);
}
#endif // WIN32
#if 0
extern "C" void malloc_stats (void)
{
TheWrapper.TheAllocator()->stats();
}
#endif