2 #include "multicoregcmark.h"
4 #include "multicoreruntime.h"
5 #include "GenericHashtable.h"
10 extern struct parameterwrapper ** objectqueues[][NUMCLASSES];
11 extern int numqueues[][NUMCLASSES];
12 extern struct genhashtable * activetasks;
13 extern struct parameterwrapper ** objectqueues[][NUMCLASSES];
14 extern struct taskparamdescriptor *currtpd;
15 extern struct LockValue runtime_locks[MAXTASKPARAMS];
16 extern int runtime_locklen;
19 extern struct global_defs_t * global_defs_p;
22 extern unsigned int gcmem_mixed_threshold;
23 extern unsigned int gcmem_mixed_usedmem;
27 extern struct lockvector bamboo_threadlocks;
30 INLINE void gettype_size(void * ptr, int * ttype, unsigned int * tsize) {
31 int type = ((int *)ptr)[0];
33 if(type < NUMCLASSES) {
35 *tsize = classsize[type];
39 struct ArrayObject *ao=(struct ArrayObject *)ptr;
40 unsigned int elementsize=classsize[type];
41 unsigned int length=ao->___length___;
42 *tsize = sizeof(struct ArrayObject)+length*elementsize;
47 INLINE bool isLarge(void * ptr, int * ttype, unsigned int * tsize) {
48 // check if a pointer is referring to a large object
49 gettype_size(ptr, ttype, tsize);
50 unsigned int bound = (BAMBOO_SMEM_SIZE);
51 if(((unsigned int)ptr-gcbaseva) < (BAMBOO_LARGE_SMEM_BOUND)) {
52 bound = (BAMBOO_SMEM_SIZE_L);
54 // ptr is a start of a block OR it acrosses the boundary of current block
55 return (((((unsigned int)ptr-gcbaseva)%(bound))==0)||
56 ((bound-(((unsigned int)ptr-gcbaseva)%bound)) < (*tsize)));
59 INLINE unsigned int hostcore(void * ptr) {
60 // check the host core of ptr
61 unsigned int host = 0;
62 RESIDECORE(ptr, &host);
66 //push the null check into the mark macro
67 //#define MARKOBJ(objptr, ii) {void * marktmpptr=objptr; if (marktmpptr!=NULL) markObj(marktmpptr, __LINE__, ii);}
69 //#define MARKOBJNONNULL(objptr, ii) {markObj(objptr, __LINE__, ii);}
71 #define MARKOBJ(objptr, ii) {void * marktmpptr=objptr; if (marktmpptr!=NULL) markObj(marktmpptr);}
73 #define MARKOBJNONNULL(objptr, ii) {markObj(objptr);}
75 // NOTE: the objptr should not be NULL and should be a shared obj
76 INLINE void markObj(void * objptr) {
77 unsigned int host = hostcore(objptr);
78 if(BAMBOO_NUM_OF_CORE == host) {
80 if(((struct ___Object___ *)objptr)->marked == INIT) {
81 // this is the first time that this object is discovered,
82 // set the flag as DISCOVERED
83 ((struct ___Object___ *)objptr)->marked = DISCOVERED;
84 BAMBOO_CACHE_FLUSH_LINE(objptr);
88 // check if this obj has been forwarded
89 if(!MGCHashcontains(gcforwardobjtbl, (int)objptr)) {
90 // send a msg to host informing that objptr is active
91 send_msg_2(host, GCMARKEDOBJ, objptr, false);
92 GCPROFILE_RECORD_FORWARD_OBJ();
94 MGCHashadd(gcforwardobjtbl, (int)objptr);
99 INLINE void markgarbagelist(struct garbagelist * listptr) {
100 for(;listptr!=NULL;listptr=listptr->next) {
101 int size=listptr->size;
102 for(int i=0; i<size; i++) {
103 MARKOBJ(listptr->array[i], i);
109 INLINE void tomark(struct garbagelist * stackptr) {
110 BAMBOO_ASSERT(MARKPHASE == gcphase);
115 // enqueue current stack
116 markgarbagelist(stackptr);
118 // enqueue static pointers global_defs_p
119 if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
120 markgarbagelist((struct garbagelist *)global_defs_p);
124 // enqueue objectsets
125 if(BAMBOO_NUM_OF_CORE < NUMCORESACTIVE) {
126 for(int i=0; i<NUMCLASSES; i++) {
127 struct parameterwrapper ** queues = objectqueues[BAMBOO_NUM_OF_CORE][i];
128 int length = numqueues[BAMBOO_NUM_OF_CORE][i];
129 for(int j = 0; j < length; ++j) {
130 struct parameterwrapper * parameter = queues[j];
131 struct ObjectHash * set=parameter->objectset;
132 struct ObjectNode * ptr=set->listhead;
133 for(;ptr!=NULL;ptr=ptr->lnext) {
134 MARKOBJNONNULL((void *)ptr->key, 0);
140 // euqueue current task descriptor
141 if(currtpd != NULL) {
142 for(int i=0; i<currtpd->numParameters; i++) {
143 // currtpd->parameterArray[i] can not be NULL
144 MARKOBJNONNULL(currtpd->parameterArray[i], i);
148 // euqueue active tasks
149 if(activetasks != NULL) {
150 struct genpointerlist * ptr=activetasks->list;
151 for(;ptr!=NULL;ptr=ptr->inext) {
152 struct taskparamdescriptor *tpd=ptr->src;
153 for(int i=0; i<tpd->numParameters; i++) {
154 // the tpd->parameterArray[i] can not be NULL
155 MARKOBJNONNULL(tpd->parameterArray[i], i);
160 // enqueue cached transferred obj
161 struct QueueItem * tmpobjptr = getHead(&objqueue);
162 for(;tmpobjptr != NULL;tmpobjptr=getNextQueueItem(tmpobjptr)) {
163 struct transObjInfo * objInfo=(struct transObjInfo *)(tmpobjptr->objectptr);
164 // the objptr can not be NULL
165 MARKOBJNONNULL(objInfo->objptr, 0);
168 // enqueue cached objs to be transferred
169 struct QueueItem * item = getHead(totransobjqueue);
170 for(;item != NULL;item=getNextQueueItem(item)) {
171 struct transObjInfo * totransobj=(struct transObjInfo *)(item->objectptr);
172 // the objptr can not be NULL
173 MARKOBJNONNULL(totransobj->objptr, 0);
176 // enqueue lock related info
177 for(int i = 0; i < runtime_locklen; i++) {
178 MARKOBJ((void *)(runtime_locks[i].redirectlock), 0);
179 MARKOBJ((void *)(runtime_locks[i].value), i);
184 // enqueue global thread queue
185 if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
187 unsigned int thread_counter = *((unsigned int*)(bamboo_thread_queue+1));
188 if(thread_counter > 0) {
189 unsigned int start = *((unsigned int*)(bamboo_thread_queue+2));
190 for(int i = thread_counter; i > 0; i--) {
191 // the thread obj can not be NULL
192 MARKOBJNONNULL((void *)bamboo_thread_queue[4+start], 0);
193 start = (start+1)&bamboo_max_thread_num_mask;
198 // enqueue the bamboo_threadlocks
199 for(int i = 0; i < bamboo_threadlocks.index; i++) {
200 // the locks can not be NULL
201 MARKOBJNONNULL((void *)(bamboo_threadlocks.locks[i].object), i);
204 // enqueue the bamboo_current_thread
205 MARKOBJ((void *)bamboo_current_thread, 0);
209 INLINE void scanPtrsInObj(void * ptr, int type) {
210 // scan all pointers in ptr
211 unsigned int * pointer = pointerarray[type];
213 /* Array of primitives */
214 #ifdef OBJECTHASPOINTERS
215 pointer=pointerarray[OBJECTTYPE];
216 //handle object class
218 for(int i=1; i<=size; i++) {
219 unsigned int offset=pointer[i];
220 void * objptr=*((void **)(((char *)ptr)+offset));
224 } else if (((unsigned int)pointer)==1) {
225 /* Array of pointers */
226 struct ArrayObject *ao=(struct ArrayObject *) ptr;
227 int length=ao->___length___;
228 for(int i=0; i<length; i++) {
229 void *objptr=((void **)(((char *)&ao->___length___)+sizeof(int)))[i];
232 #ifdef OBJECTHASPOINTERS
233 pointer=pointerarray[OBJECTTYPE];
234 //handle object class
236 for(int i=1; i<=size; i++) {
237 unsigned int offset=pointer[i];
238 void * objptr=*((void **)(((char *)ptr)+offset));
245 for(int i=1; i<=size; i++) {
246 unsigned int offset=pointer[i];
247 void * objptr=*((void **)(((char *)ptr)+offset));
253 INLINE void mark(bool isfirst, struct garbagelist * stackptr) {
257 gccurr_heaptop = 0; // record the size of all active objs in this core
258 // aligned but does not consider block boundaries
259 gcmarkedptrbound = 0;
261 unsigned int isize = 0;
262 bool sendStall = false;
264 while(MARKPHASE == gcphase) {
266 while(gc_moreItems2()) {
269 unsigned int ptr = gc_dequeue2();
271 unsigned int size = 0;
272 unsigned int isize = 0;
273 unsigned int type = 0;
274 // check if it is a local obj on this core
275 if(((struct ___Object___ *)ptr)->marked!=DISCOVERED) {
276 // ptr has been marked
278 } else if(isLarge(ptr, &type, &size)) {
279 // ptr is a large object and not marked or enqueued
280 gc_lobjenqueue(ptr, size, BAMBOO_NUM_OF_CORE);
283 // ptr is an unmarked active object on this core
284 ALIGNSIZE(size, &isize);
285 gccurr_heaptop += isize;
287 if((unsigned int)(ptr + size) > (unsigned int)gcmarkedptrbound) {
288 gcmarkedptrbound = (unsigned int)(ptr + size);
292 ((struct ___Object___ *)ptr)->marked = MARKED;
293 BAMBOO_CACHE_FLUSH_LINE(ptr);
294 // scan the pointers in object
295 scanPtrsInObj(ptr, type);
297 gcbusystatus = false;
298 // send mark finish msg to core coordinator
299 if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
300 int entry_index = waitconfirm ? (gcnumsrobjs_index==0) : gcnumsrobjs_index;
301 gccorestatus[BAMBOO_NUM_OF_CORE] = 0;
302 gcnumsendobjs[entry_index][BAMBOO_NUM_OF_CORE]=gcself_numsendobjs;
303 gcnumreceiveobjs[entry_index][BAMBOO_NUM_OF_CORE]=gcself_numreceiveobjs;
304 gcloads[BAMBOO_NUM_OF_CORE] = gccurr_heaptop;
307 send_msg_4(STARTUPCORE, GCFINISHMARK, BAMBOO_NUM_OF_CORE,gcself_numsendobjs, gcself_numreceiveobjs, false);
312 if(BAMBOO_NUM_OF_CORE == STARTUPCORE)
319 #endif // MULTICORE_GC