# HG changeset patch # User Merten Sach # Date 1316182764 -7200 # Node ID a9b72021f053310b91fd3c827b71827fb0040cae # Parent 3a295609f0457cd4c5e83da1cccfebc1f5ee807d Distributed memory management w/o free requests working diff -r 3a295609f045 -r a9b72021f053 MasterLoop.c --- a/MasterLoop.c Fri Sep 16 14:26:18 2011 +0200 +++ b/MasterLoop.c Fri Sep 16 16:19:24 2011 +0200 @@ -11,6 +11,7 @@ #include "VMS.h" #include "ProcrContext.h" +#include "scheduling.h" #include "inter_VMS_request_handlers.h" //=========================================================================== diff -r 3a295609f045 -r a9b72021f053 ProcrContext.c --- a/ProcrContext.c Fri Sep 16 14:26:18 2011 +0200 +++ b/ProcrContext.c Fri Sep 16 16:19:24 2011 +0200 @@ -4,6 +4,7 @@ #include "VMS.h" +#include "ProcrContext.h" /*Create stack, then create __cdecl structure on it and put initialData and * pointer to the new structure instance into the parameter positions on diff -r 3a295609f045 -r a9b72021f053 ProcrContext.h --- a/ProcrContext.h Fri Sep 16 14:26:18 2011 +0200 +++ b/ProcrContext.h Fri Sep 16 16:19:24 2011 +0200 @@ -9,10 +9,13 @@ #define _ProcrContext_H #define _GNU_SOURCE -#include "VMS.h" +typedef struct _VirtProcr VirtProcr; +typedef struct _VMSReqst VMSReqst; +typedef void (*VirtProcrFnPtr) ( void *, VirtProcr * ); //initData, animPr -typedef struct _SchedSlot SchedSlot; -typedef struct _VirtProcr VirtProcr; + +#include "VMS_primitive_data_types.h" +#include "scheduling.h" /*WARNING: re-arranging this data structure could cause VP switching * assembly code to fail -- hard-codes offsets of fields @@ -52,13 +55,6 @@ }; //VirtProcr -struct _SchedSlot - { - int workIsDone; - int needsProcrAssigned; - VirtProcr *procrAssignedToSlot; - }; - void saveCoreLoopReturnAddr(void **returnAddress); void switchToVP(VirtProcr *nextProcr); @@ -72,7 +68,7 @@ void *asmTerminateCoreLoop(VirtProcr *currPr); #define flushRegisters() \ - asm volatile ("":::"%rbx", "%r12", "%r13","%r14","%r15") + asm volatile ("":::"%rbx", "%r12", "%r13","%r14","%r15"); inline VirtProcr * create_procr_helper( VirtProcr *newPr, VirtProcrFnPtr fnPtr, diff -r 3a295609f045 -r a9b72021f053 VMS.c --- a/VMS.c Fri Sep 16 14:26:18 2011 +0200 +++ b/VMS.c Fri Sep 16 16:19:24 2011 +0200 @@ -13,6 +13,7 @@ #include "VMS.h" #include "ProcrContext.h" +#include "scheduling.h" #include "Queue_impl/BlockingQueue.h" #include "Histogram/Histogram.h" @@ -109,7 +110,9 @@ for(i=0; ifreeListHead[i] = VMS_ext__create_free_list(); + _VMSMasterEnv->interMasterRequestsFor[i] = NULL; } + _VMSMasterEnv->currentMasterProcrID = 0; //============================= MEASUREMENT STUFF ======================== @@ -768,7 +771,7 @@ //======================================================================== */ //These are the only two that use system free - VMS_ext__free_free_list( _VMSMasterEnv->freeListHead ); + VMS_ext__free_free_list( _VMSMasterEnv->freeListHead); free( (void *)_VMSMasterEnv ); } diff -r 3a295609f045 -r a9b72021f053 VMS.h --- a/VMS.h Fri Sep 16 14:26:18 2011 +0200 +++ b/VMS.h Fri Sep 16 16:19:24 2011 +0200 @@ -9,16 +9,16 @@ #define _VMS_H #define _GNU_SOURCE +#include +#include + #include "VMS_primitive_data_types.h" #include "Queue_impl/PrivateQueue.h" #include "Histogram/Histogram.h" #include "DynArray/DynArray.h" #include "Hash_impl/PrivateHash.h" #include "vmalloc.h" - -#include -#include - +#include "requests.h" //=============================== Debug =================================== // @@ -89,7 +89,7 @@ #define VIRT_PROCR_STACK_SIZE 0x8000 /* 32K */ // memory for VMS__malloc -#define MALLOC_ADDITIONAL_MEM_FROM_OS_SIZE 0x10000000 /* 256M */ +#define MALLOC_ADDITIONAL_MEM_FROM_OS_SIZE 0x4000000 /* 64M */ #define CACHE_LINE 64 #define PAGE_SIZE 4096 @@ -110,106 +110,15 @@ //=========================================================================== typedef unsigned long long TSCount; -typedef struct _VMSReqst VMSReqst; -typedef struct _InterMasterReqst InterMasterReqst; typedef struct _IntervalProbe IntervalProbe; typedef struct _GateStruc GateStruc; typedef VirtProcr * (*SlaveScheduler) ( void *, int ); //semEnv, coreIdx typedef void (*RequestHandler) ( VirtProcr *, void * ); //prWReqst, semEnv -typedef void (*VirtProcrFnPtr) ( void *, VirtProcr * ); //initData, animPr -typedef void VirtProcrFn ( void *, VirtProcr * ); //initData, animPr typedef void (*ResumePrFnPtr) ( VirtProcr *, void * ); -//============= Requests =========== -// - -//VMS Request is the carrier for Slave to Master requests -// it has an embedded sub-type request that is pulled out -// inside the plugin's request handler -enum VMSReqstType //For Slave->Master requests - { - semantic = 1, //avoid starting enums at 0, for debug reasons - createReq, - dissipate, - VMSSemantic //goes with VMSSemReqst below - }; - -struct _VMSReqst - { - enum VMSReqstType reqType;//used for dissipate and in future for IO requests - void *semReqData; - - VMSReqst *nextReqst; - }; -//VMSReqst - -//This is a sub-type of Slave->Master requests. -// It's for Slaves to invoke built-in VMS-core functions that have language-like -// behavior. -enum VMSSemReqstType //These are equivalent to semantic requests, but for - { // VMS's services available directly to app, like OS - createProbe = 1, // and probe services -- like a VMS-wide built-in lang - openFile, - otherIO - }; - -typedef struct - { enum VMSSemReqstType reqType; - VirtProcr *requestingPr; - char *nameStr; //for create probe - } -VMSSemReq; - -//These are for Master to Master requests -// They get re-cast to the appropriate sub-type of request -enum InterMasterReqstType //For Master->Master - { - destVMSCore = 1, //avoid starting enums at 0, for debug reasons - destPlugin - }; - -struct _InterMasterReqst //Doing a trick to save space & time -- allocate - { // space for a sub-type then cast first as InterMaster then as sub-type - enum InterMasterReqstType reqType; - InterMasterReqst *nextReqst; - }; -//InterMasterReqst (defined above in typedef block) - - -//These are a sub-type of InterMaster requests. The inter-master req gets -// re-cast to be of this type, after checking -//This ones for requests between internals of VMS-core.. such as malloc -enum InterVMSCoreReqType - { - transfer_free_ptr = 1 //avoid starting enums at 0, for debug reasons - }; - -//Doing a trick to save space & time -- allocate space -// for this, cast first as InterMaster then as this -typedef struct - { - enum InterMasterReqstType reqType; //duplicate InterMasterReqst at top - InterMasterReqst *nextReqst; - - enum InterVMSCoreReqType secondReqType; - void *freePtr; //pile up fields, add as needed - } InterVMSCoreReqst; - -//This is for requests between plugins on different cores -// Here, after casting, the pluginReq is extracted and handed to plugin -//Doing a trick to save space & time -- allocate space -// for this, cast first as InterMaster then as this -typedef struct - { - enum InterMasterReqstType reqType; //copy InterMasterReqst at top - InterMasterReqst *nextReqst; - - void *pluginReq; //plugin will cast to approp type - } InterPluginReqst; - //==================== Core data structures =================== /*Master Env is the only global variable -- has entry points for any other @@ -311,8 +220,6 @@ volatile MasterEnv *_VMSMasterEnv; - - //=========================== Function Prototypes ========================= @@ -587,7 +494,6 @@ //===== -#include "ProcrContext.h" #include "probes.h" #include "vutilities.h" diff -r 3a295609f045 -r a9b72021f053 requests.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/requests.h Fri Sep 16 16:19:24 2011 +0200 @@ -0,0 +1,103 @@ +/* + * File: requests.h + * Author: msach + * + * Created on September 16, 2011, 3:11 PM + */ + +#ifndef REQUESTS_H +#define REQUESTS_H + +#include "ProcrContext.h" + +typedef struct _InterMasterReqst InterMasterReqst; + +//============= Requests =========== +// + +//VMS Request is the carrier for Slave to Master requests +// it has an embedded sub-type request that is pulled out +// inside the plugin's request handler +enum VMSReqstType //For Slave->Master requests + { + semantic = 1, //avoid starting enums at 0, for debug reasons + createReq, + dissipate, + VMSSemantic //goes with VMSSemReqst below + }; + +struct _VMSReqst + { + enum VMSReqstType reqType;//used for dissipate and in future for IO requests + void *semReqData; + + VMSReqst *nextReqst; + }; +//VMSReqst + +//This is a sub-type of Slave->Master requests. +// It's for Slaves to invoke built-in VMS-core functions that have language-like +// behavior. +enum VMSSemReqstType //These are equivalent to semantic requests, but for + { // VMS's services available directly to app, like OS + createProbe = 1, // and probe services -- like a VMS-wide built-in lang + openFile, + otherIO + }; + +typedef struct + { enum VMSSemReqstType reqType; + VirtProcr *requestingPr; + char *nameStr; //for create probe + } +VMSSemReq; + +//These are for Master to Master requests +// They get re-cast to the appropriate sub-type of request +enum InterMasterReqstType //For Master->Master + { + destVMSCore = 1, //avoid starting enums at 0, for debug reasons + destPlugin + }; + +struct _InterMasterReqst //Doing a trick to save space & time -- allocate + { // space for a sub-type then cast first as InterMaster then as sub-type + enum InterMasterReqstType reqType; + InterMasterReqst *nextReqst; + }; +//InterMasterReqst (defined above in typedef block) + + +//These are a sub-type of InterMaster requests. The inter-master req gets +// re-cast to be of this type, after checking +//This ones for requests between internals of VMS-core.. such as malloc +enum InterVMSCoreReqType + { + transfer_free_ptr = 1 //avoid starting enums at 0, for debug reasons + }; + +//Doing a trick to save space & time -- allocate space +// for this, cast first as InterMaster then as this +typedef struct + { + enum InterMasterReqstType reqType; //duplicate InterMasterReqst at top + InterMasterReqst *nextReqst; + + enum InterVMSCoreReqType secondReqType; + void *freePtr; //pile up fields, add as needed + } InterVMSCoreReqst; + +//This is for requests between plugins on different cores +// Here, after casting, the pluginReq is extracted and handed to plugin +//Doing a trick to save space & time -- allocate space +// for this, cast first as InterMaster then as this +typedef struct + { + enum InterMasterReqstType reqType; //copy InterMasterReqst at top + InterMasterReqst *nextReqst; + + void *pluginReq; //plugin will cast to approp type + } InterPluginReqst; + +#endif /* REQUESTS_H */ + diff -r 3a295609f045 -r a9b72021f053 scheduling.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scheduling.h Fri Sep 16 16:19:24 2011 +0200 @@ -0,0 +1,23 @@ +/* + * File: scheduling.h + * Author: msach + * + * Created on September 16, 2011, 2:28 PM + */ + +#ifndef SCHEDULING_H +#define SCHEDULING_H + +#include "ProcrContext.h" + +typedef struct _SchedSlot SchedSlot; + +struct _SchedSlot + { + int workIsDone; + int needsProcrAssigned; + VirtProcr *procrAssignedToSlot; + }; + +#endif /* SCHEDULING_H */ + diff -r 3a295609f045 -r a9b72021f053 vmalloc.c --- a/vmalloc.c Fri Sep 16 14:26:18 2011 +0200 +++ b/vmalloc.c Fri Sep 16 16:19:24 2011 +0200 @@ -12,7 +12,7 @@ #include #include -#include "ProcrContext.h" +#include "VMS.h" #include "Histogram/Histogram.h" /*Helper function @@ -70,6 +70,8 @@ MallocPrologAllocated *returnElem; ssize_t amountExtra, sizeConsumed,sizeOfFound; uint32 foundElemIsTopOfHeap; + + printf("Malloc on core %d\n", procrID); //============================= MEASUREMENT STUFF ======================== #ifdef MEAS__TIME_MALLOC @@ -80,7 +82,7 @@ //step up the size to be aligned at 16-byte boundary, prob better ways sizeRequested = (sizeRequested + 16) & ~15; - currElem = (_VMSMasterEnv->freeListHead[_VMSMasterEnv->currentMasterProcrID]) + currElem = (_VMSMasterEnv->freeListHead[procrID]) ->nextChunkInFreeList; while( currElem != NULL ) @@ -105,7 +107,7 @@ // save addr of start of heap in head's nextLowerInMem //Will handle top of Heap specially foundElemIsTopOfHeap = foundElem->nextHigherInMem == - _VMSMasterEnv->freeListHead->nextHigherInMem; + _VMSMasterEnv->freeListHead[procrID]->nextHigherInMem; //before shave off and try to insert new elem, remove found elem //note, foundElem will never be the head, so always has valid prevChunk @@ -124,14 +126,14 @@ { //make new elem by adding to addr of curr elem then casting sizeConsumed = sizeof(MallocProlog) + sizeRequested; newElem = (MallocProlog *)( (uintptr_t)returnElem + sizeConsumed ); - newElem->nextLowerInMem = returnElem; //This is evil (but why?) - newElem->nextHigherInMem = returnElem->nextHigherInMem; //This is evil (but why?) + newElem->nextLowerInMem = (MallocProlog*)returnElem; + newElem->nextHigherInMem = returnElem->nextHigherInMem; returnElem->nextHigherInMem = newElem; if( ! foundElemIsTopOfHeap ) { //there is no next higher for top of heap, so can't write to it newElem->nextHigherInMem->nextLowerInMem = newElem; } - add_chunk_to_free_list( newElem, _VMSMasterEnv->freeListHead ); + add_chunk_to_free_list( newElem, _VMSMasterEnv->freeListHead[procrID] ); } else { @@ -158,7 +160,7 @@ void VMS__free(void *ptrToFree) { - MallocPrologAllocated chunk = (MallocPrologAllocated*)ptrToFree - 1; + MallocPrologAllocated *chunk = (MallocPrologAllocated*)ptrToFree - 1; if(chunk->procrID == _VMSMasterEnv->currentMasterProcrID) { VMS__free_on_core(ptrToFree, _VMSMasterEnv->currentMasterProcrID); @@ -177,7 +179,8 @@ void VMS__free_in_lib(void *ptrToFree, VirtProcr *VProc) { - MallocPrologAllocated chunk = (MallocPrologAllocated*)ptrToFree - 1; + MallocPrologAllocated *chunk = (MallocPrologAllocated*)ptrToFree - 1; + printf("Free from core %d for core %d\n", VProc->coreAnimatedBy, chunk->procrID); if(chunk->procrID == VProc->coreAnimatedBy) { VMS__free_on_core(ptrToFree, VProc->coreAnimatedBy); @@ -206,9 +209,11 @@ saveLowTimeStampCountInto( startStamp ); #endif //======================================================================== + + MallocProlog* masterListHead = _VMSMasterEnv->freeListHead[procrID]; - if( ptrToFree < (void*)_VMSMasterEnv->freeListHead->nextLowerInMem || - ptrToFree > (void*)_VMSMasterEnv->freeListHead->nextHigherInMem ) + if( ptrToFree < (void*)masterListHead->nextLowerInMem || + ptrToFree > (void*)masterListHead->nextHigherInMem ) { //outside the range of data owned by VMS's malloc, so do nothing return; } @@ -250,7 +255,7 @@ // changes size of the lower elem, which is still in free-list nextLowerElem->nextHigherInMem = nextHigherElem->nextHigherInMem; if( nextHigherElem->nextHigherInMem != - _VMSMasterEnv->freeListHead->nextHigherInMem ) + masterListHead->nextHigherInMem ) nextHigherElem->nextHigherInMem->nextLowerInMem = nextLowerElem; //notice didn't do anything to elemToFree -- it simply is no // longer reachable from any of the lists. Wonder if could be a @@ -263,7 +268,7 @@ // By side-effect, changes size of the lower elem nextLowerElem->nextHigherInMem = elemToFree->nextHigherInMem; if( elemToFree->nextHigherInMem != - _VMSMasterEnv->freeListHead->nextHigherInMem ) + masterListHead->nextHigherInMem ) elemToFree->nextHigherInMem->nextLowerInMem = nextLowerElem; } } @@ -280,18 +285,18 @@ //Now chg mem-list. By side-effect, changes size of elemToFree elemToFree->nextHigherInMem = nextHigherElem->nextHigherInMem; if( elemToFree->nextHigherInMem != - _VMSMasterEnv->freeListHead->nextHigherInMem ) + masterListHead->nextHigherInMem ) elemToFree->nextHigherInMem->nextLowerInMem = elemToFree; } else { //neither lower nor higher is availabe to coalesce so add to list // this makes prev chunk ptr non-null, which indicates it's free elemToFree->nextChunkInFreeList = - _VMSMasterEnv->freeListHead->nextChunkInFreeList; - _VMSMasterEnv->freeListHead->nextChunkInFreeList = elemToFree; + masterListHead->nextChunkInFreeList; + masterListHead->nextChunkInFreeList = elemToFree; if( elemToFree->nextChunkInFreeList != NULL ) // end-of-list? elemToFree->nextChunkInFreeList->prevChunkInFreeList =elemToFree; - elemToFree->prevChunkInFreeList = _VMSMasterEnv->freeListHead; + elemToFree->prevChunkInFreeList = masterListHead; } } //============================= MEASUREMENT STUFF ======================== @@ -376,6 +381,7 @@ //Note, this is running in the main thread -- all increases in malloc // mem and all frees of it must be done in this thread, with the // thread's original stack available + freeListHead = malloc( sizeof(MallocProlog) ); firstChunk = malloc( MALLOC_ADDITIONAL_MEM_FROM_OS_SIZE ); if( firstChunk == NULL ) {printf("malloc error\n"); exit(1);} @@ -412,12 +418,15 @@ /*Designed to be called from the main thread outside of VMS, during cleanup */ void -VMS_ext__free_free_list( MallocProlog *freeListHead ) +VMS_ext__free_free_list( MallocProlog* freeListHeads[] ) { //stashed a ptr to the one and only bug chunk malloc'd from OS in the // free list head's next lower in mem pointer - free( freeListHead->nextLowerInMem ); - + int i; + for(i=0; inextLowerInMem ); + } //don't free the head -- it'll be in an array eventually -- free whole // array when all the free lists linked from it have already been freed } diff -r 3a295609f045 -r a9b72021f053 vmalloc.h --- a/vmalloc.h Fri Sep 16 14:26:18 2011 +0200 +++ b/vmalloc.h Fri Sep 16 16:19:24 2011 +0200 @@ -67,11 +67,10 @@ void VMS__free_in_ext( void *ptrToFree ); - MallocProlog * VMS_ext__create_free_list(); void -VMS_ext__free_free_list( MallocProlog *freeListHead ); +VMS_ext__free_free_list( MallocProlog* freeListHeads[] ); #endif \ No newline at end of file diff -r 3a295609f045 -r a9b72021f053 vutilities.c --- a/vutilities.c Fri Sep 16 14:26:18 2011 +0200 +++ b/vutilities.c Fri Sep 16 16:19:24 2011 +0200 @@ -9,6 +9,7 @@ #include #include +#include #include "VMS.h"