2
0
Эх сурвалжийг харах

(Heuritisc) GC working -- using correct SP / BP

git-svn-id: https://svn.inf.ethz.ch/svn/lecturers/a2/trunk@6929 8c9fc860-2736-0410-a75d-ab315db34111
felixf 9 жил өмнө
parent
commit
1ee859c02b

+ 3 - 3
source/Generic.Linux.I386.Glue.Mod

@@ -6,8 +6,8 @@ MODULE Glue;
 IMPORT SYSTEM, Trace;
 
 CONST 
-	base = 08048000H;
-	debug* = {0};
+	base* = 08048000H;
+	debug* = {0,1};
 VAR
 	last-: RECORD END; (* empty variable linked to end of kernel *)
 	
@@ -217,7 +217,7 @@ SystemTools.DoCommands
 		Runtime Trace Glue Unix Machine Heaps Modules Objects Kernel KernelLog 
 Streams Commands StdIO TrapWriters Traps 
 Files UnixFiles Clock Dates Reals Strings Diagnostics 
-BitSets StringPool ObjectFile GenericLinker Reflection  GenericLoader  Test BootConsole  
+BitSets StringPool ObjectFile GenericLinker Reflection  GenericLoader  BootConsole  
  ~
 
 	FSTools.CloseFiles simple_elf ~

+ 4 - 2
source/Generic.Unix.I386.Machine.Mod

@@ -292,18 +292,20 @@ VAR
 		endBlockAdr := memBlockHead.endBlockAdr;
 		freeBlockAdr := beginBlockAdr;
 	END GetStaticHeap;
+	
+	VAR Last: RECORD END; (* linked to the end *)
 
 	(* returns if an address is a currently allocated heap address *)
 	PROCEDURE ValidHeapAddress*( p: ADDRESS ): BOOLEAN;
 	VAR mb: MemoryBlock; 
 	BEGIN
+		IF (p>=Glue.base) & (p<=ADDRESSOF(Last)) THEN RETURN TRUE END;
 		mb := memBlockHead;  
 		WHILE mb # NIL DO
 			IF (p >= mb.beginBlockAdr) & (p <= mb.endBlockAdr) THEN  RETURN TRUE  END;  
 			mb := mb.next;  
 		END;  
-		RETURN TRUE;
-		RETURN FALSE  
+		RETURN FALSE;
 	END ValidHeapAddress;
 	
 

+ 124 - 6
source/Generic.Unix.Objects.Mod

@@ -139,10 +139,10 @@ TYPE
 	VAR 
 		n: Heaps.FinalizerNode;  start: BOOLEAN;
 	
-		PROCEDURE Start;
+		PROCEDURE Activate;
 		BEGIN {EXCLUSIVE}
 			start := TRUE
-		END Start;
+		END Activate;
 		
 	BEGIN {ACTIVE, SAFE, PRIORITY(High)}
 		finCaller := CurrentProcess( );  start := FALSE;
@@ -191,15 +191,65 @@ TYPE
 					
 				
 		PROCEDURE FindRoots*;
-		VAR sp, ptr: ADDRESS;
+		VAR sp, ptr, bp, n, a0, a1, adr: ADDRESS; desc: Modules.ProcedureDescPointer; i: LONGINT; p {UNTRACED}: ANY;
+			me: Process;
 		BEGIN
 			IF mode # Terminated THEN
+			
+
+			IF SELF = CurrentProcess() THEN
+				context.r_sp := Machine.CurrentSP();
+				context.r_bp := Machine.CurrentBP();
+				context.r_pc := ADDRESS OF FindRoots;
+			END;
+
+			sp := context.r_sp; bp := context.r_bp; (*pc := context.r_pc;*)
+
+			IF Heaps.GCType= Heaps.HeuristicStackInspectionGC THEN
+				Heaps.Candidate( context.r_di);  Heaps.Candidate( context.r_si );
+				Heaps.Candidate( context.r_bx ); Heaps.Candidate( context.r_dx);
+				Heaps.Candidate( context.r_cx ); Heaps.Candidate( context.r_ax);
+				TRACE(sp, stackBottom);
+				IF (stackBottom # 0) & (sp # 0) & (sp <= stackBottom) THEN
+					TRACE(sp, stackBottom -sp);
+					Heaps.RegisterCandidates( sp, stackBottom - sp );
+				END;
+			ELSIF Heaps.GCType = Heaps.MetaDataForStackGC THEN
+				IF bp < stackBottom THEN
+					WHILE (bp # Heaps.NilVal) & (bp < stackBottom)  DO (* do not test for bp >= sp: could be wrong temporarily! *)
+						S.GET(bp, n);
+						IF ODD(n) THEN (* procedure descriptor at bp *)
+							desc := S.VAL(Modules.ProcedureDescPointer, n-1);
+							IF desc # NIL THEN
+								a0 := ADDRESSOF(desc.offsets);
+								a1 :=  S.VAL(ADDRESS, desc.offsets);
+								ASSERT(a0+SIZEOF(ADDRESS)=a1,54321);
+								FOR i := 0 TO LEN(desc.offsets)-1 DO
+									adr := bp + desc.offsets[i]; (* pointer at offset *)
+									S.GET(adr, p); (* load pointer *)
+									IF p # NIL THEN 
+										Heaps.Mark(p);
+									END;
+								END;
+							END;
+							S.GET(bp + SIZEOF(ADDRESS), bp);
+						ELSE (* classical stack frame *)
+							bp := n; 
+						END;
+					END;
+					
+					ASSERT((bp = stackBottom) OR (bp=0) ,12345);
+				END; 
+			END;
+
+			(*
 				sp := context.r_sp;
 				WHILE sp < stackBottom DO  
 					S.GET( sp, ptr );  
 					IF (ptr # 0) & (ptr MOD 8 = 0) THEN  Heaps.Candidate( ptr )  END;  
 					INC( sp, AddrSize )  
 				END;
+				*)
 			END;
 			Heaps.Mark( nextProcess ) 
 		END FindRoots;
@@ -266,6 +316,39 @@ TYPE
 				
 	END Process;
 
+	GCStatusExt = OBJECT(Heaps.GCStatus)
+	
+	(* called from Heaps.InvokeGC, i.e. this is a hidden upcall. However, it is necessary to take the Machine.Objects lock here since writing
+		    the set of variables here must not be interrupted, i.e. atomic writing of the set of variables is absolutely necessary.  They system may hang
+		    if the lock is not taken. *)
+		PROCEDURE SetgcOngoing(value: BOOLEAN);
+		VAR p: Heaps.ProcessLink; cur, r: Process; res: LONGINT; num: LONGINT; time: LONGINT;
+		BEGIN (* serialize writers *)
+			cur:= CurrentProcess();
+			IF value THEN
+				(*collect := TRUE; 
+				
+				TRACE(collect); 
+				collect := FALSE;
+				*)
+				Machine.Acquire( Machine.Heaps );
+				cur.context.r_sp := Machine.CurrentSP();
+				cur.context.r_bp := Machine.CurrentBP();
+				cur.context.r_pc := ADDRESS OF GCLoop;
+				TRACE(cur.context.r_sp, cur.context.r_bp, cur.context.r_pc);
+				SuspendActivities;
+				
+				Heaps.CollectGarbage( Modules.root );
+				Machine.Release( Machine.Heaps );
+				ResumeActivities;
+				finalizerCaller.Activate;
+
+				
+			END;
+		END SetgcOngoing;
+
+	END GCStatusExt;
+
 
 	
 	PROCEDURE BodyStarter;
@@ -635,13 +718,27 @@ TYPE
 	END GetContext;
 	
 	PROCEDURE SuspendActivities;
-	VAR t: Process;  
+	VAR t,me: Process;  res: LONGINT;
 	BEGIN
+		me := CurrentProcess();
+		t := root;
+				
+		WHILE t # NIL DO
+			IF (t # me) THEN  
+				Unix.ThrSuspend(t.threadId ); 
+			END;
+			t := t.nextProcess
+		END;
+	(*
+	VAR t, me: Process;  
+	BEGIN
+		
 		t := root;
 		WHILE t # NIL DO
 			IF (t # mainProcess) & (t # finCaller) THEN  Unix.ThrSuspend( t.threadId )  END;
 			t := t.nextProcess
 		END;
+	*)
 	END SuspendActivities;
 
 	PROCEDURE ResumeActivities;
@@ -665,19 +762,27 @@ TYPE
 	(*!	GCLoop gets called as last procedure in BootConsole (main thread). 
 		The stack of the main thread is not limited by the  boot parameter 'StackSize' !!
 	*)
+	
 	PROCEDURE GCLoop*;	(* Timer and GC activity *)
+	VAR cur: Process;
 	BEGIN
+		cur:= CurrentProcess();
 		SetPriority( GCPriority );
 		LOOP
 			IF collect THEN  
-				TRACE(collect);
+				TRACE(collect); 
 				collect := FALSE;
 				Machine.Acquire( Machine.Heaps );
+				cur.context.r_sp := Machine.CurrentSP();
+				cur.context.r_bp := Machine.CurrentBP();
+				cur.context.r_sp := ADDRESS OF GCLoop;
+
 				SuspendActivities;
+				
 				Heaps.CollectGarbage( Modules.root );
 				Machine.Release( Machine.Heaps );
 				ResumeActivities;
-				finalizerCaller.Start;
+				finalizerCaller.Activate;
 				Unix.ConSignal( gcFinished );
 			ELSE
 				Unix.ThrSleep( 10 ); 
@@ -688,6 +793,7 @@ TYPE
 	
 	
 	
+	
 	PROCEDURE CurrentProcessTime*(): HUGEINT;
 	BEGIN
 		RETURN  Machine.GetTimer()
@@ -770,6 +876,9 @@ TYPE
 		NEW( finalizerCaller );
 		(*
 		Heaps.saveSP := SaveSP;
+		*)
+		Heaps.gcStatus := GCStatusFactory()
+		(*
 		Heaps.GC := InvokeGC;
 		Heaps.InvokeGC := InvokeGC;
 		*)
@@ -781,6 +890,15 @@ TYPE
 		Machine.Shutdown(FALSE);
 	END Final;
 
+
+	PROCEDURE GCStatusFactory(): Heaps.GCStatus;
+	VAR gcStatusExt : GCStatusExt;
+	BEGIN
+		ASSERT(Heaps.gcStatus = NIL);
+		NEW(gcStatusExt);
+		RETURN gcStatusExt
+	END GCStatusFactory;
+
 BEGIN
 	TRACE("Objects.Body1");
 	Init;

+ 13 - 1
source/Generic.Unix.Traps.Mod

@@ -75,6 +75,16 @@ VAR
 		Machine.Release( Machine.Trap )
 	END FinishTrap;
 	
+	PROCEDURE Registers(CONST c:Unix.McontextDesc; w: Streams.Writer);
+	BEGIN
+		w.String("EAX= "); w.Address(c.r_ax);
+		w.String(" EBX= "); w.Address(c.r_bx);
+		w.String(" ECX= "); w.Address(c.r_cx);
+		w.String(" EDX= "); w.Address(c.r_dx);
+		w.String(" ESI= "); w.Address(c.r_si);
+		w.String(" EDI= "); w.Address(c.r_di);
+		w.Ln;
+	END Registers;
 	
 
 	PROCEDURE Trap( sig: LONGINT;  ucp: Unix.Ucontext;  fatalerror: BOOLEAN );  
@@ -99,6 +109,7 @@ VAR
 			w := TrapWriters.GetWriter();
 			w.Char( 1X );   (* begin of trap text *) 
 		END;
+		
 
 		w.Ln;  
 		w.String( Machine.version ); w.String( "   " );  TimeTag( w );  w.Ln; 
@@ -108,13 +119,13 @@ VAR
 		ELSE  
 			w.String( "[recursive Trap] " )  
 		END;  
+		sp := ucp.mc.r_sp;
 		CASE sig OF 
 		| 1:		w.String( "1 (Hangup signal)" );   
 		| 2:  	w.String( "2 (User interrupt)" );   
 		| 3:		w.String( "3 (Quit signal)" );   
 		| 4:  	w.String( "4 (Illegal instruction)" );   
 		| 5:   	w.String( "5." );  
-				sp := ucp.mc.r_sp;
 				S.GET( sp, trapno );  w.Int( trapno, 0 );  
 				CASE trapno OF 
 				| 1:		w.String( "  (WITH guard failed)" ) 
@@ -151,6 +162,7 @@ VAR
 			w.String( "    sp = " );  w.Address( sp );  w.String( ", fp = " );  w.Address( bp ); 
 			w.String( ", pc = " );  w.Address( pc );  w.Ln;  
 			w.Ln;  
+			Registers(ucp.mc,w);
 			Reflection.StackTraceBack( w, pc, bp, sp, Objects.GetStackBottom( process ), TRUE, FALSE );
 			SearchExceptionHandler( process, ucp, handler ); 
 		END;

+ 1 - 0
source/Heaps.Mod

@@ -342,6 +342,7 @@ BEGIN
 			Inspect(protected.awaitingLock.head);
 			Inspect(protected.awaitingCond.head);
 			Inspect(protected.lockedBy);
+			Inspect(protected.lock);
 		END;
 		orgHeapBlock := ExtractFromMarkList();
 	END;

+ 1 - 1
source/Unix.Kernel.Mod

@@ -199,7 +199,7 @@ END Left;
 BEGIN
 	ASSERT(1000 MOD Second = 0);	(* for Elapsed *)
 	second := Second;
-	
+	Heaps.GC := Heaps.InvokeGC;
 	Machine.Acquire(Machine.TraceOutput);
 	Trace.String( Machine.version ); Trace.String(": Kernel: Initialized and started."); Trace.Ln;
 	Machine.Release(Machine.TraceOutput);