[m-dev.] for review: fix :- export with threads memory leak

Tyson Dowd trd at cs.mu.OZ.AU
Wed Sep 27 15:12:03 AEDT 2000


Hi,

Roy Ward reported that MCORBA seemed to chew up 4Mb each time you call
it.  This is a fix for that problem.

===================================================================


Estimated hours taken: 2.5

Fix a bug with :- export and threads.  

Each time we called from C to Mercury, we initialized the thread engine
(if necessary).  

This allocated a new context every time we entered Mercury.
Unfortunately, these contexts were never released, so every entry into
Mercury from C cost about 4Mb of memory (almost all of which is the
deterministic stack).  In a busy CORBA application you would run out of
memory really quickly.

compiler/export.m:
	When initializing threads, remember whether we are responsible
	for finalizing the engine (e.g. if we are the first C->Mercury
	call to create the engine, we'll be the last to exit it and should 
	clean up afterwards).

runtime/mercury_engine.c:
	Finalize engines by destroying the context (this will put the
	memory zones onto a free list).

runtime/mercury_thread.c:
runtime/mercury_thread.h:
	Make init_thread return TRUE if an engine has been allocated and
	it is the caller's responsibility to finialize it.




Index: compiler/export.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/export.m,v
retrieving revision 1.36
diff -u -r1.36 export.m
--- compiler/export.m	2000/08/30 07:19:52	1.36
+++ compiler/export.m	2000/09/27 02:45:59
@@ -118,11 +118,14 @@
 	%			/* Word for input, Word* for output */
 	% {
 	% #if NUM_REAL_REGS > 0
-	%	Word c_regs[NUM_REAL_REGS];
+	%	MR_Word c_regs[NUM_REAL_REGS];
 	% #endif
 	% #if FUNCTION
-	%	Word retval;
+	%	MR_Word retval;
 	% #endif
+	% #if MR_THREAD_SAFE
+	% 	MR_Bool must_finalize_engine;
+	% #endif 
 	%
 	%		/* save the registers that our C caller may be using */
 	%	save_regs_to_mem(c_regs);
@@ -134,7 +137,7 @@
 	%		*/
 	%
 	% #if MR_THREAD_SAFE
-	% 	init_thread(MR_use_now);
+	% 	must_finalize_engine = init_thread(MR_use_now);
 	% #endif 
 	%
 	%		/* 
@@ -166,6 +169,11 @@
 	%	<copy return value register into retval>
 	% #endif
 	%	<copy output args from registers into *Mercury__Arguments>
+	% #if MR_THREAD_SAFE
+	% 	if (must_finalize_engine) {
+	% 		finalize_thread_engine();
+	% 	}
+	% #endif 
 	%	restore_regs_from_mem(c_regs);
 	% #if SEMIDET
 	%	return TRUE;
@@ -207,11 +215,14 @@
 				"#if NUM_REAL_REGS > 0\n",
 				"\tMR_Word c_regs[NUM_REAL_REGS];\n",
 				"#endif\n",
+				"#if MR_THREAD_SAFE\n",
+				"\tMR_Bool must_finalize_engine;\n", 
+				"#endif\n",
 				MaybeDeclareRetval,
 				"\n",
 				"\tsave_regs_to_mem(c_regs);\n", 
 				"#if MR_THREAD_SAFE\n",
-				"\tinit_thread(MR_use_now);\n", 
+				"\tmust_finalize_engine = init_thread(MR_use_now);\n", 
 				"#endif\n",
 				"\trestore_registers();\n", 
 				InputArgs,
@@ -221,6 +232,11 @@
 				"\trestore_transient_registers();\n",
 				MaybeFail,
 				OutputArgs,
+				"#if MR_THREAD_SAFE\n",
+				"\tif (must_finalize_engine) {\n", 
+				"\t\t finalize_thread_engine();\n", 
+				"\t}\n", 
+				"#endif\n",
 				"\trestore_regs_from_mem(c_regs);\n", 
 				MaybeSucceed,
 				"}\n\n"],
Index: runtime/mercury_engine.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_engine.c,v
retrieving revision 1.25
diff -u -r1.25 mercury_engine.c
--- runtime/mercury_engine.c	2000/09/14 11:12:16	1.25
+++ runtime/mercury_engine.c	2000/09/27 01:46:01
@@ -128,7 +128,7 @@
 
 void finalize_engine(MercuryEngine *eng)
 {
-	
+	destroy_context(eng->this_context);
 }
 
 /*---------------------------------------------------------------------------*/
Index: runtime/mercury_thread.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_thread.c,v
retrieving revision 1.12
diff -u -r1.12 mercury_thread.c
--- runtime/mercury_thread.c	2000/08/30 07:20:16	1.12
+++ runtime/mercury_thread.c	2000/09/27 01:47:40
@@ -66,7 +66,7 @@
 
 #endif /* MR_THREAD_SAFE */
 
-void
+MR_Bool
 init_thread(MR_when_to_use when_to_use)
 {
 	MercuryEngine *eng;
@@ -78,7 +78,7 @@
 		** return, there's nothing for us to do.
 		*/
 	if (pthread_getspecific(MR_engine_base_key)) {
-		return;
+		return FALSE;
 	}
 #endif
 	eng = create_engine();
@@ -108,14 +108,31 @@
 			(void) MR_call_engine(ENTRY(do_runnext), FALSE);
 
 			destroy_engine(eng);
-			return;
+			return FALSE;
 
 		case MR_use_now :
-			return;
+			return TRUE;
 		
 		default:
 			fatal_error("init_thread was passed a bad value");
 	}
+}
+
+/* 
+** Release resources associated with this thread.
+** XXX calling destroy_engine(eng) appears to segfault.
+** This should probably be investigated and fixed.
+*/
+void
+finalize_thread_engine(void)
+{
+#ifdef MR_THREAD_SAFE
+	MercuryEngine *eng;
+
+	eng = pthread_getspecific(MR_engine_base_key);
+	pthread_setspecific(MR_engine_base_key, NULL);
+	finalize_engine(eng);
+#endif
 }
 
 #ifdef	MR_THREAD_SAFE
Index: runtime/mercury_thread.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_thread.h,v
retrieving revision 1.7
diff -u -r1.7 mercury_thread.h
--- runtime/mercury_thread.h	2000/08/30 07:20:17	1.7
+++ runtime/mercury_thread.h	2000/09/27 01:45:10
@@ -130,10 +130,23 @@
 /*
 ** Create and initialize a new Mercury engine running in the current
 ** POSIX thread.
+**
 ** See the comments above for the meaning of the argument.
 ** If there is already a Mercury engine running in the current POSIX
 ** thread then init_thread is just a no-op.
+**
+** Returns TRUE if a Mercury engine was created as a result of this
+** call *and* it is the caller's responsibility to finalize it (it is
+** intended that the caller can store the return value and call
+** finalize_thread_engine if it is true).
 */
-void	init_thread(MR_when_to_use);
+int	init_thread(MR_when_to_use);
+/*
+** Finalize the thread engine running in the current POSIX thread.
+** This will release the resources used by this thread -- this is very
+** important because the memory used for the det stack for each thread
+** can be re-used by the next init_thread.
+*/
+void    finalize_thread_engine(void);
 
 #endif


-- 
       Tyson Dowd           # 
                            #  Surreal humour isn't everyone's cup of fur.
     trd at cs.mu.oz.au        # 
http://www.cs.mu.oz.au/~trd #
--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to:       mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions:          mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------



More information about the developers mailing list