Network stack: migrate to BOpenHashTable

This commit is contained in:
Adrien Destugues
2015-01-09 18:09:11 +01:00
parent 6a89f8040f
commit d4aabe75c3
+116 -120
View File
@@ -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;
} }