Removed the khash, condition variable, lock, block cache, and slab

implementations and instead use the kernel sources directly or the
libkernelland_emu sources.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@29456 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2009-03-09 00:55:55 +00:00
parent e055b92aac
commit daa674789c
14 changed files with 32 additions and 4771 deletions
@@ -8,8 +8,9 @@
#include <fs_interface.h>
#include "block_cache.h"
#include "condition_variable.h"
#include <block_cache.h>
#include <condition_variable.h>
#include "HaikuKernelVolume.h"
@@ -36,13 +37,11 @@ status_t
HaikuKernelFileSystem::Init()
{
// init condition variables
status_t error = condition_variable_init();
if (error != B_OK)
RETURN_ERROR(error);
condition_variable_init();
// TODO: Call the cleanup methods, if something goes wrong!
// init block cache
error = block_cache_init();
status_t error = block_cache_init();
if (error != B_OK)
RETURN_ERROR(error);
@@ -8,11 +8,13 @@ SubDirSysHdrs [ FDirName $(userlandFSIncludes) ] ;
SubDirHdrs [ FDirName $(userlandFSIncludes) private ] ;
SubDirHdrs [ FDirName $(userlandFSIncludes) shared ] ;
UsePrivateSystemHeaders ;
UsePrivateHeaders kernel libroot shared ;
UsePrivateKernelHeaders ;
UsePrivateHeaders libroot shared ;
SEARCH_SOURCE += [ FDirName $(userlandFSTop) private ] ;
SEARCH_SOURCE += [ FDirName $(userlandFSTop) shared ] ;
SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src tests add-ons kernel
kernelland_emu ] ;
DEFINES += USER=1 ;
DEFINES += DEBUG_APP="\\\"libuserlandfs_haiku\\\"" ;
@@ -21,15 +23,25 @@ DEFINES += BUILDING_USERLAND_FS_SERVER=1 ;
# the library providing the Haiku kernel interface for add-ons
SharedLibrary libuserlandfs_haiku_kernel.so
:
block_cache.cpp
# kernelland_emu
condition_variable.cpp
file_cache.cpp
file_map.cpp
khash.cpp
debug.cpp
lock.cpp
low_resource_manager.cpp
misc.cpp
scheduler.cpp
slab.cpp
# kernel
block_cache.cpp
file_map.cpp
khash.c
# emulation
file_cache.cpp
haiku_kernel_emu.cpp
# UserlandFS server interface
HaikuKernelFileSystem.cpp
HaikuKernelVolume.cpp
@@ -37,3 +49,12 @@ SharedLibrary libuserlandfs_haiku_kernel.so
<nogrist>userlandfs_server
be # for BLocker only
;
SEARCH on [ FGristFiles
block_cache.cpp
file_map.cpp
] = [ FDirName $(HAIKU_TOP) src system kernel cache ] ;
SEARCH on [ FGristFiles
khash.c
] = [ FDirName $(HAIKU_TOP) src system kernel util ] ;
File diff suppressed because it is too large Load Diff
@@ -1,20 +0,0 @@
/*
* Copyright 2005, Axel Dörfler, axeld@pinc-software.de.
* Distributed under the terms of the MIT License.
*/
#ifndef USERLAND_FS_HAIKU_BLOCK_CACHE_H
#define USERLAND_FS_HAIKU_BLOCK_CACHE_H
#include <SupportDefs.h>
extern "C" {
status_t block_cache_init(void);
size_t block_cache_used_memory();
}
#endif // USERLAND_FS_HAIKU_BLOCK_CACHE_H
@@ -1,254 +0,0 @@
/*
* Copyright 2007-2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "condition_variable.h"
#include <new>
#include <stdlib.h>
#include <string.h>
#include <Debug.h>
#include <KernelExport.h>
// libroot
#include <user_thread.h>
// system
#include <syscalls.h>
#include <user_thread_defs.h>
#include "lock.h"
#define STATUS_ADDED 1
#define STATUS_WAITING 2
static const int kConditionVariableHashSize = 512;
struct ConditionVariableHashDefinition {
typedef const void* KeyType;
typedef ConditionVariable ValueType;
size_t HashKey(const void* key) const
{ return (size_t)key; }
size_t Hash(ConditionVariable* variable) const
{ return (size_t)variable->fObject; }
bool Compare(const void* key, ConditionVariable* variable) const
{ return key == variable->fObject; }
HashTableLink<ConditionVariable>* GetLink(ConditionVariable* variable) const
{ return variable; }
};
typedef OpenHashTable<ConditionVariableHashDefinition> ConditionVariableHash;
static ConditionVariableHash sConditionVariableHash;
static mutex sConditionVariablesLock;
static mutex sThreadsLock;
// #pragma mark - ConditionVariableEntry
bool
ConditionVariableEntry::Add(const void* object)
{
ASSERT(object != NULL);
fThread = find_thread(NULL);
MutexLocker _(sConditionVariablesLock);
fVariable = sConditionVariableHash.Lookup(object);
if (fVariable == NULL) {
fWaitStatus = B_ENTRY_NOT_FOUND;
return false;
}
fWaitStatus = STATUS_ADDED;
fVariable->fEntries.Add(this);
return true;
}
status_t
ConditionVariableEntry::Wait(uint32 flags, bigtime_t timeout)
{
MutexLocker conditionLocker(sConditionVariablesLock);
if (fVariable == NULL)
return fWaitStatus;
user_thread* userThread = get_user_thread();
userThread->wait_status = 1;
fWaitStatus = STATUS_WAITING;
conditionLocker.Unlock();
MutexLocker threadLocker(sThreadsLock);
status_t error;
if ((flags & (B_RELATIVE_TIMEOUT | B_ABSOLUTE_TIMEOUT)) != 0)
error = _kern_block_thread(flags, timeout);
else
error = _kern_block_thread(0, 0);
threadLocker.Unlock();
conditionLocker.Lock();
// remove entry from variable, if not done yet
if (fVariable != NULL) {
fVariable->fEntries.Remove(this);
fVariable = NULL;
}
return error;
}
status_t
ConditionVariableEntry::Wait(const void* object, uint32 flags,
bigtime_t timeout)
{
if (Add(object))
return Wait(flags, timeout);
return B_ENTRY_NOT_FOUND;
}
inline void
ConditionVariableEntry::AddToVariable(ConditionVariable* variable)
{
fThread = find_thread(NULL);
MutexLocker _(sConditionVariablesLock);
fVariable = variable;
fWaitStatus = STATUS_ADDED;
fVariable->fEntries.Add(this);
}
// #pragma mark - ConditionVariable
/*! Initialization method for anonymous (unpublished) condition variables.
*/
void
ConditionVariable::Init(const void* object, const char* objectType)
{
fObject = object;
fObjectType = objectType;
new(&fEntries) EntryList;
}
void
ConditionVariable::Publish(const void* object, const char* objectType)
{
ASSERT(object != NULL);
fObject = object;
fObjectType = objectType;
new(&fEntries) EntryList;
MutexLocker locker(sConditionVariablesLock);
ASSERT(sConditionVariableHash.Lookup(object) == NULL);
sConditionVariableHash.InsertUnchecked(this);
}
void
ConditionVariable::Unpublish(bool threadsLocked)
{
ASSERT(fObject != NULL);
MutexLocker threadLocker(threadsLocked ? NULL : &sThreadsLock);
MutexLocker locker(sConditionVariablesLock);
sConditionVariableHash.RemoveUnchecked(this);
fObject = NULL;
fObjectType = NULL;
if (!fEntries.IsEmpty())
_NotifyChecked(true, B_ENTRY_NOT_FOUND);
}
void
ConditionVariable::Add(ConditionVariableEntry* entry)
{
entry->AddToVariable(this);
}
status_t
ConditionVariable::Wait(uint32 flags, bigtime_t timeout)
{
ConditionVariableEntry entry;
Add(&entry);
return entry.Wait(flags, timeout);
}
void
ConditionVariable::_Notify(bool all, bool threadsLocked)
{
MutexLocker threadLocker(threadsLocked ? NULL : &sThreadsLock);
MutexLocker locker(sConditionVariablesLock);
if (!fEntries.IsEmpty())
_NotifyChecked(all, B_OK);
}
/*! Called with interrupts disabled and the condition variable spinlock and
thread lock held.
*/
void
ConditionVariable::_NotifyChecked(bool all, status_t result)
{
// dequeue and wake up the blocked threads
while (ConditionVariableEntry* entry = fEntries.RemoveHead()) {
entry->fVariable = NULL;
if (entry->fWaitStatus <= 0)
continue;
if (entry->fWaitStatus == STATUS_WAITING)
_kern_unblock_thread(entry->fThread, result);
entry->fWaitStatus = result;
if (!all)
break;
}
}
// #pragma mark -
status_t
condition_variable_init()
{
mutex_init(&sConditionVariablesLock, "condition variables");
mutex_init(&sThreadsLock, "threads");
new(&sConditionVariableHash) ConditionVariableHash;
status_t error = sConditionVariableHash.Init(kConditionVariableHashSize);
if (error != B_OK) {
panic("condition_variable_init(): Failed to init hash table: %s",
strerror(error));
}
return error;
}
@@ -1,94 +0,0 @@
/*
* Copyright 2007-2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef USERLAND_FS_HAIKU_CONDITION_VARIABLE_H
#define USERLAND_FS_HAIKU_CONDITION_VARIABLE_H
#include <OS.h>
#include <kernel/util/DoublyLinkedList.h>
#include <kernel/util/OpenHashTable.h>
class ConditionVariable;
struct ConditionVariableEntry
: DoublyLinkedListLinkImpl<ConditionVariableEntry> {
public:
bool Add(const void* object);
status_t Wait(uint32 flags = 0, bigtime_t timeout = 0);
status_t Wait(const void* object, uint32 flags = 0,
bigtime_t timeout = 0);
inline ConditionVariable* Variable() const { return fVariable; }
private:
inline void AddToVariable(ConditionVariable* variable);
private:
ConditionVariable* fVariable;
thread_id fThread;
status_t fWaitStatus;
friend class ConditionVariable;
};
class ConditionVariable : protected HashTableLink<ConditionVariable> {
public:
void Init(const void* object,
const char* objectType);
// for anonymous (unpublished) cvars
void Publish(const void* object,
const char* objectType);
void Unpublish(bool threadsLocked = false);
inline void NotifyOne(bool threadsLocked = false);
inline void NotifyAll(bool threadsLocked = false);
void Add(ConditionVariableEntry* entry);
status_t Wait(uint32 flags = 0, bigtime_t timeout = 0);
// all-in one, i.e. doesn't need a
// ConditionVariableEntry
const void* Object() const { return fObject; }
const char* ObjectType() const { return fObjectType; }
private:
void _Notify(bool all, bool threadsLocked);
void _NotifyChecked(bool all, status_t result);
protected:
typedef DoublyLinkedList<ConditionVariableEntry> EntryList;
const void* fObject;
const char* fObjectType;
EntryList fEntries;
friend class ConditionVariableEntry;
friend class ConditionVariableHashDefinition;
};
inline void
ConditionVariable::NotifyOne(bool threadsLocked)
{
_Notify(false, threadsLocked);
}
inline void
ConditionVariable::NotifyAll(bool threadsLocked)
{
_Notify(true, threadsLocked);
}
status_t condition_variable_init();
#endif // USERLAND_FS_HAIKU_CONDITION_VARIABLE_H
@@ -1,647 +0,0 @@
/*
* Copyright 2004-2008, Axel Dörfler, axeld@pinc-software.de.
* Distributed under the terms of the MIT License.
*/
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <new>
#include <KernelExport.h>
#include <fs_cache.h>
#include <kernel/util/DoublyLinkedList.h>
#include "lock.h"
#include "vfs.h"
//#define TRACE_FILE_MAP
#ifdef TRACE_FILE_MAP
# define TRACE(x...) dprintf_no_syslog(x)
#else
# define TRACE(x...) ;
#endif
// TODO: use a sparse array - eventually, the unused BlockMap would be something
// to reuse for this. We could also have an upperbound of memory consumption
// for the whole map.
// TODO: it would be nice if we could free a file map in low memory situations.
#define CACHED_FILE_EXTENTS 2
// must be smaller than MAX_FILE_IO_VECS
// TODO: find out how much of these are typically used
struct file_extent {
off_t offset;
file_io_vec disk;
};
struct file_extent_array {
file_extent* array;
size_t max_count;
};
class FileMap
#if DEBUG_FILE_MAP
: public DoublyLinkedListLinkImpl<FileMap>
#endif
{
public:
FileMap(struct vnode* vnode, off_t size);
~FileMap();
void Invalidate(off_t offset, off_t size);
void SetSize(off_t size);
status_t Translate(off_t offset, size_t size,
file_io_vec* vecs, size_t* _count,
size_t align);
file_extent* ExtentAt(uint32 index);
size_t Count() const { return fCount; }
struct vnode* Vnode() const { return fVnode; }
off_t Size() const { return fSize; }
status_t SetMode(uint32 mode);
private:
file_extent* _FindExtent(off_t offset, uint32* _index);
status_t _MakeSpace(size_t count);
status_t _Add(file_io_vec* vecs, size_t vecCount,
off_t& lastOffset);
status_t _Cache(off_t offset, off_t size);
void _InvalidateAfter(off_t offset);
void _Free();
union {
file_extent fDirect[CACHED_FILE_EXTENTS];
file_extent_array fIndirect;
};
mutex fLock;
size_t fCount;
struct vnode* fVnode;
off_t fSize;
bool fCacheAll;
};
#if DEBUG_FILE_MAP
typedef DoublyLinkedList<FileMap> FileMapList;
static FileMapList sList;
static mutex sLock;
#endif
FileMap::FileMap(struct vnode* vnode, off_t size)
:
fCount(0),
fVnode(vnode),
fSize(size),
fCacheAll(false)
{
mutex_init(&fLock, "file map");
#if DEBUG_FILE_MAP
MutexLocker _(sLock);
sList.Add(this);
#endif
}
FileMap::~FileMap()
{
_Free();
mutex_destroy(&fLock);
#if DEBUG_FILE_MAP
MutexLocker _(sLock);
sList.Remove(this);
#endif
}
file_extent*
FileMap::ExtentAt(uint32 index)
{
if (index >= fCount)
return NULL;
if (fCount > CACHED_FILE_EXTENTS)
return &fIndirect.array[index];
return &fDirect[index];
}
file_extent*
FileMap::_FindExtent(off_t offset, uint32 *_index)
{
int32 left = 0;
int32 right = fCount - 1;
while (left <= right) {
int32 index = (left + right) / 2;
file_extent* extent = ExtentAt(index);
if (extent->offset > offset) {
// search in left part
right = index - 1;
} else if (extent->offset + extent->disk.length <= offset) {
// search in right part
left = index + 1;
} else {
// found extent
if (_index)
*_index = index;
return extent;
}
}
return NULL;
}
status_t
FileMap::_MakeSpace(size_t count)
{
if (count <= CACHED_FILE_EXTENTS) {
// just use the reserved area in the file_cache_ref structure
if (fCount > CACHED_FILE_EXTENTS) {
// the new size is smaller than the minimal array size
file_extent *array = fIndirect.array;
memcpy(fDirect, array, sizeof(file_extent) * count);
free(array);
}
} else {
// resize array if needed
file_extent* oldArray = NULL;
size_t maxCount = CACHED_FILE_EXTENTS;
if (fCount > CACHED_FILE_EXTENTS) {
oldArray = fIndirect.array;
maxCount = fIndirect.max_count;
}
if (count > maxCount) {
// allocate new array
while (maxCount < count) {
if (maxCount < 32768)
maxCount <<= 1;
else
maxCount += 32768;
}
file_extent* newArray = (file_extent *)realloc(oldArray,
maxCount * sizeof(file_extent));
if (newArray == NULL)
return B_NO_MEMORY;
if (fCount > 0 && fCount <= CACHED_FILE_EXTENTS)
memcpy(newArray, fDirect, sizeof(file_extent) * fCount);
fIndirect.array = newArray;
fIndirect.max_count = maxCount;
}
}
fCount = count;
return B_OK;
}
status_t
FileMap::_Add(file_io_vec* vecs, size_t vecCount, off_t& lastOffset)
{
TRACE("FileMap@%p::Add(vecCount = %ld)\n", this, vecCount);
uint32 start = fCount;
off_t offset = 0;
status_t status = _MakeSpace(fCount + vecCount);
if (status != B_OK)
return status;
file_extent* lastExtent = NULL;
if (start != 0) {
lastExtent = ExtentAt(start - 1);
offset = lastExtent->offset + lastExtent->disk.length;
}
for (uint32 i = 0; i < vecCount; i++) {
if (lastExtent != NULL) {
if (lastExtent->disk.offset + lastExtent->disk.length
== vecs[i].offset
|| (lastExtent->disk.offset == -1 && vecs[i].offset == -1)) {
lastExtent->disk.length += vecs[i].length;
offset += vecs[i].length;
start--;
_MakeSpace(fCount - 1);
continue;
}
}
file_extent* extent = ExtentAt(start + i);
extent->offset = offset;
extent->disk = vecs[i];
offset += extent->disk.length;
lastExtent = extent;
}
#ifdef TRACE_FILE_MAP
for (uint32 i = 0; i < fCount; i++) {
file_extent* extent = ExtentAt(i);
TRACE("[%ld] extent offset %Ld, disk offset %Ld, length %Ld\n",
i, extent->offset, extent->disk.offset, extent->disk.length);
}
#endif
lastOffset = offset;
return B_OK;
}
void
FileMap::_InvalidateAfter(off_t offset)
{
uint32 index;
file_extent* extent = _FindExtent(offset, &index);
if (extent != NULL) {
_MakeSpace(index + 1);
if (extent->offset + extent->disk.length > offset) {
extent->disk.length = offset - extent->offset;
if (extent->disk.length == 0)
_MakeSpace(index);
}
}
}
/*! Invalidates or removes the specified part of the file map.
*/
void
FileMap::Invalidate(off_t offset, off_t size)
{
MutexLocker _(fLock);
// TODO: honour size, we currently always remove everything after "offset"
if (offset == 0) {
_Free();
return;
}
_InvalidateAfter(offset);
}
void
FileMap::SetSize(off_t size)
{
MutexLocker _(fLock);
if (size < fSize)
_InvalidateAfter(size);
fSize = size;
}
void
FileMap::_Free()
{
if (fCount > CACHED_FILE_EXTENTS)
free(fIndirect.array);
fCount = 0;
}
status_t
FileMap::_Cache(off_t offset, off_t size)
{
file_extent* lastExtent = NULL;
if (fCount > 0)
lastExtent = ExtentAt(fCount - 1);
off_t mapEnd = 0;
if (lastExtent != NULL)
mapEnd = lastExtent->offset + lastExtent->disk.length;
off_t end = offset + size;
if (fCacheAll && mapEnd < end)
return B_ERROR;
status_t status = B_OK;
file_io_vec vecs[8];
const size_t kMaxVecs = 8;
while (status == B_OK && mapEnd < end) {
// We don't have the requested extents yet, retrieve them
size_t vecCount = kMaxVecs;
status = vfs_get_file_map(Vnode(), mapEnd, ~0UL, vecs, &vecCount);
if (status == B_OK || status == B_BUFFER_OVERFLOW)
status = _Add(vecs, vecCount, mapEnd);
}
return status;
}
status_t
FileMap::SetMode(uint32 mode)
{
if (mode != FILE_MAP_CACHE_ALL && mode != FILE_MAP_CACHE_ON_DEMAND)
return B_BAD_VALUE;
MutexLocker _(fLock);
if ((mode == FILE_MAP_CACHE_ALL && fCacheAll)
|| (mode == FILE_MAP_CACHE_ON_DEMAND && !fCacheAll))
return B_OK;
if (mode == FILE_MAP_CACHE_ALL) {
status_t status = _Cache(0, fSize);
if (status != B_OK)
return status;
fCacheAll = true;
} else
fCacheAll = false;
return B_OK;
}
status_t
FileMap::Translate(off_t offset, size_t size, file_io_vec* vecs, size_t* _count,
size_t align)
{
MutexLocker _(fLock);
size_t maxVecs = *_count;
size_t padLastVec = 0;
if (offset >= Size()) {
*_count = 0;
return B_OK;
}
if (offset + size > fSize) {
if (align > 1) {
off_t alignedSize = (fSize + align - 1) & ~(off_t)(align - 1);
if (offset + size >= alignedSize)
padLastVec = alignedSize - fSize;
}
size = fSize - offset;
}
// First, we need to make sure that we have already cached all file
// extents needed for this request.
status_t status = _Cache(offset, size);
if (status != B_OK)
return status;
// We now have cached the map of this file as far as we need it, now
// we need to translate it for the requested access.
uint32 index;
file_extent* fileExtent = _FindExtent(offset, &index);
offset -= fileExtent->offset;
if (fileExtent->disk.offset != -1)
vecs[0].offset = fileExtent->disk.offset + offset;
else
vecs[0].offset = -1;
vecs[0].length = fileExtent->disk.length - offset;
if (vecs[0].length >= size) {
vecs[0].length = size + padLastVec;
*_count = 1;
return B_OK;
}
// copy the rest of the vecs
size -= vecs[0].length;
uint32 vecIndex = 1;
while (true) {
fileExtent++;
vecs[vecIndex++] = fileExtent->disk;
if (size <= fileExtent->disk.length) {
vecs[vecIndex - 1].length = size + padLastVec;
break;
}
if (vecIndex >= maxVecs) {
*_count = vecIndex;
return B_BUFFER_OVERFLOW;
}
size -= fileExtent->disk.length;
}
*_count = vecIndex;
return B_OK;
}
// #pragma mark -
#if DEBUG_FILE_MAP
static int
dump_file_map(int argc, char** argv)
{
if (argc < 2) {
print_debugger_command_usage(argv[0]);
return 0;
}
bool printExtents = false;
if (argc > 2 && !strcmp(argv[1], "-p"))
printExtents = true;
FileMap* map = (FileMap*)parse_expression(argv[argc - 1]);
if (map == NULL) {
kprintf("invalid file map!\n");
return 0;
}
kprintf("FileMap %p\n", map);
kprintf(" size %Ld\n", map->Size());
kprintf(" count %lu\n", map->Count());
if (!printExtents)
return 0;
for (uint32 i = 0; i < map->Count(); i++) {
file_extent* extent = map->ExtentAt(i);
kprintf(" [%lu] offset %Ld, disk offset %Ld, length %Ld\n",
i, extent->offset, extent->disk.offset, extent->disk.length);
}
return 0;
}
static int
dump_file_map_stats(int argc, char** argv)
{
off_t minSize = 0;
off_t maxSize = -1;
if (argc == 2) {
maxSize = parse_expression(argv[1]);
} else if (argc > 2) {
minSize = parse_expression(argv[1]);
maxSize = parse_expression(argv[2]);
}
FileMapList::Iterator iterator = sList.GetIterator();
off_t size = 0;
off_t mapSize = 0;
uint32 extents = 0;
uint32 count = 0;
uint32 emptyCount = 0;
while (iterator.HasNext()) {
FileMap* map = iterator.Next();
if (minSize > map->Size() || (maxSize != -1 && maxSize < map->Size()))
continue;
if (map->Count() != 0) {
file_extent* extent = map->ExtentAt(map->Count() - 1);
if (extent != NULL)
mapSize += extent->offset + extent->disk.length;
extents += map->Count();
} else
emptyCount++;
size += map->Size();
count++;
}
kprintf("%ld file maps (%ld empty), %Ld file bytes in total, %Ld bytes "
"cached, %lu extents\n", count, emptyCount, size, mapSize, extents);
kprintf("average %lu extents per map for %Ld bytes.\n",
extents / (count - emptyCount), mapSize / (count - emptyCount));
return 0;
}
#endif // DEBUG_FILE_MAP
// #pragma mark - private kernel API
extern "C" status_t
file_map_init(void)
{
#if DEBUG_FILE_MAP
add_debugger_command_etc("file_map", &dump_file_map,
"Dumps the specified file map.",
"[-p] <file-map>\n"
" -p - causes the file extents to be printed as well.\n"
" <file-map> - pointer to the file map.\n", 0);
add_debugger_command("file_map_stats", &dump_file_map_stats,
"Dumps some file map statistics.");
mutex_init(&sLock, "file map list");
#endif
return B_OK;
}
// #pragma mark - public FS API
extern "C" void*
file_map_create(dev_t mountID, ino_t vnodeID, off_t size)
{
TRACE("file_map_create(mountID = %ld, vnodeID = %Ld, size = %Ld)\n",
mountID, vnodeID, size);
// Get the vnode for the object
// (note, this does not grab a reference to the node)
struct vnode* vnode;
if (vfs_lookup_vnode(mountID, vnodeID, &vnode) != B_OK)
return NULL;
return new(std::nothrow) FileMap(vnode, size);
}
extern "C" void
file_map_delete(void* _map)
{
FileMap* map = (FileMap*)_map;
if (map == NULL)
return;
TRACE("file_map_delete(map = %p)\n", map);
delete map;
}
extern "C" void
file_map_set_size(void* _map, off_t size)
{
FileMap* map = (FileMap*)_map;
if (map == NULL)
return;
map->SetSize(size);
}
extern "C" void
file_map_invalidate(void* _map, off_t offset, off_t size)
{
FileMap* map = (FileMap*)_map;
if (map == NULL)
return;
map->Invalidate(offset, size);
}
extern "C" status_t
file_map_set_mode(void* _map, uint32 mode)
{
FileMap* map = (FileMap*)_map;
if (map == NULL)
return B_BAD_VALUE;
return map->SetMode(mode);
}
extern "C" status_t
file_map_translate(void* _map, off_t offset, size_t size, file_io_vec* vecs,
size_t* _count, size_t align)
{
TRACE("file_map_translate(map %p, offset %Ld, size %ld)\n",
_map, offset, size);
FileMap* map = (FileMap*)_map;
if (map == NULL)
return B_BAD_VALUE;
return map->Translate(offset, size, vecs, _count, align);
}
@@ -279,76 +279,3 @@ vfs_lookup_vnode(dev_t mountID, ino_t vnodeID, struct vnode **_vnode)
return B_OK;
}
// #pragma mark - Misc
// kernel_debugger
void
kernel_debugger(const char *message)
{
UserlandFS::KernelEmu::kernel_debugger(message);
}
// panic
void
panic(const char *format, ...)
{
char buffer[1024];
strcpy(buffer, "PANIC: ");
int32 prefixLen = strlen(buffer);
int bufferSize = sizeof(buffer) - prefixLen;
va_list args;
va_start(args, format);
vsnprintf(buffer + prefixLen, bufferSize - 1, format, args);
va_end(args);
buffer[sizeof(buffer) - 1] = '\0';
debugger(buffer);
}
// add_debugger_command
int
add_debugger_command(char *name, debugger_command_hook hook, char *help)
{
return UserlandFS::KernelEmu::add_debugger_command(name, hook, help);
}
// remove_debugger_command
int
remove_debugger_command(char *name, debugger_command_hook hook)
{
return UserlandFS::KernelEmu::remove_debugger_command(name, hook);
}
// parse_expression
uint64
parse_expression(const char *string)
{
return UserlandFS::KernelEmu::parse_expression(string);
}
// dprintf
void
dprintf(const char *format, ...)
{
va_list args;
va_start(args, format);
UserlandFS::KernelEmu::vdprintf(format, args);
va_end(args);
}
// kprintf
void
kprintf(const char *format, ...)
{
}
// spawn_kernel_thread
thread_id
spawn_kernel_thread(thread_func function, const char *threadName,
int32 priority, void *arg)
{
return UserlandFS::KernelEmu::spawn_kernel_thread(function, threadName,
priority, arg);
}
@@ -1,434 +0,0 @@
/* Generic hash table
**
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
** Distributed under the terms of the NewOS License.
*/
#include "khash.h"
#include <stdlib.h>
#include <string.h>
#include <Debug.h>
#include <Errors.h>
#include <KernelExport.h>
#undef TRACE
#define TRACE_HASH 0
#if TRACE_HASH
# define TRACE(x) dprintf x
#else
# define TRACE(x) ;
#endif
// TODO: the hashtable is not expanded when necessary (no load factor, nothing)
// resizing should be optional, though, in case the hash is used at times
// that forbid resizing.
struct hash_table {
struct hash_element **table;
int next_ptr_offset;
uint32 table_size;
int num_elements;
int flags;
int (*compare_func)(void *e, const void *key);
uint32 (*hash_func)(void *e, const void *key, uint32 range);
};
// XXX gross hack
#define NEXT_ADDR(t, e) ((void *)(((unsigned long)(e)) + (t)->next_ptr_offset))
#define NEXT(t, e) ((void *)(*(unsigned long *)NEXT_ADDR(t, e)))
#define PUT_IN_NEXT(t, e, val) (*(unsigned long *)NEXT_ADDR(t, e) = (long)(val))
const uint32 kPrimes [] = {
13, 31, 61, 127, 251,
509, 1021, 2039, 4093, 8191, 16381, 32749, 65521, 131071, 262139,
524287, 1048573, 2097143, 4194301, 8388593, 16777213, 33554393, 67108859,
134217689, 268435399, 536870909, 1073741789, 2147483647, 0
};
static uint32
get_prime_table_size(uint32 size)
{
int i;
for (i = 0; kPrimes[i] != 0; i++) {
if (kPrimes[i] > size)
return kPrimes[i];
}
return kPrimes[i - 1];
}
static inline void *
next_element(hash_table *table, void *element)
{
// ToDo: should we use this instead of the NEXT() macro?
return (void *)(*(unsigned long *)NEXT_ADDR(table, element));
}
static status_t
hash_grow(struct hash_table *table)
{
uint32 newSize = get_prime_table_size(table->num_elements);
struct hash_element **newTable;
uint32 index;
if (table->table_size >= newSize)
return B_OK;
newTable = (struct hash_element **)malloc(sizeof(void *) * newSize);
if (newTable == NULL)
return B_NO_MEMORY;
memset(newTable, 0, sizeof(void *) * newSize);
// rehash all the entries and add them to the new table
for (index = 0; index < table->table_size; index++) {
void *element;
void *next;
for (element = table->table[index]; element != NULL; element = next) {
uint32 hash = table->hash_func(element, NULL, newSize);
next = NEXT(table, element);
PUT_IN_NEXT(table, element, newTable[hash]);
newTable[hash] = (struct hash_element *)element;
}
}
free(table->table);
table->table = newTable;
table->table_size = newSize;
TRACE(("hash_grow: grown table %p, new size %lu\n", table, newSize));
return B_OK;
}
// #pragma mark - kernel private API
struct hash_table *
hash_init(uint32 tableSize, int nextPointerOffset,
int compareFunc(void *e, const void *key),
uint32 hashFunc(void *e, const void *key, uint32 range))
{
struct hash_table *t;
uint32 i;
tableSize = get_prime_table_size(tableSize);
if (compareFunc == NULL || hashFunc == NULL) {
dprintf("hash_init() called with NULL function pointer\n");
return NULL;
}
t = (struct hash_table *)malloc(sizeof(struct hash_table));
if (t == NULL)
return NULL;
t->table = (struct hash_element **)malloc(sizeof(void *) * tableSize);
if (t->table == NULL) {
free(t);
return NULL;
}
for (i = 0; i < tableSize; i++)
t->table[i] = NULL;
t->table_size = tableSize;
t->next_ptr_offset = nextPointerOffset;
t->flags = 0;
t->num_elements = 0;
t->compare_func = compareFunc;
t->hash_func = hashFunc;
TRACE(("hash_init: created table %p, next_ptr_offset %d, compare_func %p, hash_func %p\n",
t, nextPointerOffset, compareFunc, hashFunc));
return t;
}
int
hash_uninit(struct hash_table *table)
{
ASSERT(table->num_elements == 0);
free(table->table);
free(table);
return 0;
}
status_t
hash_insert(struct hash_table *table, void *element)
{
uint32 hash;
ASSERT(table != NULL && element != NULL);
TRACE(("hash_insert: table %p, element %p\n", table, element));
hash = table->hash_func(element, NULL, table->table_size);
PUT_IN_NEXT(table, element, table->table[hash]);
table->table[hash] = (struct hash_element *)element;
table->num_elements++;
return B_OK;
}
status_t
hash_insert_grow(struct hash_table *table, void *element)
{
uint32 hash;
ASSERT(table != NULL && element != NULL);
TRACE(("hash_insert_grow: table %p, element %p\n", table, element));
hash = table->hash_func(element, NULL, table->table_size);
PUT_IN_NEXT(table, element, table->table[hash]);
table->table[hash] = (struct hash_element *)element;
table->num_elements++;
if ((uint32)table->num_elements > table->table_size) {
//dprintf("hash_insert: table has grown too much: %d in %d\n", table->num_elements, (int)table->table_size);
hash_grow(table);
}
return B_OK;
}
status_t
hash_remove(struct hash_table *table, void *_element)
{
uint32 hash = table->hash_func(_element, NULL, table->table_size);
void *element, *lastElement = NULL;
for (element = table->table[hash]; element != NULL;
lastElement = element, element = NEXT(table, element)) {
if (element == _element) {
if (lastElement != NULL) {
// connect the previous entry with the next one
PUT_IN_NEXT(table, lastElement, NEXT(table, element));
} else
table->table[hash] = (struct hash_element *)NEXT(table, element);
table->num_elements--;
return B_OK;
}
}
return B_ERROR;
}
void
hash_remove_current(struct hash_table *table, struct hash_iterator *iterator)
{
uint32 index = iterator->bucket;
void *element;
void *lastElement = NULL;
if (iterator->current == NULL || (element = table->table[index]) == NULL) {
panic("hash_remove_current(): invalid iteration state");
return;
}
while (element != NULL) {
if (element == iterator->current) {
iterator->current = lastElement;
if (lastElement != NULL) {
// connect the previous entry with the next one
PUT_IN_NEXT(table, lastElement, NEXT(table, element));
} else {
table->table[index] = (struct hash_element *)NEXT(table,
element);
}
table->num_elements--;
return;
}
lastElement = element;
element = NEXT(table, element);
}
panic("hash_remove_current(): current element not found!");
}
void *
hash_remove_first(struct hash_table *table, uint32 *_cookie)
{
uint32 index;
for (index = _cookie ? *_cookie : 0; index < table->table_size; index++) {
void *element = table->table[index];
if (element != NULL) {
// remove the first element we find
table->table[index] = (struct hash_element *)NEXT(table, element);
table->num_elements--;
if (_cookie)
*_cookie = index;
return element;
}
}
return NULL;
}
void *
hash_find(struct hash_table *table, void *searchedElement)
{
uint32 hash = table->hash_func(searchedElement, NULL, table->table_size);
void *element;
for (element = table->table[hash]; element != NULL; element = NEXT(table, element)) {
if (element == searchedElement)
return element;
}
return NULL;
}
void *
hash_lookup(struct hash_table *table, const void *key)
{
uint32 hash = table->hash_func(NULL, key, table->table_size);
void *element;
for (element = table->table[hash]; element != NULL; element = NEXT(table, element)) {
if (table->compare_func(element, key) == 0)
return element;
}
return NULL;
}
struct hash_iterator *
hash_open(struct hash_table *table, struct hash_iterator *iterator)
{
if (iterator == NULL) {
iterator = (struct hash_iterator *)malloc(sizeof(struct hash_iterator));
if (iterator == NULL)
return NULL;
}
hash_rewind(table, iterator);
return iterator;
}
void
hash_close(struct hash_table *table, struct hash_iterator *iterator, bool freeIterator)
{
if (freeIterator)
free(iterator);
}
void
hash_rewind(struct hash_table *table, struct hash_iterator *iterator)
{
iterator->current = NULL;
iterator->bucket = -1;
}
void *
hash_next(struct hash_table *table, struct hash_iterator *iterator)
{
uint32 index;
restart:
if (iterator->current == NULL) {
// get next bucket
for (index = (uint32)(iterator->bucket + 1); index < table->table_size; index++) {
if (table->table[index]) {
iterator->bucket = index;
iterator->current = table->table[index];
break;
}
}
} else {
iterator->current = NEXT(table, iterator->current);
if (!iterator->current)
goto restart;
}
return iterator->current;
}
uint32
hash_hash_string(const char *string)
{
uint32 hash = 0;
char c;
// we assume hash to be at least 32 bits
while ((c = *string++) != 0) {
hash ^= hash >> 28;
hash <<= 4;
hash ^= c;
}
return hash;
}
uint32
hash_count_elements(struct hash_table *table)
{
return table->num_elements;
}
uint32
hash_count_used_slots(struct hash_table *table)
{
uint32 usedSlots = 0;
uint32 i;
for (i = 0; i < table->table_size; i++) {
if (table->table[i] != NULL)
usedSlots++;
}
return usedSlots;
}
void
hash_dump_table(struct hash_table* table)
{
uint32 i;
dprintf("hash table %p, table size: %lu, elements: %u\n", table,
table->table_size, table->num_elements);
for (i = 0; i < table->table_size; i++) {
struct hash_element* element = table->table[i];
if (element != NULL) {
dprintf("%6lu:", i);
while (element != NULL) {
dprintf(" %p", element);
element = (hash_element*)NEXT(table, element);
}
dprintf("\n");
}
}
}
@@ -1,65 +0,0 @@
/*
* Copyright 2002-2008, Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
* Distributed under the terms of the NewOS License.
*/
#ifndef USERLAND_FS_HAIKU_HASH_H
#define USERLAND_FS_HAIKU_HASH_H
#include <SupportDefs.h>
// The use of offsetof() on non-PODs is invalid. Since many structs use
// templated members (i.e. DoublyLinkedList) which makes them non-PODs we
// can't use offsetof() anymore. This macro does the same, but requires an
// instance of the object in question.
#define offset_of_member(OBJECT, MEMBER) \
((size_t)((char*)&OBJECT.MEMBER - (char*)&OBJECT))
// can be allocated on the stack
typedef struct hash_iterator {
void *current;
int bucket;
} hash_iterator;
typedef struct hash_table hash_table;
extern "C" {
struct hash_table *hash_init(uint32 table_size, int next_ptr_offset,
int compare_func(void *element, const void *key),
uint32 hash_func(void *element, const void *key, uint32 range));
int hash_uninit(struct hash_table *table);
status_t hash_insert(struct hash_table *table, void *_element);
status_t hash_insert_grow(struct hash_table *table, void *_element);
status_t hash_remove(struct hash_table *table, void *_element);
void hash_remove_current(struct hash_table *table, struct hash_iterator *iterator);
void *hash_remove_first(struct hash_table *table, uint32 *_cookie);
void *hash_find(struct hash_table *table, void *e);
void *hash_lookup(struct hash_table *table, const void *key);
struct hash_iterator *hash_open(struct hash_table *table, struct hash_iterator *i);
void hash_close(struct hash_table *table, struct hash_iterator *i, bool free_iterator);
void *hash_next(struct hash_table *table, struct hash_iterator *i);
void hash_rewind(struct hash_table *table, struct hash_iterator *i);
uint32 hash_count_elements(struct hash_table *table);
uint32 hash_count_used_slots(struct hash_table *table);
void hash_dump_table(struct hash_table* table);
/* function pointers must look like this:
*
* uint32 hash_func(void *e, const void *key, uint32 range);
* hash function should calculate hash on either e or key,
* depending on which one is not NULL - they also need
* to make sure the returned value is within range.
* int compare_func(void *e, const void *key);
* compare function should compare the element with
* the key, returning 0 if equal, other if not
*/
uint32 hash_hash_string(const char *str);
} // extern "C"
#endif /* USERLAND_FS_HAIKU_HASH_H */
@@ -1,264 +0,0 @@
/*
* Copyright 2002-2007, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
* Distributed under the terms of the NewOS License.
*/
/* Mutex and recursive_lock code */
#include "lock.h"
#include <KernelExport.h>
sem_id
_init_semaphore(int32 count, const char* name)
{
sem_id sem = create_sem(count, name);
if (sem < 0)
panic("_init_semaphore(): Failed to create semaphore!\n");
return sem;
}
void
recursive_lock_init(recursive_lock *lock, const char *name)
{
recursive_lock_init_etc(lock, name, 0);
}
void
recursive_lock_init_etc(recursive_lock *lock, const char *name, uint32 flags)
{
if (lock == NULL)
panic("recursive_lock_init_etc(): NULL lock\n");
if (name == NULL)
name = "recursive lock";
lock->holder = -1;
lock->recursion = 0;
lock->sem = _init_semaphore(1, name);
}
void
recursive_lock_destroy(recursive_lock *lock)
{
if (lock == NULL)
return;
delete_sem(lock->sem);
lock->sem = -1;
}
status_t
recursive_lock_lock(recursive_lock *lock)
{
thread_id thread = find_thread(NULL);
if (thread != lock->holder) {
status_t status = acquire_sem(lock->sem);
if (status < B_OK)
return status;
lock->holder = thread;
}
lock->recursion++;
return B_OK;
}
status_t
recursive_lock_trylock(recursive_lock *lock)
{
thread_id thread = find_thread(NULL);
if (thread != lock->holder) {
status_t status = acquire_sem_etc(lock->sem, 1, B_RELATIVE_TIMEOUT, 0);
if (status < B_OK)
return status;
lock->holder = thread;
}
lock->recursion++;
return B_OK;
}
void
recursive_lock_unlock(recursive_lock *lock)
{
if (find_thread(NULL) != lock->holder)
panic("recursive_lock %p unlocked by non-holder thread!\n", lock);
if (--lock->recursion == 0) {
lock->holder = -1;
release_sem(lock->sem);
}
}
int32
recursive_lock_get_recursion(recursive_lock *lock)
{
if (lock->holder == find_thread(NULL))
return lock->recursion;
return -1;
}
// #pragma mark -
void
mutex_init(mutex *lock, const char *name)
{
mutex_init_etc(lock, name, 0);
}
void
mutex_init_etc(mutex* lock, const char* name, uint32 flags)
{
if (lock == NULL)
panic("mutex_init_etc(): NULL lock\n");
if (name == NULL)
name = "mutex_sem";
lock->holder = -1;
lock->sem = _init_semaphore(1, name);
}
void
mutex_destroy(mutex *mutex)
{
if (mutex == NULL)
return;
if (mutex->sem >= 0) {
delete_sem(mutex->sem);
mutex->sem = -1;
}
mutex->holder = -1;
}
status_t
mutex_lock(mutex *mutex)
{
thread_id me = find_thread(NULL);
status_t status;
status = acquire_sem(mutex->sem);
if (status < B_OK)
return status;
if (me == mutex->holder)
panic("mutex_lock failure: mutex %p (sem = 0x%lx) acquired twice by thread 0x%lx\n", mutex, mutex->sem, me);
mutex->holder = me;
return B_OK;
}
status_t
mutex_trylock(mutex *mutex)
{
thread_id me = find_thread(NULL);
status_t status;
status = acquire_sem_etc(mutex->sem, 1, B_RELATIVE_TIMEOUT, 0);
if (status < B_OK)
return status;
if (me == mutex->holder)
panic("mutex_lock failure: mutex %p (sem = 0x%lx) acquired twice by thread 0x%lx\n", mutex, mutex->sem, me);
mutex->holder = me;
return B_OK;
}
void
mutex_unlock(mutex *mutex)
{
thread_id me = find_thread(NULL);
if (me != mutex->holder) {
panic("mutex_unlock failure: thread 0x%lx is trying to release mutex %p (current holder 0x%lx)\n",
me, mutex, mutex->holder);
}
mutex->holder = -1;
release_sem(mutex->sem);
}
// #pragma mark -
void
rw_lock_init(rw_lock *lock, const char *name)
{
rw_lock_init_etc(lock, name, 0);
}
void
rw_lock_init_etc(rw_lock* lock, const char* name, uint32 flags)
{
if (lock == NULL)
panic("rw_lock_init_etc(): NULL lock\n");
if (name == NULL)
name = "r/w lock";
lock->sem = _init_semaphore(RW_MAX_READERS, name);
}
void
rw_lock_destroy(rw_lock *lock)
{
if (lock == NULL)
return;
delete_sem(lock->sem);
}
status_t
rw_lock_read_lock(rw_lock *lock)
{
return acquire_sem(lock->sem);
}
status_t
rw_lock_read_unlock(rw_lock *lock)
{
return release_sem(lock->sem);
}
status_t
rw_lock_write_lock(rw_lock *lock)
{
return acquire_sem_etc(lock->sem, RW_MAX_READERS, 0, 0);
}
status_t
rw_lock_write_unlock(rw_lock *lock)
{
return release_sem_etc(lock->sem, RW_MAX_READERS, 0);
}
@@ -1,139 +0,0 @@
/*
* Copyright 2002-2007, Axel Dörfler, axeld@pinc-software.de.
* Distributed under the terms of the MIT License.
*
* Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
* Distributed under the terms of the NewOS License.
*/
#ifndef USERLAND_FS_HAIKU_LOCK_H
#define USERLAND_FS_HAIKU_LOCK_H
#include <OS.h>
typedef struct recursive_lock {
sem_id sem;
thread_id holder;
int recursion;
} recursive_lock;
typedef struct mutex {
sem_id sem;
thread_id holder;
} mutex;
#define MUTEX_FLAG_CLONE_NAME 0x1
typedef struct rw_lock {
sem_id sem;
} rw_lock;
#define RW_MAX_READERS 1000000
#define RW_LOCK_FLAG_CLONE_NAME 0x1
#define ASSERT_LOCKED_RECURSIVE(r) do {} while (false)
#define ASSERT_LOCKED_MUTEX(m) do {} while (false)
#define ASSERT_WRITE_LOCKED_RW_LOCK(m) do {} while (false)
#define ASSERT_READ_LOCKED_RW_LOCK(l) do {} while (false)
// static initializers
#define MUTEX_INITIALIZER(name) { _init_semaphore(1, name), -1 }
#define RECURSIVE_LOCK_INITIALIZER(name) { _init_semaphore(1, name), -1, 0 }
#define RW_LOCK_INITIALIZER(name) \
{ _init_semaphore(RW_MAX_READERS, name) }
extern "C" {
sem_id _init_semaphore(int32 count, const char* name);
// implementation private
extern void recursive_lock_init(recursive_lock *lock, const char *name);
// name is *not* cloned nor freed in recursive_lock_destroy()
extern void recursive_lock_init_etc(recursive_lock *lock, const char *name,
uint32 flags);
extern void recursive_lock_destroy(recursive_lock *lock);
extern status_t recursive_lock_lock(recursive_lock *lock);
extern status_t recursive_lock_trylock(recursive_lock *lock);
extern void recursive_lock_unlock(recursive_lock *lock);
extern int32 recursive_lock_get_recursion(recursive_lock *lock);
extern void mutex_init(mutex* lock, const char* name);
// name is *not* cloned nor freed in mutex_destroy()
extern void mutex_init_etc(mutex* lock, const char* name, uint32 flags);
extern void mutex_destroy(mutex* lock);
//extern status_t mutex_switch_lock(mutex* from, mutex* to);
// Unlocks "from" and locks "to" such that unlocking and starting to wait
// for the lock is atomically. I.e. if "from" guards the object "to" belongs
// to, the operation is safe as long as "from" is held while destroying
// "to".
status_t mutex_lock(mutex* lock);
//status_t mutex_lock_threads_locked(mutex* lock);
status_t mutex_trylock(mutex* lock);
void mutex_unlock(mutex* lock);
//void mutex_transfer_lock(mutex* lock, thread_id thread);
extern void rw_lock_init(rw_lock* lock, const char* name);
// name is *not* cloned nor freed in rw_lock_destroy()
extern void rw_lock_init_etc(rw_lock* lock, const char* name, uint32 flags);
extern void rw_lock_destroy(rw_lock* lock);
extern status_t rw_lock_read_lock(rw_lock* lock);
extern status_t rw_lock_read_unlock(rw_lock* lock);
extern status_t rw_lock_write_lock(rw_lock* lock);
extern status_t rw_lock_write_unlock(rw_lock* lock);
} // extern "C"
/* C++ Auto Locking */
#include "AutoLocker.h"
// MutexLocking
class MutexLocking {
public:
inline bool Lock(mutex *lockable)
{
return mutex_lock(lockable) == B_OK;
}
inline void Unlock(mutex *lockable)
{
mutex_unlock(lockable);
}
};
// MutexLocker
typedef AutoLocker<mutex, MutexLocking> MutexLocker;
// RecursiveLockLocking
class RecursiveLockLocking {
public:
inline bool Lock(recursive_lock *lockable)
{
return recursive_lock_lock(lockable) == B_OK;
}
inline void Unlock(recursive_lock *lockable)
{
recursive_lock_unlock(lockable);
}
};
// RecursiveLocker
typedef AutoLocker<recursive_lock, RecursiveLockLocking> RecursiveLocker;
#endif /* USERLAND_FS_HAIKU_LOCK_H */
@@ -1,90 +0,0 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "slab.h"
#include <stdlib.h>
#include <new>
struct object_cache {
object_cache(const char *name, size_t objectSize,
size_t alignment, size_t maxByteUsage, uint32 flags, void *cookie,
object_cache_constructor constructor,
object_cache_destructor destructor, object_cache_reclaimer reclaimer)
:
objectSize(objectSize),
objectConstructor(constructor),
objectDestructor(destructor)
{
}
size_t objectSize;
object_cache_constructor objectConstructor;
object_cache_destructor objectDestructor;
};
object_cache *
create_object_cache(const char *name, size_t objectSize,
size_t alignment, void *cookie, object_cache_constructor constructor,
object_cache_destructor destructor)
{
return new(std::nothrow) object_cache(name, objectSize, alignment,
0, 0, cookie, constructor, destructor, NULL);
}
object_cache *
create_object_cache_etc(const char *name, size_t objectSize,
size_t alignment, size_t maxByteUsage, uint32 flags, void *cookie,
object_cache_constructor constructor, object_cache_destructor destructor,
object_cache_reclaimer reclaimer)
{
return new(std::nothrow) object_cache(name, objectSize, alignment,
maxByteUsage, flags, cookie, constructor, destructor, reclaimer);
}
void
delete_object_cache(object_cache *cache)
{
delete cache;
}
status_t
object_cache_set_minimum_reserve(object_cache *cache, size_t objectCount)
{
return B_OK;
}
void *
object_cache_alloc(object_cache *cache, uint32 flags)
{
return cache != NULL ? malloc(cache->objectSize) : NULL;
}
void
object_cache_free(object_cache *cache, void *object)
{
free(object);
}
status_t
object_cache_reserve(object_cache *cache, size_t object_count, uint32 flags)
{
return B_OK;
}
void object_cache_get_usage(object_cache *cache, size_t *_allocatedMemory)
{
*_allocatedMemory = 0;
}
@@ -1,59 +0,0 @@
/*
* Copyright 2008, Axel Dörfler. All Rights Reserved.
* Copyright 2007, Hugo Santos. All Rights Reserved.
*
* Distributed under the terms of the MIT License.
*/
#ifndef USERLAND_FS_HAIKU_SLAB_SLAB_H
#define USERLAND_FS_HAIKU_SLAB_SLAB_H
#include <OS.h>
enum {
/* create_object_cache_etc flags */
CACHE_NO_DEPOT = 1 << 0,
CACHE_UNLOCKED_PAGES = 1 << 1,
CACHE_LARGE_SLAB = 1 << 2,
/* object_cache_alloc flags */
CACHE_DONT_SLEEP = 1 << 8,
/* internal */
CACHE_DURING_BOOT = 1 << 31
};
typedef struct object_cache object_cache;
typedef status_t (*object_cache_constructor)(void *cookie, void *object);
typedef void (*object_cache_destructor)(void *cookie, void *object);
typedef void (*object_cache_reclaimer)(void *cookie, int32 level);
extern "C" {
object_cache *create_object_cache(const char *name, size_t object_size,
size_t alignment, void *cookie, object_cache_constructor constructor,
object_cache_destructor);
object_cache *create_object_cache_etc(const char *name, size_t object_size,
size_t alignment, size_t max_byte_usage, uint32 flags, void *cookie,
object_cache_constructor constructor, object_cache_destructor destructor,
object_cache_reclaimer reclaimer);
void delete_object_cache(object_cache *cache);
status_t object_cache_set_minimum_reserve(object_cache *cache,
size_t objectCount);
void *object_cache_alloc(object_cache *cache, uint32 flags);
void object_cache_free(object_cache *cache, void *object);
status_t object_cache_reserve(object_cache *cache, size_t object_count,
uint32 flags);
void object_cache_get_usage(object_cache *cache, size_t *_allocatedMemory);
} // extern "C"
#endif // USERLAND_FS_HAIKU_SLAB_SLAB_H