Network stack: migrate to BOpenHashTable
This commit is contained in:
@@ -22,7 +22,6 @@
|
|||||||
|
|
||||||
#include <lock.h>
|
#include <lock.h>
|
||||||
#include <util/AutoLock.h>
|
#include <util/AutoLock.h>
|
||||||
#include <util/khash.h>
|
|
||||||
|
|
||||||
#include <KernelExport.h>
|
#include <KernelExport.h>
|
||||||
|
|
||||||
@@ -68,6 +67,8 @@ struct family {
|
|||||||
ChainList chains;
|
ChainList chains;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ChainHash;
|
||||||
|
|
||||||
struct chain : DoublyLinkedListLinkImpl<chain> {
|
struct chain : DoublyLinkedListLinkImpl<chain> {
|
||||||
chain(int family, int type, int protocol);
|
chain(int family, int type, int protocol);
|
||||||
~chain();
|
~chain();
|
||||||
@@ -76,15 +77,13 @@ struct chain : DoublyLinkedListLinkImpl<chain> {
|
|||||||
void Release();
|
void Release();
|
||||||
void Uninitialize();
|
void Uninitialize();
|
||||||
|
|
||||||
static int Compare(void* _chain, const void* _key);
|
static struct chain* Lookup(BOpenHashTable<ChainHash>* chains,
|
||||||
static uint32 Hash(void* _chain, const void* _key, uint32 range);
|
int family, int type, int protocol);
|
||||||
static struct chain* Lookup(hash_table* chains, int family, int type,
|
static struct chain* Add(BOpenHashTable<ChainHash>* chains,
|
||||||
int protocol);
|
int family, int type, int protocol, va_list modules);
|
||||||
static struct chain* Add(hash_table* chains, int family, int type,
|
static struct chain* Add(BOpenHashTable<ChainHash>* chains,
|
||||||
int protocol, va_list modules);
|
int family, int type, int protocol, ...);
|
||||||
static struct chain* Add(hash_table* chains, int family, int type,
|
static void DeleteChains(BOpenHashTable<ChainHash>* chains);
|
||||||
int protocol, ...);
|
|
||||||
static void DeleteChains(hash_table* chains);
|
|
||||||
|
|
||||||
chain* next;
|
chain* next;
|
||||||
struct family* parent;
|
struct family* parent;
|
||||||
@@ -99,15 +98,78 @@ struct chain : DoublyLinkedListLinkImpl<chain> {
|
|||||||
module_info* infos[MAX_CHAIN_MODULES + 1];
|
module_info* infos[MAX_CHAIN_MODULES + 1];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ChainHash {
|
||||||
|
typedef chain_key KeyType;
|
||||||
|
typedef chain ValueType;
|
||||||
|
|
||||||
|
// TODO: check if this makes a good hash...
|
||||||
|
#define HASH(o) ((uint32)(((o)->family) ^ ((o)->type) ^ ((o)->protocol)))
|
||||||
|
|
||||||
|
size_t HashKey(KeyType key) const
|
||||||
|
{
|
||||||
|
return HASH(&key);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Hash(ValueType* value) const
|
||||||
|
{
|
||||||
|
return HASH(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef HASH
|
||||||
|
|
||||||
|
bool Compare(KeyType key, ValueType* chain) const
|
||||||
|
{
|
||||||
|
if (chain->family == key.family
|
||||||
|
&& chain->type == key.type
|
||||||
|
&& chain->protocol == key.protocol)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ValueType*& GetLink(ValueType* value) const
|
||||||
|
{
|
||||||
|
return value->next;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FamilyHash {
|
||||||
|
typedef int KeyType;
|
||||||
|
typedef family ValueType;
|
||||||
|
|
||||||
|
size_t HashKey(KeyType key) const
|
||||||
|
{
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Hash(ValueType* value) const
|
||||||
|
{
|
||||||
|
return value->type;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Compare(KeyType key, ValueType* family) const
|
||||||
|
{
|
||||||
|
return family->type == key;
|
||||||
|
}
|
||||||
|
|
||||||
|
ValueType*& GetLink(ValueType* value) const
|
||||||
|
{
|
||||||
|
return value->next;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef BOpenHashTable<ChainHash> ChainTable;
|
||||||
|
typedef BOpenHashTable<FamilyHash> FamilyTable;
|
||||||
|
|
||||||
#define CHAIN_MISSING_MODULE 0x02
|
#define CHAIN_MISSING_MODULE 0x02
|
||||||
#define CHAIN_INITIALIZED 0x01
|
#define CHAIN_INITIALIZED 0x01
|
||||||
|
|
||||||
static mutex sChainLock;
|
static mutex sChainLock;
|
||||||
static mutex sInitializeChainLock;
|
static mutex sInitializeChainLock;
|
||||||
static hash_table* sProtocolChains;
|
static ChainTable* sProtocolChains;
|
||||||
static hash_table* sDatalinkProtocolChains;
|
static ChainTable* sDatalinkProtocolChains;
|
||||||
static hash_table* sReceivingProtocolChains;
|
static ChainTable* sReceivingProtocolChains;
|
||||||
static hash_table* sFamilies;
|
static FamilyTable* sFamilies;
|
||||||
static bool sInitialized;
|
static bool sInitialized;
|
||||||
|
|
||||||
|
|
||||||
@@ -142,36 +204,10 @@ family::Release()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*static*/ int
|
|
||||||
family::Compare(void* _family, const void* _key)
|
|
||||||
{
|
|
||||||
struct family* family = (struct family*)_family;
|
|
||||||
int key = (addr_t)_key;
|
|
||||||
|
|
||||||
if (family->type == key)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*static*/ uint32
|
|
||||||
family::Hash(void* _family, const void* _key, uint32 range)
|
|
||||||
{
|
|
||||||
struct family* family = (struct family*)_family;
|
|
||||||
int key = (addr_t)_key;
|
|
||||||
|
|
||||||
if (family != NULL)
|
|
||||||
return family->type % range;
|
|
||||||
|
|
||||||
return key % range;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*static*/ struct family*
|
/*static*/ struct family*
|
||||||
family::Lookup(int type)
|
family::Lookup(int type)
|
||||||
{
|
{
|
||||||
return (struct family*)hash_lookup(sFamilies, (void*)(addr_t)type);
|
return sFamilies->Lookup(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -182,7 +218,7 @@ family::Add(int type)
|
|||||||
if (family == NULL)
|
if (family == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (hash_insert(sFamilies, family) != B_OK) {
|
if (sFamilies->Insert(family) != B_OK) {
|
||||||
delete family;
|
delete family;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -294,60 +330,23 @@ chain::Uninitialize()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*static*/ int
|
|
||||||
chain::Compare(void* _chain, const void* _key)
|
|
||||||
{
|
|
||||||
const chain_key* key = (const chain_key*)_key;
|
|
||||||
struct chain* chain = (struct chain*)_chain;
|
|
||||||
|
|
||||||
if (chain->family == key->family
|
|
||||||
&& chain->type == key->type
|
|
||||||
&& chain->protocol == key->protocol)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*static*/ uint32
|
|
||||||
chain::Hash(void* _chain, const void* _key, uint32 range)
|
|
||||||
{
|
|
||||||
const chain_key* key = (const chain_key*)_key;
|
|
||||||
struct chain* chain = (struct chain*)_chain;
|
|
||||||
|
|
||||||
// TODO: check if this makes a good hash...
|
|
||||||
#define HASH(o) ((uint32)(((o)->family) ^ ((o)->type) ^ ((o)->protocol)) % range)
|
|
||||||
#if 0
|
|
||||||
TRACE(("%d.%d.%d: Hash: %lu\n", chain ? chain->family : key->family,
|
|
||||||
chain ? chain->type : key->type, chain ? chain->protocol : key->protocol,
|
|
||||||
chain ? HASH(chain) : HASH(key)));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (chain != NULL)
|
|
||||||
return HASH(chain);
|
|
||||||
|
|
||||||
return HASH(key);
|
|
||||||
#undef HASH
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*static*/ struct chain*
|
/*static*/ struct chain*
|
||||||
chain::Lookup(hash_table* chains, int family, int type, int protocol)
|
chain::Lookup(ChainTable* chains, int family, int type, int protocol)
|
||||||
{
|
{
|
||||||
struct chain_key key = { family, type, protocol };
|
struct chain_key key = { family, type, protocol };
|
||||||
return (struct chain*)hash_lookup(chains, &key);
|
return chains->Lookup(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*static*/ struct chain*
|
/*static*/ struct chain*
|
||||||
chain::Add(hash_table* chains, int family, int type, int protocol,
|
chain::Add(ChainTable* chains, int family, int type, int protocol,
|
||||||
va_list modules)
|
va_list modules)
|
||||||
{
|
{
|
||||||
struct chain* chain = new (std::nothrow) ::chain(family, type, protocol);
|
struct chain* chain = new (std::nothrow) ::chain(family, type, protocol);
|
||||||
if (chain == NULL)
|
if (chain == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (chain->parent == NULL || hash_insert(chains, chain) != B_OK) {
|
if (chain->parent == NULL || chains->Insert(chain) != B_OK) {
|
||||||
delete chain;
|
delete chain;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -365,14 +364,14 @@ chain::Add(hash_table* chains, int family, int type, int protocol,
|
|||||||
chain->modules[count] = strdup(module);
|
chain->modules[count] = strdup(module);
|
||||||
if (chain->modules[count] == NULL
|
if (chain->modules[count] == NULL
|
||||||
|| ++count >= MAX_CHAIN_MODULES) {
|
|| ++count >= MAX_CHAIN_MODULES) {
|
||||||
hash_remove(chains, chain);
|
chains->Remove(chain);
|
||||||
delete chain;
|
delete chain;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chains == sProtocolChains && count == 0) {
|
if (chains == sProtocolChains && count == 0) {
|
||||||
hash_remove(chains, chain);
|
chains->Remove(chain);
|
||||||
delete chain;
|
delete chain;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -382,7 +381,7 @@ chain::Add(hash_table* chains, int family, int type, int protocol,
|
|||||||
|
|
||||||
|
|
||||||
/*static*/ struct chain*
|
/*static*/ struct chain*
|
||||||
chain::Add(hash_table* chains, int family, int type, int protocol, ...)
|
chain::Add(ChainTable* chains, int family, int type, int protocol, ...)
|
||||||
{
|
{
|
||||||
va_list modules;
|
va_list modules;
|
||||||
va_start(modules, protocol);
|
va_start(modules, protocol);
|
||||||
@@ -395,16 +394,16 @@ chain::Add(hash_table* chains, int family, int type, int protocol, ...)
|
|||||||
|
|
||||||
|
|
||||||
/*static*/ void
|
/*static*/ void
|
||||||
chain::DeleteChains(hash_table* chains)
|
chain::DeleteChains(ChainTable* chains)
|
||||||
{
|
{
|
||||||
uint32 cookie = 0;
|
struct chain* current;
|
||||||
while (true) {
|
current = chains->Clear(true);
|
||||||
struct chain* chain = (struct chain*)hash_remove_first(chains, &cookie);
|
while (current) {
|
||||||
if (chain == NULL)
|
struct chain* next = current->next;
|
||||||
break;
|
|
||||||
|
|
||||||
chain->Uninitialize();
|
current->Uninitialize();
|
||||||
delete chain;
|
delete current;
|
||||||
|
current = next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -799,30 +798,28 @@ init_stack()
|
|||||||
mutex_init(&sChainLock, "net chains");
|
mutex_init(&sChainLock, "net chains");
|
||||||
mutex_init(&sInitializeChainLock, "net intialize chains");
|
mutex_init(&sInitializeChainLock, "net intialize chains");
|
||||||
|
|
||||||
sFamilies = hash_init(10, offsetof(struct family, next),
|
sFamilies = new FamilyTable();
|
||||||
&family::Compare, &family::Hash);
|
if (sFamilies == NULL || sFamilies->Init(10) != B_OK) {
|
||||||
if (sFamilies == NULL) {
|
|
||||||
status = B_NO_MEMORY;
|
status = B_NO_MEMORY;
|
||||||
goto err5;
|
goto err5;
|
||||||
}
|
}
|
||||||
|
|
||||||
sProtocolChains = hash_init(10, offsetof(struct chain, next),
|
sProtocolChains = new ChainTable();
|
||||||
&chain::Compare, &chain::Hash);
|
if (sProtocolChains == NULL || sProtocolChains->Init(10) != B_OK) {
|
||||||
if (sProtocolChains == NULL) {
|
|
||||||
status = B_NO_MEMORY;
|
status = B_NO_MEMORY;
|
||||||
goto err6;
|
goto err6;
|
||||||
}
|
}
|
||||||
|
|
||||||
sDatalinkProtocolChains = hash_init(10, offsetof(struct chain, next),
|
sDatalinkProtocolChains = new ChainTable();
|
||||||
&chain::Compare, &chain::Hash);
|
if (sDatalinkProtocolChains == NULL
|
||||||
if (sDatalinkProtocolChains == NULL) {
|
|| sDatalinkProtocolChains->Init(10) != B_OK) {
|
||||||
status = B_NO_MEMORY;
|
status = B_NO_MEMORY;
|
||||||
goto err7;
|
goto err7;
|
||||||
}
|
}
|
||||||
|
|
||||||
sReceivingProtocolChains = hash_init(10, offsetof(struct chain, next),
|
sReceivingProtocolChains = new ChainTable();
|
||||||
&chain::Compare, &chain::Hash);
|
if (sReceivingProtocolChains == NULL
|
||||||
if (sReceivingProtocolChains == NULL) {
|
|| sReceivingProtocolChains->Init(10) != B_OK) {
|
||||||
status = B_NO_MEMORY;
|
status = B_NO_MEMORY;
|
||||||
goto err8;
|
goto err8;
|
||||||
}
|
}
|
||||||
@@ -850,11 +847,11 @@ init_stack()
|
|||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
err8:
|
err8:
|
||||||
hash_uninit(sDatalinkProtocolChains);
|
delete sDatalinkProtocolChains;
|
||||||
err7:
|
err7:
|
||||||
hash_uninit(sProtocolChains);
|
delete sProtocolChains;
|
||||||
err6:
|
err6:
|
||||||
hash_uninit(sFamilies);
|
delete sFamilies;
|
||||||
err5:
|
err5:
|
||||||
mutex_destroy(&sInitializeChainLock);
|
mutex_destroy(&sInitializeChainLock);
|
||||||
mutex_destroy(&sChainLock);
|
mutex_destroy(&sChainLock);
|
||||||
@@ -891,20 +888,19 @@ uninit_stack()
|
|||||||
chain::DeleteChains(sDatalinkProtocolChains);
|
chain::DeleteChains(sDatalinkProtocolChains);
|
||||||
chain::DeleteChains(sReceivingProtocolChains);
|
chain::DeleteChains(sReceivingProtocolChains);
|
||||||
|
|
||||||
uint32 cookie = 0;
|
struct family* current;
|
||||||
while (true) {
|
current = sFamilies->Clear(true);
|
||||||
struct family* family = (struct family*)hash_remove_first(sFamilies,
|
while (current) {
|
||||||
&cookie);
|
struct family* next = current->next;
|
||||||
if (family == NULL)
|
|
||||||
break;
|
|
||||||
|
|
||||||
delete family;
|
delete current;
|
||||||
|
current = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
hash_uninit(sProtocolChains);
|
delete sProtocolChains;
|
||||||
hash_uninit(sDatalinkProtocolChains);
|
delete sDatalinkProtocolChains;
|
||||||
hash_uninit(sReceivingProtocolChains);
|
delete sReceivingProtocolChains;
|
||||||
hash_uninit(sFamilies);
|
delete sFamilies;
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user