From c8eeaeb247aacd718dfe5f39f791b2a956d2d903 Mon Sep 17 00:00:00 2001 From: bdemsky Date: Fri, 16 Feb 2007 04:00:27 +0000 Subject: [PATCH] add primitive support for multithreading --- Robust/src/IR/Flat/BuildCode.java | 26 +++++- Robust/src/IR/Flat/BuildFlat.java | 13 ++- Robust/src/IR/Flat/FKind.java | 1 + Robust/src/IR/Flat/FlatBackEdge.java | 15 ++++ Robust/src/IR/State.java | 1 + Robust/src/Main/Main.java | 7 ++ Robust/src/Runtime/garbage.c | 115 +++++++++++++++++++++++++-- Robust/src/Runtime/garbage.h | 11 +++ Robust/src/Runtime/runtime.h | 2 + Robust/src/Runtime/thread.c | 42 ++++++++++ Robust/src/Runtime/thread.h | 12 +++ Robust/src/buildscript | 9 ++- 12 files changed, 244 insertions(+), 10 deletions(-) create mode 100644 Robust/src/IR/Flat/FlatBackEdge.java create mode 100644 Robust/src/Runtime/thread.c create mode 100644 Robust/src/Runtime/thread.h diff --git a/Robust/src/IR/Flat/BuildCode.java b/Robust/src/IR/Flat/BuildCode.java index 361c5da4..fc5d90ea 100644 --- a/Robust/src/IR/Flat/BuildCode.java +++ b/Robust/src/IR/Flat/BuildCode.java @@ -80,10 +80,19 @@ public class BuildCode { /* Build the virtual dispatch tables */ buildVirtualTables(outvirtual); + /* Output includes */ - outstructs.println("#include \"classdefs.h\""); + + outmethodheader.println("#ifndef METHODHEADERS_H"); + outmethodheader.println("#define METHODHEADERS_H"); outmethodheader.println("#include \"structdefs.h\""); + outstructs.println("#ifndef STRUCTDEFS_H"); + outstructs.println("#define STRUCTDEFS_H"); + outstructs.println("#include \"classdefs.h\""); + + + /* Output types for short array and string */ outstructs.println("#define STRINGARRAYTYPE "+ (state.getArrayNumber( @@ -158,6 +167,8 @@ public class BuildCode { generateTaskStructs(outstructs, outmethodheader); } + outmethodheader.println("#endif"); + outmethodheader.close(); /* Build the actual methods */ @@ -272,6 +283,8 @@ public class BuildCode { outmethod.println(" }"); break; } + if (state.THREAD) + outmethod.println("pthread_exit();"); outmethod.println("}"); } if (state.TASK) @@ -283,6 +296,7 @@ public class BuildCode { buildRepairStructs(outrepairstructs); outrepairstructs.close(); } + outstructs.println("#endif"); outstructs.close(); outmethod.close(); @@ -902,6 +916,10 @@ public class BuildCode { } } + if (state.THREAD&&GENERATEPRECISEGC) { + output.println("checkcollect(&"+localsprefix+");"); + } + //Do the actual code generation tovisit=new HashSet(); visited=new HashSet(); @@ -1006,6 +1024,12 @@ public class BuildCode { case FKind.FlatNop: output.println("/* nop */"); return; + case FKind.FlatBackEdge: + if (state.THREAD&&GENERATEPRECISEGC) { + output.println("checkcollect(&"+localsprefix+");"); + } else + output.println("/* nop */"); + return; case FKind.FlatCheckNode: generateFlatCheckNode(fm, (FlatCheckNode) fn, output); return; diff --git a/Robust/src/IR/Flat/BuildFlat.java b/Robust/src/IR/Flat/BuildFlat.java index e01e1d30..3ff20b0f 100644 --- a/Robust/src/IR/Flat/BuildFlat.java +++ b/Robust/src/IR/Flat/BuildFlat.java @@ -688,10 +688,12 @@ public class BuildFlat { FlatNode begin=initializer.getBegin(); FlatCondBranch fcb=new FlatCondBranch(cond_temp); FlatNop nopend=new FlatNop(); + FlatBackEdge backedge=new FlatBackEdge(); initializer.getEnd().addNext(condition.getBegin()); body.getEnd().addNext(update.getBegin()); - update.getEnd().addNext(condition.getBegin()); + update.getEnd().addNext(backedge); + backedge.addNext(condition.getBegin()); condition.getEnd().addNext(fcb); fcb.addFalseNext(nopend); fcb.addTrueNext(body.getBegin()); @@ -703,8 +705,11 @@ public class BuildFlat { FlatNode begin=condition.getBegin(); FlatCondBranch fcb=new FlatCondBranch(cond_temp); FlatNop nopend=new FlatNop(); + FlatBackEdge backedge=new FlatBackEdge(); + + body.getEnd().addNext(backedge); + backedge.addNext(condition.getBegin()); - body.getEnd().addNext(condition.getBegin()); condition.getEnd().addNext(fcb); fcb.addFalseNext(nopend); fcb.addTrueNext(body.getBegin()); @@ -716,11 +721,13 @@ public class BuildFlat { FlatNode begin=body.getBegin(); FlatCondBranch fcb=new FlatCondBranch(cond_temp); FlatNop nopend=new FlatNop(); + FlatBackEdge backedge=new FlatBackEdge(); body.getEnd().addNext(condition.getBegin()); condition.getEnd().addNext(fcb); fcb.addFalseNext(nopend); - fcb.addTrueNext(body.getBegin()); + fcb.addTrueNext(backedge); + backedge.addNext(body.getBegin()); return new NodePair(begin,nopend); } else throw new Error(); } diff --git a/Robust/src/IR/Flat/FKind.java b/Robust/src/IR/Flat/FKind.java index a348540a..264e5711 100644 --- a/Robust/src/IR/Flat/FKind.java +++ b/Robust/src/IR/Flat/FKind.java @@ -15,4 +15,5 @@ public class FKind { public static final int FlatElementNode=12; public static final int FlatFlagActionNode=13; public static final int FlatCheckNode=14; + public static final int FlatBackEdge=15; } diff --git a/Robust/src/IR/Flat/FlatBackEdge.java b/Robust/src/IR/Flat/FlatBackEdge.java new file mode 100644 index 00000000..b6bbb25c --- /dev/null +++ b/Robust/src/IR/Flat/FlatBackEdge.java @@ -0,0 +1,15 @@ +package IR.Flat; +import java.util.Vector; + +public class FlatBackEdge extends FlatNode { + public FlatBackEdge() { + } + + public String toString() { + return "backedge"; + } + + public int kind() { + return FKind.FlatBackEdge; + } +} diff --git a/Robust/src/IR/State.java b/Robust/src/IR/State.java index b4326130..185b8590 100644 --- a/Robust/src/IR/State.java +++ b/Robust/src/IR/State.java @@ -22,6 +22,7 @@ public class State { /** Boolean flag which indicates whether compiler is compiling a task-based * program. */ public boolean TASK; + public boolean THREAD=false; public boolean INSTRUCTIONFAILURE=false; public String structfile; public String main; diff --git a/Robust/src/Main/Main.java b/Robust/src/Main/Main.java index cda51f78..71907c57 100644 --- a/Robust/src/Main/Main.java +++ b/Robust/src/Main/Main.java @@ -35,6 +35,8 @@ public class Main { state.CONSCHECK=true; else if (option.equals("-task")) state.TASK=true; + else if (option.equals("-thread")) + state.THREAD=true; else if (option.equals("-instructionfailures")) state.INSTRUCTIONFAILURE=true; else if (option.equals("-help")) { @@ -46,6 +48,7 @@ public class Main { System.out.println("-conscheck -- turn on consistency checking"); System.out.println("-task -- compiler for tasks"); + System.out.println("-thread -- threads"); System.out.println("-instructionfailures -- insert code for instruction level failures"); System.out.println("-help -- print out help"); System.exit(0); @@ -70,6 +73,10 @@ public class Main { readSourceFile(state, ClassLibraryPrefix+"StartupObject.java"); readSourceFile(state, ClassLibraryPrefix+"Socket.java"); readSourceFile(state, ClassLibraryPrefix+"ServerSocket.java"); + } + + if (state.THREAD) { + readSourceFile(state, ClassLibraryPrefix+"Thread.java"); } BuildIR bir=new BuildIR(state); diff --git a/Robust/src/Runtime/garbage.c b/Robust/src/Runtime/garbage.c index 0b97ee33..a3543512 100644 --- a/Robust/src/Runtime/garbage.c +++ b/Robust/src/Runtime/garbage.c @@ -5,6 +5,10 @@ #include "SimpleHash.h" #include "GenericHashtable.h" #include +#ifdef THREADS +#include "thread.h" +#endif + #define NUMPTRS 100 @@ -22,6 +26,12 @@ extern struct RuntimeHash *reverse; extern struct RuntimeHash *fdtoobject; #endif +#ifdef THREADS +int needtocollect=0; +struct listitem * list=NULL; +int listcount=0; +#endif + struct pointerblock { void * ptrs[NUMPTRS]; struct pointerblock *next; @@ -33,7 +43,6 @@ struct pointerblock *tail=NULL; int tailindex=0; struct pointerblock *spare=NULL; - void enqueue(void *ptr) { if (headindex==NUMPTRS) { struct pointerblock * tmp; @@ -69,12 +78,32 @@ int moreItems() { } void collect(struct garbagelist * stackptr) { +#ifdef THREADS + needtocollect=1; + while(1) { + pthread_mutex_lock(&gclistlock); + pthread_mutex_lock(&threadtable); + if ((listcount+1)==threadcount) { + break; /* Have all other threads stopped */ + } + pthread_mutex_unlock(&threadtable); + pthread_cond_wait(&gccond, &gclistlock); + pthread_mutex_unlock(&gclistlock); + } +#endif + if (head==NULL) { headindex=0; tailindex=0; head=tail=malloc(sizeof(struct pointerblock)); } /* Check current stack */ +#ifdef THREADS + { + struct listitem *listptr=list; + while(stackptr!=NULL) { +#endif + while(stackptr!=NULL) { int i; for(i=0;isize;i++) { @@ -86,6 +115,15 @@ void collect(struct garbagelist * stackptr) { } stackptr=stackptr->next; } +#ifdef THREADS + /* Go to next thread */ + if (listptr!=NULL) { + stackptr=listptr->stackptr; + listptr=listptr->next; + } + } + } +#endif #ifdef TASK { @@ -218,6 +256,9 @@ void collect(struct garbagelist * stackptr) { } } } +#ifdef THREADS + needtocollect=0; +#endif } void * curr_heapbase=0; @@ -238,8 +279,57 @@ void * tomalloc(int size) { return ptr; } +#ifdef THREADS + +void checkcollect(void * ptr) { + if (needtocollect) { + struct listitem * tmp=stopforgc((struct garbagelist *)ptr); + pthread_mutex_lock(&gclock); + restartaftergc(tmp); + } +} + +struct listitem * stopforgc(struct garbagelist * ptr) { + struct listitem * litem=malloc(sizeof(struct listitem)); + litem->stackptr=ptr; + litem->prev=NULL; + pthread_mutex_lock(&gclistlock); + litem->next=list; + if(list!=NULL) + list->prev=litem; + list=litem; + listcount++; + pthread_cond_signal(&gccond); + pthread_mutex_unlock(&gclistlock); + return litem; +} + +void restartaftergc(struct listitem * litem) { + pthread_mutex_lock(&gclistlock); + if (litem->prev==NULL) { + list=litem->next; + } else { + litem->prev->next=litem->next; + } + if (litem->next!=NULL) { + litem->next->prev=litem->prev; + } + listcount--; + pthread_mutex_unlock(&gclistlock); + free(litem); +} +#endif + void * mygcmalloc(struct garbagelist * stackptr, int size) { - void *ptr=curr_heapptr; + void *ptr; +#ifdef THREADS + if (pthread_mutex_trylock(&gclock)!=0) { + struct listitem *tmp=stopforgc(stackptr); + pthread_mutex_lock(&gclock); + restartaftergc(tmp); + } +#endif + ptr=curr_heapptr; if ((size%4)!=0) size+=(4-(size%4)); curr_heapptr+=size; @@ -255,7 +345,11 @@ void * mygcmalloc(struct garbagelist * stackptr, int size) { to_heapbase=malloc(INITIALHEAPSIZE); to_heaptop=to_heapbase+INITIALHEAPSIZE; to_heapptr=to_heapbase; - return curr_heapbase; + ptr=curr_heapbase; +#ifdef THREADS + pthread_mutex_unlock(&gclock); +#endif + return ptr; } /* Grow the to heap if necessary */ @@ -300,14 +394,25 @@ void * mygcmalloc(struct garbagelist * stackptr, int size) { to_heapptr=to_heapbase; /* Not enough room :(, redo gc */ - if (curr_heapptr>curr_heapgcpoint) + if (curr_heapptr>curr_heapgcpoint) { +#ifdef THREADS + pthread_mutex_unlock(&gclock); +#endif return mygcmalloc(stackptr, size); + } bzero(tmp, curr_heaptop-tmp); +#ifdef THREADS + pthread_mutex_unlock(&gclock); +#endif return tmp; } - } else + } else { +#ifdef THREADS + pthread_mutex_unlock(&gclock); +#endif return ptr; + } } diff --git a/Robust/src/Runtime/garbage.h b/Robust/src/Runtime/garbage.h index bf998fb1..80171a58 100644 --- a/Robust/src/Runtime/garbage.h +++ b/Robust/src/Runtime/garbage.h @@ -6,6 +6,17 @@ struct garbagelist { void * array[]; }; +struct listitem { + struct listitem * prev; + struct listitem * next; + struct garbagelist * stackptr; +}; + +#ifdef THREADS +void checkcollect(void * ptr); +struct listitem * stopforgc(struct garbagelist * ptr); +void restartaftergc(struct listitem * litem); +#endif void collect(struct garbagelist *stackptr); int gc_createcopy(void * orig, void **); void * mygcmalloc(struct garbagelist * ptr, int size); diff --git a/Robust/src/Runtime/runtime.h b/Robust/src/Runtime/runtime.h index 03f0ddb5..f5948098 100644 --- a/Robust/src/Runtime/runtime.h +++ b/Robust/src/Runtime/runtime.h @@ -23,6 +23,7 @@ void createstartupobject(); #ifdef PRECISE_GC #define VAR(name) ___params___->name +#define CALL00(name) name(struct name ## _params * ___params___) #define CALL01(name, alt) name(struct name ## _params * ___params___) #define CALL02(name, alt1, alt2) name(struct name ## _params * ___params___) #define CALL11(name,rest, alt) name(struct name ## _params * ___params___, rest) @@ -31,6 +32,7 @@ void createstartupobject(); #define CALL23(name, rest, rest2, alt1, alt2, alt3) name(struct name ## _params * ___params___, rest, rest2) #else #define VAR(name) name +#define CALL00(name) name() #define CALL01(name, alt) name(alt) #define CALL02(name, alt1, alt2) name(alt1, alt2) #define CALL11(name,rest, alt) name(alt) diff --git a/Robust/src/Runtime/thread.c b/Robust/src/Runtime/thread.c new file mode 100644 index 00000000..5e3b27cc --- /dev/null +++ b/Robust/src/Runtime/thread.c @@ -0,0 +1,42 @@ +#include "runtime.h" +#include +#include +#include +#include +#include "thread.h" + + +#include +pthread_mutex_t threadtable; +int threadcount; +pthread_mutex_t gclock; +pthread_mutex_t gclistlock; +pthread_cond_t gccond; + +void initializethreads() { + pthread_mutex_init(&threadtable,NULL); + threadcount=1; + pthread_mutex_init(&gclock, NULL); + pthread_mutex_init(&gclistlock, NULL); + pthread_cond_init(&gccond, NULL); +} + +void initthread(struct ___Thread___ * ___this___) { +#ifdef PRECISE_GC + struct ___Thread______staticStart____L___Thread____params p={1, NULL, ___this___}; + ___Thread______staticStart____L___Thread___(&p); +#else + ___Thread______staticStart____L___Thread___(___this___); +#endif + pthread_mutex_lock(&threadtable); + threadcount--; + pthread_mutex_unlock(&threadtable); +} + +void CALL01(___Thread______nativeCreate____, struct ___Thread___ * ___this___) { + pthread_t thread; + pthread_mutex_lock(&threadtable); + threadcount++; + pthread_mutex_unlock(&threadtable); + pthread_create(&thread, NULL,(void * (*)(void *)) &initthread, VAR(___this___)); +} diff --git a/Robust/src/Runtime/thread.h b/Robust/src/Runtime/thread.h new file mode 100644 index 00000000..dc728cca --- /dev/null +++ b/Robust/src/Runtime/thread.h @@ -0,0 +1,12 @@ +#ifndef THREAD_H +#define THREAD_H +#include "methodheaders.h" +#include "pthread.h" + +extern pthread_mutex_t threadtable; +extern int threadcount; +extern pthread_mutex_t gclock; +extern pthread_mutex_t gclistlock; +extern pthread_cond_t gccond; +void initthread(struct ___Thread___ * ___this___); +#endif diff --git a/Robust/src/buildscript b/Robust/src/buildscript index 5ddacc3c..69ba9461 100755 --- a/Robust/src/buildscript +++ b/Robust/src/buildscript @@ -6,6 +6,7 @@ echo -recover compile task code echo -specdir directory echo -debug generate debug symbols echo -runtimedebug printout runtime debug messages +echo "-thread use support for multiple threads" echo "-optimize call gcc with -O9 (optimize)" echo "-nooptimize call gcc with -O0 (do not optimize)" echo -curdir directory @@ -75,6 +76,10 @@ EXTRAOPTIONS="$EXTRAOPTIONS -O0" elif [[ $1 = '-optimize' ]] then EXTRAOPTIONS="$EXTRAOPTIONS -O9" +elif [[ $1 = '-thread' ]] +then +JAVAOPTS="$JAVAOPTS -thread" +EXTRAOPTIONS="$EXTRAOPTIONS -DTHREADS" elif [[ $1 = '-curdir' ]] then CURDIR=$2 @@ -156,7 +161,9 @@ $ROBUSTROOT/Runtime/GenericHashtable.c" if $RECOVERFLAG then EXTRAOPTIONS="$EXTRAOPTIONS -DTASK" -FILES="$FILES $ROBUSTROOT/Runtime/socket.c tmpbuilddirectory/taskdefs.c $ROBUSTROOT/Runtime/checkpoint.c " +FILES="$FILES $ROBUSTROOT/Runtime/socket.c tmpbuilddirectory/taskdefs.c $ROBUSTROOT/Runtime/checkpoint.c" +else +FILES="$FILES $ROBUSTROOT/Runtime/thread.c" fi if $CHECKFLAG -- 2.34.1