From: bdemsky Date: Mon, 1 Nov 2010 09:18:04 +0000 (+0000) Subject: convert CAS -> XCHG when possible....no retry necessary this way X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=cf0f8087d6b75ed9a45318ae684d57a9c3f0db29;p=IRC.git convert CAS -> XCHG when possible....no retry necessary this way --- diff --git a/Robust/src/Runtime/memPool.h b/Robust/src/Runtime/memPool.h index 6c75f647..a4b600b7 100644 --- a/Robust/src/Runtime/memPool.h +++ b/Robust/src/Runtime/memPool.h @@ -28,7 +28,6 @@ #include static INTPTR pageSize; #endif - #include "runtime.h" #include "mem.h" #include "mlp_lock.h" @@ -142,37 +141,14 @@ static inline void poolfreeinto( MemPool* p, void* ptr ) { #else + // normal version static inline void poolfreeinto( MemPool* p, void* ptr ) { - - MemPoolItem* tailCurrent; - MemPoolItem* tailActual; - - // set up the now unneeded record to as the tail of the - // free list by treating its first bytes as next pointer, MemPoolItem* tailNew = (MemPoolItem*) ptr; - tailNew->next = NULL; - - while( 1 ) { - // make sure the null happens before the insertion, - // also makes sure that we reload tailCurrent, etc.. - BARRIER(); - - tailCurrent = p->tail; - tailActual = (MemPoolItem*) - CAS( &(p->tail), // ptr to set - (INTPTR) tailCurrent, // current tail's next should be NULL - (INTPTR) tailNew // try set to our new tail - ); - if( tailActual == tailCurrent ) { - // success, update tail - tailCurrent->next = tailNew; - return; - } - - // if CAS failed, retry entire operation - } + CFENCE; + MemPoolItem *tailCurrent=(MemPoolItem *) LOCKXCHG((INTPTR *) &p->tail, (INTPTR) tailNew); + tailCurrent->next=tailNew; } #endif @@ -220,14 +196,14 @@ static inline void* poolalloc( MemPool* p ) { MemPoolItem* headCurrent = p->head; MemPoolItem* next=headCurrent->next; int i; + + if(next == NULL) { // only one item, so don't take from pool - void* newRec = RUNMALLOC( p->itemSize ); - + void *newRec=RUNMALLOC(p->itemSize); if( p->initFreshlyAllocated != NULL ) { p->initFreshlyAllocated( newRec ); } - return newRec; } @@ -261,13 +237,3 @@ static void pooldestroy( MemPool* p ) { #endif // ___MEMPOOL_H__ - - - - - - - - - - diff --git a/Robust/src/Runtime/mlp_runtime.c b/Robust/src/Runtime/mlp_runtime.c index 9c29d0ce..c661c5ef 100644 --- a/Robust/src/Runtime/mlp_runtime.c +++ b/Robust/src/Runtime/mlp_runtime.c @@ -16,7 +16,6 @@ __thread int childSESE=0; __thread psemaphore runningSESEstallSem; - // this is for using a memPool to allocate task records, // pass this into the poolcreate so it will run your // custom init code ONLY for fresh records, reused records diff --git a/Robust/src/Runtime/squeue.h b/Robust/src/Runtime/squeue.h index 75782143..ec30fd74 100644 --- a/Robust/src/Runtime/squeue.h +++ b/Robust/src/Runtime/squeue.h @@ -33,17 +33,13 @@ typedef struct sqMemPoolItem_t { void* next; } sqMemPoolItem; - typedef struct sqMemPool_t { int itemSize; - sqMemPoolItem* head; // avoid cache line contention between producer/consumer... char buffer[CACHELINESIZE]; - sqMemPoolItem* tail; - } sqMemPool; @@ -56,12 +52,9 @@ typedef struct dequeItem_t { typedef struct deque_t { dequeItem* head; - // avoid cache line contention between producer/consumer... char buffer[CACHELINESIZE - sizeof(void*)]; - dequeItem* tail; - sqMemPool objret; } deque; @@ -81,37 +74,16 @@ static void dqInit(deque *q) { } static inline void tagpoolfreeinto( sqMemPool* p, void* ptr, void *realptr ) { - sqMemPoolItem* tailCurrent; - sqMemPoolItem* tailActual; - // set up the now unneeded record to as the tail of the // free list by treating its first bytes as next pointer, sqMemPoolItem* tailNew = (sqMemPoolItem*) realptr; tailNew->next = NULL; - - while( 1 ) { - // make sure the null happens before the insertion, - // also makes sure that we reload tailCurrent, etc.. - BARRIER(); - - tailCurrent = p->tail; - tailActual = (sqMemPoolItem*) - CAS( &(p->tail), // ptr to set - (INTPTR) tailCurrent, // current tail's next should be NULL - (INTPTR) realptr); // try set to our new tail - - if( tailActual == tailCurrent ) { - // success, update tail - tailCurrent->next = (sqMemPoolItem *) ptr; - return; - } - - // if CAS failed, retry entire operation - } + CFENCE; + sqMemPoolItem* tailCurrent=(sqMemPoolItem *)LOCKXCHG((INTPTR *) &p->tail, (INTPTR) realptr); + tailCurrent->next=(sqMemPoolItem *) ptr; } static inline void* tagpoolalloc( sqMemPool* p ) { - // to protect CAS in poolfree from dereferencing // null, treat the queue as empty when there is // only one item. The dequeue operation is only @@ -123,23 +95,12 @@ static inline void* tagpoolalloc( sqMemPool* p ) { int i; if(next == NULL) { // only one item, so don't take from pool - return (void*) RUNMALLOC( p->itemSize ); + sqMemPoolItem * newitem=(sqMemPoolItem *) RUNMALLOC( p->itemSize ); + ((dequeItem *)newitem)->next=NULL; + return newitem; } - p->head = next; - ////////////////////////////////////////////////////////// - // - // - // static inline void prefetch(void *x) - // { - // asm volatile("prefetcht0 %0" :: "m" (*(unsigned long *)x)); - // } - // - // - // but this built-in gcc one seems the most portable: - ////////////////////////////////////////////////////////// - //__builtin_prefetch( &(p->head->next) ); sqMemPoolItem* realNext=(sqMemPoolItem *) EXTRACTPTR((INTPTR)next); asm volatile( "prefetcht0 (%0)" :: "r" (realNext)); realNext=(sqMemPoolItem*)(((char *)realNext)+CACHELINESIZE); @@ -163,9 +124,8 @@ static inline void* tagpoolalloc( sqMemPool* p ) { static inline void dqPushBottom( deque* p, void* work ) { dequeItem *ptr=(dequeItem *) tagpoolalloc(&p->objret); - // dequeItem *ptr=(dequeItem *) calloc(1,sizeof(dequeItem)); - dequeItem *realptr=(dequeItem *) EXTRACTPTR((INTPTR)ptr); - ptr=(dequeItem *) (((INTPTR)ptr)+INCREMENTTAG); + dequeItem *realptr=(dequeItem *) EXTRACTPTR((unsigned INTPTR)ptr); + ptr=(dequeItem *) (((unsigned INTPTR)ptr)+INCREMENTTAG); realptr->work=work; BARRIER(); p->tail->next=ptr; @@ -195,7 +155,6 @@ static inline void* dqPopTop(deque *p) { #define dqPopBottom dqPopTop - #endif // ___MEMPOOL_H__