Improved bucketLib.c & portability changes

This commit is contained in:
Jeff Hill
1994-11-14 18:45:25 +00:00
parent 547ca9d02d
commit 0ba3898e81
3 changed files with 1035 additions and 702 deletions
+430 -239
View File
@@ -29,12 +29,17 @@
* -----------------
* .01 091493 joh fixed overzealous parameter check
* .02 121693 joh added bucketFree()
*
* NOTES:
* .01 Storage for identifier must persist until an item is deleted
*/
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <bucketLib.h>
@@ -48,142 +53,312 @@
#ifndef FALSE
#define FALSE 0
#endif /* FALSE */
#ifndef LOCAL
#define LOCAL static
#endif /* LOCAL */
#ifndef max
#define max(A,B) ((A)>(B)?(A):(B))
#endif /* max */
#define BUCKET_IX_WIDTH 12
#define BUCKET_IX_N (1<<BUCKET_IX_WIDTH)
#define BUCKET_IX_MASK (BUCKET_IX_N-1)
/*
* these data type dependent routines are
* provided in the bucketLib.c
*/
typedef BUCKETID bucketHash(BUCKET *pb, const void *pId);
typedef ITEM **bucketCompare(ITEM **ppi, const void *pId);
LOCAL bucketCompare bucketUnsignedCompare;
LOCAL bucketCompare bucketPointerCompare;
LOCAL bucketCompare bucketStringCompare;
LOCAL bucketHash bucketUnsignedHash;
LOCAL bucketHash bucketPointerHash;
LOCAL bucketHash bucketStringHash;
typedef struct {
bucketHash *pHash;
bucketCompare *pCompare;
buckTypeOfId type;
}bucketSET;
LOCAL bucketSET BSET[] = {
{bucketUnsignedHash, bucketUnsignedCompare, bidtUnsigned},
{bucketPointerHash, bucketPointerCompare, bidtPointer},
{bucketStringHash, bucketStringCompare, bidtString}
};
LOCAL int bucketAddItem(BUCKET *prb, bucketSET *pBSET, const void *pId, void *pApp);
LOCAL int bucketRemoveItem (BUCKET *prb, bucketSET *pBSET, const void *pId);
LOCAL void *bucketLookupItem(BUCKET *pb, bucketSET *pBSET, const void *pId);
/*
* bucket id bit width
*/
#define BUCKETID_BIT_WIDTH (sizeof(BUCKETID)*NBBY)
/*
* Maximum bucket size
*/
#define BUCKET_MAX_WIDTH 12
#ifdef DEBUG
#error This is out of date
main()
{
BUCKETID id;
BUCKETID id1;
BUCKETID id2;
char *pValSave1;
char *pValSave2;
int s;
BUCKET *pb;
char *pValSave;
char *pVal;
unsigned i;
clock_t start, finish;
double duration;
const int LOOPS = 500000;
pb = bucketCreate(NBBY*sizeof(BUCKETID));
pb = bucketCreate(8);
if(!pb){
return BUCKET_FAILURE;
}
id = 444;
pValSave = "fred";
s = bucketAddItem(pb, id, pValSave);
if(s != BUCKET_SUCCESS){
return BUCKET_FAILURE;
}
id1 = 0x1000a432;
pValSave1 = "fred";
s = bucketAddItemUnsignedId(pb, &id1, pValSave1);
assert(s == BUCKET_SUCCESS);
printf("Begin\n");
for(i=0; i<500000; i++){
pVal = bucketLookupItem(pb, id);
if(pVal != pValSave){
printf("failure\n");
break;
}
pVal = bucketLookupItem(pb, id);
if(pVal != pValSave){
printf("failure\n");
break;
}
pVal = bucketLookupItem(pb, id);
if(pVal != pValSave){
printf("failure\n");
break;
}
pVal = bucketLookupItem(pb, id);
if(pVal != pValSave){
printf("failure\n");
break;
}
pVal = bucketLookupItem(pb, id);
if(pVal != pValSave){
printf("failure\n");
break;
}
pVal = bucketLookupItem(pb, id);
if(pVal != pValSave){
printf("failure\n");
break;
}
pVal = bucketLookupItem(pb, id);
if(pVal != pValSave){
printf("failure\n");
break;
}
pVal = bucketLookupItem(pb, id);
if(pVal != pValSave){
printf("failure\n");
break;
}
pVal = bucketLookupItem(pb, id);
if(pVal != pValSave){
printf("failure\n");
break;
}
pVal = bucketLookupItem(pb, id);
if(pVal != pValSave){
printf("failure\n");
break;
}
pValSave2 = "jane";
s = bucketAddItemStringId(pb, pValSave2, pValSave2);
assert(s == BUCKET_SUCCESS);
start = clock();
for(i=0; i<LOOPS; i++){
pVal = bucketLookupItem(pb, id1);
assert(pVal == pValSave1);
pVal = bucketLookupItem(pb, id1);
assert(pVal == pValSave1);
pVal = bucketLookupItem(pb, id1);
assert(pVal == pValSave1);
pVal = bucketLookupItem(pb, id1);
assert(pVal == pValSave1);
pVal = bucketLookupItem(pb, id1);
assert(pVal == pValSave1);
pVal = bucketLookupItem(pb, id1);
assert(pVal == pValSave1);
pVal = bucketLookupItem(pb, id1);
assert(pVal == pValSave1);
pVal = bucketLookupItem(pb, id1);
assert(pVal == pValSave1);
pVal = bucketLookupItem(pb, id1);
assert(pVal == pValSave1);
pVal = bucketLookupItem(pb, id2);
assert(pVal == pValSave2);
}
printf("End\n");
finish = clock();
duration = finish-start;
duration = duration/CLOCKS_PER_SEC;
printf("It took %15.10f total sec\n", duration);
duration = duration/LOOPS;
duration = duration/10;
duration = duration * 1e6;
printf("It took %15.10f u sec per hash lookup\n", duration);
bucketShow(pb);
return BUCKET_SUCCESS;
}
#endif
/*
* bucketUnsignedCompare()
*/
LOCAL ITEM **bucketUnsignedCompare (ITEM **ppi, const void *pId)
{
unsigned id;
unsigned *pItemId;
ITEM *pi;
id = * (unsigned *) pId;
while (pi = *ppi) {
if (bidtUnsigned == pi->type) {
pItemId = (unsigned *) pi->pId;
if (id == *pItemId) {
return ppi;
}
}
ppi = &pi->pItem;
}
return NULL;
}
/*
* bucketPointerCompare()
*/
ITEM **bucketPointerCompare (ITEM **ppi, const void *pId)
{
void *ptr;
void **pItemId;
ITEM *pi;
ptr = * (void **) pId;
while (pi = *ppi) {
if (bidtPointer == pi->type ) {
pItemId = (void **) pi->pId;
if (ptr == *pItemId) {
return ppi;
}
}
ppi = &pi->pItem;
}
return NULL;
}
/*
* bucketStringCompare ()
*/
ITEM **bucketStringCompare (ITEM **ppi, const void *pId)
{
const char *pStr = pId;
ITEM *pi;
int status;
while (pi = *ppi) {
if (bidtString == pi->type) {
status = strcmp (pStr, (char *)pi->pId);
if (status == '\0') {
return ppi;
}
}
ppi = &pi->pItem;
}
return NULL;
}
/*
* bucketUnsignedHash ()
*/
BUCKETID bucketUnsignedHash (BUCKET *pb, const void *pId)
{
const unsigned *pUId = pId;
unsigned src;
BUCKETID hashid;
src = *pUId;
hashid = src;
src = src >> pb->hashIdNBits;
while (src) {
hashid = hashid ^ src;
src = src >> pb->hashIdNBits;
}
hashid = hashid & pb->hashIdMask;
return hashid;
}
/*
* bucketPointerHash ()
*
*/
BUCKETID bucketPointerHash (BUCKET *pb, const void *pId)
{
void * const *ppId = pId;
unsigned long src;
BUCKETID hashid;
/*
* This makes the assumption that
* a pointer will fit inside of a long
* (this assumption may not port to all
* CPU architectures)
*/
src = (unsigned long) *ppId;
hashid = src;
src = src >> pb->hashIdNBits;
while(src){
hashid = hashid ^ src;
src = src >> pb->hashIdNBits;
}
hashid = hashid & pb->hashIdMask;
return hashid;
}
/*
* bucketStringHash ()
*/
BUCKETID bucketStringHash (BUCKET *pb, const void *pId)
{
const char *pStr = pId;
BUCKETID hashid;
unsigned i;
hashid = 0;
i = 1;
while(*pStr){
hashid += *pStr * i;
pStr++;
i++;
}
hashid = hashid % (pb->hashIdMask+1);
return hashid;
}
/*
* bucketCreate()
*/
#ifdef __STDC__
BUCKET *bucketCreate(unsigned indexWidth)
#else
BUCKET *bucketCreate(indexWidth)
unsigned indexWidth;
#endif
BUCKET *bucketCreate (unsigned nHashTableEntries)
{
BUCKETID mask;
unsigned nbits;
BUCKET *pb;
if (nHashTableEntries==0) {
return NULL;
}
/*
* count the number of bits in the bucket id
*/
for (nbits=0; nbits<BUCKETID_BIT_WIDTH; nbits++) {
mask = (1<<nbits) - 1;
if ( ((nHashTableEntries-1) & ~mask) == 0){
break;
}
}
/*
* indexWidth must be specified at least one
* bit less than the bit size of type BUCKETID
*/
if(indexWidth>sizeof(BUCKETID)*NBBY){
printf("%s at %d: Requested index width=%d is to large. max=%d\n" ,
if (nbits>=BUCKETID_BIT_WIDTH) {
printf("%s at %d: Requested index width=%d to large. max=%d\n",
__FILE__,
__LINE__,
indexWidth,
sizeof(BUCKETID)*NBBY-1);
nbits,
BUCKETID_BIT_WIDTH-1);
return NULL;
}
pb = (BUCKET *) calloc(1, sizeof(*pb));
if(!pb){
if (!pb) {
return pb;
}
if(indexWidth>BUCKET_IX_WIDTH){
pb->indexShift = indexWidth - BUCKET_IX_WIDTH;
}
else{
pb->indexShift = 0;
}
pb->nextIndexMask = (1<<pb->indexShift)-1;
pb->nEntries = 1<<(indexWidth-pb->indexShift);
if(indexWidth == sizeof(BUCKETID)*NBBY){
pb->indexMask = 0;
pb->indexMask = ~pb->indexMask;
}
else{
pb->indexMask = (1<<indexWidth)-1;
}
pb->hashIdMask = mask;
pb->hashIdNBits = nbits;
pb->pTable = (ITEMPTR *) calloc(
pb->nEntries,
sizeof(ITEMPTR));
pb->pTable = (ITEM **) calloc (mask+1, sizeof(*pb->pTable));
if(!pb->pTable){
free(pb);
return NULL;
@@ -202,14 +377,24 @@ int bucketFree(prb)
BUCKET *prb;
#endif
{
ITEM *pi;
ITEM *pni;
/*
* deleting a bucket with entries in use
* will cause memory leaks and is not allowed
*/
if(prb->nInUse){
return BUCKET_FAILURE;
}
assert(prb->nInUse==0);
/*
* free the free list
*/
pi = prb->pFreeItems;
while (pi) {
pni = pi->pItem;
free (pi);
pi = pni;
}
free(prb->pTable);
free(prb);
@@ -220,69 +405,49 @@ BUCKET *prb;
/*
* bucketAddItem()
*/
#ifdef __STDC__
int bucketAddItem(BUCKET *prb, BUCKETID id, void *pItem)
#else
int bucketAddItem(prb, id, pItem)
BUCKET *prb;
BUCKETID id;
void *pItem;
#endif
int bucketAddItemUnsignedId(BUCKET *prb, const unsigned *pId, void *pApp)
{
int s;
ITEMPTR *pi;
return bucketAddItem(prb, &BSET[bidtUnsigned], pId, pApp);
}
int bucketAddItemPointerId(BUCKET *prb, void * const *pId, void *pApp)
{
return bucketAddItem(prb, &BSET[bidtPointer], pId, pApp);
}
int bucketAddItemStringId(BUCKET *prb, const char *pId, void *pApp)
{
return bucketAddItem(prb, &BSET[bidtString], pId, pApp);
}
LOCAL int bucketAddItem(BUCKET *prb, bucketSET *pBSET, const void *pId, void *pApp)
{
BUCKETID hashid;
ITEM *pi;
/*
* is the id to big ?
* try to get it off the free list first. If
* that fails then malloc()
*/
if(id&~prb->indexMask){
return BUCKET_FAILURE;
pi = prb->pFreeItems;
if (pi) {
prb->pFreeItems = pi->pItem;
}
if(prb->indexShift){
int new;
BUCKET *pb;
pi = &prb->pTable[id>>prb->indexShift];
pb = pi->pBucket;
if(!pb){
pb = bucketCreate(prb->indexShift);
if(!pb){
return BUCKET_FAILURE;
}
pi->pBucket = pb;
prb->nInUse++;
new = TRUE;
}
else{
new = FALSE;
else {
pi = (ITEM *) malloc(sizeof(ITEM));
if(!pi){
return BUCKET_FAILURE;
}
s = bucketAddItem(
pb,
id&prb->nextIndexMask,
pItem);
/*
* if memory cant be allocated at a lower
* level dont leak everything allocated for this new
* item so far
*/
if(s != BUCKET_SUCCESS && new){
s = bucketFree(pb);
assert(s == BUCKET_SUCCESS);
pi->pBucket = NULL;
prb->nInUse--;
}
return s;
}
pi = &prb->pTable[id];
if(pi->pItem){
return BUCKET_FAILURE;
}
pi->pItem = pItem;
/*
* create the hash index
*/
hashid = (*pBSET->pHash) (prb, pId);
pi->pApp = pApp;
pi->pId = pId;
pi->type = pBSET->type;
assert((hashid & ~prb->hashIdMask) == 0);
pi->pItem = prb->pTable[hashid];
prb->pTable[hashid] = pi;
prb->nInUse++;
return BUCKET_SUCCESS;
@@ -292,97 +457,85 @@ void *pItem;
/*
* bucketRemoveItem()
*/
#ifdef __STDC__
int bucketRemoveItem (BUCKET *prb, BUCKETID id, void *pItem)
#else
int bucketRemoveItem (prb, id, pItem)
BUCKET *prb;
BUCKETID id;
void *pItem;
#endif
int bucketRemoveItemUnsignedId (BUCKET *prb, const unsigned *pId)
{
ITEMPTR *ppi;
return bucketRemoveItem(prb, &BSET[bidtUnsigned], pId);
}
int bucketRemoveItemPointerId (BUCKET *prb, void * const *pId)
{
return bucketRemoveItem(prb, &BSET[bidtPointer], pId);
}
int bucketRemoveItemStringId (BUCKET *prb, const char *pId)
{
return bucketRemoveItem(prb, &BSET[bidtString], pId);
}
LOCAL int bucketRemoveItem (BUCKET *prb, bucketSET *pBSET, const void *pId)
{
BUCKETID hashid;
ITEM **ppi;
ITEM *pi;
/*
* is the id to big ?
* create the hash index
*/
if(id&~prb->indexMask){
hashid = (*pBSET->pHash) (prb, pId);
assert((hashid & ~prb->hashIdMask) == 0);
ppi = &prb->pTable[hashid];
ppi = (*pBSET->pCompare) (ppi, pId);
if(!ppi){
return BUCKET_FAILURE;
}
if(prb->indexShift){
BUCKET *pb;
int s;
ppi = &prb->pTable[id>>prb->indexShift];
pb = ppi->pBucket;
if(!pb){
return BUCKET_FAILURE;
}
s = bucketRemoveItem(
pb,
id&prb->nextIndexMask,
pItem);
if(s!=BUCKET_SUCCESS){
return s;
}
if(pb->nInUse==0){
free(pb->pTable);
free(pb);
ppi->pBucket = NULL;
prb->nInUse--;
}
return s;
}
ppi = &prb->pTable[id];
if(ppi->pItem != pItem){
return BUCKET_FAILURE;
}
prb->nInUse--;
ppi->pItem = NULL;
pi = *ppi;
*ppi = pi->pItem;
/*
* stuff it on the free list
*/
pi->pItem = prb->pFreeItems;
prb->pFreeItems = pi;
return BUCKET_SUCCESS;
}
/*
* bucketLookupItem()
*/
#ifdef __STDC__
void *bucketLookupItem(BUCKET *pb, BUCKETID id)
#else
void *bucketLookupItem(pb, id)
BUCKET *pb;
BUCKETID id;
#endif
void *bucketLookupItemUnsignedId (BUCKET *prb, const unsigned *pId)
{
unsigned shift;
return bucketLookupItem(prb, &BSET[bidtUnsigned], pId);
}
void *bucketLookupItemPointerId (BUCKET *prb, void * const *pId)
{
return bucketLookupItem(prb, &BSET[bidtPointer], pId);
}
void *bucketLookupItemStringId (BUCKET *prb, const char *pId)
{
return bucketLookupItem(prb, &BSET[bidtString], pId);
}
LOCAL void *bucketLookupItem(BUCKET *pb, bucketSET *pBSET, const void *pId)
{
BUCKETID hashid;
ITEM **ppi;
/*
* is the id to big ?
* create the hash index
*/
if(id&~pb->indexMask){
return NULL;
hashid = (*pBSET->pHash) (pb, pId);
assert((hashid & ~pb->hashIdMask) == 0);
/*
* at the bottom level just
* linear search for it.
*/
ppi = (*pBSET->pCompare) (&pb->pTable[hashid], pId);
if(ppi){
return (*ppi)->pApp;
}
while(shift = pb->indexShift){
BUCKETID nextId;
nextId = id & pb->nextIndexMask;
pb = pb->pTable[id>>shift].pBucket;
if(!pb){
return pb;
}
id = nextId;
}
return pb->pTable[id].pItem;
return NULL;
}
@@ -397,24 +550,62 @@ int bucketShow(pb)
BUCKET *pb;
#endif
{
ITEMPTR *pi;
ITEM **ppi;
ITEM *pi;
ITEM *pni;
unsigned nElem;
double X;
double XX;
double mean;
double stdDev;
unsigned count;
unsigned maxEntries;
unsigned freeListCount;
pi = pb->pTable;
printf( "Bucket: mask=%x entries in use=%d bytes in use=%d\n",
(pb->nEntries-1)<<pb->indexShift,
pb->nInUse,
sizeof(*pb)+pb->nEntries*sizeof(*pi));
if(pb->indexShift){
for( pi = pb->pTable;
pi<&pb->pTable[pb->nEntries];
pi++){
if(pi->pBucket){
bucketShow(pi->pBucket);
}
}
/*
* count bytes on the free list
*/
pi = pb->pFreeItems;
freeListCount = 0;
while (pi) {
freeListCount++;
pni = pi->pItem;
pi = pni;
}
printf( "Bucket entries in use = %d bytes in use = %d\n",
pb->nInUse,
sizeof(*pb)+(pb->hashIdMask+1)*
sizeof(ITEM *)+pb->nInUse*sizeof(ITEM));
printf( "Free list bytes in use = %d\n",
freeListCount*sizeof(ITEM));
ppi = pb->pTable;
nElem = pb->hashIdMask+1;
X = 0.0;
XX = 0.0;
maxEntries = 0;
while (ppi < &pb->pTable[nElem]) {
pi = *ppi;
count = 0;
while (pi) {
count++;
pi = pi->pItem;
}
X += count;
XX += count*count;
maxEntries = max (count, maxEntries);
ppi++;
}
mean = X/nElem;
stdDev = sqrt(XX/nElem - mean*mean);
printf( "Bucket entries/hash id - mean = %f std dev = %f max = %d\n",
mean,
stdDev,
maxEntries);
return BUCKET_SUCCESS;
}
+430 -239
View File
@@ -29,12 +29,17 @@
* -----------------
* .01 091493 joh fixed overzealous parameter check
* .02 121693 joh added bucketFree()
*
* NOTES:
* .01 Storage for identifier must persist until an item is deleted
*/
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <bucketLib.h>
@@ -48,142 +53,312 @@
#ifndef FALSE
#define FALSE 0
#endif /* FALSE */
#ifndef LOCAL
#define LOCAL static
#endif /* LOCAL */
#ifndef max
#define max(A,B) ((A)>(B)?(A):(B))
#endif /* max */
#define BUCKET_IX_WIDTH 12
#define BUCKET_IX_N (1<<BUCKET_IX_WIDTH)
#define BUCKET_IX_MASK (BUCKET_IX_N-1)
/*
* these data type dependent routines are
* provided in the bucketLib.c
*/
typedef BUCKETID bucketHash(BUCKET *pb, const void *pId);
typedef ITEM **bucketCompare(ITEM **ppi, const void *pId);
LOCAL bucketCompare bucketUnsignedCompare;
LOCAL bucketCompare bucketPointerCompare;
LOCAL bucketCompare bucketStringCompare;
LOCAL bucketHash bucketUnsignedHash;
LOCAL bucketHash bucketPointerHash;
LOCAL bucketHash bucketStringHash;
typedef struct {
bucketHash *pHash;
bucketCompare *pCompare;
buckTypeOfId type;
}bucketSET;
LOCAL bucketSET BSET[] = {
{bucketUnsignedHash, bucketUnsignedCompare, bidtUnsigned},
{bucketPointerHash, bucketPointerCompare, bidtPointer},
{bucketStringHash, bucketStringCompare, bidtString}
};
LOCAL int bucketAddItem(BUCKET *prb, bucketSET *pBSET, const void *pId, void *pApp);
LOCAL int bucketRemoveItem (BUCKET *prb, bucketSET *pBSET, const void *pId);
LOCAL void *bucketLookupItem(BUCKET *pb, bucketSET *pBSET, const void *pId);
/*
* bucket id bit width
*/
#define BUCKETID_BIT_WIDTH (sizeof(BUCKETID)*NBBY)
/*
* Maximum bucket size
*/
#define BUCKET_MAX_WIDTH 12
#ifdef DEBUG
#error This is out of date
main()
{
BUCKETID id;
BUCKETID id1;
BUCKETID id2;
char *pValSave1;
char *pValSave2;
int s;
BUCKET *pb;
char *pValSave;
char *pVal;
unsigned i;
clock_t start, finish;
double duration;
const int LOOPS = 500000;
pb = bucketCreate(NBBY*sizeof(BUCKETID));
pb = bucketCreate(8);
if(!pb){
return BUCKET_FAILURE;
}
id = 444;
pValSave = "fred";
s = bucketAddItem(pb, id, pValSave);
if(s != BUCKET_SUCCESS){
return BUCKET_FAILURE;
}
id1 = 0x1000a432;
pValSave1 = "fred";
s = bucketAddItemUnsignedId(pb, &id1, pValSave1);
assert(s == BUCKET_SUCCESS);
printf("Begin\n");
for(i=0; i<500000; i++){
pVal = bucketLookupItem(pb, id);
if(pVal != pValSave){
printf("failure\n");
break;
}
pVal = bucketLookupItem(pb, id);
if(pVal != pValSave){
printf("failure\n");
break;
}
pVal = bucketLookupItem(pb, id);
if(pVal != pValSave){
printf("failure\n");
break;
}
pVal = bucketLookupItem(pb, id);
if(pVal != pValSave){
printf("failure\n");
break;
}
pVal = bucketLookupItem(pb, id);
if(pVal != pValSave){
printf("failure\n");
break;
}
pVal = bucketLookupItem(pb, id);
if(pVal != pValSave){
printf("failure\n");
break;
}
pVal = bucketLookupItem(pb, id);
if(pVal != pValSave){
printf("failure\n");
break;
}
pVal = bucketLookupItem(pb, id);
if(pVal != pValSave){
printf("failure\n");
break;
}
pVal = bucketLookupItem(pb, id);
if(pVal != pValSave){
printf("failure\n");
break;
}
pVal = bucketLookupItem(pb, id);
if(pVal != pValSave){
printf("failure\n");
break;
}
pValSave2 = "jane";
s = bucketAddItemStringId(pb, pValSave2, pValSave2);
assert(s == BUCKET_SUCCESS);
start = clock();
for(i=0; i<LOOPS; i++){
pVal = bucketLookupItem(pb, id1);
assert(pVal == pValSave1);
pVal = bucketLookupItem(pb, id1);
assert(pVal == pValSave1);
pVal = bucketLookupItem(pb, id1);
assert(pVal == pValSave1);
pVal = bucketLookupItem(pb, id1);
assert(pVal == pValSave1);
pVal = bucketLookupItem(pb, id1);
assert(pVal == pValSave1);
pVal = bucketLookupItem(pb, id1);
assert(pVal == pValSave1);
pVal = bucketLookupItem(pb, id1);
assert(pVal == pValSave1);
pVal = bucketLookupItem(pb, id1);
assert(pVal == pValSave1);
pVal = bucketLookupItem(pb, id1);
assert(pVal == pValSave1);
pVal = bucketLookupItem(pb, id2);
assert(pVal == pValSave2);
}
printf("End\n");
finish = clock();
duration = finish-start;
duration = duration/CLOCKS_PER_SEC;
printf("It took %15.10f total sec\n", duration);
duration = duration/LOOPS;
duration = duration/10;
duration = duration * 1e6;
printf("It took %15.10f u sec per hash lookup\n", duration);
bucketShow(pb);
return BUCKET_SUCCESS;
}
#endif
/*
* bucketUnsignedCompare()
*/
LOCAL ITEM **bucketUnsignedCompare (ITEM **ppi, const void *pId)
{
unsigned id;
unsigned *pItemId;
ITEM *pi;
id = * (unsigned *) pId;
while (pi = *ppi) {
if (bidtUnsigned == pi->type) {
pItemId = (unsigned *) pi->pId;
if (id == *pItemId) {
return ppi;
}
}
ppi = &pi->pItem;
}
return NULL;
}
/*
* bucketPointerCompare()
*/
ITEM **bucketPointerCompare (ITEM **ppi, const void *pId)
{
void *ptr;
void **pItemId;
ITEM *pi;
ptr = * (void **) pId;
while (pi = *ppi) {
if (bidtPointer == pi->type ) {
pItemId = (void **) pi->pId;
if (ptr == *pItemId) {
return ppi;
}
}
ppi = &pi->pItem;
}
return NULL;
}
/*
* bucketStringCompare ()
*/
ITEM **bucketStringCompare (ITEM **ppi, const void *pId)
{
const char *pStr = pId;
ITEM *pi;
int status;
while (pi = *ppi) {
if (bidtString == pi->type) {
status = strcmp (pStr, (char *)pi->pId);
if (status == '\0') {
return ppi;
}
}
ppi = &pi->pItem;
}
return NULL;
}
/*
* bucketUnsignedHash ()
*/
BUCKETID bucketUnsignedHash (BUCKET *pb, const void *pId)
{
const unsigned *pUId = pId;
unsigned src;
BUCKETID hashid;
src = *pUId;
hashid = src;
src = src >> pb->hashIdNBits;
while (src) {
hashid = hashid ^ src;
src = src >> pb->hashIdNBits;
}
hashid = hashid & pb->hashIdMask;
return hashid;
}
/*
* bucketPointerHash ()
*
*/
BUCKETID bucketPointerHash (BUCKET *pb, const void *pId)
{
void * const *ppId = pId;
unsigned long src;
BUCKETID hashid;
/*
* This makes the assumption that
* a pointer will fit inside of a long
* (this assumption may not port to all
* CPU architectures)
*/
src = (unsigned long) *ppId;
hashid = src;
src = src >> pb->hashIdNBits;
while(src){
hashid = hashid ^ src;
src = src >> pb->hashIdNBits;
}
hashid = hashid & pb->hashIdMask;
return hashid;
}
/*
* bucketStringHash ()
*/
BUCKETID bucketStringHash (BUCKET *pb, const void *pId)
{
const char *pStr = pId;
BUCKETID hashid;
unsigned i;
hashid = 0;
i = 1;
while(*pStr){
hashid += *pStr * i;
pStr++;
i++;
}
hashid = hashid % (pb->hashIdMask+1);
return hashid;
}
/*
* bucketCreate()
*/
#ifdef __STDC__
BUCKET *bucketCreate(unsigned indexWidth)
#else
BUCKET *bucketCreate(indexWidth)
unsigned indexWidth;
#endif
BUCKET *bucketCreate (unsigned nHashTableEntries)
{
BUCKETID mask;
unsigned nbits;
BUCKET *pb;
if (nHashTableEntries==0) {
return NULL;
}
/*
* count the number of bits in the bucket id
*/
for (nbits=0; nbits<BUCKETID_BIT_WIDTH; nbits++) {
mask = (1<<nbits) - 1;
if ( ((nHashTableEntries-1) & ~mask) == 0){
break;
}
}
/*
* indexWidth must be specified at least one
* bit less than the bit size of type BUCKETID
*/
if(indexWidth>sizeof(BUCKETID)*NBBY){
printf("%s at %d: Requested index width=%d is to large. max=%d\n" ,
if (nbits>=BUCKETID_BIT_WIDTH) {
printf("%s at %d: Requested index width=%d to large. max=%d\n",
__FILE__,
__LINE__,
indexWidth,
sizeof(BUCKETID)*NBBY-1);
nbits,
BUCKETID_BIT_WIDTH-1);
return NULL;
}
pb = (BUCKET *) calloc(1, sizeof(*pb));
if(!pb){
if (!pb) {
return pb;
}
if(indexWidth>BUCKET_IX_WIDTH){
pb->indexShift = indexWidth - BUCKET_IX_WIDTH;
}
else{
pb->indexShift = 0;
}
pb->nextIndexMask = (1<<pb->indexShift)-1;
pb->nEntries = 1<<(indexWidth-pb->indexShift);
if(indexWidth == sizeof(BUCKETID)*NBBY){
pb->indexMask = 0;
pb->indexMask = ~pb->indexMask;
}
else{
pb->indexMask = (1<<indexWidth)-1;
}
pb->hashIdMask = mask;
pb->hashIdNBits = nbits;
pb->pTable = (ITEMPTR *) calloc(
pb->nEntries,
sizeof(ITEMPTR));
pb->pTable = (ITEM **) calloc (mask+1, sizeof(*pb->pTable));
if(!pb->pTable){
free(pb);
return NULL;
@@ -202,14 +377,24 @@ int bucketFree(prb)
BUCKET *prb;
#endif
{
ITEM *pi;
ITEM *pni;
/*
* deleting a bucket with entries in use
* will cause memory leaks and is not allowed
*/
if(prb->nInUse){
return BUCKET_FAILURE;
}
assert(prb->nInUse==0);
/*
* free the free list
*/
pi = prb->pFreeItems;
while (pi) {
pni = pi->pItem;
free (pi);
pi = pni;
}
free(prb->pTable);
free(prb);
@@ -220,69 +405,49 @@ BUCKET *prb;
/*
* bucketAddItem()
*/
#ifdef __STDC__
int bucketAddItem(BUCKET *prb, BUCKETID id, void *pItem)
#else
int bucketAddItem(prb, id, pItem)
BUCKET *prb;
BUCKETID id;
void *pItem;
#endif
int bucketAddItemUnsignedId(BUCKET *prb, const unsigned *pId, void *pApp)
{
int s;
ITEMPTR *pi;
return bucketAddItem(prb, &BSET[bidtUnsigned], pId, pApp);
}
int bucketAddItemPointerId(BUCKET *prb, void * const *pId, void *pApp)
{
return bucketAddItem(prb, &BSET[bidtPointer], pId, pApp);
}
int bucketAddItemStringId(BUCKET *prb, const char *pId, void *pApp)
{
return bucketAddItem(prb, &BSET[bidtString], pId, pApp);
}
LOCAL int bucketAddItem(BUCKET *prb, bucketSET *pBSET, const void *pId, void *pApp)
{
BUCKETID hashid;
ITEM *pi;
/*
* is the id to big ?
* try to get it off the free list first. If
* that fails then malloc()
*/
if(id&~prb->indexMask){
return BUCKET_FAILURE;
pi = prb->pFreeItems;
if (pi) {
prb->pFreeItems = pi->pItem;
}
if(prb->indexShift){
int new;
BUCKET *pb;
pi = &prb->pTable[id>>prb->indexShift];
pb = pi->pBucket;
if(!pb){
pb = bucketCreate(prb->indexShift);
if(!pb){
return BUCKET_FAILURE;
}
pi->pBucket = pb;
prb->nInUse++;
new = TRUE;
}
else{
new = FALSE;
else {
pi = (ITEM *) malloc(sizeof(ITEM));
if(!pi){
return BUCKET_FAILURE;
}
s = bucketAddItem(
pb,
id&prb->nextIndexMask,
pItem);
/*
* if memory cant be allocated at a lower
* level dont leak everything allocated for this new
* item so far
*/
if(s != BUCKET_SUCCESS && new){
s = bucketFree(pb);
assert(s == BUCKET_SUCCESS);
pi->pBucket = NULL;
prb->nInUse--;
}
return s;
}
pi = &prb->pTable[id];
if(pi->pItem){
return BUCKET_FAILURE;
}
pi->pItem = pItem;
/*
* create the hash index
*/
hashid = (*pBSET->pHash) (prb, pId);
pi->pApp = pApp;
pi->pId = pId;
pi->type = pBSET->type;
assert((hashid & ~prb->hashIdMask) == 0);
pi->pItem = prb->pTable[hashid];
prb->pTable[hashid] = pi;
prb->nInUse++;
return BUCKET_SUCCESS;
@@ -292,97 +457,85 @@ void *pItem;
/*
* bucketRemoveItem()
*/
#ifdef __STDC__
int bucketRemoveItem (BUCKET *prb, BUCKETID id, void *pItem)
#else
int bucketRemoveItem (prb, id, pItem)
BUCKET *prb;
BUCKETID id;
void *pItem;
#endif
int bucketRemoveItemUnsignedId (BUCKET *prb, const unsigned *pId)
{
ITEMPTR *ppi;
return bucketRemoveItem(prb, &BSET[bidtUnsigned], pId);
}
int bucketRemoveItemPointerId (BUCKET *prb, void * const *pId)
{
return bucketRemoveItem(prb, &BSET[bidtPointer], pId);
}
int bucketRemoveItemStringId (BUCKET *prb, const char *pId)
{
return bucketRemoveItem(prb, &BSET[bidtString], pId);
}
LOCAL int bucketRemoveItem (BUCKET *prb, bucketSET *pBSET, const void *pId)
{
BUCKETID hashid;
ITEM **ppi;
ITEM *pi;
/*
* is the id to big ?
* create the hash index
*/
if(id&~prb->indexMask){
hashid = (*pBSET->pHash) (prb, pId);
assert((hashid & ~prb->hashIdMask) == 0);
ppi = &prb->pTable[hashid];
ppi = (*pBSET->pCompare) (ppi, pId);
if(!ppi){
return BUCKET_FAILURE;
}
if(prb->indexShift){
BUCKET *pb;
int s;
ppi = &prb->pTable[id>>prb->indexShift];
pb = ppi->pBucket;
if(!pb){
return BUCKET_FAILURE;
}
s = bucketRemoveItem(
pb,
id&prb->nextIndexMask,
pItem);
if(s!=BUCKET_SUCCESS){
return s;
}
if(pb->nInUse==0){
free(pb->pTable);
free(pb);
ppi->pBucket = NULL;
prb->nInUse--;
}
return s;
}
ppi = &prb->pTable[id];
if(ppi->pItem != pItem){
return BUCKET_FAILURE;
}
prb->nInUse--;
ppi->pItem = NULL;
pi = *ppi;
*ppi = pi->pItem;
/*
* stuff it on the free list
*/
pi->pItem = prb->pFreeItems;
prb->pFreeItems = pi;
return BUCKET_SUCCESS;
}
/*
* bucketLookupItem()
*/
#ifdef __STDC__
void *bucketLookupItem(BUCKET *pb, BUCKETID id)
#else
void *bucketLookupItem(pb, id)
BUCKET *pb;
BUCKETID id;
#endif
void *bucketLookupItemUnsignedId (BUCKET *prb, const unsigned *pId)
{
unsigned shift;
return bucketLookupItem(prb, &BSET[bidtUnsigned], pId);
}
void *bucketLookupItemPointerId (BUCKET *prb, void * const *pId)
{
return bucketLookupItem(prb, &BSET[bidtPointer], pId);
}
void *bucketLookupItemStringId (BUCKET *prb, const char *pId)
{
return bucketLookupItem(prb, &BSET[bidtString], pId);
}
LOCAL void *bucketLookupItem(BUCKET *pb, bucketSET *pBSET, const void *pId)
{
BUCKETID hashid;
ITEM **ppi;
/*
* is the id to big ?
* create the hash index
*/
if(id&~pb->indexMask){
return NULL;
hashid = (*pBSET->pHash) (pb, pId);
assert((hashid & ~pb->hashIdMask) == 0);
/*
* at the bottom level just
* linear search for it.
*/
ppi = (*pBSET->pCompare) (&pb->pTable[hashid], pId);
if(ppi){
return (*ppi)->pApp;
}
while(shift = pb->indexShift){
BUCKETID nextId;
nextId = id & pb->nextIndexMask;
pb = pb->pTable[id>>shift].pBucket;
if(!pb){
return pb;
}
id = nextId;
}
return pb->pTable[id].pItem;
return NULL;
}
@@ -397,24 +550,62 @@ int bucketShow(pb)
BUCKET *pb;
#endif
{
ITEMPTR *pi;
ITEM **ppi;
ITEM *pi;
ITEM *pni;
unsigned nElem;
double X;
double XX;
double mean;
double stdDev;
unsigned count;
unsigned maxEntries;
unsigned freeListCount;
pi = pb->pTable;
printf( "Bucket: mask=%x entries in use=%d bytes in use=%d\n",
(pb->nEntries-1)<<pb->indexShift,
pb->nInUse,
sizeof(*pb)+pb->nEntries*sizeof(*pi));
if(pb->indexShift){
for( pi = pb->pTable;
pi<&pb->pTable[pb->nEntries];
pi++){
if(pi->pBucket){
bucketShow(pi->pBucket);
}
}
/*
* count bytes on the free list
*/
pi = pb->pFreeItems;
freeListCount = 0;
while (pi) {
freeListCount++;
pni = pi->pItem;
pi = pni;
}
printf( "Bucket entries in use = %d bytes in use = %d\n",
pb->nInUse,
sizeof(*pb)+(pb->hashIdMask+1)*
sizeof(ITEM *)+pb->nInUse*sizeof(ITEM));
printf( "Free list bytes in use = %d\n",
freeListCount*sizeof(ITEM));
ppi = pb->pTable;
nElem = pb->hashIdMask+1;
X = 0.0;
XX = 0.0;
maxEntries = 0;
while (ppi < &pb->pTable[nElem]) {
pi = *ppi;
count = 0;
while (pi) {
count++;
pi = pi->pItem;
}
X += count;
XX += count*count;
maxEntries = max (count, maxEntries);
ppi++;
}
mean = X/nElem;
stdDev = sqrt(XX/nElem - mean*mean);
printf( "Bucket entries/hash id - mean = %f std dev = %f max = %d\n",
mean,
stdDev,
maxEntries);
return BUCKET_SUCCESS;
}
+175 -224
View File
@@ -1,6 +1,6 @@
/*
*
* $Id$
* share/src/libCom/%W% %G%
*
* A file descriptor manager for use with the UNIX system call select
*
@@ -62,7 +62,6 @@
* if we are in fdmgr_pend_event()
* .15 joh 011993 Created fdmgr header file
* .16 joh 011993 Converted to ANSI C
* .17 pg 050494 HPUX cpp changes (elif converted to else & if)
*
* NOTES:
*
@@ -90,12 +89,26 @@
*
*/
static char *pSccsId = "$Id$";
static char *pSccsId = "%W%\t%G%";
/*
* ANSI
*/
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <stdarg.h>
#ifdef vxWorks
#include <vxWorks.h>
#include <taskLib.h>
#include <sysLib.h>
#include <tickLib.h>
#include <logLib.h>
#include <selectLib.h>
#endif
#include <fdmgr.h>
#ifdef vxWorks
#include <taskLib.h>
#endif
#ifndef TRUE
#define TRUE 1
@@ -113,6 +126,10 @@ static char *pSccsId = "$Id$";
#define NULL 0
#endif
#ifndef LOCAL
#define LOCAL static
#endif
#ifndef max
#define max(x, y) (((x) < (y)) ? (y) : (x))
#endif
@@ -130,9 +147,6 @@ typedef struct{
#if defined(vxWorks)
# define LOCK(PFDCTX) FASTLOCK(&(PFDCTX)->lock)
# define UNLOCK(PFDCTX) FASTUNLOCK(&(PFDCTX)->lock)
# define LOCK_FDMGR_PEND_EVENT(PFDCTX) \
FASTLOCK(&(PFDCTX)->fdmgr_pend_event_lock) \
(PFDCTX)->fdmgr_pend_event_tid = taskIdCurrent
# define UNLOCK_FDMGR_PEND_EVENT(PFDCTX) \
FASTUNLOCK(&(PFDCTX)->fdmgr_pend_event_lock) \
(PFDCTX)->fdmgr_pend_event_tid = NULL;
@@ -144,109 +158,55 @@ typedef struct{
FASTLOCK(&(PFDCTX)->fd_handler_lock)
# define UNLOCK_FD_HANDLER(PFDCTX) \
FASTUNLOCK(&(PFDCTX)->fd_handler_lock)
# define printf logMsg
# define fdmgr_gettimeval fdmgr_vxWorks_gettimeval
# define memset(D,V,N) bfill(D,N,V)
#else
#if defined(UNIX)
#elif defined(UNIX) || defined(VMS) || defined(_WIN32)
# define LOCK(PFDCTX)
# define UNLOCK(PFDCTX)
# define LOCK_FDMGR_PEND_EVENT(PFDCTX) \
{ \
if((PFDCTX)->fdmgr_pend_event_in_use){ \
printf("Double invocation of fdmgr_pend_event()\n"); \
abort(); \
} \
(PFDCTX)->fdmgr_pend_event_in_use++; \
}
# define UNLOCK_FDMGR_PEND_EVENT(PFDCTX) \
{(PFDCTX)->fdmgr_pend_event_in_use--;}
# define fdmgr_gettimeval fdmgr_UNIX_gettimeval
# define LOCK_EXPIRED(PFDCTX)
# define UNLOCK_EXPIRED(PFDCTX)
# define LOCK_FD_HANDLER(PFDCTX)
# define UNLOCK_FD_HANDLER(PFDCTX)
#else
#if defined(VMS)
# define LOCK(PFDCTX)
# define UNLOCK(PFDCTX)
# define LOCK_FDMGR_PEND_EVENT(PFDCTX) \
{ \
if((PFDCTX)->fdmgr_pend_event_in_use){ \
printf("Double invocation of fdmgr_pend_event()\n"); \
abort(); \
} \
(PFDCTX)->fdmgr_pend_event_in_use++; \
}
# define UNLOCK_FDMGR_PEND_EVENT(PFDCTX) \
{(PFDCTX)->fdmgr_pend_event_in_use--;}
# define fdmgr_gettimeval fdmgr_VMS_gettimeval
# define LOCK_EXPIRED(PFDCTX)
# define UNLOCK_EXPIRED(PFDCTX)
# define LOCK_FD_HANDLER(PFDCTX)
# define UNLOCK_FD_HANDLER(PFDCTX)
#else
@@@@ dont compile in this case @@@@
#endif
#endif
#error Please define the host OS type
#endif
#define USEC_PER_SEC 1000000
#ifdef __STDC__
#define printf @@@@ Please dont use printf in this source @@@@
LOCAL int fdmgrPrintf(char *pformat, ...);
static int fdmgr_vxWorks_gettimeval(
LOCAL int fdmgr_gettimeval(
fdctx *pfdctx,
struct timeval *pt
);
static int fdmgr_UNIX_gettimeval(
fdctx *pfdctx,
struct timeval *pt
);
static void select_alarm(
LOCAL void select_alarm(
fdctx *pfdctx
);
static int fdmgr_select(
LOCAL int fdmgr_select(
fdctx *pfdctx,
struct timeval *ptimeout
);
static void fdmgr_finish_off_fdentry(
LOCAL void fdmgr_finish_off_fdentry(
fdctx *pfdctx,
register fdentry *pfdentry
);
#else
static int fdmgr_vxWorks_gettimeval();
static int fdmgr_UNIX_gettimeval();
static void select_alarm();
static int fdmgr_select();
static void fdmgr_finish_off_fdentry();
#endif
#if defined(vxWorks)
# define abort(A) taskSuspend(taskIdSelf())
#endif
LOCAL void lockFDMGRPendEvent (fdctx *pfdctx);
/*
* This routine is to be only called from fdmgr_pend_event()
* If other uses are needed then locking issues must be
* reinvestigated
*/
#ifdef __STDC__
static void process_alarm_queue(
fdctx *pfdctx,
struct timeval *poffset
);
#else
static void process_alarm_queue();
#endif
LOCAL void process_alarm_queue(
fdctx *pfdctx,
struct timeval *poffset
);
/*
@@ -254,11 +214,7 @@ static void fdmgr_finish_off_fdentry();
* fdmgr_init()
*
*/
#ifdef __STDC__
fdctx *fdmgr_init(void)
#else
fdctx *fdmgr_init()
#endif
{
fdctx *pfdctx;
@@ -284,29 +240,41 @@ fdctx *fdmgr_init()
return pfdctx;
}
/*
*
* fdmgr_delete()
*
*/
int fdmgr_delete(fdctx *pfdctx)
{
if(!pfdctx){
return ERROR;
}
# if defined(vxWorks)
FASTLOCKFREE(&pfdctx->lock);
FASTLOCKFREE(&pfdctx->fdmgr_pend_event_lock);
FASTLOCKFREE(&pfdctx->expired_alarm_lock);
FASTLOCKFREE(&pfdctx->fd_handler_lock);
# endif
return OK;
}
/*
* fdmgr_add_timeout()
*/
#ifdef __STDC__
alarm *fdmgr_add_timeout(
fdmgrAlarm *fdmgr_add_timeout(
fdctx *pfdctx,
struct timeval *ptimeout,
void (*func)(),
void *param
)
#else
alarm *fdmgr_add_timeout(pfdctx,ptimeout,func,param)
fdctx *pfdctx;
struct timeval *ptimeout;
void (*func)();
void *param;
#endif
{
alarm *palarm=NULL;
alarm *pa;
fdmgrAlarm *palarm=NULL;
fdmgrAlarm *pa;
struct timeval t;
int status;
@@ -320,10 +288,10 @@ void *param;
return NULL;
LOCK(pfdctx);
palarm = (alarm *) ellGet(&pfdctx->free_alarm_list);
palarm = (fdmgrAlarm *) ellGet(&pfdctx->free_alarm_list);
UNLOCK(pfdctx);
if(!palarm){
palarm = (alarm *) malloc(sizeof(alarm));
palarm = (fdmgrAlarm *) malloc(sizeof(fdmgrAlarm));
if(!palarm){
return NULL;
}
@@ -332,7 +300,7 @@ void *param;
/*
* force all fields to a known state
*/
memset(palarm, 0, sizeof(*palarm));
memset((char *)palarm, 0, sizeof(*palarm));
ptimeout->tv_sec += ptimeout->tv_usec/USEC_PER_SEC;
ptimeout->tv_usec = ptimeout->tv_usec%USEC_PER_SEC;
@@ -347,9 +315,9 @@ void *param;
palarm->t.tv_usec = (t.tv_usec + ptimeout->tv_usec)%USEC_PER_SEC;
LOCK(pfdctx);
for( pa=(alarm *)pfdctx->alarm_list.node.next;
for( pa=(fdmgrAlarm *)pfdctx->alarm_list.node.next;
pa;
pa=(alarm *)pa->node.next){
pa=(fdmgrAlarm *)pa->node.next){
if(pa->t.tv_sec > palarm->t.tv_sec){
break;
}
@@ -379,16 +347,10 @@ void *param;
* fdmgr_clear_timeout()
*
*/
#ifdef __STDC__
int fdmgr_clear_timeout(
fdctx *pfdctx,
alarm *palarm
fdmgrAlarm *palarm
)
#else
int fdmgr_clear_timeout(pfdctx, palarm)
fdctx *pfdctx;
alarm *palarm;
#endif
{
int status;
enum alarm_list_type alt;
@@ -458,20 +420,12 @@ alarm *palarm;
* this rouitine is supplied solely for compatibility
* with earlier versions of this software
*/
#if __STDC__
int fdmgr_add_fd(
fdctx *pfdctx,
int fd,
void (*pfunc)(),
void *param
)
#else
int fdmgr_add_fd(pfdctx,fd,pfunc,param)
fdctx *pfdctx;
int fd;
void (*pfunc)();
void *param;
#endif
{
int status;
@@ -491,7 +445,6 @@ void *param;
* fdmgr_add_fd_callback()
*
*/
#ifdef __STDC__
int fdmgr_add_callback(
fdctx *pfdctx,
int fd,
@@ -499,14 +452,6 @@ enum fdi_type fdi,
void (*pfunc)(),
void *param
)
#else
int fdmgr_add_callback(pfdctx,fd,fdi,pfunc,param)
fdctx *pfdctx;
int fd;
enum fdi_type fdi;
void (*pfunc)();
void *param;
#endif
{
fdentry *pfdentry;
fd_set *pfds;
@@ -540,7 +485,7 @@ void *param;
/*
* force all fields to a known state
*/
memset(pfdentry, 0, sizeof(*pfdentry));
memset((char *)pfdentry, 0, sizeof(*pfdentry));
pfdentry->fd = fd;
pfdentry->fdi = fdi;
@@ -564,16 +509,10 @@ void *param;
* included solely for compatibility with previous release
*
*/
#ifdef __STDC__
int fdmgr_clear_fd(
fdctx *pfdctx,
int fd
)
#else
int fdmgr_clear_fd(pfdctx,fd)
fdctx *pfdctx;
int fd;
#endif
{
return fdmgr_clear_callback(pfdctx, fd, fdi_read);
}
@@ -584,18 +523,11 @@ int fd;
* fdmgr_clear_callback()
*
*/
#ifdef __STDC__
int fdmgr_clear_callback(
fdctx *pfdctx,
int fd,
enum fdi_type fdi
)
#else
int fdmgr_clear_callback(pfdctx,fd,fdi)
fdctx *pfdctx;
int fd;
enum fdi_type fdi;
#endif
{
register fdentry *pfdentry;
int status;
@@ -641,6 +573,7 @@ enum fdi_type fdi;
*/
# ifdef vxWorks
if(delete_pending == TRUE){
@@@@ review all of this delete pending stuff
LOCK_FD_HANDLER(pfdctx);
UNLOCK_FD_HANDLER(pfdctx);
}
@@ -650,7 +583,7 @@ enum fdi_type fdi;
* If it is an ukn fd its a problem worth printing out
*/
if(status != OK){
printf("fdmg: delete of ukn fd failed\n");
fdmgrPrintf("fdmg: delete of ukn fd failed\n");
}
return status;
@@ -664,16 +597,10 @@ enum fdi_type fdi;
* !! LOCK(pfdctx) must be applied !!
*
*/
#ifdef __STDC__
static void fdmgr_finish_off_fdentry(
LOCAL void fdmgr_finish_off_fdentry(
fdctx *pfdctx,
register fdentry *pfdentry
)
#else
static void fdmgr_finish_off_fdentry(pfdctx,pfdentry)
fdctx *pfdctx;
register fdentry *pfdentry;
#endif
{
FD_CLR(pfdentry->fd, pfdentry->pfds);
ellAdd(&pfdctx->fdentry_free_list, (ELLNODE*)pfdentry);
@@ -685,24 +612,18 @@ register fdentry *pfdentry;
* fdmgr_pend_event()
*
*/
#ifdef __STDC__
int fdmgr_pend_event(
fdctx *pfdctx,
struct timeval *ptimeout
)
#else
int fdmgr_pend_event(pfdctx,ptimeout)
fdctx *pfdctx;
struct timeval *ptimeout;
#endif
{
int status;
extern errno;
struct timeval t;
alarm *palarm;
fdmgrAlarm *palarm;
LOCK_FDMGR_PEND_EVENT(pfdctx);
lockFDMGRPendEvent(pfdctx);
/*
* If its a poll dont add a timeout
@@ -757,21 +678,14 @@ struct timeval *ptimeout;
* returns TRUE if any labor was performed, otherwise FALSE
*
*/
#ifdef __STDC__
static int fdmgr_select(
LOCAL int fdmgr_select(
fdctx *pfdctx,
struct timeval *ptimeout
)
#else
static int fdmgr_select(pfdctx,ptimeout)
fdctx *pfdctx;
struct timeval *ptimeout;
#endif
{
register fdentry *pfdentry;
int labor_performed;
int status;
int s;
labor_performed = FALSE;
@@ -790,8 +704,8 @@ struct timeval *ptimeout;
* it is in select() so I am turning
* on task delete disable to be safe
*/
# ifdef vxWorks
TASK_SAFE();
# ifdef vxWorks
taskSafe();
# endif
status = select(
pfdctx->maxfd,
@@ -799,8 +713,8 @@ struct timeval *ptimeout;
&pfdctx->writech,
&pfdctx->excpch,
ptimeout);
# ifdef vxWorks
TASK_UNSAFE();
# ifdef vxWorks
taskUnsafe();
# endif
if(status == 0){
return labor_performed;
@@ -809,12 +723,14 @@ struct timeval *ptimeout;
if(errno == EINTR)
;
else if(errno == EINVAL)
printf( "fdmgr: bad select args ? %d %d %d\n",
fdmgrPrintf(
"fdmgr: bad select args ? %d %d %d\n",
pfdctx->maxfd,
ptimeout->tv_sec,
ptimeout->tv_usec);
else
printf( "fdmgr: error from select %d\n",
fdmgrPrintf(
"fdmgr: error from select %d\n",
errno);
return labor_performed;
@@ -822,7 +738,6 @@ struct timeval *ptimeout;
pfdentry = (fdentry *) &pfdctx->fdentry_list.node;
while(TRUE){
void *pfunc;
LOCK(pfdctx)
pfdentry = (fdentry *) pfdentry->node.next;
@@ -896,36 +811,28 @@ struct timeval *ptimeout;
* only to be called by fdmgr_pend_event(). If other uses
* come up then the locking must be revisited
*/
#ifdef __STDC__
static void process_alarm_queue(
LOCAL void process_alarm_queue(
fdctx *pfdctx,
struct timeval *poffset
)
#else
static void process_alarm_queue(pfdctx,poffset)
fdctx *pfdctx;
struct timeval *poffset;
#endif
{
struct timeval t;
int status;
alarm *pa;
alarm *nextpa;
fdmgrAlarm *pa;
fdmgrAlarm *nextpa;
status = fdmgr_gettimeval(pfdctx, &t);
if(status < 0){
abort();
}
assert (status >= 0);
LOCK(pfdctx);
for(pa = (alarm*)pfdctx->alarm_list.node.next; pa; pa = nextpa){
for(pa = (fdmgrAlarm*)pfdctx->alarm_list.node.next; pa; pa = nextpa){
if(pa->t.tv_sec > t.tv_sec)
break;
else if(pa->t.tv_sec == t.tv_sec)
if(pa->t.tv_usec > t.tv_usec)
break;
nextpa = (alarm*)pa->node.next;
nextpa = (fdmgrAlarm*)pa->node.next;
ellDelete(&pfdctx->alarm_list, (ELLNODE*)pa);
ellAdd(&pfdctx->expired_alarm_list, (ELLNODE*)pa);
pa->alt = alt_expired;
@@ -954,7 +861,7 @@ struct timeval *poffset;
* on multithreaded OS
*/
LOCK_EXPIRED(pfdctx);
pa = (alarm*) pfdctx->expired_alarm_list.node.next;
pa = (fdmgrAlarm*) pfdctx->expired_alarm_list.node.next;
while(pa){
void (*pfunc)();
@@ -966,7 +873,7 @@ struct timeval *poffset;
if(pfunc){
(*pfunc)(pa->param);
}
pa = (alarm*)pa->node.next;
pa = (fdmgrAlarm*)pa->node.next;
}
UNLOCK_EXPIRED(pfdctx);
@@ -976,14 +883,14 @@ struct timeval *poffset;
* expired list onto the free list
*/
LOCK(pfdctx);
pa = (alarm*) pfdctx->expired_alarm_list.node.next;
pa = (fdmgrAlarm*) pfdctx->expired_alarm_list.node.next;
while(pa){
pa->alt = alt_free;
pa = (alarm *) pa->node.next;
pa = (fdmgrAlarm *) pa->node.next;
}
ellConcat(&pfdctx->free_alarm_list, &pfdctx->expired_alarm_list);
pa = (alarm *)pfdctx->alarm_list.node.next;
pa = (fdmgrAlarm *)pfdctx->alarm_list.node.next;
if(pa){
if(pa->t.tv_usec >= t.tv_usec){
poffset->tv_sec = pa->t.tv_sec - t.tv_sec;
@@ -1007,14 +914,9 @@ struct timeval *poffset;
* select_alarm()
*
*/
#ifdef __STDC__
static void select_alarm(
LOCAL void select_alarm(
fdctx *pfdctx
)
#else
static void select_alarm(pfdctx)
fdctx *pfdctx;
#endif
{
pfdctx->select_tmo = TRUE;
}
@@ -1024,21 +926,15 @@ fdctx *pfdctx;
/*
*
* fdmgr_UNIX_gettimeval
*
* UNIX & VMS
* fdmgr_gettimeval
*
*/
#ifdef UNIX
#ifdef __STDC__
static int fdmgr_UNIX_gettimeval(
#if defined(UNIX) || defined(VMS)
LOCAL int fdmgr_gettimeval(
fdctx *pfdctx,
struct timeval *pt
)
#else
static int fdmgr_UNIX_gettimeval(pfdctx,pt)
fdctx *pfdctx;
struct timeval *pt;
#endif
{
struct timezone tz;
@@ -1049,46 +945,38 @@ struct timeval *pt;
/*
*
* fdmgr_VMS_gettimeval
* WIN32
* fdmgr_gettimeval
*
*
*/
#ifdef VMS
#ifdef __STDC__
static int fdmgr_VMS_gettimeval(
fdctx *pfdctx,
struct timeval *pt
#ifdef _WIN32
LOCAL int fdmgr_gettimeval(
fdctx *pfdctx,
struct timeval *pt
)
#else
static int fdmgr_VMS_gettimeval(pfdctx,pt)
fdctx *pfdctx;
struct timeval *pt;
#endif
{
struct timezone tz;
SYSTEMTIME st;
GetSystemTime(&st);
pt->tv_sec = (long)st.wSecond + (long)st.wMinute*60 + (long)st.wHour*360
0;
pt->tv_usec = st.wMilliseconds*1000;
return gettimeofday(pt, &tz);
return 0;
}
#endif
/*
*
* fdmgr_vxWorks_gettimeval
*
* vxWorks
* fdmgr_gettimeval
*
*/
#ifdef vxWorks
#ifdef __STDC__
static int fdmgr_vxWorks_gettimeval(
LOCAL int fdmgr_gettimeval(
fdctx *pfdctx,
struct timeval *pt
)
#else
static int fdmgr_vxWorks_gettimeval(pfdctx,pt)
fdctx *pfdctx;
struct timeval *pt;
#endif
{
unsigned long current;
@@ -1108,3 +996,66 @@ struct timeval *pt;
return OK;
}
#endif
/*
* lockFDMGRPendEvent()
*/
LOCAL void lockFDMGRPendEvent (fdctx *pfdctx)
{
# if defined(vxWorks)
FASTLOCK(&pfdctx->fdmgr_pend_event_lock);
pfdctx->fdmgr_pend_event_tid = taskIdCurrent;
# else
assert (pfdctx->fdmgr_pend_event_in_use==0);
pfdctx->fdmgr_pend_event_in_use++;
# endif
}
/*
*
*
* fdmgrPrintf()
*
* Dump error messages to the appropriate place
*
*/
LOCAL int fdmgrPrintf(char *pformat, ...)
{
va_list args;
int status;
va_start(args, pformat);
#ifndef vxWorks
status = vfprintf(
stderr,
pformat,
args);
#else /*vxWorks*/
{
int logMsgArgs[6];
int i;
for(i=0; i< NELEMENTS(logMsgArgs); i++){
logMsgArgs[i] = va_arg(args, int);
}
status = logMsg(
pformat,
logMsgArgs[0],
logMsgArgs[1],
logMsgArgs[2],
logMsgArgs[3],
logMsgArgs[4],
logMsgArgs[5]);
}
#endif /*vxWorks*/
va_end(args);
return status;
}