3 #include "multicoreruntime.h"
4 #include "GenericHashtable.h"
6 #include "multicoregcmark.h"
7 #include "multicoregarbage.h"
11 extern struct parameterwrapper ** objectqueues[][NUMCLASSES];
12 extern int numqueues[][NUMCLASSES];
13 extern struct genhashtable * activetasks;
14 extern struct parameterwrapper ** objectqueues[][NUMCLASSES];
15 extern struct taskparamdescriptor *currtpd;
16 extern struct LockValue runtime_locks[MAXTASKPARAMS];
17 extern int runtime_locklen;
20 extern struct global_defs_t * global_defs_p;
23 extern struct lockvector bamboo_threadlocks;
26 INLINE void gettype_size(void * ptr, int * ttype, unsigned int * tsize) {
27 int type = ((int *)ptr)[0];
28 if(type < NUMCLASSES) {
30 *tsize = classsize[type];
34 struct ArrayObject *ao=(struct ArrayObject *)ptr;
35 unsigned int elementsize=classsize[type];
36 unsigned int length=ao->___length___;
37 *tsize = sizeof(struct ArrayObject)+length*elementsize;
42 INLINE bool isLarge(void * ptr, int * ttype, unsigned int * tsize) {
43 // check if a pointer refers to a large object
44 gettype_size(ptr, ttype, tsize);
45 unsigned INTPTR blocksize = (((unsigned INTPTR)(ptr-gcbaseva)) < BAMBOO_LARGE_SMEM_BOUND)? BAMBOO_SMEM_SIZE_L:BAMBOO_SMEM_SIZE;
47 // ptr is a start of a block OR it crosses the boundary of current block
48 return (*tsize) > blocksize;
51 //push the null check into the mark macro
53 //#define MARKOBJ(objptr) {void * marktmpptr=objptr; if (marktmpptr!=NULL) {markObj(marktmpptr);if ((marktmpptr<gcbaseva)||(marktmpptr>(gcbaseva+BAMBOO_SHARED_MEM_SIZE))) tprintf("Bad pointer %x in line %u\n",marktmpptr, __LINE__); }}
55 #define MARKOBJ(objptr) {void * marktmpptr=objptr; if (marktmpptr!=NULL) {markObj(marktmpptr);}}
57 #define MARKOBJNONNULL(objptr) {markObj(objptr);}
59 // NOTE: the objptr should not be NULL and should be a shared obj
60 void markObj(void * objptr) {
61 unsigned int host = hostcore(objptr);
62 if(BAMBOO_NUM_OF_CORE == host) {
64 if(!checkMark(objptr)) {
65 // this is the first time that this object is discovered,
66 // set the flag as DISCOVERED
72 // check if this obj has been forwarded already
73 if(MGCHashadd(gcforwardobjtbl, (unsigned int)objptr)) {
74 // if not, send msg to host informing that objptr is active
75 send_msg_2(host,GCMARKEDOBJ,objptr);
76 GCPROFILE_RECORD_FORWARD_OBJ();
82 void markgarbagelist(struct garbagelist * listptr) {
83 for(;listptr!=NULL;listptr=listptr->next) {
84 int size=listptr->size;
85 for(int i=0; i<size; i++) {
86 MARKOBJ(listptr->array[i]);
92 void tomark(struct garbagelist * stackptr) {
93 BAMBOO_ASSERT(MARKPHASE == gc_status_info.gcphase);
95 gc_status_info.gcbusystatus = true;
97 // enqueue current stack
98 markgarbagelist(stackptr);
100 // enqueue static pointers global_defs_p
101 if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
102 markgarbagelist((struct garbagelist *)global_defs_p);
106 // enqueue objectsets
107 if(BAMBOO_NUM_OF_CORE < NUMCORESACTIVE) {
108 for(int i=0; i<NUMCLASSES; i++) {
109 struct parameterwrapper ** queues = objectqueues[BAMBOO_NUM_OF_CORE][i];
110 int length = numqueues[BAMBOO_NUM_OF_CORE][i];
111 for(int j = 0; j < length; ++j) {
112 struct parameterwrapper * parameter = queues[j];
113 struct ObjectHash * set=parameter->objectset;
114 struct ObjectNode * ptr=set->listhead;
115 for(;ptr!=NULL;ptr=ptr->lnext) {
116 MARKOBJNONNULL((void *)ptr->key);
122 // enqueue current task descriptor
123 if(currtpd != NULL) {
124 for(int i=0; i<currtpd->numParameters; i++) {
125 // currtpd->parameterArray[i] can not be NULL
126 MARKOBJNONNULL(currtpd->parameterArray[i]);
130 // enqueue active tasks
131 if(activetasks != NULL) {
132 struct genpointerlist * ptr=activetasks->list;
133 for(;ptr!=NULL;ptr=ptr->inext) {
134 struct taskparamdescriptor *tpd=ptr->src;
135 for(int i=0; i<tpd->numParameters; i++) {
136 // the tpd->parameterArray[i] can not be NULL
137 MARKOBJNONNULL(tpd->parameterArray[i]);
142 // enqueue cached transferred obj
143 struct QueueItem * tmpobjptr = getHead(&objqueue);
144 for(;tmpobjptr != NULL;tmpobjptr=getNextQueueItem(tmpobjptr)) {
145 struct transObjInfo * objInfo=(struct transObjInfo *)(tmpobjptr->objectptr);
146 // the objptr can not be NULL
147 MARKOBJNONNULL(objInfo->objptr);
150 // enqueue cached objs to be transferred
151 struct QueueItem * item = getHead(totransobjqueue);
152 for(;item != NULL;item=getNextQueueItem(item)) {
153 struct transObjInfo * totransobj=(struct transObjInfo *)(item->objectptr);
154 // the objptr can not be NULL
155 MARKOBJNONNULL(totransobj->objptr);
158 // enqueue lock related info
159 for(int i = 0; i < runtime_locklen; i++) {
160 MARKOBJ((void *)(runtime_locks[i].redirectlock));
161 MARKOBJ((void *)(runtime_locks[i].value));
166 // enqueue global thread queue
167 if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
169 unsigned int thread_counter = *((unsigned int*)(bamboo_thread_queue+1));
170 if(thread_counter > 0) {
171 unsigned int start = *((unsigned int*)(bamboo_thread_queue+2));
172 for(int i = thread_counter; i > 0; i--) {
173 // the thread obj can not be NULL
174 MARKOBJNONNULL((void *)bamboo_thread_queue[4+start]);
175 start = (start+1)&bamboo_max_thread_num_mask;
180 // enqueue the bamboo_threadlocks
181 for(int i = 0; i < bamboo_threadlocks.index; i++) {
182 // the locks can not be NULL
183 MARKOBJNONNULL((void *)(bamboo_threadlocks.locks[i].object));
186 // enqueue the bamboo_current_thread
187 MARKOBJ(bamboo_current_thread);
191 INLINE void scanPtrsInObj(void * ptr, int type) {
192 // scan all pointers in ptr
193 unsigned int * pointer = pointerarray[type];
195 /* Array of primitives */
196 #ifdef OBJECTHASPOINTERS
197 pointer=pointerarray[OBJECTTYPE];
198 //handle object class
200 for(int i=1; i<=size; i++) {
201 unsigned int offset=pointer[i];
202 void * objptr=*((void **)(((char *)ptr)+offset));
206 } else if (((unsigned int)pointer)==1) {
207 /* Array of pointers */
208 struct ArrayObject *ao=(struct ArrayObject *) ptr;
209 int length=ao->___length___;
210 for(int i=0; i<length; i++) {
211 void *objptr=((void **)(((char *)&ao->___length___)+sizeof(int)))[i];
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));
227 for(int i=1; i<=size; i++) {
228 unsigned int offset=pointer[i];
229 void * objptr=*((void **)(((char *)ptr)+offset));
235 void mark(struct garbagelist * stackptr) {
239 unsigned int isize = 0;
240 bool sendStall = false;
242 while(MARKPHASE == gc_status_info.gcphase) {
244 while(gc_moreItems()) {
246 gc_status_info.gcbusystatus = true;
247 void * ptr = gc_dequeue();
248 unsigned int size = 0;
249 unsigned int type = 0;
250 bool islarge=isLarge(ptr, &type, &size);
251 unsigned int iunits = ALIGNUNITS(size);
253 //debugging for the next five lines
255 setLengthMarked(ptr,iunits);
257 //tprintf("Marking object %x, type %u, length %u, units %u\n", ptr, type, size, iunits);
260 // ptr is a large object and not marked or enqueued
261 printf("NEED TO SUPPORT LARGE OBJECTS!\n");
263 // ptr is an unmarked active object on this core
264 unsigned int isize=iunits<<ALIGNMENTSHIFT;
265 gccurr_heaptop += isize;
267 // scan the pointers in object
268 scanPtrsInObj(ptr, type);
271 BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
272 //make sure the queue is still empty...now we have interrupts off, things can't change on us...
274 if (!gc_moreItems_I()) {
275 gc_status_info.gcbusystatus = false;
276 // send mark finish msg to core coordinator
277 if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
278 int entry_index = waitconfirm ? (gcnumsrobjs_index==0) : gcnumsrobjs_index;
279 gccorestatus[BAMBOO_NUM_OF_CORE] = 0;
280 gcnumsendobjs[entry_index][BAMBOO_NUM_OF_CORE]=gcself_numsendobjs;
281 gcnumreceiveobjs[entry_index][BAMBOO_NUM_OF_CORE]=gcself_numreceiveobjs;
282 BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
286 send_msg_4(STARTUPCORE,GCFINISHMARK,BAMBOO_NUM_OF_CORE,gcself_numsendobjs,gcself_numreceiveobjs);
289 BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
295 #endif // MULTICORE_GC