From f8db8b4dc0930f43a9afd1b53fe611b2dbe274ee Mon Sep 17 00:00:00 2001 From: Jeff Hill Date: Wed, 12 Feb 2003 18:54:48 +0000 Subject: [PATCH] switched to epicsMutex for locking --- src/gdd/gddAppTable.cc | 13 +++-- src/gdd/gddAppTable.h | 4 +- src/gdd/gddNewDel.cc | 46 +++++++++++---- src/gdd/gddNewDel.h | 128 +++++++++++++++++++---------------------- 4 files changed, 103 insertions(+), 88 deletions(-) diff --git a/src/gdd/gddAppTable.cc b/src/gdd/gddAppTable.cc index 4b2fd85ed..254a403a1 100644 --- a/src/gdd/gddAppTable.cc +++ b/src/gdd/gddAppTable.cc @@ -224,9 +224,10 @@ gddStatus gddApplicationTypeTable::registerApplicationType( return gddErrorAtLimit; } - sem.take(); - rapp=total_registered++; - sem.give(); + { + epicsGuard < epicsMutex > guard ( sem ); + rapp=total_registered++; + } if((rc=splitApplicationType(rapp,group,app))<0) return rc; @@ -382,16 +383,16 @@ gdd* gddApplicationTypeTable::getDD(aitUint32 rapp) switch(attr_table[group][app].type) { case gddApplicationTypeProto: - attr_table[group][app].sem.take(); + attr_table[group][app].sem.lock (); if( (dd=attr_table[group][app].free_list) ) { //fprintf(stderr,"Popping a proto DD from list! %d %8.8x\n",app,dd); attr_table[group][app].free_list=dd->next(); - attr_table[group][app].sem.give(); + attr_table[group][app].sem.unlock (); } else { - attr_table[group][app].sem.give(); + attr_table[group][app].sem.unlock (); // copy the prototype blk=new aitUint8[attr_table[group][app].proto_size]; // fprintf(stderr,"Creating a new proto DD! %d %8.8x\n",app,blk); diff --git a/src/gdd/gddAppTable.h b/src/gdd/gddAppTable.h index 4f3cba066..88b8f68ad 100644 --- a/src/gdd/gddAppTable.h +++ b/src/gdd/gddAppTable.h @@ -79,7 +79,7 @@ public: aitIndex total_dds; gdd* proto; gdd* free_list; - gddSemaphore sem; + epicsMutex sem; gddApplicationTypeType type; aitUint32 user_value; aitUint16* map; @@ -162,7 +162,7 @@ private: aitUint32 max_groups; gddApplicationTypeElement** attr_table; - gddSemaphore sem; + epicsMutex sem; }; inline aitUint32 gddApplicationTypeTable::group(aitUint32 rapp) const diff --git a/src/gdd/gddNewDel.cc b/src/gdd/gddNewDel.cc index 8e70c1bcf..5943cb966 100644 --- a/src/gdd/gddNewDel.cc +++ b/src/gdd/gddNewDel.cc @@ -17,17 +17,42 @@ #include "gddNewDel.h" #include -gddCleanUp gddBufferCleanUp; +class gddCleanUpNode +{ +public: + void* buffer; + gddCleanUpNode* next; +}; -gddCleanUp::gddCleanUp(void) { } +class gddCleanUp +{ +public: + gddCleanUp(); + ~gddCleanUp(); + void Add(void*); +private: + gddCleanUpNode * bufs; + epicsMutex lock; +}; -gddCleanUp::~gddCleanUp(void) { gddCleanUp::CleanUp(); } +static gddCleanUp * pBufferCleanUpGDD = NULL; -gddCleanUpNode* gddCleanUp::bufs = NULL; +static epicsThreadOnceId gddCleanupOnce = EPICS_THREAD_ONCE_INIT; +static void gddCleanupInit ( void * ) +{ + pBufferCleanUpGDD = new gddCleanUp; + assert ( pBufferCleanUpGDD ); +} -gddSemaphore gddCleanUp::lock; +void gddGlobalCleanupAdd ( void * pBuf ) +{ + epicsThreadOnce ( & gddCleanupOnce, gddCleanupInit, 0 ); + pBufferCleanUpGDD->Add ( pBuf ); +} -void gddCleanUp::CleanUp(void) +gddCleanUp::gddCleanUp() : bufs ( NULL ) {} + +gddCleanUp::~gddCleanUp() { gddCleanUpNode *p1,*p2; @@ -44,9 +69,10 @@ void gddCleanUp::Add(void* v) { gddCleanUpNode* p = new gddCleanUpNode; p->buffer=v; - lock.take(); - p->next=gddCleanUp::bufs; - gddCleanUp::bufs=p; - lock.give(); + { + epicsGuard < epicsMutex > guard ( lock ); + p->next=gddCleanUp::bufs; + gddCleanUp::bufs=p; + } } diff --git a/src/gdd/gddNewDel.h b/src/gdd/gddNewDel.h index 09c2c3670..d15993021 100644 --- a/src/gdd/gddNewDel.h +++ b/src/gdd/gddNewDel.h @@ -21,7 +21,9 @@ // this file if formatted with tab stop = 4 #include -#include "gddSemaphore.h" +#include "epicsMutex.h" +#include "epicsGuard.h" +#include "epicsThread.h" // Avoid using templates at the cost of very poor readability. // This forces the user to have a static data member named "gddNewDel_freelist" @@ -29,51 +31,56 @@ // To use this stuff: // // ** In class description header file: -// class myClass -// { -// public: -// gdd_NEWDEL_FUNC(address_to_be_used_for_freelist_next_pointer) -// private: -// gdd_NEWDEL_DATA(myClass) -// }; +// class myClass +// { +// public: +// gdd_NEWDEL_FUNC(address_to_be_used_for_freelist_next_pointer) +// private: +// gdd_NEWDEL_DATA(myClass) +// }; // // ** In source file where functions for class are written: -// gdd_NEWDEL_STAT(myClass) -// gdd_NEWDEL_DEL(myClass) -// gdd_NEWDEL_NEW(myClass) +// gdd_NEWDEL_STAT(myClass) +// gdd_NEWDEL_DEL(myClass) +// gdd_NEWDEL_NEW(myClass) #define gdd_CHUNK_NUM 20 #define gdd_CHUNK(mine) (gdd_CHUNK_NUM*sizeof(mine)) +void gddGlobalCleanupAdd ( void * pBuf ); + // private data to add to a class #define gdd_NEWDEL_DATA \ - static char* newdel_freelist; \ - static gddSemaphore newdel_lock; + static char* newdel_freelist; \ + static epicsMutex *pNewdel_lock; \ + static epicsThreadOnceId once; // public interface for the new/delete stuff // user gives this macro the address they want to use for the next pointer #define gdd_NEWDEL_FUNC(fld) \ - void* operator new(size_t); \ - void operator delete(void*); \ - char* newdel_next(void) { char** x=(char**)&(fld); return *x; } \ - void newdel_setNext(char* n) { char** x=(char**)&(fld); *x=n; } + void* operator new(size_t); \ + void operator delete(void*); \ + char* newdel_next(void) { char** x=(char**)&(fld); return *x; } \ + void newdel_setNext(char* n) { char** x=(char**)&(fld); *x=n; } \ + static void gddNewDelInit ( void * ) { pNewdel_lock = new epicsMutex; } + // declaration of the static variable for the free list #define gdd_NEWDEL_STAT(clas) \ - char* clas::newdel_freelist=NULL; \ - gddSemaphore clas::newdel_lock; + char* clas::newdel_freelist=NULL; \ + epicsMutex * clas::pNewdel_lock = NULL; \ + epicsThreadOnceId clas::once = EPICS_THREAD_ONCE_INIT; // code for the delete function #define gdd_NEWDEL_DEL(clas) \ void clas::operator delete(void* v) { \ - clas* dn = (clas*)v; \ - if(dn->newdel_next()==(char*)(-1)) free((char*)v); \ - else { \ - clas::newdel_lock.take(); \ - dn->newdel_setNext(clas::newdel_freelist); \ - clas::newdel_freelist=(char*)dn; \ - clas::newdel_lock.give(); \ - } \ + clas* dn = (clas*)v; \ + if(dn->newdel_next()==(char*)(-1)) free((char*)v); \ + else { \ + epicsGuard < epicsMutex > guard ( *clas::pNewdel_lock ); \ + dn->newdel_setNext(clas::newdel_freelist); \ + clas::newdel_freelist=(char*)dn; \ + } \ } // following function assumes that reading/writing address is atomic @@ -81,50 +88,31 @@ // code for the new function #define gdd_NEWDEL_NEW(clas) \ void* clas::operator new(size_t size) { \ - int tot; \ - clas *nn,*dn; \ - if(!clas::newdel_freelist) { \ - tot=gdd_CHUNK_NUM; \ - nn=(clas*)malloc(gdd_CHUNK(clas)); \ - gddCleanUp::Add(nn); \ - for(dn=nn;--tot;dn++) dn->newdel_setNext((char*)(dn+1)); \ - clas::newdel_lock.take(); \ - (dn)->newdel_setNext(clas::newdel_freelist); \ - clas::newdel_freelist=(char*)nn; \ - clas::newdel_lock.give(); \ - } \ - if(size==sizeof(clas)) { \ - clas::newdel_lock.take(); \ - dn=(clas*)clas::newdel_freelist; \ - clas::newdel_freelist=((clas*)clas::newdel_freelist)->newdel_next(); \ - clas::newdel_lock.give(); \ - dn->newdel_setNext(NULL); \ - } else { \ - dn=(clas*)malloc(size); \ - dn->newdel_setNext((char*)(-1)); \ - } \ - return (void*)dn; \ + int tot; \ + clas *nn,*dn; \ + epicsThreadOnce ( &once, gddNewDelInit, 0 ); \ + if(!clas::newdel_freelist) { \ + tot=gdd_CHUNK_NUM; \ + nn=(clas*)malloc(gdd_CHUNK(clas)); \ + gddGlobalCleanupAdd (nn); \ + for(dn=nn;--tot;dn++) dn->newdel_setNext((char*)(dn+1)); \ + epicsGuard < epicsMutex > guard ( *clas::pNewdel_lock ); \ + (dn)->newdel_setNext(clas::newdel_freelist); \ + clas::newdel_freelist=(char*)nn; \ + } \ + if(size==sizeof(clas)) { \ + { \ + epicsGuard < epicsMutex > guard ( *clas::pNewdel_lock ); \ + dn=(clas*)clas::newdel_freelist; \ + clas::newdel_freelist=((clas*)clas::newdel_freelist)->newdel_next(); \ + } \ + dn->newdel_setNext(NULL); \ + } else { \ + dn=(clas*)malloc(size); \ + dn->newdel_setNext((char*)(-1)); \ + } \ + return (void*)dn; \ } -class gddCleanUpNode -{ -public: - void* buffer; - gddCleanUpNode* next; -}; - -class gddCleanUp -{ -public: - gddCleanUp(void); - ~gddCleanUp(void); - - static void Add(void*); - static void CleanUp(void); -private: - static gddCleanUpNode* bufs; - static gddSemaphore lock; -}; - #endif