浏览代码

removed duplicated call to Modules.Initialize in Modules.ThisModule;
changed the way how concurrent calls to Modules.CetProcedure are handled; in cases when one of the threads has already initiated module body execution but has not yet finished it, other threads can trap at "ASSERT(m.init)"; to avoid that the following was introduced: threads, which see that the module is not yet initialized, wait until module initialization completes or timeout expires (currently ~3 seconds for 1 GHz CPU); in case if timeout expired return NIL

git-svn-id: https://svn.inf.ethz.ch/svn/lecturers/a2/trunk@6481 8c9fc860-2736-0410-a75d-ab315db34111

eth.morozova 9 年之前
父节点
当前提交
f70ed14610
共有 1 个文件被更改,包括 17 次插入4 次删除
  1. 17 4
      source/Generic.Modules.Mod

+ 17 - 4
source/Generic.Modules.Mod

@@ -458,7 +458,7 @@ BEGIN
 			Machine.Release (Machine.TraceOutput);
 		END;
 		p := m;
-		IF (m # NIL) & ~m.published THEN	(* no race on m.published, as update is done below in Publish *)			Initialize(m);
+		IF (m # NIL) & ~m.published THEN	(* no race on m.published, as update is done below in Publish *)
 			Initialize(m);
 		END;
 		IF trace THEN
@@ -515,13 +515,26 @@ BEGIN
 	RETURN m
 END ThisModuleByAdr;
 
+CONST ModuleInitTimeout = HUGEINT(3000000000); (* Timeout for waiting until a module get initialized, 3 seconds for 1 GHz CPU *)
+
 (*	Retrieve a procedure given a module name, the procedure name and some type information (kernel call) *)
 PROCEDURE GetProcedure*(CONST moduleName, procedureName : ARRAY OF CHAR; argTdAdr, retTdAdr : ADDRESS; VAR entryAdr : ADDRESS);
-VAR module : Module; ignoreMsg : ARRAY 32 OF CHAR; i, res : LONGINT;
+VAR module : Module; ignoreMsg : ARRAY 32 OF CHAR; i, res : LONGINT; t: HUGEINT;
 BEGIN
 	module := ThisModule(moduleName, res, ignoreMsg);
 	IF (res = Ok) THEN
-		ASSERT(module.init);	(* module body must have been called (see note at end of module) *)
+		(*! 
+			module body must have been called (see note at the end of this module);
+			return NIL if the module does not get initialized within the specified timeout
+		*)
+		IF ~module.init THEN
+			t := Machine.GetTimer();
+			WHILE ~module.init & (Machine.GetTimer() - t < ModuleInitTimeout) DO END;
+			IF ~module.init THEN (* timeout has expired *)
+				RETURN;
+			END;
+		END;
+
 		Machine.Acquire(Machine.Modules);
 		i := 0; entryAdr := Heaps.NilVal;
 		WHILE (entryAdr = Heaps.NilVal) & (i # LEN(module.command^)) DO
@@ -1020,5 +1033,5 @@ END Modules.
 06.10.1998	pjm	FreeModule
 
 Note:
-o ThisCommand race: process A calls ThisModule, the module is published, but before its body has finished executing, process B calls ThisCommand, causing the assert (m.init) to fail. Process B should perhaps wait in this case until the body has executed, or ThisCommand should return NIL (but that will just move the race to the user).
+o GetProcedure race: process A calls ThisModule, the module is published, but before its body has finished executing, process B calls GetProcedure, causing the assert (m.init) to fail. Process B should perhaps wait in this case until the body has executed, or GetProcedure should return NIL (but that will just move the race to the user).
 *)