diff --git a/src/as/asLib.h b/src/as/asLib.h index bd8d5ca83..a42245d17 100644 --- a/src/as/asLib.h +++ b/src/as/asLib.h @@ -126,12 +126,14 @@ epicsShareExtern int asActive; /* definition of access rights*/ typedef enum{asNOACCESS,asREAD,asWRITE} asAccessRights; +struct gphPvt; + /*Base pointers for access security*/ typedef struct asBase{ ELLLIST uagList; ELLLIST hagList; ELLLIST asgList; - void *phash; + struct gphPvt *phash; } ASBASE; epicsShareExtern volatile ASBASE *pasbase; diff --git a/src/as/asLibRoutines.c b/src/as/asLibRoutines.c index 1d4a711d5..e2d0ac41d 100644 --- a/src/as/asLibRoutines.c +++ b/src/as/asLibRoutines.c @@ -113,7 +113,7 @@ long epicsShareAPI asInitialize(ASINPUTFUNCPTR inputfunction) pasg->pavalue = asCalloc(CALCPERFORM_NARGS, sizeof(double)); pasg = (ASG *)ellNext((ELLNODE *)pasg); } - gphInitPvt(&((ASBASE *)pasbasenew)->phash,256); + gphInitPvt(&pasbasenew->phash, 256); /*Hash each uagname and each hagname*/ puag = (UAG *)ellFirst(&pasbasenew->uagList); while(puag) { diff --git a/src/dbStatic/dbBase.h b/src/dbStatic/dbBase.h index 1bf619bf8..92917ea8d 100644 --- a/src/dbStatic/dbBase.h +++ b/src/dbStatic/dbBase.h @@ -140,7 +140,7 @@ typedef struct dbRecordType { short no_fields; /* number of fields defined */ short no_prompt; /* number of fields to configure*/ short no_links; /* number of links */ - short no_aliases; + short no_aliases; /* number of aliases in recList */ short *link_ind; /* addr of array of ind in papFldDes*/ char **papsortFldName;/* ptr to array of ptr to fld names*/ short *sortFldInd; /* addr of array of ind in papFldDes*/ @@ -152,6 +152,9 @@ typedef struct dbRecordType { int rec_size; /*record size in bytes */ }dbRecordType; +struct dbPvd; /* Contents private to dbPvdLib code */ +struct gphPvt; /* Contents private to gpHashLib code */ + typedef struct dbBase { ELLLIST menuList; ELLLIST recordTypeList; @@ -159,10 +162,10 @@ typedef struct dbBase { ELLLIST registrarList; ELLLIST functionList; ELLLIST variableList; - ELLLIST bptList; /*Break Point Table Head*/ + ELLLIST bptList; void *pathPvt; - void *ppvd; /* pointer to process variable directory*/ - void *pgpHash; /*General purpose Hash Table*/ + struct dbPvd *ppvd; + struct gphPvt *pgpHash; short ignoreMissingMenus; short loadCdefs; }dbBase; diff --git a/src/dbStatic/dbPvdLib.c b/src/dbStatic/dbPvdLib.c index 16288cfb9..ee485662a 100644 --- a/src/dbStatic/dbPvdLib.c +++ b/src/dbStatic/dbPvdLib.c @@ -1,5 +1,5 @@ /*************************************************************************\ -* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne +* Copyright (c) 2009 UChicago Argonne LLC, as Operator of Argonne * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. @@ -13,241 +13,215 @@ #include #include #include -#include #include "dbDefs.h" #include "ellLib.h" #include "dbBase.h" #include "epicsStdio.h" +#include "epicsString.h" +#include "epicsMutex.h" #define epicsExportSharedSymbols #include "dbStaticLib.h" #include "dbStaticPvt.h" -int dbPvdHashTableSize = 512; -static int dbPvdHashTableShift; -#define NTABLESIZES 9 -static struct { - unsigned int tablesize; - int shift; -}hashTableParms[9] = { - {256,0}, - {512,1}, - {1024,2}, - {2048,3}, - {4096,4}, - {8192,5}, - {16384,6}, - {32768,7}, - {65536,8} -}; +typedef struct { + ELLLIST list; + epicsMutexId lock; +} dbPvdBucket; -/*The hash algorithm is a modification of the algorithm described in */ -/* Fast Hashing of Variable Length Text Strings, Peter K. Pearson, */ -/* Communications of the ACM, June 1990 */ -/* The modifications were designed by Marty Kraimer */ +typedef struct dbPvd { + unsigned int size; + unsigned int mask; + dbPvdBucket **buckets; +} dbPvd; -static unsigned char T[256] = { - 39,159,180,252, 71, 6, 13,164,232, 35,226,155, 98,120,154, 69, -157, 24,137, 29,147, 78,121, 85,112, 8,248,130, 55,117,190,160, -176,131,228, 64,211,106, 38, 27,140, 30, 88,210,227,104, 84, 77, - 75,107,169,138,195,184, 70, 90, 61,166, 7,244,165,108,219, 51, - 9,139,209, 40, 31,202, 58,179,116, 33,207,146, 76, 60,242,124, -254,197, 80,167,153,145,129,233,132, 48,246, 86,156,177, 36,187, - 45, 1, 96, 18, 19, 62,185,234, 99, 16,218, 95,128,224,123,253, - 42,109, 4,247, 72, 5,151,136, 0,152,148,127,204,133, 17, 14, -182,217, 54,199,119,174, 82, 57,215, 41,114,208,206,110,239, 23, -189, 15, 3, 22,188, 79,113,172, 28, 2,222, 21,251,225,237,105, -102, 32, 56,181,126, 83,230, 53,158, 52, 59,213,118,100, 67,142, -220,170,144,115,205, 26,125,168,249, 66,175, 97,255, 92,229, 91, -214,236,178,243, 46, 44,201,250,135,186,150,221,163,216,162, 43, - 11,101, 34, 37,194, 25, 50, 12, 87,198,173,240,193,171,143,231, -111,141,191,103, 74,245,223, 20,161,235,122, 63, 89,149, 73,238, -134, 68, 93,183,241, 81,196, 49,192, 65,212, 94,203, 10,200, 47 -}; +unsigned int dbPvdHashTableSize = 0; - -static unsigned short hash( const char *pname, int length) +#define MIN_SIZE 256 +#define DEFAULT_SIZE 512 +#define MAX_SIZE 65536 + + +int dbPvdTableSize(int size) { - unsigned char h0=0; - unsigned char h1=0; - unsigned short ind0,ind1; - int isOdd; - int i,n; - - isOdd = length%2; /*See if length is odd number of chanacters*/ - n = (isOdd ? (length-1) : length); - if(isOdd) h0 = T[h0^*(pname + length -1)]; - for(i=0; i MAX_SIZE) + size = MAX_SIZE; + + dbPvdHashTableSize = size; + return 0; } -int epicsShareAPI dbPvdTableSize(int size) +void dbPvdInitPvt(dbBase *pdbbase) { - int i; + dbPvd *ppvd; - for(i=0; i< NTABLESIZES; i++) { - if(size==hashTableParms[i].tablesize) { - dbPvdHashTableSize = hashTableParms[i].tablesize; - dbPvdHashTableShift = hashTableParms[i].shift; - return(0); - } + if (pdbbase->ppvd) return; + + if (dbPvdHashTableSize == 0) { + dbPvdHashTableSize = DEFAULT_SIZE; } - printf("Illegal Size for Process Variable Directory\n"); - return(-1); -} + ppvd = (dbPvd *)dbMalloc(sizeof(dbPvd)); + ppvd->size = dbPvdHashTableSize; + ppvd->mask = dbPvdHashTableSize - 1; + ppvd->buckets = dbCalloc(ppvd->size, sizeof(dbPvdBucket *)); -void dbPvdInitPvt(dbBase *pdbbase) -{ - ELLLIST **ppvd; - int i; - - for(i=0; i< NTABLESIZES; i++) { - if((i==NTABLESIZES-1) - ||((dbPvdHashTableSize>=hashTableParms[i].tablesize) - && (dbPvdHashTableSizeppvd = (void *) ppvd; + pdbbase->ppvd = ppvd; return; } PVDENTRY *dbPvdFind(dbBase *pdbbase, const char *name, int lenName) { - unsigned short hashInd; - ELLLIST **ppvd = (ELLLIST **) pdbbase->ppvd; - ELLLIST *pvdlist; - PVDENTRY *ppvdNode; + dbPvd *ppvd = pdbbase->ppvd; + dbPvdBucket *pbucket; + PVDENTRY *ppvdNode; - hashInd = hash(name, lenName); - pvdlist = ppvd[hashInd]; - if (pvdlist == NULL) return NULL; - ppvdNode = (PVDENTRY *) ellFirst(pvdlist); + pbucket = ppvd->buckets[epicsMemHash(name, lenName, 0) & ppvd->mask]; + if (pbucket == NULL) return NULL; + + epicsMutexMustLock(pbucket->lock); + ppvdNode = (PVDENTRY *) ellFirst(&pbucket->list); while (ppvdNode) { - if (strncmp(name, ppvdNode->precnode->recordname, lenName) == 0) - return ppvdNode; - ppvdNode = (PVDENTRY *) ellNext((ELLNODE*)ppvdNode); + const char *recordname = ppvdNode->precnode->recordname; + + if (strncmp(name, recordname, lenName) == 0 && + strlen(recordname) == lenName) + break; + ppvdNode = (PVDENTRY *) ellNext((ELLNODE *)ppvdNode); } - return NULL; + epicsMutexUnlock(pbucket->lock); + return ppvdNode; } -PVDENTRY *dbPvdAdd(dbBase *pdbbase, dbRecordType *precordType, dbRecordNode *precnode) +PVDENTRY *dbPvdAdd(dbBase *pdbbase, dbRecordType *precordType, + dbRecordNode *precnode) { - unsigned short hashInd; - ELLLIST **ppvd = (ELLLIST **) pdbbase->ppvd; - ELLLIST *ppvdlist; - PVDENTRY *ppvdNode; - int lenName; - char *name = precnode->recordname; + dbPvd *ppvd = pdbbase->ppvd; + dbPvdBucket *pbucket; + PVDENTRY *ppvdNode; + char *name = precnode->recordname; + unsigned int h; - lenName = strlen(name); - hashInd = hash(name, lenName); - ppvdlist = ppvd[hashInd]; - if (ppvdlist == NULL) { - ppvdlist = dbCalloc(1, sizeof(ELLLIST)); - ellInit(ppvdlist); - ppvd[hashInd] = ppvdlist; + h = epicsStrHash(name, 0) & ppvd->mask; + pbucket = ppvd->buckets[h]; + if (pbucket == NULL) { + pbucket = dbCalloc(1, sizeof(dbPvdBucket)); + ellInit(&pbucket->list); + pbucket->lock = epicsMutexCreate(); + ppvd->buckets[h] = pbucket; } - ppvdNode = (PVDENTRY *) ellFirst(ppvdlist); + + epicsMutexMustLock(pbucket->lock); + ppvdNode = (PVDENTRY *) ellFirst(&pbucket->list); while (ppvdNode) { - if (strcmp(name, ppvdNode->precnode->recordname) == 0) return NULL; + if (strcmp(name, ppvdNode->precnode->recordname) == 0) { + epicsMutexUnlock(pbucket->lock); + return NULL; + } ppvdNode = (PVDENTRY *) ellNext((ELLNODE *)ppvdNode); } ppvdNode = dbCalloc(1, sizeof(PVDENTRY)); ppvdNode->precordType = precordType; ppvdNode->precnode = precnode; - ellAdd(ppvdlist, (ELLNODE *)ppvdNode); + ellAdd(&pbucket->list, (ELLNODE *)ppvdNode); + epicsMutexUnlock(pbucket->lock); return ppvdNode; } -void dbPvdDelete(dbBase *pdbbase,dbRecordNode *precnode) +void dbPvdDelete(dbBase *pdbbase, dbRecordNode *precnode) { - char *name=precnode->recordname; - unsigned short hashInd; - ELLLIST **ppvd = (ELLLIST **) pdbbase->ppvd; - ELLLIST *ppvdlist; - PVDENTRY *ppvdNode; - int lenName; - - lenName=strlen(name); - hashInd = hash(name, lenName); - if (ppvd[hashInd] == NULL)return; - ppvdlist=ppvd[hashInd]; - ppvdNode = (PVDENTRY *) ellFirst(ppvdlist); - while(ppvdNode) { - if(ppvdNode->precnode && ppvdNode->precnode->recordname - && strcmp(name,(char *)ppvdNode->precnode->recordname) == 0) { - ellDelete(ppvdlist, (ELLNODE*)ppvdNode); - free((void *)ppvdNode); - return; - } - ppvdNode = (PVDENTRY *) ellNext((ELLNODE*)ppvdNode); + dbPvd *ppvd = pdbbase->ppvd; + dbPvdBucket *pbucket; + PVDENTRY *ppvdNode; + char *name = precnode->recordname; + + pbucket = ppvd->buckets[epicsStrHash(name, 0) & ppvd->mask]; + if (pbucket == NULL) return; + + epicsMutexMustLock(pbucket->lock); + ppvdNode = (PVDENTRY *) ellFirst(&pbucket->list); + while (ppvdNode) { + if (ppvdNode->precnode && + ppvdNode->precnode->recordname && + strcmp(name, ppvdNode->precnode->recordname) == 0) { + ellDelete(&pbucket->list, (ELLNODE *)ppvdNode); + free(ppvdNode); + break; + } + ppvdNode = (PVDENTRY *) ellNext((ELLNODE *)ppvdNode); } + epicsMutexUnlock(pbucket->lock); return; } - + void dbPvdFreeMem(dbBase *pdbbase) { - unsigned short hashInd; - ELLLIST **ppvd = (ELLLIST **) pdbbase->ppvd; - ELLLIST *ppvdlist; - PVDENTRY *ppvdNode; - PVDENTRY *next; - + dbPvd *ppvd = pdbbase->ppvd; + unsigned int h; + if (ppvd == NULL) return; - for (hashInd=0; hashInd<(unsigned short)dbPvdHashTableSize; hashInd++) { - if(ppvd[hashInd] == NULL) continue; - ppvdlist=ppvd[hashInd]; - ppvdNode = (PVDENTRY *) ellFirst(ppvdlist); - while(ppvdNode) { - next = (PVDENTRY *) ellNext((ELLNODE*)ppvdNode); - ellDelete(ppvdlist,(ELLNODE*)ppvdNode); - free((void *)ppvdNode); - ppvdNode = next; - } - free((void *)ppvd[hashInd]); - } - free((void *)ppvd); pdbbase->ppvd = NULL; + + for (h = 0; h < ppvd->size; h++) { + dbPvdBucket *pbucket = ppvd->buckets[h]; + PVDENTRY *ppvdNode; + + if (pbucket == NULL) continue; + epicsMutexMustLock(pbucket->lock); + ppvd->buckets[h] = NULL; + while ((ppvdNode = (PVDENTRY *) ellFirst(&pbucket->list))) { + ellDelete(&pbucket->list, (ELLNODE *)ppvdNode); + free(ppvdNode); + } + epicsMutexDestroy(pbucket->lock); + free(pbucket); + } + free(ppvd->buckets); + free(ppvd); } -void epicsShareAPI dbPvdDump(dbBase *pdbbase,int verbose) +void dbPvdDump(dbBase *pdbbase, int verbose) { - unsigned short hashInd; - ELLLIST **ppvd; - ELLLIST *ppvdlist; - PVDENTRY *ppvdNode; - int number; - - if(!pdbbase) { + unsigned int empty = 0; + dbPvd *ppvd; + unsigned int h; + + if (!pdbbase) { fprintf(stderr,"pdbbase not specified\n"); return; } - ppvd = (ELLLIST **)pdbbase->ppvd; + ppvd = pdbbase->ppvd; if (ppvd == NULL) return; - printf("Process Variable Directory\n"); - printf("dbPvdHashTableSize %d dbPvdHashTableShift %d\n", - dbPvdHashTableSize,dbPvdHashTableShift); - for (hashInd=0; hashInd<(unsigned short)dbPvdHashTableSize; hashInd++) { - if(ppvd[hashInd] == NULL) continue; - ppvdlist=ppvd[hashInd]; - ppvdNode = (PVDENTRY *) ellFirst(ppvdlist); - printf("\n%3.3hd=%3.3d ",hashInd,ellCount(ppvdlist)); - number=0; - while(ppvdNode && verbose) { - printf(" %s",(char *)ppvdNode->precnode->recordname); - if(number++ ==2) {number=0;printf("\n ");} - ppvdNode = (PVDENTRY *) ellNext((ELLNODE*)ppvdNode); - } + + printf("Process Variable Directory has %u buckets", ppvd->size); + + for (h = 0; h < ppvd->size; h++) { + dbPvdBucket *pbucket = ppvd->buckets[h]; + PVDENTRY *ppvdNode; + int i = 1; + + if (pbucket == NULL) { + empty++; + continue; + } + epicsMutexMustLock(pbucket->lock); + ppvdNode = (PVDENTRY *) ellFirst(&pbucket->list); + printf("\n [%4u] %4d ", h, ellCount(&pbucket->list)); + while (ppvdNode && verbose) { + if (!(++i % 4)) + printf("\n "); + printf(" %s", ppvdNode->precnode->recordname); + ppvdNode = (PVDENTRY *) ellNext((ELLNODE*)ppvdNode); + } + epicsMutexUnlock(pbucket->lock); } - printf("\nEnd of Process Variable Directory\n"); + printf("\n%u buckets empty.\n", empty); } diff --git a/src/libCom/gpHash/gpHash.h b/src/libCom/gpHash/gpHash.h index 2d254f165..5dd9fd8f8 100644 --- a/src/libCom/gpHash/gpHash.h +++ b/src/libCom/gpHash/gpHash.h @@ -7,13 +7,13 @@ * and higher are distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. \*************************************************************************/ -/* gpHash.h */ -/* share/epicsH $Id$ */ +/* $Id$ */ /* Author: Marty Kraimer Date: 04-07-94 */ /* gph provides a general purpose directory accessed via a hash table*/ -#ifndef INCgpHashh -#define INCgpHashh 1 + +#ifndef INC_gpHash_H +#define INC_gpHash_H #include "shareLib.h" @@ -26,24 +26,27 @@ typedef struct{ void *userPvt; /*private for user*/ } GPHENTRY; +struct gphPvt; + #ifdef __cplusplus extern "C" { #endif /*tableSize must be power of 2 in range 256 to 65536*/ -epicsShareFunc void epicsShareAPI gphInitPvt(void **ppvt,int tableSize); -epicsShareFunc GPHENTRY * epicsShareAPI - gphFind(void *pvt,const char *name,void *pvtid); -epicsShareFunc GPHENTRY * epicsShareAPI - gphAdd(void *pvt,const char *name,void *pvtid); epicsShareFunc void epicsShareAPI - gphDelete(void *pvt,const char *name,void *pvtid); -epicsShareFunc void epicsShareAPI gphFreeMem(void *pvt); -epicsShareFunc void epicsShareAPI gphDump(void *pvt); -epicsShareFunc void epicsShareAPI gphDumpFP(FILE *fp,void *pvt); + gphInitPvt(struct gphPvt **ppvt, int tableSize); +epicsShareFunc GPHENTRY * epicsShareAPI + gphFind(struct gphPvt *pvt, const char *name, void *pvtid); +epicsShareFunc GPHENTRY * epicsShareAPI + gphAdd(struct gphPvt *pvt, const char *name, void *pvtid); +epicsShareFunc void epicsShareAPI + gphDelete(struct gphPvt *pvt, const char *name, void *pvtid); +epicsShareFunc void epicsShareAPI gphFreeMem(struct gphPvt *pvt); +epicsShareFunc void epicsShareAPI gphDump(struct gphPvt *pvt); +epicsShareFunc void epicsShareAPI gphDumpFP(FILE *fp, struct gphPvt *pvt); #ifdef __cplusplus } #endif -#endif /*INCgpHashh*/ +#endif /* INC_gpHash_H */ diff --git a/src/libCom/gpHash/gpHashLib.c b/src/libCom/gpHash/gpHashLib.c index 0ca9bf4b3..e1a9f84ff 100644 --- a/src/libCom/gpHash/gpHashLib.c +++ b/src/libCom/gpHash/gpHashLib.c @@ -1,13 +1,13 @@ /*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* Copyright (c) 2009 UChicago Argonne LLC, as Operator of Argonne * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found +* EPICS BASE is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. \*************************************************************************/ /* $Id$ */ + /* Author: Marty Kraimer Date: 04-07-94 */ #include @@ -18,240 +18,214 @@ #define epicsExportSharedSymbols #include "cantProceed.h" #include "epicsMutex.h" +#include "epicsString.h" #include "dbDefs.h" #include "ellLib.h" #include "epicsPrint.h" #include "gpHash.h" typedef struct gphPvt { - int tableSize; - int nShift; - ELLLIST **paplist; /*pointer to array of pointers to ELLLIST */ + int size; + unsigned int mask; + ELLLIST **paplist; /*pointer to array of pointers to ELLLIST */ epicsMutexId lock; -}gphPvt; +} gphPvt; +#define MIN_SIZE 256 +#define DEFAULT_SIZE 512 +#define MAX_SIZE 65536 -/*The hash algorithm is the algorithm described in */ -/* Fast Hashing of Variable Length Text Strings, Peter K. Pearson, */ -/* Communications of the ACM, June 1990 */ - -static unsigned char T[256] = { - 39,159,180,252, 71, 6, 13,164,232, 35,226,155, 98,120,154, 69, -157, 24,137, 29,147, 78,121, 85,112, 8,248,130, 55,117,190,160, -176,131,228, 64,211,106, 38, 27,140, 30, 88,210,227,104, 84, 77, - 75,107,169,138,195,184, 70, 90, 61,166, 7,244,165,108,219, 51, - 9,139,209, 40, 31,202, 58,179,116, 33,207,146, 76, 60,242,124, -254,197, 80,167,153,145,129,233,132, 48,246, 86,156,177, 36,187, - 45, 1, 96, 18, 19, 62,185,234, 99, 16,218, 95,128,224,123,253, - 42,109, 4,247, 72, 5,151,136, 0,152,148,127,204,133, 17, 14, -182,217, 54,199,119,174, 82, 57,215, 41,114,208,206,110,239, 23, -189, 15, 3, 22,188, 79,113,172, 28, 2,222, 21,251,225,237,105, -102, 32, 56,181,126, 83,230, 53,158, 52, 59,213,118,100, 67,142, -220,170,144,115,205, 26,125,168,249, 66,175, 97,255, 92,229, 91, -214,236,178,243, 46, 44,201,250,135,186,150,221,163,216,162, 43, - 11,101, 34, 37,194, 25, 50, 12, 87,198,173,240,193,171,143,231, -111,141,191,103, 74,245,223, 20,161,235,122, 63, 89,149, 73,238, -134, 68, 93,183,241, 81,196, 49,192, 65,212, 94,203, 10,200, 47 -}; - -#define NSIZES 9 -static int allowSize[NSIZES] = {256,512,1024,2048,4096,8192,16384,32768,65536}; - -static int hash(const char *pname,int nShift) -{ - unsigned char h0=0; - unsigned char h1=0; - unsigned short ind0,ind1; - int even = TRUE; - unsigned char c; - - while(*pname) { - c = *pname; - if(even) {h0 = T[h0^c]; even = FALSE;} - else {h1 = T[h1^c]; even = TRUE;} - pname++; - } - ind0 = (unsigned short)h0; - ind1 = (unsigned short)h1; - return((ind1< MAX_SIZE) + size = MAX_SIZE; + pgphPvt = callocMustSucceed(1, sizeof(gphPvt), "gphInitPvt"); - pgphPvt->tableSize = tableSize; - pgphPvt->nShift = nShift; - pgphPvt->paplist = callocMustSucceed(tableSize, sizeof(ELLLIST *), "gphInitPvt"); + pgphPvt->size = size; + pgphPvt->mask = size - 1; + pgphPvt->paplist = callocMustSucceed(size, sizeof(ELLLIST *), "gphInitPvt"); pgphPvt->lock = epicsMutexMustCreate(); - *ppvt = (void *)pgphPvt; + *ppvt = pgphPvt; return; } -GPHENTRY * epicsShareAPI gphFind(void *pvt, const char *name, void *pvtid) +GPHENTRY * epicsShareAPI gphFind(gphPvt *pgphPvt, const char *name, void *pvtid) { - int hashInd; - gphPvt *pgphPvt = (gphPvt *)pvt; - ELLLIST **paplist; - ELLLIST *gphlist; - GPHENTRY *pgphNode; + ELLLIST **paplist; + ELLLIST *gphlist; + GPHENTRY *pgphNode; + int hash; if (pgphPvt == NULL) return NULL; paplist = pgphPvt->paplist; - hashInd = hash(name, pgphPvt->nShift); + hash = epicsMemHash((char *)&pvtid, sizeof(void *), 0); + hash = epicsStrHash(name, hash) & pgphPvt->mask; + epicsMutexMustLock(pgphPvt->lock); - gphlist = paplist[hashInd]; + gphlist = paplist[hash]; if (gphlist == NULL) { pgphNode = NULL; } else { pgphNode = (GPHENTRY *) ellFirst(gphlist); } + while (pgphNode) { - if (strcmp(name, pgphNode->name) == 0) { - if (pvtid == pgphNode->pvtid) break; - } + if (pvtid == pgphNode->pvtid && + strcmp(name, pgphNode->name) == 0) break; pgphNode = (GPHENTRY *) ellNext((ELLNODE *)pgphNode); } + epicsMutexUnlock(pgphPvt->lock); return pgphNode; } -GPHENTRY * epicsShareAPI gphAdd(void *pvt,const char *name,void *pvtid) +GPHENTRY * epicsShareAPI gphAdd(gphPvt *pgphPvt, const char *name, void *pvtid) { - int hashInd; - gphPvt *pgphPvt = (gphPvt *)pvt; - ELLLIST **paplist; - ELLLIST *plist; - GPHENTRY *pgphNode; - - if (pgphPvt==NULL) return NULL; + ELLLIST **paplist; + ELLLIST *plist; + GPHENTRY *pgphNode; + int hash; + + if (pgphPvt == NULL) return NULL; paplist = pgphPvt->paplist; - hashInd = hash(name,pgphPvt->nShift); + hash = epicsMemHash((char *)&pvtid, sizeof(void *), 0); + hash = epicsStrHash(name, hash) & pgphPvt->mask; + epicsMutexMustLock(pgphPvt->lock); - plist = paplist[hashInd]; + plist = paplist[hash]; if (plist == NULL) { plist = callocMustSucceed(1, sizeof(ELLLIST), "gphAdd"); ellInit(plist); - paplist[hashInd] = plist; + paplist[hash] = plist; } + pgphNode = (GPHENTRY *) ellFirst(plist); while (pgphNode) { - if ((strcmp(name, pgphNode->name) == 0) && - (pvtid == pgphNode->pvtid)) { + if (pvtid == pgphNode->pvtid && + strcmp(name, pgphNode->name) == 0) { epicsMutexUnlock(pgphPvt->lock); return NULL; } pgphNode = (GPHENTRY *) ellNext((ELLNODE *)pgphNode); } + pgphNode = callocMustSucceed(1, sizeof(GPHENTRY), "gphAdd"); pgphNode->name = name; pgphNode->pvtid = pvtid; ellAdd(plist, (ELLNODE *)pgphNode); + epicsMutexUnlock(pgphPvt->lock); return (pgphNode); } -void epicsShareAPI gphDelete(void *pvt,const char *name,void *pvtid) +void epicsShareAPI gphDelete(gphPvt *pgphPvt, const char *name, void *pvtid) { - int hashInd; - gphPvt *pgphPvt = (gphPvt *)pvt; - ELLLIST **paplist; - ELLLIST *plist = NULL; - GPHENTRY *pgphNode; - - if(pgphPvt==NULL) return; + ELLLIST **paplist; + ELLLIST *plist = NULL; + GPHENTRY *pgphNode; + int hash; + + if (pgphPvt == NULL) return; paplist = pgphPvt->paplist; - hashInd = hash(name,pgphPvt->nShift); + hash = epicsMemHash((char *)&pvtid, sizeof(void *), 0); + hash = epicsStrHash(name, hash) & pgphPvt->mask; + epicsMutexMustLock(pgphPvt->lock); - if(paplist[hashInd] == NULL) { - pgphNode = NULL; + if (paplist[hash] == NULL) { + pgphNode = NULL; } else { - plist=paplist[hashInd]; - pgphNode = (GPHENTRY *) ellFirst(plist); + plist = paplist[hash]; + pgphNode = (GPHENTRY *) ellFirst(plist); } + while(pgphNode) { - if((strcmp(name,(char *)pgphNode->name) == 0) - &&(pvtid == pgphNode->pvtid)) { - ellDelete(plist, (ELLNODE*)pgphNode); - free((void *)pgphNode); - break; - } - pgphNode = (GPHENTRY *) ellNext((ELLNODE*)pgphNode); + if (pvtid == pgphNode->pvtid && + strcmp(name, pgphNode->name) == 0) { + ellDelete(plist, (ELLNODE*)pgphNode); + free((void *)pgphNode); + break; + } + pgphNode = (GPHENTRY *) ellNext((ELLNODE*)pgphNode); } + epicsMutexUnlock(pgphPvt->lock); return; } -void epicsShareAPI gphFreeMem(void *pvt) +void epicsShareAPI gphFreeMem(gphPvt *pgphPvt) { - int hashInd; - gphPvt *pgphPvt = (gphPvt *)pvt; - ELLLIST **paplist; - ELLLIST *plist; - GPHENTRY *pgphNode; - GPHENTRY *next;; - - /*caller must ensure that no other thread is using *pvt */ - if(pgphPvt==NULL) return; + ELLLIST **paplist; + int h; + + /* Caller must ensure that no other thread is using *pvt */ + if (pgphPvt == NULL) return; + paplist = pgphPvt->paplist; - for (hashInd=0; hashIndtableSize; hashInd++) { - if(paplist[hashInd] == NULL) continue; - plist=paplist[hashInd]; - pgphNode = (GPHENTRY *) ellFirst(plist); - while(pgphNode) { - next = (GPHENTRY *) ellNext((ELLNODE*)pgphNode); - ellDelete(plist,(ELLNODE*)pgphNode); - free((void *)pgphNode); - pgphNode = next; - } - free((void *)paplist[hashInd]); + for (h = 0; h < pgphPvt->size; h++) { + ELLLIST *plist = paplist[h]; + GPHENTRY *pgphNode; + GPHENTRY *next; + + if (plist == NULL) continue; + pgphNode = (GPHENTRY *) ellFirst(plist); + + while (pgphNode) { + next = (GPHENTRY *) ellNext((ELLNODE*)pgphNode); + ellDelete(plist, (ELLNODE*)pgphNode); + free(pgphNode); + pgphNode = next; + } + free(paplist[h]); } epicsMutexDestroy(pgphPvt->lock); - free((void *)paplist); - free((void *)pgphPvt); + free(paplist); + free(pgphPvt); } -void epicsShareAPI gphDump(void *pvt) +void epicsShareAPI gphDump(gphPvt *pgphPvt) { - gphDumpFP(stdout,pvt); + gphDumpFP(stdout, pgphPvt); } -void epicsShareAPI gphDumpFP(FILE *fp,void *pvt) +void epicsShareAPI gphDumpFP(FILE *fp, gphPvt *pgphPvt) { - int hashInd; - gphPvt *pgphPvt = (gphPvt *)pvt; - ELLLIST **paplist; - ELLLIST *plist; - GPHENTRY *pgphNode; - int number; - - if(pgphPvt==NULL) return; + unsigned int empty = 0; + ELLLIST **paplist; + int h; + + if (pgphPvt == NULL) return; + + printf("Hash table has %d buckets", pgphPvt->size); + paplist = pgphPvt->paplist; - for (hashInd=0; hashIndtableSize; hashInd++) { - if(paplist[hashInd] == NULL) continue; - plist=paplist[hashInd]; - pgphNode = (GPHENTRY *) ellFirst(plist); - fprintf(fp,"\n %3.3hd=%3.3d",hashInd,ellCount(plist)); - number=0; - while(pgphNode) { - fprintf(fp," %s %p",pgphNode->name,pgphNode->pvtid); - if(number++ ==2) {number=0;fprintf(fp,"\n ");} - pgphNode = (GPHENTRY *) ellNext((ELLNODE*)pgphNode); - } + for (h = 0; h < pgphPvt->size; h++) { + ELLLIST *plist = paplist[h]; + GPHENTRY *pgphNode; + int i = 0; + + if (plist == NULL) { + empty++; + continue; + } + pgphNode = (GPHENTRY *) ellFirst(plist); + + fprintf(fp, "\n [%3d] %3d ", h, ellCount(plist)); + while (pgphNode) { + if (!(++i % 3)) + fprintf(fp, "\n "); + fprintf(fp, " %s %p", pgphNode->name, pgphNode->pvtid); + pgphNode = (GPHENTRY *) ellNext((ELLNODE*)pgphNode); + } } - fprintf(fp,"\n End of General Purpose Hash\n"); + fprintf(fp, "\n%u buckets empty.\n", empty); }