--- /dev/null
+#ifdef MULTICORE_GC
+
+#include "GCSharedHash.h"
+#ifdef MULTICORE
+#include "runtime_arch.h"
+#else
+#include <stdio.h>
+#endif
+
+#ifndef INTPTR
+#ifdef BIT64
+#define INTPTR long
+#define INTPTRSHIFT 3
+#else
+#define INTPTR int
+#define INTPTRSHIFT 2
+#endif
+#endif
+
+#ifndef INLINE
+#define INLINE inline __attribute__((always_inline))
+#endif // #ifndef INLINE
+
+/* GCSHARED HASH ********************************************************/
+
+// params: startaddr -- the start addr of the shared memory
+// rsize -- remaining size of the available shared memory
+struct GCSharedHash * noargallocateGCSharedHash() {
+ return allocateGCSharedHash(100);
+}
+
+struct GCSharedHash * allocateGCSharedHash(int size) {
+ struct GCSharedHash *thisvar;
+ if (size <= 0) {
+#ifdef MULTICORE
+ BAMBOO_EXIT(0xf201);
+#else
+ printf("Negative Hashtable size Exception\n");
+ exit(-1);
+#endif
+ }
+ thisvar=(struct GCSharedHash *)FREEMALLOC_NGC(sizeof(struct GCSharedHash));
+ if(thisvar == NULL) {
+ return NULL;
+ }
+ thisvar->size = size;
+ thisvar->bucket =
+ (struct GCSharedNode **)FREEMALLOC_NGC(sizeof(struct GCSharedNode *)*size);
+ if(thisvar->bucket == NULL) {
+ FREE_NGC(thisvar);
+ return NULL;
+ }
+ /* Set allocation blocks*/
+ thisvar->listhead=NULL;
+ thisvar->listtail=NULL;
+ /*Set data counts*/
+ thisvar->numelements = 0;
+ return thisvar;
+}
+
+void freeGCSharedHash(struct GCSharedHash *thisvar) {
+ struct GCSharedNode *ptr=thisvar->listhead;
+ FREE_NGC(thisvar->bucket);
+ while(ptr) {
+ struct GCSharedNode *next=ptr->lnext;
+ FREE_NGC(ptr);
+ ptr=next;
+ }
+ FREE_NGC(thisvar);
+}
+
+bool GCSharedHashrehash(struct GCSharedHash * thisvar) {
+ int newsize=thisvar->size;
+ struct GCSharedNode ** newbucket = (struct GCSharedNode **)
+ FREEMALLOC_NGC(sizeof(struct GCSharedNode *)*newsize);
+ if(newbucket == NULL) {
+ return false;
+ }
+ int i;
+ for(i=thisvar->size-1; i>=0; i--) {
+ struct GCSharedNode *ptr;
+ for(ptr=thisvar->bucket[i]; ptr!=NULL;) {
+ struct GCSharedNode * nextptr=ptr->next;
+ unsigned int newhashkey=(unsigned int)ptr->key % newsize;
+ ptr->next=newbucket[newhashkey];
+ newbucket[newhashkey]=ptr;
+ ptr=nextptr;
+ }
+ }
+ thisvar->size=newsize;
+ FREE_NGC(thisvar->bucket);
+ thisvar->bucket=newbucket;
+ return true;
+}
+
+int GCSharedHashadd(struct GCSharedHash * thisvar,int key, int data) {
+ /* Rehash code */
+ unsigned int hashkey;
+ struct GCSharedNode **ptr;
+
+ if (thisvar->numelements>=thisvar->size) {
+ int newsize=2*thisvar->size+1;
+ struct GCSharedNode ** newbucket =
+ (struct GCSharedNode **)FREEMALLOC_NGC(
+ sizeof(struct GCSharedNode *)*newsize);
+ if(newbucket == NULL) {
+ return -1;
+ }
+ int i;
+ for(i=thisvar->size-1; i>=0; i--) {
+ struct GCSharedNode *ptr;
+ for(ptr=thisvar->bucket[i]; ptr!=NULL;) {
+ struct GCSharedNode * nextptr=ptr->next;
+ unsigned int newhashkey=(unsigned int)ptr->key % newsize;
+ ptr->next=newbucket[newhashkey];
+ newbucket[newhashkey]=ptr;
+ ptr=nextptr;
+ }
+ }
+ thisvar->size=newsize;
+ FREE_NGC(thisvar->bucket);
+ thisvar->bucket=newbucket;
+ }
+
+ hashkey = (unsigned int)key % thisvar->size;
+ ptr = &thisvar->bucket[hashkey];
+
+ /* check that thisvar key/object pair isn't already here */
+ /* TBD can be optimized for set v. relation */
+
+ while (*ptr) {
+ if ((*ptr)->key == key && (*ptr)->data == data) {
+ return 0;
+ }
+ ptr = &((*ptr)->next);
+ }
+
+ {
+ struct GCSharedNode *node=FREEMALLOC_NGC(sizeof(struct GCSharedNode));
+ if(node == NULL) {
+ return -1;
+ }
+ node->data=data;
+ node->key=key;
+ node->next=(*ptr);
+ *ptr=node;
+ if (thisvar->listhead==NULL) {
+ thisvar->listhead=node;
+ thisvar->listtail=node;
+ node->lnext=NULL;
+ node->lprev=NULL;
+ } else {
+ node->lprev=NULL;
+ node->lnext=thisvar->listhead;
+ thisvar->listhead->lprev=node;
+ thisvar->listhead=node;
+ }
+ }
+
+ thisvar->numelements++;
+ return 1;
+}
+
+#ifdef MULTICORE
+struct GCSharedHash * allocateGCSharedHash_I(int size) {
+ struct GCSharedHash *thisvar;
+ if (size <= 0) {
+#ifdef MULTICORE
+ BAMBOO_EXIT(0xf203);
+#else
+ printf("Negative Hashtable size Exception\n");
+ exit(-1);
+#endif
+ }
+ thisvar=(struct GCSharedHash *)FREEMALLOC_NGC_I(sizeof(struct GCSharedHash));
+ if(thisvar == NULL) {
+ return NULL;
+ }
+ thisvar->size = size;
+ thisvar->bucket =
+ (struct GCSharedNode **)FREEMALLOC_NGC_I(
+ sizeof(struct GCSharedNode *)*size);
+ if(thisvar->bucket == NULL) {
+ FREE_NGC_I(thisvar);
+ return NULL;
+ }
+ /* Set allocation blocks*/
+ thisvar->listhead=NULL;
+ thisvar->listtail=NULL;
+ /*Set data counts*/
+ thisvar->numelements = 0;
+ return thisvar;
+}
+
+int GCSharedHashadd_I(struct GCSharedHash * thisvar,int key, int data) {
+ /* Rehash code */
+ unsigned int hashkey;
+ struct GCSharedNode **ptr;
+
+ if (thisvar->numelements>=thisvar->size) {
+ int newsize=2*thisvar->size+1;
+ struct GCSharedNode ** newbucket =
+ (struct GCSharedNode **)FREEMALLOC_NGC_I(
+ sizeof(struct GCSharedNode *)*newsize);
+ if(newbucket == NULL) {
+ return -1;
+ }
+ int i;
+ for(i=thisvar->size-1; i>=0; i--) {
+ struct GCSharedNode *ptr;
+ for(ptr=thisvar->bucket[i]; ptr!=NULL;) {
+ struct GCSharedNode * nextptr=ptr->next;
+ unsigned int newhashkey=(unsigned int)ptr->key % newsize;
+ ptr->next=newbucket[newhashkey];
+ newbucket[newhashkey]=ptr;
+ ptr=nextptr;
+ }
+ }
+ thisvar->size=newsize;
+ FREE_NGC_I(thisvar->bucket);
+ thisvar->bucket=newbucket;
+ }
+
+ hashkey = (unsigned int)key % thisvar->size;
+ ptr = &thisvar->bucket[hashkey];
+
+ /* check that thisvar key/object pair isn't already here */
+ /* TBD can be optimized for set v. relation */
+
+ while (*ptr) {
+ if ((*ptr)->key == key && (*ptr)->data == data) {
+ return 0;
+ }
+ ptr = &((*ptr)->next);
+ }
+
+ {
+ struct GCSharedNode *node=FREEMALLOC_NGC_I(sizeof(struct GCSharedNode));
+ if(node == NULL) {
+ return -1;
+ }
+ node->data=data;
+ node->key=key;
+ node->next=(*ptr);
+ *ptr=node;
+ if (thisvar->listhead==NULL) {
+ thisvar->listhead=node;
+ thisvar->listtail=node;
+ node->lnext=NULL;
+ node->lprev=NULL;
+ } else {
+ node->lprev=NULL;
+ node->lnext=thisvar->listhead;
+ thisvar->listhead->lprev=node;
+ thisvar->listhead=node;
+ }
+ }
+
+ thisvar->numelements++;
+ return 1;
+}
+#endif
+
+int GCSharedHashget(struct GCSharedHash *thisvar, int key, int *data) {
+ unsigned int hashkey = (unsigned int)key % thisvar->size;
+
+ struct GCSharedNode *ptr = thisvar->bucket[hashkey];
+ while (ptr) {
+ if (ptr->key == key) {
+ *data = ptr->data;
+ return 1; /* success */
+ }
+ ptr = ptr->next;
+ }
+
+ return 0; /* failure */
+}
+
+/* MGCSHAREDHASH ********************************************************/
+
+mgcsharedhashtbl_t * mgcsharedhashCreate(unsigned int size,
+ double loadfactor) {
+ mgcsharedhashtbl_t * ctable;
+ mgcsharedhashlistnode_t * nodes;
+ int i;
+
+ ctable = (mgcsharedhashtbl_t *)FREEMALLOC_NGC(sizeof(mgcsharedhashtbl_t));
+ if(ctable == NULL) {
+ // TODO
+ BAMBOO_EXIT(0xeeee);
+ return NULL;
+ }
+ // Allocate space for the hash table
+ ctable->table = (mgcsharedhashlistnode_t *)FREEMALLOC_NGC(
+ size*sizeof(mgcsharedhashlistnode_t));
+ if(ctable->table == NULL) {
+ BAMBOO_EXIT(0xffff); // TODO
+ return NULL;
+ }
+ ctable->size = size;
+ ctable->loadfactor = loadfactor;
+ ctable->threshold = size*loadfactor;
+
+ ctable->mask = (size << 7)-1;
+
+ ctable->structs = NULL ; //FREEMALLOC_NGC(1*sizeof(mgcliststruct_t));
+ ctable->numelements = 0; // Initial number of elements in the hash
+ ctable->list = NULL;
+
+ return ctable;
+}
+
+void mgcsharedhashReset(mgcsharedhashtbl_t * tbl) {
+ mgcsharedhashlistnode_t * ptr = tbl->table;
+
+ if ((tbl->numelements) < (tbl->size>>6)) {
+ mgcsharedhashlistnode_t * list = tbl->list;
+ while(list != NULL) {
+ mgcsharedhashlistnode_t *top = &ptr[tbl->size];
+ mgcsharedhashlistnode_t * next = list->next;
+ if ((list >= ptr) && (list < top)) {
+ //zero in list
+ list->key=NULL;
+ list->next=NULL;
+ }
+ list = next;
+ }
+ } else {
+ BAMBOO_MEMSET_WH(tbl->table, '\0',
+ sizeof(mgcsharedhashlistnode_t)*tbl->size);
+ }
+
+ mgcsharedliststruct_t * structs = tbl->structs;
+ while(structs != NULL) {
+ mgcsharedliststruct_t * next = structs->next;
+ BAMBOO_MEMSET_WH(structs->array, '\0',
+ structs->num * sizeof(mgcsharedhashlistnode_t));
+ structs->num = 0;
+ structs = next;
+ }
+ tbl->numelements = 0;
+}
+
+//Store objects and their pointers into hash
+//Using open addressing
+int mgcsharedhashInsert(mgcsharedhashtbl_t * tbl, void * key, void * val) {
+ mgcsharedhashlistnode_t * ptr;
+
+ if(tbl->numelements > (tbl->threshold)) {
+ //Never resize, simply don't insert any more
+ return -1;
+ }
+
+ ptr=&tbl->table[(((unsigned INTPTR)key)&tbl->mask)>>7];
+ //printf("%x \n", (((unsigned INTPTR)key)&tbl->mask)>>7); // TODO
+
+ if(ptr->key==0) {
+ // the first time insert a value for the key
+ ptr->key=key;
+ ptr->val=val;
+ } else { // Insert to the next empty place
+ mgcsharedhashlistnode_t *top = &tbl->table[tbl->size];
+ do {
+ ptr++;
+ } while((ptr < top) && (ptr->key != NULL));
+ if(ptr >= top) {
+ return -1;
+ } else {
+ ptr->key = key;
+ ptr->val = val;
+ }
+ }
+ tbl->numelements++;
+ return 1;
+}
+
+int mgcsharedhashInsert_I(mgcsharedhashtbl_t * tbl, void * key, void * val) {
+ mgcsharedhashlistnode_t * ptr;
+
+ if(tbl->numelements > (tbl->threshold)) {
+ //Never resize, simply don't insert any more
+ return -1;
+ }
+
+ ptr=&tbl->table[(((unsigned INTPTR)key)&tbl->mask)>>7];
+ //printf("%x \n", (((unsigned INTPTR)key)&tbl->mask)>>7); // TODO
+
+ if(ptr->key==0) {
+ // the first time insert a value for the key
+ ptr->key=key;
+ ptr->val=val;
+ } else { // Insert to the next empty place
+ mgcsharedhashlistnode_t * top = &tbl->table[tbl->size];
+ mgcsharedhashlistnode_t * start = ptr;
+ do {
+ ptr++;
+ if(ptr->key == 0) {
+ break;
+ }
+ } while(ptr < top);
+ if(ptr >= top) {
+ return -1;
+ } else {
+ ptr->key = key;
+ ptr->val = val;
+ }
+ }
+ tbl->numelements++;
+ return 1;
+}
+
+// Search for an address for a given oid
+INLINE void * mgcsharedhashSearch(mgcsharedhashtbl_t * tbl, void * key) {
+ //REMOVE HASH FUNCTION CALL TO MAKE SURE IT IS INLINED HERE]
+ mgcsharedhashlistnode_t * node =
+ &tbl->table[(((unsigned INTPTR)key)&tbl->mask)>>6];
+ mgcsharedhashlistnode_t *top = &tbl->table[tbl->size];
+
+ int i = 0;
+ do {
+ i++;
+ if(node->key == key) {
+ // TODO
+ printf("%x \n", 0xe000+i);
+ return node->val;
+ }
+ node++;
+ } while(node < top);
+
+ return NULL;
+}
+
+#endif
--- /dev/null
+#ifdef MULTICORE_GC
+
+#ifndef GCSHAREDHASH_H
+#define GCSHAREDHASH_H
+
+#ifndef bool
+#define bool int
+#endif
+
+#ifndef true
+#define true 1
+#endif
+
+#ifndef false
+#define false 0
+#endif
+
+#include "mem.h"
+
+/* GCSharedHash *********************************************************/
+
+struct GCSharedHash * noargallocateGCSharedHash();
+struct GCSharedHash * allocateGCSharedHash(int size);
+void freeGCSharedHash(struct GCSharedHash *);
+
+bool GCSharedHashrehash(struct GCSharedHash * thisvar);
+int GCSharedHashadd(struct GCSharedHash *, int key, int data);
+#ifdef MULTICORE
+struct GCSharedHash * allocateGCSharedHash_I(int size);
+int GCSharedHashadd_I(struct GCSharedHash *, int key, int data);
+#endif
+int GCSharedHashget(struct GCSharedHash *,int key, int* data);
+
+struct GCSharedHash {
+ int numelements;
+ int size;
+ struct GCSharedNode **bucket;
+ struct GCSharedNode *listhead;
+ struct GCSharedNode *listtail;
+};
+
+inline int GCSharedHashcountset(struct GCSharedHash * thisvar);
+
+/* RuntimeHashException *************************************************/
+
+
+/* RuntimeIterator *****************************************************/
+struct GCSharedNode {
+ struct GCSharedNode *next;
+ struct GCSharedNode *lnext;
+ struct GCSharedNode *lprev;
+ int data;
+ int key;
+};
+
+/* MGCSharedHash *********************************************************/
+typedef struct mgcsharedhashlistnode {
+ void * key;
+ void * val; //this can be cast to another type or used to point to a
+ //larger structure
+ struct mgcsharedhashlistnode * next;
+} mgcsharedhashlistnode_t;
+
+#define NUMMGCSHAREDLIST 250
+typedef struct mgcsharedlist {
+ struct mgcsharedhashlistnode array[NUMMGCSHAREDLIST];
+ int num;
+ struct mgcsharedlist *next;
+} mgcsharedliststruct_t;
+
+typedef struct mgcsharedhashtbl {
+ mgcsharedhashlistnode_t * table; // points to beginning of hash table
+ mgcsharedhashlistnode_t * list;
+ mgcsharedliststruct_t * structs;
+ unsigned int size;
+ unsigned int mask;
+ unsigned int numelements;
+ unsigned int threshold;
+ double loadfactor;
+} mgcsharedhashtbl_t;
+
+mgcsharedhashtbl_t * mgcsharedhashCreate(unsigned int size, double loadfactor);
+int mgcsharedhashInsert(mgcsharedhashtbl_t * tbl, void * key, void * val);
+void * mgcsharedhashSearch(mgcsharedhashtbl_t * tbl, void * key);
+//unsigned int mgchashResize(unsigned int newsize);
+int mgcsharedhashInsert_I(mgcsharedhashtbl_t * tbl, void * key, void * val);
+//unsigned int mgchashResize_I(unsigned int newsize);
+//void mgcsharedhashDelete(mgcsharedhashtbl_t * tbl);
+void mgcsharedhashReset(mgcsharedhashtbl_t * tbl);
+
+#endif
+
+#endif
typedef struct mgchashlistnode {
void * key;
void * val; //this can be cast to another type or used to point to a
- //larger structure
+ //larger structure
struct mgchashlistnode *next;
} mgchashlistnode_t;
#include "runtime_arch.h"
void * mycalloc(int m,
- int size) {
+ int size) {
void * p = NULL;
int isize = size;
BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
#ifdef MULTICORE_GC
void * mycalloc_share(struct garbagelist * stackptr,
- int m,
- int size) {
+ int m,
+ int size) {
void * p = NULL;
int isize = 2*BAMBOO_CACHE_LINE_SIZE-4+(size-1)&(~BAMBOO_CACHE_LINE_MASK);
bool hasgc = false;
BAMBOO_MEMSET_WH(alignedp + size, -2, p + isize - alignedp - size);
return alignedp;
}
+
+void * mycalloc_share_ngc(int m,
+ int size) {
+ void * p = NULL;
+ BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
+#ifdef DEBUG
+ tprintf("ask for shared mem: %x \n", size);
+#endif
+ p = BAMBOO_SHARED_MEM_CALLOC_NGC_I(m, size); // calloc(m, isize);
+#ifdef DEBUG
+ printf("new obj in shared mem: %x, %x \n", p, size);
+#endif
+ BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
+ return p;
+}
+
+void * mycalloc_share_ngc_I(int m,
+ int size) {
+ void * p = NULL;
+#ifdef DEBUG
+ tprintf("ask for shared mem: %x \n", size);
+#endif
+ p = BAMBOO_SHARED_MEM_CALLOC_NGC_I(m, size); // calloc(m, isize);
+#ifdef DEBUG
+ printf("new obj in shared mem: %x, %x \n", p, size);
+#endif
+ return p;
+}
+
+void mycalloc_free_ngc(void * ptr) {
+ BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
+ BAMBOO_SHARED_MEM_FREE_NGC_I(ptr);
+ BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
+}
+
+void mycalloc_free_ngc_I(void * ptr) {
+ BAMBOO_SHARED_MEM_FREE_NGC_I(ptr);
+}
#else
void * mycalloc_share(int m,
int size) {
#endif
void * mycalloc_i(int m,
- int size) {
+ int size) {
void * p = NULL;
int isize = size;
#ifdef DEBUG
- tprintf("ask for local mem: %x \n", isize);
+ tprintf("ask for local mem: %x \n", isize);
#endif
- p = BAMBOO_LOCAL_MEM_CALLOC(m, isize); // calloc(m, isize);
+ p = BAMBOO_LOCAL_MEM_CALLOC(m, isize); // calloc(m, isize);
#ifdef DEBUG
- tprintf("new obj in local mem: %x, %x \n", p, isize);
+ tprintf("new obj in local mem: %x, %x \n", p, isize);
#endif
- if(p == NULL) {
- BAMBOO_EXIT(0xc004);
+ if(p == NULL) {
+ BAMBOO_EXIT(0xc004);
}
return p;
}
#ifdef MULTICORE_GC
#include "multicoregc.h"
void * mycalloc_share(struct garbagelist * stackptr, int m, int size);
+void * mycalloc_share_ngc(int m, int size);
+void * mycalloc_share_ngc_I(int m, int size);
+void mycalloc_free_ngc(void * ptr);
+void mycalloc_free_ngc_I(void * ptr);
#define FREEMALLOC(s, x) mycalloc_share((s),1,(x))
+#define FREEMALLOC_NGC(x) mycalloc_share_ngc(1, (x))
+#define FREEMALLOC_NGC_I(x) mycalloc_share_ngc_I(1, (x))
+#define FREE_NGC(x) mycalloc_free_ngc(x)
+#define FREE_NGC_I(x) mycalloc_free_ngc_I(x)
#else
void * mycalloc_share(int m, int size);
#define FREEMALLOC(x) mycalloc_share(1,x)
#include "SimpleHash.h"
#include "GenericHashtable.h"
#include "ObjectHash.h"
+#include "GCSharedHash.h"
// TODO for profiling the flush phase
#ifdef GC_PROFILE
gcforwardobjtbl = allocateMGCHash(20, 3);
// initialize the mapping info related structures
- freeRuntimeHash(gcrcoretbl);
- gcrcoretbl = allocateRuntimeHash(20);
- BAMBOO_MEMSET_WH(gcmappingtbl, 0,
- sizeof(void *)*NUMCORESACTIVE*NUM_MAPPING);
+ if((BAMBOO_NUM_OF_CORE < NUMCORES4GC) && (gcsharedptbl != NULL)) {
+ // Never free the shared hash table, just reset it
+ /*freeGCSharedHash(gcsharedptbl);
+ gcsharedptbl = allocateGCSharedHash(20);*/
+ mgcsharedhashReset(gcsharedptbl);
+ }
+ // the shared hash tables are never changed
+ //BAMBOO_MEMSET_WH(gcrpointertbls,0,sizeof(struct RuntimeHash *)*NUMCORES4GC);
#ifdef GC_PROFILE
// TODO
num_mapinforequest = 0;
BAMBOO_DEBUGPRINT_REG(gcheaptop);
#endif
- gcheaptop = dst; // Note: record the start of cached lobjs with gcheaptop
+ gcheaptop = dst; // Note: record the start of cached lobjs with gcheaptop
// cache the largeObjs to the top of the shared heap
//gclobjtail2 = gclobjtail;
//gclobjtailindex2 = gclobjtailindex;
if(((int *)objptr)[6] == INIT) {
// this is the first time that this object is discovered,
// set the flag as DISCOVERED
- ((int *)objptr)[6] = DISCOVERED;
+ ((int *)objptr)[6] |= DISCOVERED;
gc_enqueue_I(objptr);
- // insert the obj and request core info into mapping hashtable
- /*struct nodemappinginfo * nodeinfo =
- (struct nodemappinginfo *)RUNMALLOC_I(sizeof(struct nodemappinginfo));
- nodeinfo->ptr = NULL;
- nodeinfo->cores = NULL;
- RuntimeHashadd_I(gcpointertbl, (int)objptr, (int)nodeinfo);*/
}
BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
} else {
// TODO unsigned long long ttime = BAMBOO_GET_EXE_TIME();
#endif
// send a msg to host informing that objptr is active
- send_msg_3(host, GCMARKEDOBJ, objptr, BAMBOO_NUM_OF_CORE, false);
+ send_msg_2(host, GCMARKEDOBJ, objptr, /*BAMBOO_NUM_OF_CORE,*/ false);
#ifdef GC_PROFILE
// TODO
/*
#endif
// enqueue root objs
tomark(stackptr);
- gccurr_heaptop = 0; // record the size of all active objs in this core
- // aligned but does not consider block boundaries
+ gccurr_heaptop = 0; // record the size of all active objs in this core
+ // aligned but does not consider block boundaries
gcmarkedptrbound = 0;
}
#ifdef DEBUG
int host = hostcore(ptr);
bool islocal = (host == BAMBOO_NUM_OF_CORE);
if(islocal) {
- bool isnotmarked = (((int *)ptr)[6] == DISCOVERED);
+ bool isnotmarked = ((((int *)ptr)[6] & DISCOVERED) != 0);
if(isLarge(ptr, &type, &size) && isnotmarked) {
// ptr is a large object and not marked or enqueued
#ifdef DEBUG
gcnumlobjs++;
BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
// mark this obj
- ((int *)ptr)[6] = MARKED;
+ ((int *)ptr)[6] = ((int *)ptr)[6] & (~DISCOVERED) | MARKED;
} else if(isnotmarked) {
// ptr is an unmarked active object on this core
ALIGNSIZE(size, &isize);
BAMBOO_DEBUGPRINT(((int *)(ptr))[0]);
#endif
// mark this obj
- ((int *)ptr)[6] = MARKED;
-
- if(ptr + size > gcmarkedptrbound) {
+ ((int *)ptr)[6] = ((int *)ptr)[6] & (~DISCOVERED) | MARKED;
+
+ if(ptr + size > gcmarkedptrbound) {
gcmarkedptrbound = ptr + size;
- } // if(ptr + size > gcmarkedptrbound)
+ } // if(ptr + size > gcmarkedptrbound)
} else {
// ptr is not an active obj or has been marked
checkfield = false;
- } // if(isLarge(ptr, &type, &size)) else ...
+ } // if(isLarge(ptr, &type, &size)) else ...
} /* can never reach here
else {
#ifdef DEBUG
// check if this obj has been forwarded
if(!MGCHashcontains(gcforwardobjtbl, (int)ptr)) {
// send a msg to host informing that ptr is active
- send_msg_3(host, GCMARKEDOBJ, ptr, BAMBOO_NUM_OF_CORE, false);
+ send_msg_2(host, GCMARKEDOBJ, ptr, false);
gcself_numsendobjs++;
MGCHashadd(gcforwardobjtbl, (int)ptr);
}
void * objptr=*((void **)(((char *)ptr)+offset));
markObj(objptr);
}
- } // if (pointer==0) else if ... else ...
- } // if(checkfield)
- } // while(gc_moreItems2())
+ } // if (pointer==0) else if ... else ...
+ } // if(checkfield)
+ } // while(gc_moreItems2())
#ifdef DEBUG
BAMBOO_DEBUGPRINT(0xed07);
#endif
size=sizeof(struct ArrayObject)+length*elementsize;
}
mark = ((int *)(orig->ptr))[6];
+ bool isremote = ((((int *)(orig->ptr))[6] & REMOTEM) != 0);
#ifdef DEBUG
BAMBOO_DEBUGPRINT(0xe203);
BAMBOO_DEBUGPRINT_REG(orig->ptr);
#endif
ALIGNSIZE(size, &isize); // no matter is the obj marked or not
// should be able to across it
- if(mark == MARKED) {
+ if((mark & MARKED) != 0) {
#ifdef DEBUG
BAMBOO_DEBUGPRINT(0xe204);
#endif
BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
//mgchashInsert_I(orig->ptr, to->ptr);
RuntimeHashadd_I(gcpointertbl, orig->ptr, to->ptr);
- /*struct nodemappinginfo * nodeinfo = NULL;
- RuntimeHashget(gcpointertbl, orig->ptr, &nodeinfo);
- nodeinfo->ptr = to->ptr;*/
+ if(isremote) {
+ // add to the sharedptbl
+ if(gcsharedptbl != NULL) {
+ //GCSharedHashadd_I(gcsharedptbl, orig->ptr, to->ptr);
+ mgcsharedhashInsert_I(gcsharedptbl, orig->ptr, to->ptr);
+ }
+ }
//MGCHashadd_I(gcpointertbl, orig->ptr, to->ptr);
BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
//}
#endif
//dstptr = mgchashSearch(objptr);
RuntimeHashget(gcpointertbl, objptr, &dstptr);
- /*struct nodemappinginfo * nodeinfo = NULL;
- RuntimeHashget(gcpointertbl, objptr, &nodeinfo);
- if(nodeinfo == NULL) {
- // currenly the mapping info is not ready TODO
- // busy waiting until we get the mapping info
- while(true) {
- BAMBOO_WAITING_FOR_LOCK(0);
- RuntimeHashget(gcpointertbl, objptr, &nodeinfo);
- if(nodeinfo != NULL) {
- break;
- }
- }
- }
- dstptr = nodeinfo->ptr;*/
#ifdef GC_PROFILE
// TODO flushstalltime += BAMBOO_GET_EXE_TIME()-ttime;
#endif
// assume that the obj has not been moved, use the original address
//dstptr = objptr;
} else {
- // send msg to host core for the mapping info
- gcobj2map = (int)objptr;
- gcismapped = false;
- gcmappedobj = NULL;
+ int hostc = hostcore(objptr);
+ // check the corresponsing sharedptbl
+ BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
+ //struct GCSharedHash * sptbl = gcrpointertbls[hostcore(objptr)];
+ mgcsharedhashtbl_t * sptbl = gcrpointertbls[hostc];
+ if(sptbl != NULL) {
+ //GCSharedHashget(sptbl, (int)objptr, &dstptr);
+ dstptr = mgcsharedhashSearch(sptbl, (int)objptr);
+ if(dstptr != NULL) {
+ RuntimeHashadd_I(gcpointertbl, (int)objptr, (int)dstptr);
+ }
+ }
+ BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
+
+ if(dstptr == NULL) {
+ // still can not get the mapping info,
+ // send msg to host core for the mapping info
+ gcobj2map = (int)objptr;
+ gcismapped = false;
+ gcmappedobj = NULL;
#ifdef GC_PROFILE
// TODO
- //num_mapinforequest++;
+ num_mapinforequest++;
//unsigned long long ttime = BAMBOO_GET_EXE_TIME();
#endif
#ifdef GC_PROFILE
- // TODO unsigned long long ttimet = BAMBOO_GET_EXE_TIME();
-#endif
- // the first time require the mapping, send msg to the hostcore
- // for the mapping info
- send_msg_3(hostcore(objptr), GCMAPREQUEST, (int)objptr,
- BAMBOO_NUM_OF_CORE, false);
- while(true) {
- if(gcismapped) {
- break;
- }
- }
+ unsigned long long ttimet = BAMBOO_GET_EXE_TIME();
+#endif
+ // the first time require the mapping, send msg to the hostcore
+ // for the mapping info
+ send_msg_3(hostc, GCMAPREQUEST, (int)objptr,
+ BAMBOO_NUM_OF_CORE, false);
+ while(true) {
+ if(gcismapped) {
+ break;
+ }
+ }
#ifdef GC_PROFILE
- // TODO flushstalltime_i += BAMBOO_GET_EXE_TIME()-ttimet;
+ flushstalltime_i += BAMBOO_GET_EXE_TIME()-ttimet;
#endif
#ifdef GC_PROFILE
// TODO
//flushstalltime += BAMBOO_GET_EXE_TIME() - ttime;
#endif
- BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
- //dstptr = mgchashSearch(objptr);
- RuntimeHashget(gcpointertbl, objptr, &dstptr);
- /*struct nodemappinginfo * nodeinfo = NULL;
- RuntimeHashget(gcpointertbl, objptr, &nodeinfo);
- dstptr = nodeinfo->ptr;*/
- //MGCHashget(gcpointertbl, objptr, &dstptr);
- BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
- } // if(hostcore(objptr) == BAMBOO_NUM_OF_CORE) else ...
+ BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
+ //dstptr = mgchashSearch(objptr);
+ RuntimeHashget(gcpointertbl, objptr, &dstptr);
+ //MGCHashget(gcpointertbl, objptr, &dstptr);
+ BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
+ } // if(dstptr == NULL)
+ } // if(hostcore(objptr) == BAMBOO_NUM_OF_CORE) else ...
#ifdef DEBUG
BAMBOO_DEBUGPRINT_REG(dstptr);
#endif
RUNFREE(tmp); // release the node
}
}*/
- int core = (BAMBOO_NUM_OF_CORE + 1) % NUMCORESACTIVE;
+/* int core = (BAMBOO_NUM_OF_CORE + 1) % NUMCORESACTIVE;
for(int i = 0; i < NUMCORESACTIVE - 1; i++) {
for(int j = 1; j < gcmappingtbl[core][0]+1; j++) {
int obj = gcmappingtbl[core][j];
//tprintf("send mapping to core %d \n", core);
core = (core + 1) % NUMCORESACTIVE;
}
+*/
+
+ // broadcast the sharedptbl pointer
+ for(int i = 0; i < NUMCORESACTIVE; i++) {
+ if(i != BAMBOO_NUM_OF_CORE) {
+ send_msg_3(i, GCMAPTBL, gcsharedptbl, BAMBOO_NUM_OF_CORE, false);
+ }
+ }
// TODO
//BAMBOO_DEBUGPRINT(0xeeee);
if(ptr == NULL) {
BAMBOO_EXIT(0xb105);
}
- } // if(ISSHAREDOBJ(ptr))
+ } // if(ISSHAREDOBJ(ptr))
if((!ISSHAREDOBJ(ptr)) || (((int *)(ptr))[6] == COMPACTED)) {
int type = ((int *)(ptr))[0];
// scan all pointers in ptr
if(ISSHAREDOBJ(ptr)) {
((int *)(ptr))[6] = INIT;
}
- } // if((!ISSHAREDOBJ(ptr)) || (((int *)(ptr))[6] == COMPACTED))
+ } // if((!ISSHAREDOBJ(ptr)) || (((int *)(ptr))[6] == COMPACTED))
} // while(gc_moreItems())
#ifdef DEBUG
BAMBOO_DEBUGPRINT(0xe308);
}
}
} // for(i=1; i<=size; i++)
- } // if (pointer==0) else if (((INTPTR)pointer)==1) else ()
- // restore the mark field, indicating that this obj has been flushed
+ } // if (pointer==0) else if (((INTPTR)pointer)==1) else ()
+ // restore the mark field, indicating that this obj has been flushed
((int *)(ptr))[6] = INIT;
} // if(((int *)(ptr))[6] == COMPACTED)
} // while(gc_lobjmoreItems())
}
#ifdef GC_PROFILE
// TODO
- /*if(BAMBOO_NUM_OF_CORE == 0) {
+ if(BAMBOO_NUM_OF_CORE == 0) {
BAMBOO_DEBUGPRINT(0xffff);
- //BAMBOO_DEBUGPRINT_REG(num_mapinforequest);
+ BAMBOO_DEBUGPRINT_REG(num_mapinforequest);
//BAMBOO_DEBUGPRINT_REG(flushstalltime);
//BAMBOO_DEBUGPRINT_REG(num_mapinforequest_i);
- //BAMBOO_DEBUGPRINT_REG(flushstalltime_i);
- }*/
+ BAMBOO_DEBUGPRINT_REG(flushstalltime_i);
+ }
//BAMBOO_DEBUGPRINT_REG(flushstalltime);
#endif
#ifdef DEBUG
#include "multicorehelper.h" // for mappins between core # and block #
#include "structdefs.h"
#include "MGCHash.h"
+#include "GCSharedHash.h"
#ifndef bool
#define bool int
typedef enum {
INIT = 0, // 0
- DISCOVERED, // 1
- MARKED, // 2
- COMPACTED, // 3
- FLUSHED, // 4
- END // 5
+ DISCOVERED = 2, // 2
+ REMOTEM = 4, // 4
+ MARKED = 8, // 8
+ COMPACTED = 16, // 16
+ FLUSHED = 32, // 32
+ END = 33 // 33
} GCOBJFLAG;
typedef enum {
int gcrequiredmems[NUMCORES4GC]; //record pending mem requests
volatile int gcmovepending;
-/*struct flushlist {
- void * key;
- struct flushnode * val;
- struct flushlist * next;
-};
-
-struct flushnode {
- void ** ptr;
- struct flushnode * next;
-};*/
-//volatile struct flushlist * gcflushlist; // list of (key, list of reference
-// to be flushed)
-//volatile int gcnumflush;
-
-// mapping of old address to new address
-/*struct requestcoreinfo {
- int core;
- struct requestcoreinfo * next;
-};
-
-struct nodemappinginfo {
- void * ptr;
- struct requestcoreinfo * cores;
-};*/
// data structures to record remote cores that transferred the marked
// objs in the mark phase
-struct rcoreinfo{
+/*struct rcoreinfo{
int high;
int low;
};
struct RuntimeHash * gcrcoretbl;
#define NUM_MAPPING 40
-void * gcmappingtbl[NUMCORESACTIVE][NUM_MAPPING];
+void * gcmappingtbl[NUMCORESACTIVE][NUM_MAPPING];*/
+
+// shared memory pointer for shared pointer mapping tbls
+// In GC version, this block of memory is located at the bottom of the
+// shared memory, right on the top of the smem tbl.
+// The bottom of the shared memory = sbstart tbl + smemtbl
+// + NUMCORES4GC bamboo_rmsp
+// These three types of table are always reside at the bottom of the shared
+// memory and will never be moved or garbage collected
+#define BAMBOO_RMSP_SIZE (BAMBOO_SMEM_SIZE * 64)
+mspace bamboo_rmsp;
+// shared pointer mapping tbl
+//volatile struct GCSharedHash * gcsharedptbl;
+mgcsharedhashtbl_t * gcsharedptbl;
+// remote shared pointer tbls
+//struct GCSharedHash * gcrpointertbls[NUMCORES4GC];
+mgcsharedhashtbl_t * gcrpointertbls[NUMCORES4GC];
volatile struct RuntimeHash * gcpointertbl;
//struct MGCHash * gcpointertbl;
GCMOVESTART, // 0xF0
GCMAPREQUEST, // 0xF1
GCMAPINFO, // 0xF2
- GCLOBJREQUEST, // 0xF3
- GCLOBJINFO, // 0xF4
- GCLOBJMAPPING, // 0xF5
+ GCMAPTBL, // 0xF3
+ GCLOBJREQUEST, // 0xF4
+ GCLOBJINFO, // 0xF5
+ GCLOBJMAPPING, // 0xF6
#endif
MSGEND
} MSGTYPE;
#include "multicoregarbage.h"
typedef enum {
- SMEMLOCAL = 0x0, // 0x0, using local mem only
- SMEMFIXED, // 0x1, use local mem in lower address space(1 block only)
- // and global mem in higher address space
- SMEMMIXED, // 0x2, like FIXED mode but use a threshold to control
- SMEMGLOBAL, // 0x3, using global mem only
+ SMEMLOCAL = 0x0,// 0x0, using local mem only
+ SMEMFIXED, // 0x1, use local mem in lower address space(1 block only)
+ // and global mem in higher address space
+ SMEMMIXED, // 0x2, like FIXED mode but use a threshold to control
+ SMEMGLOBAL, // 0x3, using global mem only
SMEMEND
} SMEMSTRATEGY;
struct freeMemList {
struct freeMemItem * head;
struct freeMemItem * backuplist; // hold removed freeMemItem for reuse;
- // only maintain 1 fremmMemItem
+ // only maintain 1 freemMemItem
};
// table recording the number of allocated bytes on each block
gcsbstarttbl = BAMBOO_BASE_VA;
bamboo_smemtbl = (void *)gcsbstarttbl
+ (BAMBOO_SHARED_MEM_SIZE/BAMBOO_SMEM_SIZE)*sizeof(INTPTR);
- // for mapping info structures
- gcrcoretbl = allocateRuntimeHash_I(20);
- BAMBOO_MEMSET_WH(gcmappingtbl, 0,
- sizeof(void *)*NUMCORESACTIVE*NUM_MAPPING);
+ if(BAMBOO_NUM_OF_CORE < NUMCORES4GC) {
+ int t_size = ((BAMBOO_RMSP_SIZE)-sizeof(mgcsharedhashtbl_t)*2
+ -128*sizeof(size_t))/sizeof(mgcsharedhashlistnode_t)-2;
+ gcsharedptbl = mgcsharedhashCreate(t_size,0.30);//allocateGCSharedHash_I(20);
+ } else {
+ gcsharedptbl = NULL;
+ }
+ BAMBOO_MEMSET_WH(gcrpointertbls,0,sizeof(mgcsharedhashtbl_t *)*NUMCORES4GC);
+ //sizeof(struct RuntimeHash *)*NUMCORES4GC);
#else
// create the lock table, lockresult table and obj queue
locktable.size = 20;
//freeMGCHash(gcpointertbl);
freeMGCHash(gcforwardobjtbl);
// for mapping info structures
- freeRuntimeHash(gcrcoretbl);
+ //freeRuntimeHash(gcrcoretbl);
#else
freeRuntimeHash(lockRedirectTbl);
freeRuntimeHash(objRedirectLockTbl);
case PROFILEFINISH:
#ifdef MULTICORE_GC
case GCSTARTCOMPACT:
+ case GCMARKEDOBJ:
case GCFINISHINIT:
case GCFINISHMAPINFO:
case GCFINISHFLUSH:
case MEMREQUEST:
case MEMRESPONSE:
#ifdef MULTICORE_GC
- case GCMARKEDOBJ:
case GCMAPREQUEST:
case GCMAPINFO:
+ case GCMAPTBL:
case GCLOBJMAPPING:
#endif
{
INLINE void processmsg_gcmarkedobj_I() {
int data1 = msgdata[msgdataindex];
MSG_INDEXINC_I();
- int data2 = msgdata[msgdataindex];
- MSG_INDEXINC_I();
// received a markedObj msg
if(((int *)data1)[6] == INIT) {
// this is the first time that this object is discovered,
// set the flag as DISCOVERED
- ((int *)data1)[6] = DISCOVERED;
+ ((int *)data1)[6] |= DISCOVERED;
gc_enqueue_I(data1);
- // insert the obj and request core info into mapping hashtable
- /*struct requestcoreinfo * coreinfo =
- (struct requestcoreinfo *)RUNMALLOC_I(sizeof(struct requestcoreinfo));
- coreinfo->core = data2;
- coreinfo->next = NULL;
- struct nodemappinginfo * nodeinfo =
- (struct nodemappinginfo *)RUNMALLOC_I(sizeof(struct nodemappinginfo));
- nodeinfo->ptr = NULL;
- nodeinfo->cores = coreinfo;
- RuntimeHashadd_I(gcpointertbl, data1, (int)nodeinfo);*/
- struct rcoreinfo * coreinfo =
- (struct rcoreinfo *)RUNMALLOC_I(sizeof(struct rcoreinfo));
- coreinfo->high = coreinfo->low = 0;
- if(data2 > 31) {
- coreinfo->high |= 1<<(data2-32);
- } else {
- coreinfo->low |= 1<<data2;
- }
- RuntimeHashadd_I(gcrcoretbl, data1, (int)coreinfo);
- if(gcmappingtbl[data2][0] < NUM_MAPPING-1) {
- int pos = ++gcmappingtbl[data2][0];
- gcmappingtbl[data2][pos] = data1;
- }
- } else {
- // record the request core
- /*struct nodemappinginfo * nodeinfo = NULL;
- RuntimeHashget(gcpointertbl, data1, &nodeinfo);
- if(nodeinfo == NULL) {
- // did not mark the obj, error!
- BAMBOO_DEBUGPRINT_REG(((int *)data1)[6]);
- BAMBOO_EXIT(0xb008);
- } else {
- struct requestcoreinfo * coreinfo = nodeinfo->cores;
- if(coreinfo == NULL) {
- nodeinfo->cores =
- (struct requestcoreinfo *)RUNMALLOC_I(
- sizeof(struct requestcoreinfo));
- nodeinfo->cores->core = data2;
- nodeinfo->cores->next = NULL;
- } else {
- while(true) {
- if(coreinfo->core == data2) {
- break;
- } else if ((coreinfo->core > data2) ||
- (coreinfo->next == NULL)) {
- // insert here
- struct requestcoreinfo * toinsert =
- (struct requestcoreinfo *)RUNMALLOC_I(
- sizeof(struct requestcoreinfo));
- if(coreinfo->core > data2) {
- toinsert->next = coreinfo->next;
- toinsert->core = coreinfo->core;
- coreinfo->core = data2;
- } else {
- toinsert->core = data2;
- }
- coreinfo->next = toinsert;
- break;
- } else {
- coreinfo = coreinfo->next;
- }
- }
- }
- }*/
- struct rcoreinfo * coreinfo = NULL;
- RuntimeHashget(gcrcoretbl, data1, &coreinfo);
- if(coreinfo == NULL) {
- coreinfo =
- (struct rcoreinfo *)RUNMALLOC_I(sizeof(struct rcoreinfo));
- coreinfo->high = coreinfo->low = 0;
- if(data2 > 31) {
- coreinfo->high |= 1<<(data2-32);
- } else {
- coreinfo->low |= 1<<data2;
- }
- RuntimeHashadd_I(gcrcoretbl, data1, (int)coreinfo);
- if(gcmappingtbl[data2][0] < NUM_MAPPING-1) {
- int pos = ++gcmappingtbl[data2][0];
- gcmappingtbl[data2][pos] = data1;
- }
- } else {
- bool toadd = false;
- if(data2 > 31) {
- if((coreinfo->high)&(1<<(data2-32))==0) {
- toadd = true;
- coreinfo->high |= 1<<(data2-32);
- }
- } else {
- if((coreinfo->low)&(1<<data2)==0) {
- toadd = true;
- coreinfo->low |= 1<<data2;
- }
- }
- if((toadd) && (gcmappingtbl[data2][0] < NUM_MAPPING-1)) {
- int pos = ++gcmappingtbl[data2][0];
- gcmappingtbl[data2][pos] = data1;
- }
- }
- }
+ }
+ // set the remote flag
+ ((int *)data1)[6] |= REMOTEM;
gcself_numreceiveobjs++;
gcbusystatus = true;
}
}
INLINE void processmsg_gcmaprequest_I() {
- // should not have such msg any more
- //BAMBOO_EXIT(0xb009);
#ifdef GC_PROFILE
//unsigned long long ttime = BAMBOO_GET_EXE_TIME();
#endif
#endif
}
+INLINE void processmsg_gcmaptbl_I() {
+ int data1 = msgdata[msgdataindex];
+ MSG_INDEXINC_I();
+ int data2 = msgdata[msgdataindex];
+ MSG_INDEXINC_I();
+ gcrpointertbls[data2] = (mgcsharedhashtbl_t *)data1; //(struct GCSharedHash *)data1;
+}
+
INLINE void processmsg_gclobjinfo_I() {
numconfirm--;
MSG_INDEXINC_I();
//mgchashInsert_I(msgdata[1], msgdata[2]);
RuntimeHashadd_I(gcpointertbl, data1, data2);
- /*struct nodemappinginfo * nodeinfo =
- (struct nodemappinginfo *)RUNMALLOC_I(sizeof(struct nodemappinginfo));
- nodeinfo->ptr = (void *)data2;
- nodeinfo->cores = NULL;
- RuntimeHashadd_I(gcpointertbl, data1, (int)nodeinfo);*/
+ mgcsharedhashInsert_I(gcsharedptbl, data1, data2);
+ //GCSharedHashadd_I(gcsharedptbl, data1, data2);
//MGCHashadd_I(gcpointertbl, msgdata[1], msgdata[2]);
}
#endif // #ifdef MULTICORE_GC
break;
} // case GCMAPINFO
- case GCLOBJREQUEST: {
+ case GCMAPTBL: {
+ // received a mapping tbl response msg
+ processmsg_gcmaptbl_I();
+ break;
+ } // case GCMAPTBL
+
+ case GCLOBJREQUEST: {
// received a large objs info request msg
transferMarkResults_I();
break;
cp ../Runtime/object.c ./
cp ../Runtime/GenericHashtable.c ./
cp ../Runtime/SimpleHash.c ./
+cp ../Runtime/GCSharedHash.c ./
cp ../Runtime/ObjectHash.c ./
cp ../Runtime/socket.c ./
cp ../Runtime/mem.c ./
cp ../Runtime/Queue.h ./
cp ../Runtime/runtime.h ./
cp ../Runtime/SimpleHash.h ./
+cp ../Runtime/GCSharedHash.h ./
cp ../Runtime/multicoregc.h ./
cp ../Runtime/multicoregarbage.h ./
cp ../Runtime/multicorehelper.h ./