Added Haiku block cache interface to the UserlandFS server. Basically
copied and adjusted the respective kernel code. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20367 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -40,6 +40,9 @@ Application UserlandFSServer
|
|||||||
BeOSKernelVolume.cpp
|
BeOSKernelVolume.cpp
|
||||||
DispatcherFileSystem.cpp
|
DispatcherFileSystem.cpp
|
||||||
FileSystem.cpp
|
FileSystem.cpp
|
||||||
|
haiku_block_cache.cpp
|
||||||
|
haiku_hash.cpp
|
||||||
|
haiku_lock.cpp
|
||||||
HaikuKernelFileSystem.cpp
|
HaikuKernelFileSystem.cpp
|
||||||
HaikuKernelVolume.cpp
|
HaikuKernelVolume.cpp
|
||||||
kernel_emu.cpp
|
kernel_emu.cpp
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
#include "DispatcherDefs.h"
|
#include "DispatcherDefs.h"
|
||||||
#include "FileSystem.h"
|
#include "FileSystem.h"
|
||||||
#include "FSInfo.h"
|
#include "FSInfo.h"
|
||||||
|
#include "haiku_block_cache_priv.h"
|
||||||
#include "HaikuKernelFileSystem.h"
|
#include "HaikuKernelFileSystem.h"
|
||||||
#include "RequestThread.h"
|
#include "RequestThread.h"
|
||||||
#include "ServerDefs.h"
|
#include "ServerDefs.h"
|
||||||
@@ -275,6 +276,11 @@ UserlandFSServer::_CreateHaikuKernelInterface(const char* fsName,
|
|||||||
RETURN_ERROR(B_NO_MEMORY);
|
RETURN_ERROR(B_NO_MEMORY);
|
||||||
ObjectDeleter<HaikuKernelFileSystem> fsDeleter(fileSystem);
|
ObjectDeleter<HaikuKernelFileSystem> fsDeleter(fileSystem);
|
||||||
|
|
||||||
|
// init block cache
|
||||||
|
error = UserlandFS::HaikuKernelEmu::block_cache_init();
|
||||||
|
if (error != B_OK)
|
||||||
|
RETURN_ERROR(error);
|
||||||
|
|
||||||
// init the FS
|
// init the FS
|
||||||
error = fileSystem->Init();
|
error = fileSystem->Init();
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2004-2006, Axel Dörfler, [email protected]. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef USERLAND_FS_HAIKU_BLOCK_CACHE_PRIVATE_H
|
||||||
|
#define USERLAND_FS_HAIKU_BLOCK_CACHE_PRIVATE_H
|
||||||
|
|
||||||
|
#include "haiku_lock.h"
|
||||||
|
|
||||||
|
#include <kernel/util/DoublyLinkedList.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace UserlandFS {
|
||||||
|
namespace HaikuKernelEmu {
|
||||||
|
|
||||||
|
struct hash_table;
|
||||||
|
struct vm_page;
|
||||||
|
|
||||||
|
|
||||||
|
#define DEBUG_CHANGED
|
||||||
|
|
||||||
|
|
||||||
|
struct cache_transaction;
|
||||||
|
struct cached_block;
|
||||||
|
struct block_cache;
|
||||||
|
typedef DoublyLinkedListLink<cached_block> block_link;
|
||||||
|
|
||||||
|
|
||||||
|
struct cached_block {
|
||||||
|
cached_block *next; // next in hash
|
||||||
|
cached_block *transaction_next;
|
||||||
|
block_link link;
|
||||||
|
off_t block_number;
|
||||||
|
void *current_data;
|
||||||
|
void *original_data;
|
||||||
|
void *parent_data;
|
||||||
|
#ifdef DEBUG_CHANGED
|
||||||
|
void *compare;
|
||||||
|
#endif
|
||||||
|
int32 ref_count;
|
||||||
|
int32 accessed;
|
||||||
|
bool busy : 1;
|
||||||
|
bool is_writing : 1;
|
||||||
|
bool is_dirty : 1;
|
||||||
|
bool unused : 1;
|
||||||
|
bool unmapped : 1;
|
||||||
|
cache_transaction *transaction;
|
||||||
|
cache_transaction *previous_transaction;
|
||||||
|
|
||||||
|
static int Compare(void *_cacheEntry, const void *_block);
|
||||||
|
static uint32 Hash(void *_cacheEntry, const void *_block, uint32 range);
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef DoublyLinkedList<cached_block,
|
||||||
|
DoublyLinkedListMemberGetLink<cached_block,
|
||||||
|
&cached_block::link> > block_list;
|
||||||
|
|
||||||
|
struct block_cache {
|
||||||
|
hash_table *hash;
|
||||||
|
benaphore lock;
|
||||||
|
int fd;
|
||||||
|
off_t max_blocks;
|
||||||
|
size_t block_size;
|
||||||
|
int32 allocated_block_count;
|
||||||
|
int32 next_transaction_id;
|
||||||
|
cache_transaction *last_transaction;
|
||||||
|
hash_table *transaction_hash;
|
||||||
|
|
||||||
|
block_list unmapped_blocks;
|
||||||
|
block_list unused_blocks;
|
||||||
|
|
||||||
|
bool read_only;
|
||||||
|
|
||||||
|
block_cache(int fd, off_t numBlocks, size_t blockSize, bool readOnly);
|
||||||
|
~block_cache();
|
||||||
|
|
||||||
|
status_t InitCheck();
|
||||||
|
|
||||||
|
void RemoveUnusedBlocks(int32 maxAccessed = LONG_MAX, int32 count = LONG_MAX);
|
||||||
|
void FreeBlock(cached_block *block);
|
||||||
|
cached_block *NewBlock(off_t blockNumber);
|
||||||
|
void Free(void *address);
|
||||||
|
void *Allocate();
|
||||||
|
|
||||||
|
static void LowMemoryHandler(void *data, int32 level);
|
||||||
|
};
|
||||||
|
|
||||||
|
status_t block_cache_init();
|
||||||
|
|
||||||
|
} // namespace HaikuKernelEmu
|
||||||
|
} // namespace UserlandFS
|
||||||
|
|
||||||
|
#endif /* USERLAND_FS_HAIKU_BLOCK_CACHE_PRIVATE_H */
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
/* File System File and Block Caches
|
||||||
|
*
|
||||||
|
* Copyright 2004-2005, Haiku Inc. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef USERLAND_FS_HAIKU_FS_CACHE_H
|
||||||
|
#define USERLAND_FS_HAIKU_FS_CACHE_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <fs_cache.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace UserlandFS {
|
||||||
|
namespace HaikuKernelEmu {
|
||||||
|
|
||||||
|
/* transactions */
|
||||||
|
extern int32 cache_start_transaction(void *_cache);
|
||||||
|
extern status_t cache_sync_transaction(void *_cache, int32 id);
|
||||||
|
extern status_t cache_end_transaction(void *_cache, int32 id,
|
||||||
|
transaction_notification_hook hook, void *data);
|
||||||
|
extern status_t cache_abort_transaction(void *_cache, int32 id);
|
||||||
|
extern int32 cache_detach_sub_transaction(void *_cache, int32 id,
|
||||||
|
transaction_notification_hook hook, void *data);
|
||||||
|
extern status_t cache_abort_sub_transaction(void *_cache, int32 id);
|
||||||
|
extern status_t cache_start_sub_transaction(void *_cache, int32 id);
|
||||||
|
extern status_t cache_next_block_in_transaction(void *_cache, int32 id,
|
||||||
|
uint32 *_cookie, off_t *_blockNumber, void **_data,
|
||||||
|
void **_unchangedData);
|
||||||
|
extern int32 cache_blocks_in_transaction(void *_cache, int32 id);
|
||||||
|
extern int32 cache_blocks_in_sub_transaction(void *_cache, int32 id);
|
||||||
|
|
||||||
|
/* block cache */
|
||||||
|
extern void block_cache_delete(void *_cache, bool allowWrites);
|
||||||
|
extern void *block_cache_create(int fd, off_t numBlocks, size_t blockSize,
|
||||||
|
bool readOnly);
|
||||||
|
extern status_t block_cache_sync(void *_cache);
|
||||||
|
|
||||||
|
extern status_t block_cache_make_writable(void *_cache, off_t blockNumber,
|
||||||
|
int32 transaction);
|
||||||
|
extern void *block_cache_get_writable_etc(void *_cache, off_t blockNumber,
|
||||||
|
off_t base, off_t length, int32 transaction);
|
||||||
|
extern void *block_cache_get_writable(void *_cache, off_t blockNumber,
|
||||||
|
int32 transaction);
|
||||||
|
extern void *block_cache_get_empty(void *_cache, off_t blockNumber,
|
||||||
|
int32 transaction);
|
||||||
|
extern const void *block_cache_get_etc(void *_cache, off_t blockNumber,
|
||||||
|
off_t base, off_t length);
|
||||||
|
extern const void *block_cache_get(void *_cache, off_t blockNumber);
|
||||||
|
extern status_t block_cache_set_dirty(void *_cache, off_t blockNumber,
|
||||||
|
bool isDirty, int32 transaction);
|
||||||
|
extern void block_cache_put(void *_cache, off_t blockNumber);
|
||||||
|
|
||||||
|
/* file cache */
|
||||||
|
extern void *file_cache_create(mount_id mountID, vnode_id vnodeID, off_t size,
|
||||||
|
int fd);
|
||||||
|
extern void file_cache_delete(void *_cacheRef);
|
||||||
|
extern status_t file_cache_set_size(void *_cacheRef, off_t size);
|
||||||
|
extern status_t file_cache_sync(void *_cache);
|
||||||
|
extern status_t file_cache_invalidate_file_map(void *_cacheRef, off_t offset,
|
||||||
|
off_t size);
|
||||||
|
|
||||||
|
extern status_t file_cache_read_pages(void *_cacheRef, off_t offset,
|
||||||
|
const iovec *vecs, size_t count, size_t *_numBytes);
|
||||||
|
extern status_t file_cache_write_pages(void *_cacheRef, off_t offset,
|
||||||
|
const iovec *vecs, size_t count, size_t *_numBytes);
|
||||||
|
extern status_t file_cache_read(void *_cacheRef, off_t offset, void *bufferBase,
|
||||||
|
size_t *_size);
|
||||||
|
extern status_t file_cache_write(void *_cacheRef, off_t offset,
|
||||||
|
const void *buffer, size_t *_size);
|
||||||
|
|
||||||
|
} // namespace HaikuKernelEmu
|
||||||
|
} // namespace UserlandFS
|
||||||
|
|
||||||
|
#endif /* USERLAND_FS_HAIKU_FS_CACHE_H */
|
||||||
@@ -0,0 +1,274 @@
|
|||||||
|
/* Generic hash table
|
||||||
|
**
|
||||||
|
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
||||||
|
** Distributed under the terms of the NewOS License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "haiku_hash.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
|
||||||
|
|
||||||
|
namespace UserlandFS {
|
||||||
|
namespace HaikuKernelEmu {
|
||||||
|
|
||||||
|
|
||||||
|
// ToDo: the hashtable is not expanded when necessary (no load factor, no nothing)
|
||||||
|
// Could try to use pools instead of malloc() for the elements - might be
|
||||||
|
// faster than the current approach.
|
||||||
|
|
||||||
|
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))
|
||||||
|
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct hash_table *
|
||||||
|
hash_init(uint32 table_size, int next_ptr_offset,
|
||||||
|
int compare_func(void *e, const void *key),
|
||||||
|
uint32 hash_func(void *e, const void *key, uint32 range))
|
||||||
|
{
|
||||||
|
struct hash_table *t;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
if (compare_func == NULL || hash_func == 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 *) * table_size);
|
||||||
|
if (t->table == NULL) {
|
||||||
|
free(t);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < table_size; i++)
|
||||||
|
t->table[i] = NULL;
|
||||||
|
|
||||||
|
t->table_size = table_size;
|
||||||
|
t->next_ptr_offset = next_ptr_offset;
|
||||||
|
t->flags = 0;
|
||||||
|
t->num_elements = 0;
|
||||||
|
t->compare_func = compare_func;
|
||||||
|
t->hash_func = hash_func;
|
||||||
|
|
||||||
|
TRACE(("hash_init: created table %p, next_ptr_offset %d, compare_func %p, hash_func %p\n",
|
||||||
|
t, next_ptr_offset, compare_func, hash_func));
|
||||||
|
|
||||||
|
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 0x%x, element 0x%x\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++;
|
||||||
|
|
||||||
|
// ToDo: resize hash table if it's grown too much!
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace HaikuKernelEmu
|
||||||
|
} // namespace UserlandFS
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
** 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>
|
||||||
|
|
||||||
|
namespace UserlandFS {
|
||||||
|
namespace HaikuKernelEmu {
|
||||||
|
|
||||||
|
// can be allocated on the stack
|
||||||
|
typedef struct hash_iterator {
|
||||||
|
void *current;
|
||||||
|
int bucket;
|
||||||
|
} hash_iterator;
|
||||||
|
|
||||||
|
typedef struct hash_table hash_table;
|
||||||
|
|
||||||
|
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_remove(struct hash_table *table, void *_element);
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* function ptrs 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
|
||||||
|
* int compare_func(void *e, const void *key);
|
||||||
|
* compare function should compare the element with
|
||||||
|
* the key, returning 0 if equal, other if not
|
||||||
|
* NOTE: compare func can be null, in which case the hash
|
||||||
|
* code will compare the key pointer with the target
|
||||||
|
* ToDo: check this!
|
||||||
|
*/
|
||||||
|
|
||||||
|
uint32 hash_hash_string(const char *str);
|
||||||
|
|
||||||
|
} // namespace HaikuKernelEmu
|
||||||
|
} // namespace UserlandFS
|
||||||
|
|
||||||
|
#endif /* USERLAND_FS_HAIKU_HASH_H */
|
||||||
@@ -4,11 +4,13 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <fs_cache.h>
|
||||||
#include <fs_interface.h>
|
#include <fs_interface.h>
|
||||||
#include <KernelExport.h>
|
#include <KernelExport.h>
|
||||||
#include <NodeMonitor.h>
|
#include <NodeMonitor.h>
|
||||||
|
|
||||||
#include "Debug.h"
|
#include "Debug.h"
|
||||||
|
#include "haiku_fs_cache.h"
|
||||||
#include "kernel_emu.h"
|
#include "kernel_emu.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -157,6 +159,177 @@ get_vnode_removed(mount_id mountID, vnode_id vnodeID, bool* removed)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - Transaction
|
||||||
|
|
||||||
|
|
||||||
|
// cache_start_transaction
|
||||||
|
int32
|
||||||
|
cache_start_transaction(void *_cache)
|
||||||
|
{
|
||||||
|
return UserlandFS::HaikuKernelEmu::cache_start_transaction(_cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
// cache_sync_transaction
|
||||||
|
status_t
|
||||||
|
cache_sync_transaction(void *_cache, int32 id)
|
||||||
|
{
|
||||||
|
return UserlandFS::HaikuKernelEmu::cache_sync_transaction(_cache, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// cache_end_transaction
|
||||||
|
status_t
|
||||||
|
cache_end_transaction(void *_cache, int32 id,
|
||||||
|
transaction_notification_hook hook, void *data)
|
||||||
|
{
|
||||||
|
return UserlandFS::HaikuKernelEmu::cache_end_transaction(_cache, id, hook,
|
||||||
|
data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// cache_abort_transaction
|
||||||
|
status_t
|
||||||
|
cache_abort_transaction(void *_cache, int32 id)
|
||||||
|
{
|
||||||
|
return UserlandFS::HaikuKernelEmu::cache_abort_transaction(_cache, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// cache_detach_sub_transaction
|
||||||
|
int32
|
||||||
|
cache_detach_sub_transaction(void *_cache, int32 id,
|
||||||
|
transaction_notification_hook hook, void *data)
|
||||||
|
{
|
||||||
|
return UserlandFS::HaikuKernelEmu::cache_detach_sub_transaction(_cache, id,
|
||||||
|
hook, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// cache_abort_sub_transaction
|
||||||
|
status_t
|
||||||
|
cache_abort_sub_transaction(void *_cache, int32 id)
|
||||||
|
{
|
||||||
|
return UserlandFS::HaikuKernelEmu::cache_abort_sub_transaction(_cache, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// cache_start_sub_transaction
|
||||||
|
status_t
|
||||||
|
cache_start_sub_transaction(void *_cache, int32 id)
|
||||||
|
{
|
||||||
|
return UserlandFS::HaikuKernelEmu::cache_start_sub_transaction(_cache, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// cache_next_block_in_transaction
|
||||||
|
status_t
|
||||||
|
cache_next_block_in_transaction(void *_cache, int32 id, uint32 *_cookie,
|
||||||
|
off_t *_blockNumber, void **_data, void **_unchangedData)
|
||||||
|
{
|
||||||
|
return UserlandFS::HaikuKernelEmu::cache_next_block_in_transaction(_cache,
|
||||||
|
id, _cookie, _blockNumber, _data, _unchangedData);
|
||||||
|
}
|
||||||
|
|
||||||
|
// cache_blocks_in_transaction
|
||||||
|
int32
|
||||||
|
cache_blocks_in_transaction(void *_cache, int32 id)
|
||||||
|
{
|
||||||
|
return UserlandFS::HaikuKernelEmu::cache_blocks_in_transaction(_cache, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// cache_blocks_in_sub_transaction
|
||||||
|
int32
|
||||||
|
cache_blocks_in_sub_transaction(void *_cache, int32 id)
|
||||||
|
{
|
||||||
|
return UserlandFS::HaikuKernelEmu::cache_blocks_in_sub_transaction(_cache,
|
||||||
|
id);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - Block Cache
|
||||||
|
|
||||||
|
|
||||||
|
// block_cache_delete
|
||||||
|
void
|
||||||
|
block_cache_delete(void *_cache, bool allowWrites)
|
||||||
|
{
|
||||||
|
UserlandFS::HaikuKernelEmu::block_cache_delete(_cache, allowWrites);
|
||||||
|
}
|
||||||
|
|
||||||
|
// block_cache_create
|
||||||
|
void *
|
||||||
|
block_cache_create(int fd, off_t numBlocks, size_t blockSize, bool readOnly)
|
||||||
|
{
|
||||||
|
return UserlandFS::HaikuKernelEmu::block_cache_create(fd, numBlocks,
|
||||||
|
blockSize, readOnly);
|
||||||
|
}
|
||||||
|
|
||||||
|
// block_cache_sync
|
||||||
|
status_t
|
||||||
|
block_cache_sync(void *_cache)
|
||||||
|
{
|
||||||
|
return UserlandFS::HaikuKernelEmu::block_cache_sync(_cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
// block_cache_make_writable
|
||||||
|
status_t
|
||||||
|
block_cache_make_writable(void *_cache, off_t blockNumber, int32 transaction)
|
||||||
|
{
|
||||||
|
return UserlandFS::HaikuKernelEmu::block_cache_make_writable(_cache,
|
||||||
|
blockNumber, transaction);
|
||||||
|
}
|
||||||
|
|
||||||
|
// block_cache_get_writable_etc
|
||||||
|
void *
|
||||||
|
block_cache_get_writable_etc(void *_cache, off_t blockNumber, off_t base,
|
||||||
|
off_t length, int32 transaction)
|
||||||
|
{
|
||||||
|
return UserlandFS::HaikuKernelEmu::block_cache_get_writable_etc(_cache,
|
||||||
|
blockNumber, base, length, transaction);
|
||||||
|
}
|
||||||
|
|
||||||
|
// block_cache_get_writable
|
||||||
|
void *
|
||||||
|
block_cache_get_writable(void *_cache, off_t blockNumber, int32 transaction)
|
||||||
|
{
|
||||||
|
return UserlandFS::HaikuKernelEmu::block_cache_get_writable(_cache,
|
||||||
|
blockNumber, transaction);
|
||||||
|
}
|
||||||
|
|
||||||
|
// block_cache_get_empty
|
||||||
|
void *
|
||||||
|
block_cache_get_empty(void *_cache, off_t blockNumber, int32 transaction)
|
||||||
|
{
|
||||||
|
return UserlandFS::HaikuKernelEmu::block_cache_get_empty(_cache,
|
||||||
|
blockNumber, transaction);
|
||||||
|
}
|
||||||
|
|
||||||
|
// block_cache_get_etc
|
||||||
|
const void *
|
||||||
|
block_cache_get_etc(void *_cache, off_t blockNumber, off_t base, off_t length)
|
||||||
|
{
|
||||||
|
return UserlandFS::HaikuKernelEmu::block_cache_get_etc(_cache, blockNumber,
|
||||||
|
base, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
// block_cache_get
|
||||||
|
const void *
|
||||||
|
block_cache_get(void *_cache, off_t blockNumber)
|
||||||
|
{
|
||||||
|
return UserlandFS::HaikuKernelEmu::block_cache_get(_cache, blockNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
// block_cache_set_dirty
|
||||||
|
status_t
|
||||||
|
block_cache_set_dirty(void *_cache, off_t blockNumber, bool isDirty,
|
||||||
|
int32 transaction)
|
||||||
|
{
|
||||||
|
return UserlandFS::HaikuKernelEmu::block_cache_set_dirty(_cache,
|
||||||
|
blockNumber, isDirty, transaction);
|
||||||
|
}
|
||||||
|
|
||||||
|
// block_cache_put
|
||||||
|
void
|
||||||
|
block_cache_put(void *_cache, off_t blockNumber)
|
||||||
|
{
|
||||||
|
UserlandFS::HaikuKernelEmu::block_cache_put(_cache, blockNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - Misc
|
// #pragma mark - Misc
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,247 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2002-2007, Axel Dörfler, [email protected]. 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 "haiku_lock.h"
|
||||||
|
|
||||||
|
#include <OS.h>
|
||||||
|
|
||||||
|
#include "kernel_emu.h"
|
||||||
|
|
||||||
|
using UserlandFS::KernelEmu::panic;
|
||||||
|
|
||||||
|
namespace UserlandFS {
|
||||||
|
namespace HaikuKernelEmu {
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
recursive_lock_get_recursion(recursive_lock *lock)
|
||||||
|
{
|
||||||
|
if (lock->holder == find_thread(NULL))
|
||||||
|
return lock->recursion;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
recursive_lock_init(recursive_lock *lock, const char *name)
|
||||||
|
{
|
||||||
|
if (lock == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
if (name == NULL)
|
||||||
|
name = "recursive lock";
|
||||||
|
|
||||||
|
lock->holder = -1;
|
||||||
|
lock->recursion = 0;
|
||||||
|
lock->sem = create_sem(1, name);
|
||||||
|
|
||||||
|
if (lock->sem >= B_OK)
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
return lock->sem;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
mutex_init(mutex *m, const char *name)
|
||||||
|
{
|
||||||
|
if (m == NULL)
|
||||||
|
return EINVAL;
|
||||||
|
|
||||||
|
if (name == NULL)
|
||||||
|
name = "mutex_sem";
|
||||||
|
|
||||||
|
m->holder = -1;
|
||||||
|
|
||||||
|
m->sem = create_sem(1, name);
|
||||||
|
if (m->sem >= B_OK)
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
return m->sem;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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 -
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
benaphore_init(benaphore *ben, const char *name)
|
||||||
|
{
|
||||||
|
if (ben == NULL || name == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
ben->count = 1;
|
||||||
|
ben->sem = create_sem(0, name);
|
||||||
|
if (ben->sem >= B_OK)
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
return ben->sem;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
benaphore_destroy(benaphore *ben)
|
||||||
|
{
|
||||||
|
delete_sem(ben->sem);
|
||||||
|
ben->sem = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
rw_lock_init(rw_lock *lock, const char *name)
|
||||||
|
{
|
||||||
|
if (lock == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
if (name == NULL)
|
||||||
|
name = "r/w lock";
|
||||||
|
|
||||||
|
lock->sem = create_sem(RW_MAX_READERS, name);
|
||||||
|
if (lock->sem >= B_OK)
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
return lock->sem;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace HaikuKernelEmu
|
||||||
|
} // namespace UserlandFS
|
||||||
@@ -0,0 +1,159 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2002-2007, Axel Dörfler, [email protected].
|
||||||
|
* 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>
|
||||||
|
|
||||||
|
|
||||||
|
namespace UserlandFS {
|
||||||
|
namespace HaikuKernelEmu {
|
||||||
|
|
||||||
|
typedef struct recursive_lock {
|
||||||
|
sem_id sem;
|
||||||
|
thread_id holder;
|
||||||
|
int recursion;
|
||||||
|
} recursive_lock;
|
||||||
|
|
||||||
|
typedef struct mutex {
|
||||||
|
sem_id sem;
|
||||||
|
thread_id holder;
|
||||||
|
} mutex;
|
||||||
|
|
||||||
|
typedef struct benaphore {
|
||||||
|
sem_id sem;
|
||||||
|
int32 count;
|
||||||
|
} benaphore;
|
||||||
|
|
||||||
|
// Note: this is currently a trivial r/w lock implementation
|
||||||
|
// it will be replaced with something better later - this
|
||||||
|
// or a similar API will be made publically available at this point.
|
||||||
|
typedef struct rw_lock {
|
||||||
|
sem_id sem;
|
||||||
|
int32 count;
|
||||||
|
benaphore writeLock;
|
||||||
|
} rw_lock;
|
||||||
|
|
||||||
|
#define RW_MAX_READERS 1000000
|
||||||
|
|
||||||
|
|
||||||
|
extern status_t recursive_lock_init(recursive_lock *lock, const char *name);
|
||||||
|
extern void recursive_lock_destroy(recursive_lock *lock);
|
||||||
|
extern status_t recursive_lock_lock(recursive_lock *lock);
|
||||||
|
extern void recursive_lock_unlock(recursive_lock *lock);
|
||||||
|
extern int32 recursive_lock_get_recursion(recursive_lock *lock);
|
||||||
|
|
||||||
|
extern status_t mutex_init(mutex *m, const char *name);
|
||||||
|
extern void mutex_destroy(mutex *m);
|
||||||
|
extern status_t mutex_lock(mutex *m);
|
||||||
|
extern void mutex_unlock(mutex *m);
|
||||||
|
|
||||||
|
extern status_t benaphore_init(benaphore *ben, const char *name);
|
||||||
|
extern void benaphore_destroy(benaphore *ben);
|
||||||
|
|
||||||
|
static inline status_t
|
||||||
|
benaphore_lock_etc(benaphore *ben, uint32 flags, bigtime_t timeout)
|
||||||
|
{
|
||||||
|
if (atomic_add(&ben->count, -1) <= 0)
|
||||||
|
return acquire_sem_etc(ben->sem, 1, flags, timeout);
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline status_t
|
||||||
|
benaphore_lock(benaphore *ben)
|
||||||
|
{
|
||||||
|
if (atomic_add(&ben->count, -1) <= 0)
|
||||||
|
return acquire_sem(ben->sem);
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline status_t
|
||||||
|
benaphore_unlock(benaphore *ben)
|
||||||
|
{
|
||||||
|
if (atomic_add(&ben->count, 1) < 0)
|
||||||
|
return release_sem(ben->sem);
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern status_t rw_lock_init(rw_lock *lock, const char *name);
|
||||||
|
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);
|
||||||
|
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
|
||||||
|
// BenaphoreLocking
|
||||||
|
class BenaphoreLocking {
|
||||||
|
public:
|
||||||
|
inline bool Lock(benaphore *lockable)
|
||||||
|
{
|
||||||
|
return benaphore_lock(lockable) == B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Unlock(benaphore *lockable)
|
||||||
|
{
|
||||||
|
benaphore_unlock(lockable);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// BenaphoreLocker
|
||||||
|
typedef AutoLocker<benaphore, BenaphoreLocking> BenaphoreLocker;
|
||||||
|
|
||||||
|
} // namespace HaikuKernelEmu
|
||||||
|
} // namespace UserlandFS
|
||||||
|
|
||||||
|
using UserlandFS::HaikuKernelEmu::MutexLocker;
|
||||||
|
using UserlandFS::HaikuKernelEmu::RecursiveLocker;
|
||||||
|
using UserlandFS::HaikuKernelEmu::BenaphoreLocker;
|
||||||
|
|
||||||
|
#endif /* USERLAND_FS_HAIKU_LOCK_H */
|
||||||
@@ -512,27 +512,60 @@ UserlandFS::KernelEmu::kernel_debugger(const char *message)
|
|||||||
debugger(message);
|
debugger(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
// panic
|
// vpanic
|
||||||
void
|
void
|
||||||
UserlandFS::KernelEmu::panic(const char *format, ...)
|
UserlandFS::KernelEmu::vpanic(const char *format, va_list args)
|
||||||
{
|
{
|
||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
strcpy(buffer, "PANIC: ");
|
strcpy(buffer, "PANIC: ");
|
||||||
int32 prefixLen = strlen(buffer);
|
int32 prefixLen = strlen(buffer);
|
||||||
int bufferSize = sizeof(buffer) - prefixLen;
|
int bufferSize = sizeof(buffer) - prefixLen;
|
||||||
va_list args;
|
|
||||||
va_start(args, format);
|
|
||||||
// no vsnprintf() on PPC
|
// no vsnprintf() on PPC
|
||||||
#if defined(__INTEL__)
|
#if defined(__INTEL__)
|
||||||
vsnprintf(buffer + prefixLen, bufferSize - 1, format, args);
|
vsnprintf(buffer + prefixLen, bufferSize - 1, format, args);
|
||||||
#else
|
#else
|
||||||
vsprintf(buffer + prefixLen, format, args);
|
vsprintf(buffer + prefixLen, format, args);
|
||||||
#endif
|
#endif
|
||||||
va_end(args);
|
|
||||||
buffer[sizeof(buffer) - 1] = '\0';
|
buffer[sizeof(buffer) - 1] = '\0';
|
||||||
debugger(buffer);
|
debugger(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// panic
|
||||||
|
void
|
||||||
|
UserlandFS::KernelEmu::panic(const char *format, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
va_start(args, format);
|
||||||
|
vpanic(format, args);
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
// vdprintf
|
||||||
|
void
|
||||||
|
UserlandFS::KernelEmu::vdprintf(const char *format, va_list args)
|
||||||
|
{
|
||||||
|
vprintf(format, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
// dprintf
|
||||||
|
void
|
||||||
|
UserlandFS::KernelEmu::dprintf(const char *format, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
va_start(args, format);
|
||||||
|
dprintf(format, args);
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
UserlandFS::KernelEmu::dump_block(const char *buffer, int size,
|
||||||
|
const char *prefix)
|
||||||
|
{
|
||||||
|
// TODO: Implement!
|
||||||
|
}
|
||||||
|
|
||||||
// parse_expression
|
// parse_expression
|
||||||
//ulong
|
//ulong
|
||||||
//parse_expression(char *str)
|
//parse_expression(char *str)
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
// kernel_emu.h
|
// kernel_emu.h
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
#include <OS.h>
|
#include <OS.h>
|
||||||
|
|
||||||
struct selectsync;
|
struct selectsync;
|
||||||
@@ -31,7 +33,14 @@ status_t unremove_vnode(mount_id nsid, vnode_id vnid);
|
|||||||
status_t get_vnode_removed(mount_id nsid, vnode_id vnid, bool* removed);
|
status_t get_vnode_removed(mount_id nsid, vnode_id vnid, bool* removed);
|
||||||
|
|
||||||
void kernel_debugger(const char *message);
|
void kernel_debugger(const char *message);
|
||||||
void panic(const char *format, ...);
|
void vpanic(const char *format, va_list args);
|
||||||
|
void panic(const char *format, ...) __attribute__ ((format (__printf__, 1, 2)));
|
||||||
|
|
||||||
|
void vdprintf(const char *format, va_list args);
|
||||||
|
void dprintf(const char *format, ...)
|
||||||
|
__attribute__ ((format (__printf__, 1, 2)));
|
||||||
|
|
||||||
|
void dump_block(const char *buffer, int size, const char *prefix);
|
||||||
|
|
||||||
int add_debugger_command(char *name, int (*func)(int argc, char **argv),
|
int add_debugger_command(char *name, int (*func)(int argc, char **argv),
|
||||||
char *help);
|
char *help);
|
||||||
|
|||||||
Reference in New Issue
Block a user