[m-dev.] for review: add thread fixes for pragma export in .par grade.

Tyson Dowd trd at cs.mu.OZ.AU
Fri Aug 25 17:25:00 AEST 2000


Hi,

This one is required for getting MCORBA working properly in
a multi-threading environment.  

Tom might want to review this, since he helped me nut out this solution.

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


Estimated hours taken: 4

When exposing a Mercury predicate to C, you need to make sure there is
an engine for it to run in before calling it.

For single-threaded programs, we simply make sure that the engine is run
soon after main().  But for multi-threaded programs, code written in C
could create new threads and call Mercury using one of these threads.
Of course the same code could be called from a thread where there is
already a Mercury engine.

This change fixes this problem by creating a Mercury engine if and only
if it is required.

compiler/export.m:
	Run init_engine when calling into Mercury.  It is important to
	run this after we save the C registers, but before we try to use
	the Mercury registers.

runtime/mercury_thread.c:
runtime/mercury_thread.h:
	If an existing Mercury engine is already in the current thread,
	don't create a new one.


Index: compiler/export.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/export.m,v
retrieving revision 1.35
diff -u -r1.35 export.m
--- compiler/export.m	2000/08/09 07:46:29	1.35
+++ compiler/export.m	2000/08/24 05:34:58
@@ -127,10 +127,24 @@
 	%		/* save the registers that our C caller may be using */
 	%	save_regs_to_mem(c_regs);
 	%
-	%		/* restore Mercury's registers that were saved as */
-	%		/* we entered C from Mercury (the process must    */
-	%		/* always start in Mercury so that we can 	  */
-	%		/* init_engine() etc.)				  */
+	%		/* 
+	%		** start a new Mercury engine inside this POSIX 
+	%		** thread, if necessary (the C code may be 
+	%		** multi-threaded itself).
+	%		*/
+	%
+	% #if MR_THREAD_SAFE
+	% 	init_thread(MR_use_now);
+	% #endif 
+	%
+	%		/* 
+	%		** restore Mercury's registers that were saved as
+	%		** we entered C from Mercury.  For single threaded
+	%		** programs the process must always start in Mercury
+	%		** so that we can init_engine() etc.  For
+	%		** multi-threaded init_thread (above) takes care
+	%		** of making a new engine if required.
+	%		*/
 	%	restore_registers();
 	%	<copy input arguments from Mercury__Arguments into registers>
 	%		/* save the registers which may be clobbered      */
@@ -196,6 +210,9 @@
 				MaybeDeclareRetval,
 				"\n",
 				"\tsave_regs_to_mem(c_regs);\n", 
+				"#if MR_THREAD_SAFE\n",
+				"\tinit_thread(MR_use_now);\n", 
+				"#endif\n",
 				"\trestore_registers();\n", 
 				InputArgs,
 				"\tsave_transient_registers();\n",
Index: runtime/mercury_thread.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_thread.c,v
retrieving revision 1.11
diff -u -r1.11 mercury_thread.c
--- runtime/mercury_thread.c	2000/02/09 19:32:36	1.11
+++ runtime/mercury_thread.c	2000/08/24 23:36:32
@@ -71,6 +71,16 @@
 {
 	MercuryEngine *eng;
 
+#ifdef MR_THREAD_SAFE
+		/* 
+		** Check to see whether there is already an engine 
+		** that is initialized in this thread.  If so we just
+		** return, there's nothing for us to do.
+		*/
+	if (pthread_getspecific(MR_engine_base_key)) {
+		return;
+	}
+#endif
 	eng = create_engine();
 
 #ifdef MR_THREAD_SAFE
Index: runtime/mercury_thread.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_thread.h,v
retrieving revision 1.6
diff -u -r1.6 mercury_thread.h
--- runtime/mercury_thread.h	1998/12/16 17:51:30	1.6
+++ runtime/mercury_thread.h	2000/08/25 06:28:11
@@ -131,6 +131,8 @@
 ** 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.
 */
 void	init_thread(MR_when_to_use);
 


-- 
       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