changeset 134:a9b72021f053 Inter-Master Requests

Distributed memory management w/o free requests working
author Merten Sach <msach@mailbox.tu-berlin.de>
date Fri, 16 Sep 2011 16:19:24 +0200
parents 3a295609f045
children 0b49fd35afc1
files MasterLoop.c ProcrContext.c ProcrContext.h VMS.c VMS.h requests.h scheduling.h vmalloc.c vmalloc.h vutilities.c
diffstat 10 files changed, 174 insertions(+), 132 deletions(-) [+]
line diff
     1.1 --- a/MasterLoop.c	Fri Sep 16 14:26:18 2011 +0200
     1.2 +++ b/MasterLoop.c	Fri Sep 16 16:19:24 2011 +0200
     1.3 @@ -11,6 +11,7 @@
     1.4  
     1.5  #include "VMS.h"
     1.6  #include "ProcrContext.h"
     1.7 +#include "scheduling.h"
     1.8  #include "inter_VMS_request_handlers.h"
     1.9  
    1.10  //===========================================================================
     2.1 --- a/ProcrContext.c	Fri Sep 16 14:26:18 2011 +0200
     2.2 +++ b/ProcrContext.c	Fri Sep 16 16:19:24 2011 +0200
     2.3 @@ -4,6 +4,7 @@
     2.4  
     2.5  
     2.6  #include "VMS.h"
     2.7 +#include "ProcrContext.h"
     2.8  
     2.9  /*Create stack, then create __cdecl structure on it and put initialData and
    2.10   * pointer to the new structure instance into the parameter positions on
     3.1 --- a/ProcrContext.h	Fri Sep 16 14:26:18 2011 +0200
     3.2 +++ b/ProcrContext.h	Fri Sep 16 16:19:24 2011 +0200
     3.3 @@ -9,10 +9,13 @@
     3.4  #define	_ProcrContext_H
     3.5  #define _GNU_SOURCE
     3.6  
     3.7 -#include "VMS.h"
     3.8 +typedef struct _VirtProcr VirtProcr;
     3.9 +typedef struct _VMSReqst  VMSReqst;
    3.10 +typedef void  (*VirtProcrFnPtr)  ( void *, VirtProcr * ); //initData, animPr
    3.11  
    3.12 -typedef struct _SchedSlot SchedSlot;
    3.13 -typedef struct _VirtProcr     VirtProcr;
    3.14 +
    3.15 +#include "VMS_primitive_data_types.h"
    3.16 +#include "scheduling.h"
    3.17  
    3.18  /*WARNING: re-arranging this data structure could cause VP switching
    3.19   *         assembly code to fail -- hard-codes offsets of fields
    3.20 @@ -52,13 +55,6 @@
    3.21   };
    3.22  //VirtProcr
    3.23  
    3.24 -struct _SchedSlot
    3.25 - {
    3.26 -   int         workIsDone;
    3.27 -   int         needsProcrAssigned;
    3.28 -   VirtProcr  *procrAssignedToSlot;
    3.29 - };
    3.30 -
    3.31  void saveCoreLoopReturnAddr(void **returnAddress);
    3.32  
    3.33  void switchToVP(VirtProcr *nextProcr);
    3.34 @@ -72,7 +68,7 @@
    3.35  void *asmTerminateCoreLoop(VirtProcr *currPr);
    3.36  
    3.37  #define flushRegisters() \
    3.38 -        asm volatile ("":::"%rbx", "%r12", "%r13","%r14","%r15")
    3.39 +        asm volatile ("":::"%rbx", "%r12", "%r13","%r14","%r15");
    3.40  
    3.41  inline VirtProcr *
    3.42  create_procr_helper( VirtProcr *newPr,       VirtProcrFnPtr  fnPtr,
     4.1 --- a/VMS.c	Fri Sep 16 14:26:18 2011 +0200
     4.2 +++ b/VMS.c	Fri Sep 16 16:19:24 2011 +0200
     4.3 @@ -13,6 +13,7 @@
     4.4  
     4.5  #include "VMS.h"
     4.6  #include "ProcrContext.h"
     4.7 +#include "scheduling.h"
     4.8  #include "Queue_impl/BlockingQueue.h"
     4.9  #include "Histogram/Histogram.h"
    4.10  
    4.11 @@ -109,7 +110,9 @@
    4.12     for(i=0; i<NUM_CORES; i++)
    4.13     {
    4.14         _VMSMasterEnv->freeListHead[i]        = VMS_ext__create_free_list();
    4.15 +       _VMSMasterEnv->interMasterRequestsFor[i] = NULL;
    4.16     }
    4.17 +   _VMSMasterEnv->currentMasterProcrID = 0;
    4.18  
    4.19  
    4.20     //============================= MEASUREMENT STUFF ========================
    4.21 @@ -768,7 +771,7 @@
    4.22     //========================================================================
    4.23  */
    4.24        //These are the only two that use system free 
    4.25 -   VMS_ext__free_free_list( _VMSMasterEnv->freeListHead );
    4.26 +   VMS_ext__free_free_list( _VMSMasterEnv->freeListHead);
    4.27     free( (void *)_VMSMasterEnv );
    4.28   }
    4.29  
     5.1 --- a/VMS.h	Fri Sep 16 14:26:18 2011 +0200
     5.2 +++ b/VMS.h	Fri Sep 16 16:19:24 2011 +0200
     5.3 @@ -9,16 +9,16 @@
     5.4  #define	_VMS_H
     5.5  #define _GNU_SOURCE
     5.6  
     5.7 +#include <pthread.h>
     5.8 +#include <sys/time.h>
     5.9 +
    5.10  #include "VMS_primitive_data_types.h"
    5.11  #include "Queue_impl/PrivateQueue.h"
    5.12  #include "Histogram/Histogram.h"
    5.13  #include "DynArray/DynArray.h"
    5.14  #include "Hash_impl/PrivateHash.h"
    5.15  #include "vmalloc.h"
    5.16 -
    5.17 -#include <pthread.h>
    5.18 -#include <sys/time.h>
    5.19 -
    5.20 +#include "requests.h"
    5.21  
    5.22  //===============================  Debug  ===================================
    5.23  //
    5.24 @@ -89,7 +89,7 @@
    5.25  #define VIRT_PROCR_STACK_SIZE 0x8000 /* 32K */
    5.26  
    5.27     // memory for VMS__malloc
    5.28 -#define MALLOC_ADDITIONAL_MEM_FROM_OS_SIZE 0x10000000 /* 256M */
    5.29 +#define MALLOC_ADDITIONAL_MEM_FROM_OS_SIZE 0x4000000 /* 64M */
    5.30  
    5.31  #define CACHE_LINE 64
    5.32  #define PAGE_SIZE 4096
    5.33 @@ -110,106 +110,15 @@
    5.34  //===========================================================================
    5.35  typedef unsigned long long TSCount;
    5.36  
    5.37 -typedef struct _VMSReqst      VMSReqst;
    5.38 -typedef struct _InterMasterReqst InterMasterReqst;
    5.39  typedef struct _IntervalProbe IntervalProbe;
    5.40  typedef struct _GateStruc     GateStruc;
    5.41  
    5.42  
    5.43  typedef VirtProcr * (*SlaveScheduler)  ( void *, int );   //semEnv, coreIdx
    5.44  typedef void  (*RequestHandler)  ( VirtProcr *, void * ); //prWReqst, semEnv
    5.45 -typedef void  (*VirtProcrFnPtr)  ( void *, VirtProcr * ); //initData, animPr
    5.46 -typedef void    VirtProcrFn      ( void *, VirtProcr * ); //initData, animPr
    5.47  typedef void  (*ResumePrFnPtr)   ( VirtProcr *, void * );
    5.48  
    5.49  
    5.50 -//============= Requests ===========
    5.51 -//
    5.52 -
    5.53 -//VMS Request is the carrier for Slave to Master requests
    5.54 -// it has an embedded sub-type request that is pulled out
    5.55 -// inside the plugin's request handler
    5.56 -enum VMSReqstType   //For Slave->Master requests
    5.57 - { 
    5.58 -   semantic = 1,    //avoid starting enums at 0, for debug reasons
    5.59 -   createReq,
    5.60 -   dissipate,
    5.61 -   VMSSemantic      //goes with VMSSemReqst below
    5.62 - };
    5.63 -
    5.64 -struct _VMSReqst
    5.65 - {
    5.66 -   enum VMSReqstType  reqType;//used for dissipate and in future for IO requests
    5.67 -   void              *semReqData;
    5.68 -
    5.69 -   VMSReqst *nextReqst;
    5.70 - };
    5.71 -//VMSReqst
    5.72 -
    5.73 -//This is a sub-type of Slave->Master requests.
    5.74 -// It's for Slaves to invoke built-in VMS-core functions that have language-like
    5.75 -// behavior.
    5.76 -enum VMSSemReqstType   //These are equivalent to semantic requests, but for
    5.77 - {                     // VMS's services available directly to app, like OS
    5.78 -   createProbe = 1,    // and probe services -- like a VMS-wide built-in lang
    5.79 -   openFile,
    5.80 -   otherIO
    5.81 - };
    5.82 -
    5.83 -typedef struct
    5.84 - { enum VMSSemReqstType reqType;
    5.85 -   VirtProcr           *requestingPr;
    5.86 -   char                *nameStr;  //for create probe
    5.87 - }
    5.88 -VMSSemReq;
    5.89 -
    5.90 -//These are for Master to Master requests
    5.91 -// They get re-cast to the appropriate sub-type of request
    5.92 -enum InterMasterReqstType    //For Master->Master
    5.93 - {
    5.94 -   destVMSCore = 1,          //avoid starting enums at 0, for debug reasons
    5.95 -   destPlugin
    5.96 - };
    5.97 -
    5.98 -struct _InterMasterReqst //Doing a trick to save space & time -- allocate
    5.99 - {  // space for a sub-type then cast first as InterMaster then as sub-type
   5.100 -   enum InterMasterReqstType  reqType;
   5.101 -   InterMasterReqst *nextReqst;
   5.102 - };
   5.103 -//InterMasterReqst  (defined above in typedef block)
   5.104 -
   5.105 -
   5.106 -//These are a sub-type of InterMaster requests.  The inter-master req gets
   5.107 -// re-cast to be of this type, after checking
   5.108 -//This ones for requests between internals of VMS-core.. such as malloc
   5.109 -enum InterVMSCoreReqType   
   5.110 - {
   5.111 -   transfer_free_ptr = 1     //avoid starting enums at 0, for debug reasons
   5.112 - };
   5.113 -
   5.114 -//Doing a trick to save space & time -- allocate space
   5.115 -// for this, cast first as InterMaster then as this
   5.116 -typedef struct  
   5.117 - {
   5.118 -   enum InterMasterReqstType  reqType;  //duplicate InterMasterReqst at top
   5.119 -   InterMasterReqst *nextReqst;
   5.120 -   
   5.121 -   enum InterVMSCoreReqType  secondReqType;
   5.122 -   void                     *freePtr;  //pile up fields, add as needed
   5.123 - } InterVMSCoreReqst;
   5.124 -
   5.125 -//This is for requests between plugins on different cores
   5.126 -// Here, after casting, the pluginReq is extracted and handed to plugin
   5.127 -//Doing a trick to save space & time -- allocate space
   5.128 -// for this, cast first as InterMaster then as this
   5.129 -typedef struct  
   5.130 - {
   5.131 -   enum InterMasterReqstType  reqType;  //copy InterMasterReqst at top
   5.132 -   InterMasterReqst          *nextReqst;
   5.133 -   
   5.134 -   void                      *pluginReq; //plugin will cast to approp type
   5.135 - } InterPluginReqst;
   5.136 -
   5.137  //====================  Core data structures  ===================
   5.138  
   5.139  /*Master Env is the only global variable -- has entry points for any other
   5.140 @@ -311,8 +220,6 @@
   5.141  volatile MasterEnv      *_VMSMasterEnv;
   5.142  
   5.143  
   5.144 -
   5.145 -
   5.146  //===========================  Function Prototypes  =========================
   5.147  
   5.148  
   5.149 @@ -587,7 +494,6 @@
   5.150  
   5.151  //=====
   5.152  
   5.153 -#include "ProcrContext.h"
   5.154  #include "probes.h"
   5.155  #include "vutilities.h"
   5.156  
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/requests.h	Fri Sep 16 16:19:24 2011 +0200
     6.3 @@ -0,0 +1,103 @@
     6.4 +/* 
     6.5 + * File:   requests.h
     6.6 + * Author: msach
     6.7 + *
     6.8 + * Created on September 16, 2011, 3:11 PM
     6.9 + */
    6.10 +
    6.11 +#ifndef REQUESTS_H
    6.12 +#define	REQUESTS_H
    6.13 +
    6.14 +#include "ProcrContext.h"
    6.15 +
    6.16 +typedef struct _InterMasterReqst InterMasterReqst;
    6.17 +
    6.18 +//============= Requests ===========
    6.19 +//
    6.20 +
    6.21 +//VMS Request is the carrier for Slave to Master requests
    6.22 +// it has an embedded sub-type request that is pulled out
    6.23 +// inside the plugin's request handler
    6.24 +enum VMSReqstType   //For Slave->Master requests
    6.25 + { 
    6.26 +   semantic = 1,    //avoid starting enums at 0, for debug reasons
    6.27 +   createReq,
    6.28 +   dissipate,
    6.29 +   VMSSemantic      //goes with VMSSemReqst below
    6.30 + };
    6.31 +
    6.32 +struct _VMSReqst
    6.33 + {
    6.34 +   enum VMSReqstType  reqType;//used for dissipate and in future for IO requests
    6.35 +   void              *semReqData;
    6.36 +
    6.37 +   VMSReqst *nextReqst;
    6.38 + };
    6.39 +//VMSReqst
    6.40 +
    6.41 +//This is a sub-type of Slave->Master requests.
    6.42 +// It's for Slaves to invoke built-in VMS-core functions that have language-like
    6.43 +// behavior.
    6.44 +enum VMSSemReqstType   //These are equivalent to semantic requests, but for
    6.45 + {                     // VMS's services available directly to app, like OS
    6.46 +   createProbe = 1,    // and probe services -- like a VMS-wide built-in lang
    6.47 +   openFile,
    6.48 +   otherIO
    6.49 + };
    6.50 +
    6.51 +typedef struct
    6.52 + { enum VMSSemReqstType reqType;
    6.53 +   VirtProcr           *requestingPr;
    6.54 +   char                *nameStr;  //for create probe
    6.55 + }
    6.56 +VMSSemReq;
    6.57 +
    6.58 +//These are for Master to Master requests
    6.59 +// They get re-cast to the appropriate sub-type of request
    6.60 +enum InterMasterReqstType    //For Master->Master
    6.61 + {
    6.62 +   destVMSCore = 1,          //avoid starting enums at 0, for debug reasons
    6.63 +   destPlugin
    6.64 + };
    6.65 +
    6.66 +struct _InterMasterReqst //Doing a trick to save space & time -- allocate
    6.67 + {  // space for a sub-type then cast first as InterMaster then as sub-type
    6.68 +   enum InterMasterReqstType  reqType;
    6.69 +   InterMasterReqst *nextReqst;
    6.70 + };
    6.71 +//InterMasterReqst  (defined above in typedef block)
    6.72 +
    6.73 +
    6.74 +//These are a sub-type of InterMaster requests.  The inter-master req gets
    6.75 +// re-cast to be of this type, after checking
    6.76 +//This ones for requests between internals of VMS-core.. such as malloc
    6.77 +enum InterVMSCoreReqType   
    6.78 + {
    6.79 +   transfer_free_ptr = 1     //avoid starting enums at 0, for debug reasons
    6.80 + };
    6.81 +
    6.82 +//Doing a trick to save space & time -- allocate space
    6.83 +// for this, cast first as InterMaster then as this
    6.84 +typedef struct  
    6.85 + {
    6.86 +   enum InterMasterReqstType  reqType;  //duplicate InterMasterReqst at top
    6.87 +   InterMasterReqst *nextReqst;
    6.88 +   
    6.89 +   enum InterVMSCoreReqType  secondReqType;
    6.90 +   void                     *freePtr;  //pile up fields, add as needed
    6.91 + } InterVMSCoreReqst;
    6.92 +
    6.93 +//This is for requests between plugins on different cores
    6.94 +// Here, after casting, the pluginReq is extracted and handed to plugin
    6.95 +//Doing a trick to save space & time -- allocate space
    6.96 +// for this, cast first as InterMaster then as this
    6.97 +typedef struct  
    6.98 + {
    6.99 +   enum InterMasterReqstType  reqType;  //copy InterMasterReqst at top
   6.100 +   InterMasterReqst          *nextReqst;
   6.101 +   
   6.102 +   void                      *pluginReq; //plugin will cast to approp type
   6.103 + } InterPluginReqst;
   6.104 +
   6.105 +#endif	/* REQUESTS_H */
   6.106 +
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/scheduling.h	Fri Sep 16 16:19:24 2011 +0200
     7.3 @@ -0,0 +1,23 @@
     7.4 +/* 
     7.5 + * File:   scheduling.h
     7.6 + * Author: msach
     7.7 + *
     7.8 + * Created on September 16, 2011, 2:28 PM
     7.9 + */
    7.10 +
    7.11 +#ifndef SCHEDULING_H
    7.12 +#define	SCHEDULING_H
    7.13 +
    7.14 +#include "ProcrContext.h"
    7.15 +
    7.16 +typedef struct _SchedSlot SchedSlot;
    7.17 +
    7.18 +struct _SchedSlot
    7.19 + {
    7.20 +   int         workIsDone;
    7.21 +   int         needsProcrAssigned;
    7.22 +   VirtProcr  *procrAssignedToSlot;
    7.23 + };
    7.24 + 
    7.25 +#endif	/* SCHEDULING_H */
    7.26 +
     8.1 --- a/vmalloc.c	Fri Sep 16 14:26:18 2011 +0200
     8.2 +++ b/vmalloc.c	Fri Sep 16 16:19:24 2011 +0200
     8.3 @@ -12,7 +12,7 @@
     8.4  #include <stdlib.h>
     8.5  #include <stdio.h>
     8.6  
     8.7 -#include "ProcrContext.h"
     8.8 +#include "VMS.h"
     8.9  #include "Histogram/Histogram.h"
    8.10  
    8.11  /*Helper function
    8.12 @@ -70,6 +70,8 @@
    8.13     MallocPrologAllocated *returnElem;
    8.14     ssize_t        amountExtra, sizeConsumed,sizeOfFound;
    8.15     uint32        foundElemIsTopOfHeap;
    8.16 +   
    8.17 +   printf("Malloc on core %d\n", procrID);
    8.18  
    8.19     //============================= MEASUREMENT STUFF ========================
    8.20     #ifdef MEAS__TIME_MALLOC
    8.21 @@ -80,7 +82,7 @@
    8.22     
    8.23        //step up the size to be aligned at 16-byte boundary, prob better ways
    8.24     sizeRequested = (sizeRequested + 16) & ~15;
    8.25 -   currElem = (_VMSMasterEnv->freeListHead[_VMSMasterEnv->currentMasterProcrID])
    8.26 +   currElem = (_VMSMasterEnv->freeListHead[procrID])
    8.27                          ->nextChunkInFreeList;
    8.28  
    8.29     while( currElem != NULL )
    8.30 @@ -105,7 +107,7 @@
    8.31        // save addr of start of heap in head's nextLowerInMem
    8.32        //Will handle top of Heap specially
    8.33     foundElemIsTopOfHeap = foundElem->nextHigherInMem ==
    8.34 -                          _VMSMasterEnv->freeListHead->nextHigherInMem;
    8.35 +                          _VMSMasterEnv->freeListHead[procrID]->nextHigherInMem;
    8.36     
    8.37        //before shave off and try to insert new elem, remove found elem
    8.38        //note, foundElem will never be the head, so always has valid prevChunk
    8.39 @@ -124,14 +126,14 @@
    8.40      {   //make new elem by adding to addr of curr elem then casting
    8.41          sizeConsumed = sizeof(MallocProlog) + sizeRequested; 
    8.42          newElem = (MallocProlog *)( (uintptr_t)returnElem + sizeConsumed );
    8.43 -        newElem->nextLowerInMem    = returnElem; //This is evil (but why?) 
    8.44 -        newElem->nextHigherInMem   = returnElem->nextHigherInMem; //This is evil (but why?)
    8.45 +        newElem->nextLowerInMem    = (MallocProlog*)returnElem;
    8.46 +        newElem->nextHigherInMem   = returnElem->nextHigherInMem;
    8.47          returnElem->nextHigherInMem = newElem;
    8.48          if( ! foundElemIsTopOfHeap )
    8.49          {  //there is no next higher for top of heap, so can't write to it
    8.50             newElem->nextHigherInMem->nextLowerInMem = newElem;
    8.51          }
    8.52 -        add_chunk_to_free_list( newElem, _VMSMasterEnv->freeListHead );
    8.53 +        add_chunk_to_free_list( newElem, _VMSMasterEnv->freeListHead[procrID] );
    8.54      }
    8.55     else
    8.56      {
    8.57 @@ -158,7 +160,7 @@
    8.58  void
    8.59  VMS__free(void *ptrToFree)
    8.60  {
    8.61 -    MallocPrologAllocated chunk = (MallocPrologAllocated*)ptrToFree - 1;
    8.62 +    MallocPrologAllocated *chunk = (MallocPrologAllocated*)ptrToFree - 1;
    8.63      if(chunk->procrID == _VMSMasterEnv->currentMasterProcrID)
    8.64      {
    8.65          VMS__free_on_core(ptrToFree, _VMSMasterEnv->currentMasterProcrID);
    8.66 @@ -177,7 +179,8 @@
    8.67  void
    8.68  VMS__free_in_lib(void *ptrToFree, VirtProcr *VProc)
    8.69  {
    8.70 -    MallocPrologAllocated chunk = (MallocPrologAllocated*)ptrToFree - 1;
    8.71 +    MallocPrologAllocated *chunk = (MallocPrologAllocated*)ptrToFree - 1;
    8.72 +    printf("Free from core %d for core %d\n", VProc->coreAnimatedBy, chunk->procrID);
    8.73      if(chunk->procrID == VProc->coreAnimatedBy)
    8.74      {
    8.75          VMS__free_on_core(ptrToFree, VProc->coreAnimatedBy);
    8.76 @@ -206,9 +209,11 @@
    8.77     saveLowTimeStampCountInto( startStamp );
    8.78     #endif
    8.79     //========================================================================
    8.80 +   
    8.81 +   MallocProlog* masterListHead = _VMSMasterEnv->freeListHead[procrID];
    8.82  
    8.83 -   if( ptrToFree < (void*)_VMSMasterEnv->freeListHead->nextLowerInMem ||
    8.84 -       ptrToFree > (void*)_VMSMasterEnv->freeListHead->nextHigherInMem )
    8.85 +   if( ptrToFree < (void*)masterListHead->nextLowerInMem ||
    8.86 +       ptrToFree > (void*)masterListHead->nextHigherInMem )
    8.87      {    //outside the range of data owned by VMS's malloc, so do nothing
    8.88        return;
    8.89      }
    8.90 @@ -250,7 +255,7 @@
    8.91              // changes size of the lower elem, which is still in free-list
    8.92           nextLowerElem->nextHigherInMem = nextHigherElem->nextHigherInMem;
    8.93           if( nextHigherElem->nextHigherInMem !=
    8.94 -             _VMSMasterEnv->freeListHead->nextHigherInMem )
    8.95 +             masterListHead->nextHigherInMem )
    8.96              nextHigherElem->nextHigherInMem->nextLowerInMem = nextLowerElem;
    8.97              //notice didn't do anything to elemToFree -- it simply is no
    8.98              // longer reachable from any of the lists.  Wonder if could be a
    8.99 @@ -263,7 +268,7 @@
   8.100              // By side-effect, changes size of the lower elem
   8.101           nextLowerElem->nextHigherInMem = elemToFree->nextHigherInMem;
   8.102           if( elemToFree->nextHigherInMem !=
   8.103 -             _VMSMasterEnv->freeListHead->nextHigherInMem )
   8.104 +             masterListHead->nextHigherInMem )
   8.105              elemToFree->nextHigherInMem->nextLowerInMem = nextLowerElem;
   8.106         }
   8.107      }
   8.108 @@ -280,18 +285,18 @@
   8.109              //Now chg mem-list. By side-effect, changes size of elemToFree
   8.110           elemToFree->nextHigherInMem = nextHigherElem->nextHigherInMem;
   8.111           if( elemToFree->nextHigherInMem !=
   8.112 -             _VMSMasterEnv->freeListHead->nextHigherInMem )
   8.113 +             masterListHead->nextHigherInMem )
   8.114              elemToFree->nextHigherInMem->nextLowerInMem = elemToFree;
   8.115         }
   8.116        else
   8.117         {    //neither lower nor higher is availabe to coalesce so add to list
   8.118              // this makes prev chunk ptr non-null, which indicates it's free
   8.119           elemToFree->nextChunkInFreeList =
   8.120 -                            _VMSMasterEnv->freeListHead->nextChunkInFreeList;
   8.121 -         _VMSMasterEnv->freeListHead->nextChunkInFreeList = elemToFree;
   8.122 +                            masterListHead->nextChunkInFreeList;
   8.123 +         masterListHead->nextChunkInFreeList = elemToFree;
   8.124           if( elemToFree->nextChunkInFreeList != NULL ) // end-of-list?
   8.125              elemToFree->nextChunkInFreeList->prevChunkInFreeList =elemToFree;
   8.126 -         elemToFree->prevChunkInFreeList = _VMSMasterEnv->freeListHead;
   8.127 +         elemToFree->prevChunkInFreeList = masterListHead;
   8.128         }
   8.129      }
   8.130     //============================= MEASUREMENT STUFF ========================
   8.131 @@ -376,6 +381,7 @@
   8.132        //Note, this is running in the main thread -- all increases in malloc
   8.133        // mem and all frees of it must be done in this thread, with the
   8.134        // thread's original stack available
   8.135 + 
   8.136     freeListHead = malloc( sizeof(MallocProlog) );
   8.137     firstChunk   = malloc( MALLOC_ADDITIONAL_MEM_FROM_OS_SIZE );
   8.138     if( firstChunk == NULL ) {printf("malloc error\n"); exit(1);}
   8.139 @@ -412,12 +418,15 @@
   8.140  /*Designed to be called from the main thread outside of VMS, during cleanup
   8.141   */
   8.142  void
   8.143 -VMS_ext__free_free_list( MallocProlog *freeListHead )
   8.144 +VMS_ext__free_free_list( MallocProlog* freeListHeads[] )
   8.145   {    
   8.146        //stashed a ptr to the one and only bug chunk malloc'd from OS in the
   8.147        // free list head's next lower in mem pointer
   8.148 -   free( freeListHead->nextLowerInMem );
   8.149 -
   8.150 +    int i;
   8.151 +    for(i=0; i<NUM_CORES; i++)
   8.152 +    {
   8.153 +        free( freeListHeads[i]->nextLowerInMem );
   8.154 +    }
   8.155     //don't free the head -- it'll be in an array eventually -- free whole
   8.156     // array when all the free lists linked from it have already been freed
   8.157   }
     9.1 --- a/vmalloc.h	Fri Sep 16 14:26:18 2011 +0200
     9.2 +++ b/vmalloc.h	Fri Sep 16 16:19:24 2011 +0200
     9.3 @@ -67,11 +67,10 @@
     9.4  void
     9.5  VMS__free_in_ext( void *ptrToFree );
     9.6  
     9.7 -
     9.8  MallocProlog *
     9.9  VMS_ext__create_free_list();
    9.10  
    9.11  void
    9.12 -VMS_ext__free_free_list( MallocProlog *freeListHead );
    9.13 +VMS_ext__free_free_list( MallocProlog* freeListHeads[] );
    9.14  
    9.15  #endif
    9.16 \ No newline at end of file
    10.1 --- a/vutilities.c	Fri Sep 16 14:26:18 2011 +0200
    10.2 +++ b/vutilities.c	Fri Sep 16 16:19:24 2011 +0200
    10.3 @@ -9,6 +9,7 @@
    10.4  
    10.5  #include <malloc.h>
    10.6  #include <stdlib.h>
    10.7 +#include <string.h>
    10.8  
    10.9  #include "VMS.h"
   10.10