generalize mempool so that one can create multiple instances of it.
authorGengbin Zheng <gzheng@illinois.edu>
Wed, 5 Oct 2011 20:33:39 +0000 (13:33 -0700)
committerGengbin Zheng <gzheng@illinois.edu>
Wed, 5 Oct 2011 20:33:39 +0000 (13:33 -0700)
src/arch/gemini_gni/conv-common.h
src/arch/gemini_gni/machine.c
src/arch/util/mempool.c [moved from src/arch/gemini_gni/mempool.c with 52% similarity]

index 142271b2eb3f6f7f1fc75ec11bd6be8832776035..5baa4b0e02c94bb20a0aa5c3e68386437d545719 100644 (file)
@@ -1,4 +1,6 @@
 
+#define CMK_CONVERSE_GEMINI_UGNI                           1
+
 #define CMK_CMIDELIVERS_USE_COMMON_CODE                    1
 
 #define CMK_CMIPRINTF_IS_A_BUILTIN                         0
index 87a4149ba0a0fcc3d35555d836e2ece8f9f3a870..7c3d48073e9b029601a0a9b0bbcd3a3919aeae47 100644 (file)
@@ -37,7 +37,7 @@ static void sleep(int secs) {
 
 
 #define REMOTE_EVENT         0
-#define USE_LRTS_MEMPOOL   1
+#define USE_LRTS_MEMPOOL     1
 
 #if USE_LRTS_MEMPOOL
 static CmiInt8 _mempool_size = 1024ll*1024*32;
@@ -82,6 +82,8 @@ uint8_t   onesided_hnd, omdh;
 #define  MEMORY_DEREGISTER(handler, nic_hndl, mem_hndl, myomdh)  GNI_MemDeregister(nic_hndl, (mem_hndl))
 #endif
 
+#define GetMemHndl(x)  ((mempool_header*)((char*)x-ALIGNBUF))->mem_hndl
+
 #define CmiGetMsgSize(m)  ((CmiMsgHeaderExt*)m)->size
 #define CmiSetMsgSize(m,s)  ((((CmiMsgHeaderExt*)m)->size)=(s))
 
@@ -387,6 +389,8 @@ static MSG_LIST *buffered_fma_tail = 0;
 
 #include "mempool.c"
 
+static mempool_type  *mempool = NULL;
+
 /* get the upper bound of log 2 */
 int mylog2(int size)
 {
@@ -1766,7 +1770,12 @@ static void LrtsInit(int *argc, char ***argv, int *numNodes, int *myNodeID)
 #if     USE_LRTS_MEMPOOL
     CmiGetArgLong(*argv, "+useMemorypoolSize", &_mempool_size);
     if (myrank==0) printf("Charm++> use memorypool size: %1.fMB\n", _mempool_size/1024.0/1024);
-    init_mempool(_mempool_size);
+    void *pool = memalign(ALIGNBUF, _mempool_size);
+    gni_mem_handle_t mem_hndl;
+    status = MEMORY_REGISTER(onesided_hnd, nic_hndl, pool, _mempool_size,  &mem_hndl, &omdh);
+    GNI_RC_CHECK("Mempool register", status);
+    mempool = init_mempool(pool, _mempool_size, mem_hndl);
+    //init_mempool(Mempool_MaxSize);
 #endif
     //init_mempool(Mempool_MaxSize);
 
@@ -1794,7 +1803,7 @@ void* LrtsAlloc(int n_bytes, int header)
         CmiAssert(header <= ALIGNBUF);
 #if     USE_LRTS_MEMPOOL
         n_bytes = ALIGN64(n_bytes);
-        char *res = syh_mempool_malloc(ALIGNBUF+n_bytes);
+        char *res = mempool_malloc(mempool, ALIGNBUF+n_bytes, 1);
 #else
         n_bytes = ALIGN4(n_bytes);           /* make sure size if 4 aligned */
         char *res = memalign(ALIGNBUF, n_bytes+ALIGNBUF);
@@ -1818,7 +1827,7 @@ void  LrtsFree(void *msg)
         CmiPrintf("[PE:%d] Free lrts for bytes=%d, ptr=%p\n", CmiMyPe(), size, (char*)msg + sizeof(CmiChunkHeader) - ALIGNBUF);
 #endif
 #if     USE_LRTS_MEMPOOL
-        syh_mempool_free((char*)msg + sizeof(CmiChunkHeader) - ALIGNBUF);
+        mempool_free(mempool, (char*)msg + sizeof(CmiChunkHeader) - ALIGNBUF);
 #else
         free((char*)msg + sizeof(CmiChunkHeader) - ALIGNBUF);
 #endif
@@ -1832,7 +1841,7 @@ static void LrtsExit()
 {
     /* free memory ? */
 #if     USE_LRTS_MEMPOOL
-    kill_allmempool();
+    kill_allmempool(mempool);
 #endif
     PMI_Finalize();
     exit(0);
similarity index 52%
rename from src/arch/gemini_gni/mempool.c
rename to src/arch/util/mempool.c
index 24f52bf611cac4b6b1434b9380721a7f9f23215c..d78dbfb2991f82503c7392d1b675ab45706c5467 100644 (file)
-/*****************************************************************************
- * $Source$
- * $Author$ Yanhua Sun 
- * $Date$   08-27-2011
- * $Revision$
- *****************************************************************************/
-
-/** Memory pool implementation , It is only good for Charm++ usage. The first 64 bytes provides additional information. sizeof(int)- size of this block(free or allocated), next gni_mem_handle_t, then void** point to the next available block, */
+
+/** 
+
+Memory pool implementation , It is only good for Charm++ usage. The first 64 bytes provides additional information. sizeof(int)- size of this block(free or allocated), next gni_mem_handle_t, then void** point to the next available block. 
+
+Written by Yanhua Sun 08-27-2011
+
+*/
+
 #define MEMPOOL_DEBUG   0
 
 #define POOLS_NUM       2
 #define MAX_INT        2147483647
 
-#define  GetMemHndl(x)  ((mempool_header*)((char*)x-ALIGNBUF))->mem_hndl
-
 static      size_t     expand_mem = 1024ll*1024*16;
 
+#if ! CMK_CONVERSE_GEMINI_UGNI
+  // in uGNI, it is memory handler, other versions, this is an integer
+  // a unique integer to represent the memory block
+typedef int    gni_mem_handle_t;
+#endif
+
 // multiple mempool for different size allocation
 typedef struct mempool_block_t
 {
     void                *mempool_ptr;
-    gni_mem_handle_t    mem_hndl;
     struct              mempool_block_t *next;
+    gni_mem_handle_t    mem_hndl;
 } mempool_block;
 
-mempool_block       *mempools_head = 0;
 
 typedef struct mempool_header
 {
   int size;
   gni_mem_handle_t  mem_hndl;
-  struct mempool_header *next;
+  size_t            next_free;
 } mempool_header;
 
-mempool_header    *freelist_head = NULL;
 
-void init_mempool(size_t pool_size)
+// only at beginning of first block of mempool
+typedef struct mempool_type
 {
-    gni_return_t status;
+  mempool_block   mempools_head;
+  size_t          freelist_head;
+} mempool_type;
+
+
+mempool_type *init_mempool(void *pool, size_t pool_size, gni_mem_handle_t mem_hndl)
+{
+    mempool_type *mptr;
     mempool_header *header;
-    //CmiPrintf("[%d] mempool ask for init size %d\n", CmiMyPe(), pool_size);
-    mempools_head = (mempool_block*)malloc(sizeof(mempool_block));
-    mempools_head->mempool_ptr = memalign(ALIGNBUF, pool_size);
-    freelist_head = header = (mempool_header *) mempools_head->mempool_ptr;
-    status = MEMORY_REGISTER(onesided_hnd, nic_hndl, header, pool_size,  &(mempools_head->mem_hndl), &omdh);
-    mempools_head->next = NULL;
-    GNI_RC_CHECK("Mempool register", status);
-    header->size = pool_size;
-    header->mem_hndl = mempools_head->mem_hndl;
-    header->next = NULL;
+    gni_return_t status;
 
-#if  MEMPOOL_DEBUG
-    CmiPrintf("[%d] mempool init, MEM:%p, next=%p\n", CmiMyPe(), freelist_head, freelist_head->next);
-#endif
+    mptr = (mempool_type*)pool;
+    mptr->mempools_head.mempool_ptr = pool;
+    mptr->mempools_head.mem_hndl = mem_hndl;
+    mptr->mempools_head.next = NULL;
+    header = (mempool_header *) ((char*)pool+sizeof(mempool_type));
+    mptr->freelist_head = sizeof(mempool_type);
+//printf("[%d] pool: %p  free: %p\n", myrank, pool, header);
+    header->size = pool_size-sizeof(mempool_type)-sizeof(mempool_header);
+    header->mem_hndl = mem_hndl;
+    header->next_free = 0;
+    return mptr;
 }
 
-void kill_allmempool()
+void kill_allmempool(mempool_type *mptr)
 {
     gni_return_t status;
-    
-    mempool_block *current = mempools_head;
+    mempool_block *current, *mempools_head;
+
+    current = mempools_head = &(mptr->mempools_head);
+
     while(mempools_head!= NULL)
     {
+#if CMK_CONVERSE_GEMINI_UGNI
         status = GNI_MemDeregister(nic_hndl, &(mempools_head->mem_hndl));
         GNI_RC_CHECK("Mempool de-register", status);
+#endif
         //printf("[%d] free mempool:%p\n", CmiMyPe(), mempools_head->mempool_ptr);
-        free( mempools_head->mempool_ptr);
         current=mempools_head;
         mempools_head = mempools_head->next;
-        free(current);
+        free(current->mempool_ptr);
     }
 }
 
 // append size before the real memory buffer
-void*  syh_mempool_malloc(int size)
+void*  mempool_malloc(mempool_type *mptr, int size, int expand)
 {
     int     bestfit_size = MAX_INT; //most close size 
-    mempool_block   *expand_pool;
     gni_return_t    status;
-    mempool_header    *current = freelist_head;
+    size_t    *freelist_head = &mptr->freelist_head;
+    mempool_header    *freelist_head_ptr = mptr->freelist_head?(mempool_header*)((char*)mptr+mptr->freelist_head):NULL;
+    mempool_header    *current = freelist_head_ptr;
     mempool_header    *previous = NULL;
     mempool_header    *bestfit = NULL;
     mempool_header    *bestfit_previous = NULL;
+    mempool_block     *mempools_head = &(mptr->mempools_head);
     int     expand_size;
 
 #if  MEMPOOL_DEBUG
-    CmiPrintf("[%d] request malloc for size %d, freelist:%p\n", CmiMyPe(), size, freelist_head);
+    CmiPrintf("[%d] request malloc from pool: %p  free_head: %p %d for size %d, \n", CmiMyPe(), mptr, freelist_head_ptr, mptr->freelist_head, size);
 #endif
+
 #if 1
     while(current!= NULL)     /* best fit */
     {
@@ -99,7 +115,7 @@ void*  syh_mempool_malloc(int size)
             bestfit_previous = previous;
         }
         previous = current;
-        current = current->next;
+        current = current->next_free?(mempool_header*)((char*)mptr + current->next_free):NULL;
     }
 #else
     while(current!= NULL)             /*  first fit */
@@ -107,6 +123,7 @@ void*  syh_mempool_malloc(int size)
 #if  MEMPOOL_DEBUG
         CmiPrintf("[%d] current=%p size:%d ->%p \n", CmiMyPe(), current, current->size, (char*)current+current->size);
 #endif
+        CmiAssert(current->size != 0);
         if(current->size >= size)
         {
             bestfit_size = current->size;
@@ -115,25 +132,34 @@ void*  syh_mempool_malloc(int size)
             break;
         }
         previous = current;
-        current = current->next;
+        current = current->next_free?(mempool_header*)((char*)mptr + current->next_free):NULL;
     }
 #endif
 
     if(bestfit == NULL)
     {
+        mempool_block   *expand_pool;
+        void *pool;
+
+        if (!expand) return NULL;
+
         expand_size = expand_mem>size ? expand_mem:2*size; 
-        expand_pool         = (mempool_block*)malloc(sizeof(mempool_block));
-        expand_pool->mempool_ptr = memalign(ALIGNBUF, expand_size);
+        pool = memalign(ALIGNBUF, expand_size);
+        expand_pool = (mempool_block*)pool;
+        expand_pool->mempool_ptr = pool;
         printf("[%d] No memory has such free empty chunck of %d. expanding %p (%d)\n", CmiMyPe(), size, expand_pool->mempool_ptr, expand_size);
+#if CMK_CONVERSE_GEMINI_UGNI
         status = MEMORY_REGISTER(onesided_hnd, nic_hndl, expand_pool->mempool_ptr, expand_size,  &(expand_pool->mem_hndl), &omdh);
         GNI_RC_CHECK("Mempool register", status);
-        expand_pool->next = mempools_head;
-        mempools_head = expand_pool;
-        
-        bestfit = expand_pool->mempool_ptr;
-        bestfit->size = expand_size;
+#endif
+        expand_pool->next = NULL;
+        while (mempools_head->next != NULL) mempools_head = mempools_head->next;
+        mempools_head->next = expand_pool;
+
+        bestfit = (mempool_header*)((char*)expand_pool->mempool_ptr + sizeof(mempool_block));
+        bestfit->size = expand_size-sizeof(mempool_block);
         bestfit->mem_hndl = expand_pool->mem_hndl;
-        bestfit->next = NULL;
+        bestfit->next_free = 0;
         bestfit_size = expand_size;
 #if 0
         current = freelist_head;
@@ -147,9 +173,9 @@ void*  syh_mempool_malloc(int size)
 #endif
         bestfit_previous = previous;
         if (previous == NULL)
-           freelist_head = bestfit;
+           *freelist_head = (char*)bestfit - (char*)mptr;
         else
-           previous->next = bestfit;
+           previous->next_free = (char*)bestfit-(char*)mptr;
     }
 
     bestfit->size = size;
@@ -158,40 +184,51 @@ void*  syh_mempool_malloc(int size)
         mempool_header *ptr = (mempool_header *)((char*)bestfit + size);
         ptr->size = bestfit_size - size;
         ptr->mem_hndl = bestfit->mem_hndl;
-        ptr->next = bestfit->next;
-        if(bestfit == freelist_head)
-            freelist_head = ptr;
+        ptr->next_free = bestfit->next_free;
+        if(bestfit == freelist_head_ptr)
+           *freelist_head = (char*)ptr - (char*)mptr;
         if(bestfit_previous != NULL)
-            bestfit_previous->next= ptr;
+           bestfit_previous->next_free = (char*)ptr - (char*)mptr;
     }
     else {  
           //delete this free entry
-        if(bestfit == freelist_head)
-            freelist_head = freelist_head->next;
+        if(bestfit == freelist_head_ptr)
+            *freelist_head = freelist_head_ptr->next_free;
         else
-            bestfit_previous->next = bestfit->next;
+            bestfit_previous->next_free = bestfit->next_free;
     }
 #if  MEMPOOL_DEBUG
     printf("[%d] ++MALLOC served: %d, ptr:%p\n", CmiMyPe(), size, bestfit);
+printf("[%d] freelist_head in malloc  offset:%d free_head: %ld %ld %d %d\n", myrank, (char*)bestfit-(char*)mptr, *freelist_head, ((mempool_header*)((char*)mptr+*freelist_head))->next_free, bestfit_size, size);
 #endif
+    CmiAssert(*freelist_head >= 0);
     return (char*)bestfit;
 }
 
 //sorted free_list and merge it if it become continous 
-void syh_mempool_free(void *ptr_free)
+void mempool_free(mempool_type *mptr, void *ptr_free)
 {
     int i;
     int merged = 0;
     int free_size;
     void *free_lastbytes_pos;
-    mempool_header *current = freelist_head;
+    mempool_block     *mempools_head;
+    size_t    *freelist_head;
+    mempool_header    *freelist_head_ptr;
+    mempool_header    *current;
     mempool_header *previous = NULL;
     mempool_header *to_free = (mempool_header *)ptr_free;
 
+    mempools_head = &(mptr->mempools_head);
+    freelist_head = &mptr->freelist_head;
+    freelist_head_ptr = mptr->freelist_head?(mempool_header*)((char*)mptr+mptr->freelist_head):NULL;
+    current = freelist_head_ptr;
+
     free_size = to_free->size;
     free_lastbytes_pos = (char*)ptr_free +free_size;
+
 #if  MEMPOOL_DEBUG
-    printf("[%d] INSIDE FREE ptr=%p, size=%d freehead=%p\n", CmiMyPe(), ptr_free, free_size, freelist_head);
+    printf("[%d] INSIDE FREE ptr=%p, size=%d freehead=%p mutex: %p\n", CmiMyPe(), ptr_free, free_size, freelist_head, mptr->mutex);
 #endif
     
     while(current!= NULL && current < to_free )
@@ -200,7 +237,7 @@ void syh_mempool_free(void *ptr_free)
         CmiPrintf("[%d] previous=%p, current=%p size:%d %p\n", CmiMyPe(), previous, current, current->size, (char*)current+current->size);
 #endif
         previous = current;
-        current = current->next;
+        current = current->next_free?(mempool_header*)((char*)mptr + current->next_free):NULL;
     }
 #if  MEMPOOL_DEBUG
     if (current) CmiPrintf("[%d] previous=%p, current=%p size:%d %p\n", CmiMyPe(), previous, current, current->size, free_lastbytes_pos);
@@ -214,32 +251,34 @@ void syh_mempool_free(void *ptr_free)
     else if(current!= NULL && free_lastbytes_pos == current && memcmp(&current->mem_hndl, &to_free->mem_hndl, sizeof(gni_mem_handle_t))==0)
     {
         to_free->size += current->size;
-        to_free->next = current->next;
+        to_free->next_free = current->next_free;
         current = to_free;
         merged = 1;
         if(previous == NULL)
-            freelist_head = current;
+            *freelist_head = (char*)current - (char*)mptr;
         else
-            previous->next = to_free;
+            previous->next_free = (char*)to_free - (char*)mptr;
     }
     //continous, merge
     if(merged) {
        if (previous!= NULL && current!= NULL && (char*)previous + previous->size  == (char *)current && memcmp(&previous->mem_hndl, &current->mem_hndl, sizeof(gni_mem_handle_t))==0)
       {
          previous->size += current->size;
-         previous->next = current->next;
+         previous->next_free = current->next_free;
       }
     }
     else {
           // no merge to previous, current, create new entry
-        to_free->next = current;
+        to_free->next_free = current?(char*)current - (char*)mptr: 0;
         if(previous == NULL)
-            freelist_head = to_free;
+            *freelist_head = (char*)to_free - (char*)mptr;
         else
-            previous->next = to_free;
+            previous->next_free = (char*)to_free - (char*)mptr;
     }
 #if  MEMPOOL_DEBUG
     printf("[%d] Memory free done %p, freelist_head=%p\n", CmiMyPe(), ptr_free,  freelist_head);
 #endif
+
+    CmiAssert(*freelist_head >= 0);
 }