Checkpoint - more work done.
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@1685 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
4b8670624a
commit
3dcf5034e5
@ -1,64 +1,89 @@
|
||||
#ifndef _HASH_H
|
||||
#define _HASH_H
|
||||
#include "list.h"
|
||||
#include "vm.h"
|
||||
#include "page.h"
|
||||
#include "pageManager.h"
|
||||
#include "vmHeaderBlock.h"
|
||||
#include <new.h>
|
||||
|
||||
static bool throwException (node &foo)
|
||||
{ throw ("Attempting to use an hash table without setting up a 'hash' function"); }
|
||||
extern vmHeaderBlock *vmBlock;
|
||||
|
||||
class hashTable : public list
|
||||
{
|
||||
public:
|
||||
hashTable(int size)
|
||||
{
|
||||
hashTable(int size) {
|
||||
nodeCount=0;
|
||||
numRocks=size;
|
||||
int pageCount=PAGE_SIZE*size/sizeof(list);
|
||||
|
||||
if (size*sizeof (list *)>PAGE_SIZE)
|
||||
throw ("Hash table too big!");
|
||||
page *newPage=vmBlock->pageMan->getPage();
|
||||
if (!newPage)
|
||||
throw ("Out of pages to allocate a pool!");
|
||||
int newCount=PAGE_SIZE/sizeof(area);
|
||||
acquire_sem(inUse);
|
||||
//error ("poolarea::get: Adding %d new elements to the pool!\n",newCount);
|
||||
for (int i=0;i<newCount;i++)
|
||||
unused.add(((node *)(newPage->getAddress()+(i*sizeof(area)))));
|
||||
release_sem(inUse);
|
||||
rocks=(list **)(newPage->getAddress());
|
||||
|
||||
int listsPerPage=PAGE_SIZE/sizeof(list);
|
||||
int pages=(size+(listsPerPage-1))/listsPerPage;
|
||||
for (int pageCount=0;pageCount<pages;pageCount++)
|
||||
{
|
||||
page *newPage=vmBlock->pageMan->getPage();
|
||||
if (!newPage)
|
||||
throw ("Out of pages to allocate a pool!");
|
||||
for (int i=0;i<listsPerPage;i++)
|
||||
rocks[i]=new ((list *)(newPage->getAddress()+(i*sizeof(list)))) list;
|
||||
}
|
||||
}
|
||||
|
||||
void setHash (ulong (*hash_in)(node &)) { hash=hash_in; }
|
||||
void setIsEqual (ulong (*isEqual_in)(node &,node &)) { isEqual=isEqual_in; }
|
||||
void setIsEqual (bool (*isEqual_in)(node &,node &)) { isEqual=isEqual_in; }
|
||||
|
||||
int count(void) {return nodeCount;}
|
||||
void add (node *newNode) {
|
||||
unsigned long hashValue=hash(*newNode)%numRocks;
|
||||
// Note - no looking for duplicates; no ordering.
|
||||
rocks[hashValue].add(newNode);
|
||||
}
|
||||
node *next(void) { return NULL; // This operation doesn't make sense for this class}
|
||||
void remove(node *toNuke)
|
||||
{
|
||||
unsigned long hashValue=hash(*findNode)%numRocks;
|
||||
rocks[hashValue].remove(newNode);
|
||||
if (!hash)
|
||||
throw ("Attempting to use a hash table without setting up a 'hash' function");
|
||||
unsigned long hashValue=hash(*newNode)%numRocks;
|
||||
// Note - no looking for duplicates; no ordering.
|
||||
rocks[hashValue]->add(newNode);
|
||||
}
|
||||
void dump(void)
|
||||
{
|
||||
|
||||
node *next(void) {throw ("Next is invalid in a hash table!");} // This operation doesn't make sense for this class
|
||||
|
||||
void remove(node *toNuke) {
|
||||
if (!hash)
|
||||
throw ("Attempting to use a hash table without setting up a 'hash' function");
|
||||
unsigned long hashValue=hash(*toNuke)%numRocks;
|
||||
rocks[hashValue]->remove(toNuke);
|
||||
}
|
||||
|
||||
void dump(void) {
|
||||
for (int i=0;i<numRocks;i++)
|
||||
for (struct node *cur=rocks[hashValue].rock;cur && !done;cur=cur->next)
|
||||
error ("hashTable::dump: At %p, next = %p\n",cur,cur->next);
|
||||
for (struct node *cur=rocks[i]->rock;cur;cur=cur->next)
|
||||
error ("hashTable::dump: On bucket %d of %d, At %p, next = %p\n",i,numRocks,cur,cur->next);
|
||||
}
|
||||
node *find(node *findNode)
|
||||
{
|
||||
|
||||
bool ensureSane (void) {
|
||||
bool ok=true;
|
||||
for (int i=0;i<numRocks;i++)
|
||||
ok|=rocks[i]->ensureSane();
|
||||
return ok;
|
||||
}
|
||||
node *find(node *findNode) {
|
||||
if (!hash)
|
||||
throw ("Attempting to use a hash table without setting up a 'hash' function");
|
||||
if (!isEqual)
|
||||
throw ("Attempting to use a hash table without setting up an 'isEqual' function");
|
||||
unsigned long hashValue=hash(*findNode)%numRocks;
|
||||
for (struct node *cur=rocks[hashValue].rock;cur && !done;cur=cur->next)
|
||||
for (struct node *cur=rocks[hashValue]->rock;cur ;cur=cur->next)
|
||||
if (isEqual(*findNode,*cur))
|
||||
return cur;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
private:
|
||||
ulong (*hash)(node &a);
|
||||
bool (*isEqual)(node &a,node &b);
|
||||
list *rocks;
|
||||
list **rocks;
|
||||
int numRocks;
|
||||
|
||||
|
||||
};
|
||||
#endif
|
||||
|
107
src/kernel/vm2/hashTest.C
Normal file
107
src/kernel/vm2/hashTest.C
Normal file
@ -0,0 +1,107 @@
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include "hashTable.h"
|
||||
#include "OS.h"
|
||||
#include "vmInterface.h"
|
||||
|
||||
vmInterface vm(30);
|
||||
|
||||
struct hashTest : public node {
|
||||
hashTest(int i) {value=i;}
|
||||
int value;
|
||||
};
|
||||
|
||||
ulong hash(node &a) {
|
||||
hashTest &a1=reinterpret_cast<hashTest &>(a);
|
||||
return a1.value;
|
||||
}
|
||||
|
||||
bool isEqual (node &a,node &b) {
|
||||
hashTest &a1=reinterpret_cast<hashTest &>(a);
|
||||
hashTest &b1=reinterpret_cast<hashTest &>(b);
|
||||
return (a1.value==b1.value);
|
||||
}
|
||||
|
||||
int main(int argc,char **argv) {
|
||||
// Test 1 - Try to add to foo without setting an isLessThan function
|
||||
try {
|
||||
hashTable foo(10);
|
||||
node tmp;
|
||||
foo.add(&tmp);
|
||||
}
|
||||
catch (const char *badness)
|
||||
{
|
||||
if (strcmp(badness,"Attempting to use a hash table without setting up a 'hash' function"))
|
||||
error ("Failure on adding with no hash, error = %s\n", badness);
|
||||
error ("Success on adding with no hash, \n" );
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
error ("Failure on adding with no hash, unknown exception\n");
|
||||
}
|
||||
|
||||
hashTable foo(20);
|
||||
foo.setHash(hash);
|
||||
foo.setIsEqual(isEqual);
|
||||
|
||||
error ("Add the first couple, in order (easy)\n");
|
||||
hashTest first(1);
|
||||
foo.add(&first);
|
||||
hashTest second(2);
|
||||
foo.add(&second);
|
||||
foo.dump();
|
||||
|
||||
error ("Add the next three, not in order (harder)\n");
|
||||
hashTest third(3);
|
||||
hashTest fourth(4);
|
||||
hashTest fifth(5);
|
||||
foo.add(&fourth);
|
||||
foo.add(&third);
|
||||
foo.add(&fifth);
|
||||
foo.dump();
|
||||
|
||||
error ("Create bar, populated with 1000 values");
|
||||
hashTable bar(200);
|
||||
bar.setHash(hash);
|
||||
bar.setIsEqual(isEqual);
|
||||
for (int a=0;a<100;a++)
|
||||
bar.add(new hashTest(a));
|
||||
for (int a=1000;a>=100;a--)
|
||||
bar.add(new hashTest(a));
|
||||
bar.dump();
|
||||
|
||||
error ("Removing simple case: remove 1,leave 2,3,4,5 \n");
|
||||
foo.remove(&first);
|
||||
foo.dump();
|
||||
error ("Removing simple case: remove 2,leave 3,4,5 \n");
|
||||
foo.remove(&second);
|
||||
foo.dump();
|
||||
|
||||
error ("Setting up middle case (readding 1 and 2)\n");
|
||||
foo.add(&first);
|
||||
foo.add(&second);
|
||||
foo.dump();
|
||||
error ("Removing middle case (removing 2)\n");
|
||||
foo.remove(&second);
|
||||
foo.dump();
|
||||
error ("Removing middle case (removing 1)\n");
|
||||
foo.remove(&first);
|
||||
foo.dump();
|
||||
|
||||
error ("Finding 1\n");
|
||||
hashTest findOne(1);
|
||||
hashTest *found=(hashTest *)bar.find(&findOne);
|
||||
error ("found value = %d\n",found->value);
|
||||
|
||||
error ("Finding 77\n");
|
||||
hashTest findSeventySeven(77);
|
||||
hashTest *found77=(hashTest *)bar.find(&findSeventySeven);
|
||||
error ("found value = %d\n",found77->value);
|
||||
|
||||
error ("ensuringSane on smaller (foo) = %s\n",((foo.ensureSane())?"OK":"BAD!"));
|
||||
error ("ensuringSane on larger (bar) = %s\n",((bar.ensureSane())?"OK":"BAD!"));
|
||||
|
||||
return 0;
|
||||
}
|
@ -13,41 +13,34 @@ struct node
|
||||
class list {
|
||||
public:
|
||||
list(void){nodeCount=0;rock=NULL;}
|
||||
void add (node *newNode)
|
||||
{
|
||||
void add (node *newNode) {
|
||||
newNode->next=rock;
|
||||
rock=newNode;
|
||||
nodeCount++;
|
||||
}
|
||||
//int count(void) {error ("list::count: About to return %d\n",nodeCount);return nodeCount;}
|
||||
int count(void) {return nodeCount;}
|
||||
node *next(void)
|
||||
{
|
||||
node *next(void) {
|
||||
//dump();
|
||||
node *n=rock;
|
||||
if (rock)
|
||||
{
|
||||
if (rock) {
|
||||
rock=rock->next;
|
||||
nodeCount--;
|
||||
}
|
||||
//dump();
|
||||
return n;
|
||||
}
|
||||
void remove(node *toNuke)
|
||||
{
|
||||
void remove(node *toNuke) {
|
||||
//error ("list::remove starting: nuking %x \n",toNuke);
|
||||
//dump();
|
||||
if (rock==toNuke)
|
||||
{
|
||||
if (rock==toNuke) {
|
||||
rock=rock->next;
|
||||
nodeCount--;
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
bool done=false;
|
||||
for (struct node *cur=rock;!done && cur->next;cur=cur->next)
|
||||
if (cur->next==toNuke)
|
||||
{
|
||||
if (cur->next==toNuke) {
|
||||
cur->next=toNuke->next;
|
||||
nodeCount--;
|
||||
done=true;
|
||||
@ -56,13 +49,25 @@ class list {
|
||||
//error ("list::remove ending: \n");
|
||||
//dump();
|
||||
}
|
||||
void dump(void)
|
||||
{
|
||||
void dump(void) {
|
||||
for (struct node *cur=rock;cur;cur=cur->next)
|
||||
{
|
||||
error ("list::dump: At %p, next = %p\n",cur,cur->next);
|
||||
}
|
||||
{ error ("list::dump: At %p, next = %p\n",cur,cur->next); }
|
||||
}
|
||||
|
||||
bool ensureSane (void) {
|
||||
int temp=nodeCount;
|
||||
for (struct node *cur=rock;cur && --temp;cur=cur->next) ; // Intentional to have no body
|
||||
if (temp<0) {
|
||||
error ("list::ensureSane: found too many records!\n");
|
||||
return false;
|
||||
}
|
||||
if (temp>0) {
|
||||
error ("list::ensureSane: found too few records!\n");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
struct node *rock;
|
||||
int nodeCount;
|
||||
private:
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "pageManager.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
void *addOffset(void *base,unsigned long offset)
|
||||
{
|
||||
@ -74,6 +75,41 @@ page *pageManager::getPage(void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool pageManager::getContiguousPages(int pages,page **location)
|
||||
{
|
||||
unsigned long current, start=0, next;
|
||||
page *curPage;
|
||||
int count=0;
|
||||
while (count<pages)
|
||||
{
|
||||
curPage=getPage();
|
||||
current=curPage->getAddress();
|
||||
if (start==0)
|
||||
{
|
||||
start=current;
|
||||
location[count++]=curPage;
|
||||
}
|
||||
else if (current==start+PAGE_SIZE*count) // This is the next one in line
|
||||
location[count++]=curPage;
|
||||
else if (current==start-PAGE_SIZE) // Found the one directly previous
|
||||
{
|
||||
memmove(location[1],location[0],count*sizeof(page *));
|
||||
start=current;
|
||||
location[0]=curPage;
|
||||
count++;
|
||||
}
|
||||
else // Forget this series - it doesn't seem to be going anywhere...
|
||||
{
|
||||
while (--count>=0)
|
||||
{
|
||||
freePage(location[count]);
|
||||
location[count]=NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void pageManager::freePage(page *toFree)
|
||||
{
|
||||
error ("pageManager::freePage; old value = %d\n",toFree->count);
|
||||
|
@ -9,6 +9,7 @@ class pageManager {
|
||||
pageManager(void);
|
||||
void setup(void *memory,int pages);
|
||||
page *getPage(void);
|
||||
bool getContiguousPages(int pages,page **location);
|
||||
void freePage(page *);
|
||||
void cleaner(void);
|
||||
int desperation(void);
|
||||
|
@ -21,6 +21,7 @@ class vpage : public node
|
||||
void flush(void); // write page to vnode, if necessary
|
||||
void refresh(void); // Read page back in from vnode
|
||||
vpage(void);
|
||||
// Setup should now only be called by the vpage manager...
|
||||
void setup(unsigned long start,vnode *backing, page *physMem,protectType prot,pageState state); // backing and/or physMem can be NULL/0.
|
||||
void cleanup(void);
|
||||
void setProtection(protectType prot);
|
||||
|
@ -14,6 +14,7 @@ class vpageManager
|
||||
private:
|
||||
|
||||
public:
|
||||
vpage *getVpage(unsigned long start,vnode *backing, page *physMem,protectType prot,pageState state);
|
||||
vpage *getVpage(vnode &vn);
|
||||
void putVpage(vpage &vp);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user