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:
parent
577c5fac30
commit
71aa315c95
@ -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
|
||||
;
|
||||
|
@ -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
|
||||
|
||||
}
|
||||
|
@ -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_
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
|
||||
|
@ -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_
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user