2 #include "multicoregcmark.h"
4 #include "multicoreruntime.h"
5 #include "GenericHashtable.h"
9 extern struct parameterwrapper ** objectqueues[][NUMCLASSES];
10 extern int numqueues[][NUMCLASSES];
11 extern struct genhashtable * activetasks;
12 extern struct parameterwrapper ** objectqueues[][NUMCLASSES];
13 extern struct taskparamdescriptor *currtpd;
14 extern struct LockValue runtime_locks[MAXTASKPARAMS];
15 extern int runtime_locklen;
18 extern struct global_defs_t * global_defs_p;
21 extern unsigned int gcmem_mixed_threshold;
22 extern unsigned int gcmem_mixed_usedmem;
26 extern struct lockvector bamboo_threadlocks;
29 INLINE void gettype_size(void * ptr, int * ttype, unsigned int * tsize) {
30 int type = ((int *)ptr)[0];
31 if(type < NUMCLASSES) {
33 *tsize = classsize[type];
37 struct ArrayObject *ao=(struct ArrayObject *)ptr;
38 unsigned int elementsize=classsize[type];
39 unsigned int length=ao->___length___;
40 *tsize = sizeof(struct ArrayObject)+length*elementsize;
45 INLINE bool isLarge(void * ptr, int * ttype, unsigned int * tsize) {
46 // check if a pointer refers to a large object
47 gettype_size(ptr, ttype, tsize);
48 unsigned INTPTR blocksize = (((unsigned INTPTR)(ptr-gcbaseva)) < BAMBOO_LARGE_SMEM_BOUND)? BAMBOO_SMEM_SIZE_L:BAMBOO_SMEM_SIZE;
50 // ptr is a start of a block OR it crosses the boundary of current block
51 return (*tsize) > blocksize;
54 INLINE unsigned int hostcore(void * ptr) {
55 // check the host core of ptr
56 unsigned int host = 0;
57 if(1 == (NUMCORES4GC)) {
60 unsigned int t = (unsigned int)ptr - (unsigned int)gcbaseva;
61 unsigned int b = (t < BAMBOO_LARGE_SMEM_BOUND) ? t / (BAMBOO_SMEM_SIZE_L) : NUMCORES4GC+((t-(BAMBOO_LARGE_SMEM_BOUND))/(BAMBOO_SMEM_SIZE));
62 host = gc_block2core[(b%(NUMCORES4GC*2))];
67 //push the null check into the mark macro
68 //#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 void markObj(void * objptr) {
77 unsigned int host = hostcore(objptr);
78 if(BAMBOO_NUM_OF_CORE == host) {
80 if(!checkMark(objptr)) {
81 // this is the first time that this object is discovered,
82 // set the flag as DISCOVERED
87 // check if this obj has been forwarded already
88 if(MGCHashadd(gcforwardobjtbl, (unsigned int)objptr)) {
89 // if not, send msg to host informing that objptr is active
90 send_msg_2(host,GCMARKEDOBJ,objptr);
91 GCPROFILE_RECORD_FORWARD_OBJ();
97 INLINE void markgarbagelist(struct garbagelist * listptr) {
98 for(;listptr!=NULL;listptr=listptr->next) {
99 int size=listptr->size;
100 for(int i=0; i<size; i++) {
101 MARKOBJ(listptr->array[i], i);
107 INLINE void tomark(struct garbagelist * stackptr) {
108 BAMBOO_ASSERT(MARKPHASE == gc_status_info.gcphase);
110 gc_status_info.gcbusystatus = true;
113 // enqueue current stack
114 markgarbagelist(stackptr);
116 // enqueue static pointers global_defs_p
117 if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
118 markgarbagelist((struct garbagelist *)global_defs_p);
122 // enqueue objectsets
123 if(BAMBOO_NUM_OF_CORE < NUMCORESACTIVE) {
124 for(int i=0; i<NUMCLASSES; i++) {
125 struct parameterwrapper ** queues = objectqueues[BAMBOO_NUM_OF_CORE][i];
126 int length = numqueues[BAMBOO_NUM_OF_CORE][i];
127 for(int j = 0; j < length; ++j) {
128 struct parameterwrapper * parameter = queues[j];
129 struct ObjectHash * set=parameter->objectset;
130 struct ObjectNode * ptr=set->listhead;
131 for(;ptr!=NULL;ptr=ptr->lnext) {
132 MARKOBJNONNULL((void *)ptr->key, 0);
138 // enqueue current task descriptor
139 if(currtpd != NULL) {
140 for(int i=0; i<currtpd->numParameters; i++) {
141 // currtpd->parameterArray[i] can not be NULL
142 MARKOBJNONNULL(currtpd->parameterArray[i], i);
146 // enqueue active tasks
147 if(activetasks != NULL) {
148 struct genpointerlist * ptr=activetasks->list;
149 for(;ptr!=NULL;ptr=ptr->inext) {
150 struct taskparamdescriptor *tpd=ptr->src;
151 for(int i=0; i<tpd->numParameters; i++) {
152 // the tpd->parameterArray[i] can not be NULL
153 MARKOBJNONNULL(tpd->parameterArray[i], i);
158 // enqueue cached transferred obj
159 struct QueueItem * tmpobjptr = getHead(&objqueue);
160 for(;tmpobjptr != NULL;tmpobjptr=getNextQueueItem(tmpobjptr)) {
161 struct transObjInfo * objInfo=(struct transObjInfo *)(tmpobjptr->objectptr);
162 // the objptr can not be NULL
163 MARKOBJNONNULL(objInfo->objptr, 0);
166 // enqueue cached objs to be transferred
167 struct QueueItem * item = getHead(totransobjqueue);
168 for(;item != NULL;item=getNextQueueItem(item)) {
169 struct transObjInfo * totransobj=(struct transObjInfo *)(item->objectptr);
170 // the objptr can not be NULL
171 MARKOBJNONNULL(totransobj->objptr, 0);
174 // enqueue lock related info
175 for(int i = 0; i < runtime_locklen; i++) {
176 MARKOBJ((void *)(runtime_locks[i].redirectlock), 0);
177 MARKOBJ((void *)(runtime_locks[i].value), i);
182 // enqueue global thread queue
183 if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
185 unsigned int thread_counter = *((unsigned int*)(bamboo_thread_queue+1));
186 if(thread_counter > 0) {
187 unsigned int start = *((unsigned int*)(bamboo_thread_queue+2));
188 for(int i = thread_counter; i > 0; i--) {
189 // the thread obj can not be NULL
190 MARKOBJNONNULL((void *)bamboo_thread_queue[4+start], 0);
191 start = (start+1)&bamboo_max_thread_num_mask;
196 // enqueue the bamboo_threadlocks
197 for(int i = 0; i < bamboo_threadlocks.index; i++) {
198 // the locks can not be NULL
199 MARKOBJNONNULL((void *)(bamboo_threadlocks.locks[i].object), i);
202 // enqueue the bamboo_current_thread
203 MARKOBJ(bamboo_current_thread, 0);
207 INLINE void scanPtrsInObj(void * ptr, int type) {
208 // scan all pointers in ptr
209 unsigned int * pointer = pointerarray[type];
211 /* Array of primitives */
212 #ifdef OBJECTHASPOINTERS
213 pointer=pointerarray[OBJECTTYPE];
214 //handle object class
216 for(int i=1; i<=size; i++) {
217 unsigned int offset=pointer[i];
218 void * objptr=*((void **)(((char *)ptr)+offset));
222 } else if (((unsigned int)pointer)==1) {
223 /* Array of pointers */
224 struct ArrayObject *ao=(struct ArrayObject *) ptr;
225 int length=ao->___length___;
226 for(int i=0; i<length; i++) {
227 void *objptr=((void **)(((char *)&ao->___length___)+sizeof(int)))[i];
230 #ifdef OBJECTHASPOINTERS
231 pointer=pointerarray[OBJECTTYPE];
232 //handle object class
234 for(int i=1; i<=size; i++) {
235 unsigned int offset=pointer[i];
236 void * objptr=*((void **)(((char *)ptr)+offset));
243 for(int i=1; i<=size; i++) {
244 unsigned int offset=pointer[i];
245 void * objptr=*((void **)(((char *)ptr)+offset));
251 void mark(bool isfirst, struct garbagelist * stackptr) {
255 gccurr_heaptop = 0; // record the size of all active objs in this core
256 // aligned but does not consider block boundaries
257 gcmarkedptrbound = 0;
259 unsigned int isize = 0;
260 bool sendStall = false;
262 while(MARKPHASE == gc_status_info.gcphase) {
265 while(gc_moreItems2()) {
267 gc_status_info.gcbusystatus = true;
268 void * ptr = gc_dequeue2();
270 unsigned int size = 0;
271 unsigned int type = 0;
272 bool islarge=isLarge(ptr, &type, &size);
273 unsigned int iunits = ALIGNUNITS(size);
275 setLengthMarked(ptr,iunits);
278 // ptr is a large object and not marked or enqueued
279 gc_lobjenqueue(ptr, size, BAMBOO_NUM_OF_CORE);
282 // ptr is an unmarked active object on this core
283 unsigned int isize=iunits<<ALIGNMENTSHIFT;
284 gccurr_heaptop += isize;
286 if (top>gcmarkedptrbound)
287 gcmarkedptrbound=top;
290 // scan the pointers in object
291 scanPtrsInObj(ptr, type);
293 gc_status_info.gcbusystatus = false;
294 // send mark finish msg to core coordinator
295 if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
296 int entry_index = waitconfirm ? (gcnumsrobjs_index==0) : gcnumsrobjs_index;
297 gccorestatus[BAMBOO_NUM_OF_CORE] = 0;
298 gcnumsendobjs[entry_index][BAMBOO_NUM_OF_CORE]=gcself_numsendobjs;
299 gcnumreceiveobjs[entry_index][BAMBOO_NUM_OF_CORE]=gcself_numreceiveobjs;
300 gcloads[BAMBOO_NUM_OF_CORE] = gccurr_heaptop;
303 send_msg_4(STARTUPCORE,GCFINISHMARK,BAMBOO_NUM_OF_CORE,gcself_numsendobjs,gcself_numreceiveobjs);
308 if(BAMBOO_NUM_OF_CORE == STARTUPCORE)
315 #endif // MULTICORE_GC