[m-rev.] for review: thread safe exceptions

Peter Ross pro at missioncriticalit.com
Fri Feb 28 20:50:47 AEDT 2003


Hi,

Well the previous patch didn't work as the thread local storage wasn't
being initialised in the hl* grades.

This change is now bootstrapping and if it succeeds I will check it
in.


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


Estimated hours taken: 4
Branches: main, release

Get exception handling working in the parallel grades.

library/exception.m:
	Define the macros ML_GET_EXCEPTION_HANDLER and
	ML_SET_EXCEPTION_HANDLER which either save the exception
	handler into thread local storage for the parallel grades or
	save it into a global variable.

runtime/mercury_context.c:
	Initialise the thread local storage for holding the exception
	handler.
	
runtime/mercury_thread.c:
runtime/mercury_thread.h:
	Define the key used to access the thread local storage for the
	exception handler.


Index: library/exception.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/exception.m,v
retrieving revision 1.72.2.1
diff -u -r1.72.2.1 exception.m
--- library/exception.m	25 Nov 2002 00:27:32 -0000	1.72.2.1
+++ library/exception.m	28 Feb 2003 09:39:34 -0000
@@ -777,25 +777,34 @@
 	MR_Univ		exception;
 } ML_ExceptionHandler;
 
-/*
-** XXX This is currently not thread-safe!
-** The ML_exception_handler variable should be thread-local.
-*/
-ML_ExceptionHandler *ML_exception_handler;
+#ifndef MR_THREAD_SAFE
+  ML_ExceptionHandler	*ML_exception_handler;
+#endif
+
+#ifdef MR_THREAD_SAFE
+  #define ML_GET_EXCEPTION_HANDLER	MR_GETSPECIFIC(MR_exception_handler_key)
+  #define ML_SET_EXCEPTION_HANDLER(val)	\
+  	pthread_setspecific(MR_exception_handler_key, (val))
+#else  /* !MR_THREAD_SAFE */
+  #define ML_GET_EXCEPTION_HANDLER	ML_exception_handler
+  #define ML_SET_EXCEPTION_HANDLER(val)	ML_exception_handler = (val)
+#endif /* !MR_THREAD_SAFE */
 
 void MR_CALL
 mercury__exception__builtin_throw_1_p_0(MR_Univ exception)
 {
-	if (ML_exception_handler == NULL) {
+	ML_ExceptionHandler *exception_handler = ML_GET_EXCEPTION_HANDLER;
+
+	if (exception_handler == NULL) {
 		ML_report_uncaught_exception((MR_Word) exception);
 		exit(EXIT_FAILURE);
 	} else {
 #ifdef	MR_DEBUG_JMPBUFS
 		fprintf(stderr, ""throw longjmp %p\\n"",
-			ML_exception_handler->handler);
+			exception_handler->handler);
 #endif
-		ML_exception_handler->exception = exception;
-		longjmp(ML_exception_handler->handler, 1);
+		exception_handler->exception = exception;
+		longjmp(exception_handler->handler, 1);
 	}
 }
 
@@ -880,8 +889,8 @@
 	ML_ExceptionHandler this_handler;
 	ML_DECLARE_AGC_HANDLER
 	
-	this_handler.prev = ML_exception_handler;
-	ML_exception_handler = &this_handler;
+	this_handler.prev = ML_GET_EXCEPTION_HANDLER;
+	ML_SET_EXCEPTION_HANDLER(&this_handler);
 
 	ML_INSTALL_AGC_HANDLER(type_info, handler_pred);
 
@@ -891,7 +900,7 @@
 
 	if (setjmp(this_handler.handler) == 0) {
 		ML_call_goal_det_handcoded(type_info, pred, output);
-		ML_exception_handler = this_handler.prev;
+		ML_SET_EXCEPTION_HANDLER(this_handler.prev);
 		ML_UNINSTALL_AGC_HANDLER();
 	} else {
 #ifdef	MR_DEBUG_JMPBUFS
@@ -899,7 +908,7 @@
 			this_handler.handler);
 #endif
 
-		ML_exception_handler = this_handler.prev;
+		ML_SET_EXCEPTION_HANDLER(this_handler.prev);
 		ML_UNINSTALL_AGC_HANDLER();
 		ML_call_handler_det_handcoded(
 			ML_AGC_LOCAL(type_info), ML_AGC_LOCAL(handler_pred),
@@ -914,8 +923,8 @@
 	ML_ExceptionHandler this_handler;
 	ML_DECLARE_AGC_HANDLER
 
-	this_handler.prev = ML_exception_handler;
-	ML_exception_handler = &this_handler;
+	this_handler.prev = ML_GET_EXCEPTION_HANDLER;
+	ML_SET_EXCEPTION_HANDLER(&this_handler);
 
 	ML_INSTALL_AGC_HANDLER(type_info, handler_pred);
 
@@ -926,7 +935,7 @@
 	if (setjmp(this_handler.handler) == 0) {
 		MR_bool result = ML_call_goal_semi_handcoded(type_info, pred,
 			output);
-		ML_exception_handler = this_handler.prev;
+		ML_SET_EXCEPTION_HANDLER(this_handler.prev);
 		ML_UNINSTALL_AGC_HANDLER();
 		return result;
 	} else {
@@ -935,7 +944,7 @@
 			this_handler.handler);
 #endif
 
-		ML_exception_handler = this_handler.prev;
+		ML_SET_EXCEPTION_HANDLER(this_handler.prev);
 		ML_UNINSTALL_AGC_HANDLER();
 		ML_call_handler_det_handcoded(
 			ML_AGC_LOCAL(type_info), ML_AGC_LOCAL(handler_pred),
@@ -962,7 +971,7 @@
 		** need to restore the previous exception
 		** handler before calling its continuation
 		*/
-		ML_exception_handler = this_handler.prev;
+		ML_SET_EXCEPTION_HANDLER(this_handler.prev);
 		(*cont)();
 
 		/* 
@@ -971,11 +980,11 @@
 		** nondet goal.  Thus we need to re-establish
 		** its exception handler.
 		*/
-		ML_exception_handler = &this_handler;
+		ML_SET_EXCEPTION_HANDLER(&this_handler);
 	}
 
-	this_handler.prev = ML_exception_handler;
-	ML_exception_handler = &this_handler;
+	this_handler.prev = ML_GET_EXCEPTION_HANDLER;
+	ML_SET_EXCEPTION_HANDLER(&this_handler);
 
 	ML_INSTALL_AGC_HANDLER(type_info, handler_pred);
 
@@ -986,7 +995,7 @@
 	if (setjmp(this_handler.handler) == 0) {
 		ML_call_goal_non_handcoded(type_info, pred, output,
 			success_cont);
-		ML_exception_handler = this_handler.prev;
+		ML_SET_EXCEPTION_HANDLER(this_handler.prev);
 		ML_UNINSTALL_AGC_HANDLER();
 	} else {
 #ifdef	MR_DEBUG_JMPBUFS
@@ -994,7 +1003,7 @@
 			this_handler.handler);
 #endif
 
-		ML_exception_handler = this_handler.prev;
+		ML_SET_EXCEPTION_HANDLER(this_handler.prev);
 		ML_UNINSTALL_AGC_HANDLER();
 		ML_call_handler_det_handcoded(
 			ML_AGC_LOCAL(type_info), ML_AGC_LOCAL(handler_pred),
@@ -1021,7 +1030,7 @@
 	** need to restore the previous exception
 	** handler before calling its continuation
 	*/
-	ML_exception_handler = env->this_handler.prev;
+	ML_SET_EXCEPTION_HANDLER(env->this_handler.prev);
 	(*env->cont)(env->cont_env);
 
 	/* 
@@ -1030,7 +1039,7 @@
 	** nondet goal.  Thus we need to re-establish
 	** its exception handler.
 	*/
-	ML_exception_handler = &env->this_handler;
+	ML_SET_EXCEPTION_HANDLER(&env->this_handler);
 }
 
 void MR_CALL
@@ -1043,8 +1052,8 @@
 	locals.cont = cont;
 	locals.cont_env = cont_env;
 
-	locals.this_handler.prev = ML_exception_handler;
-	ML_exception_handler = &locals.this_handler;
+	locals.this_handler.prev = ML_GET_EXCEPTION_HANDLER;
+	ML_SET_EXCEPTION_HANDLER(&locals.this_handler);
 
 	ML_INSTALL_AGC_HANDLER(type_info, handler_pred);
 
@@ -1061,7 +1070,7 @@
 		** need to restore the previous exception
 		** handler 
 		*/
-		ML_exception_handler = locals.this_handler.prev;
+		ML_SET_EXCEPTION_HANDLER(locals.this_handler.prev);
 		ML_UNINSTALL_AGC_HANDLER();
 		return;
 	} else {
@@ -1078,7 +1087,7 @@
 #endif
 
 
-		ML_exception_handler = locals.this_handler.prev;
+		ML_SET_EXCEPTION_HANDLER(locals.this_handler.prev);
 		ML_UNINSTALL_AGC_HANDLER();
 		ML_call_handler_det_handcoded(
 			ML_AGC_LOCAL(type_info), ML_AGC_LOCAL(handler_pred),
Index: runtime/mercury_context.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_context.c,v
retrieving revision 1.33
diff -u -r1.33 mercury_context.c
--- runtime/mercury_context.c	4 Jun 2002 09:12:24 -0000	1.33
+++ runtime/mercury_context.c	28 Feb 2003 09:39:35 -0000
@@ -67,6 +67,8 @@
 
 	MR_KEY_CREATE(&MR_engine_base_key, NULL);
 
+	MR_KEY_CREATE(&MR_exception_handler_key, NULL);
+
 #endif
 }
 
Index: runtime/mercury_thread.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_thread.c,v
retrieving revision 1.19
diff -u -r1.19 mercury_thread.c
--- runtime/mercury_thread.c	18 Feb 2002 07:01:21 -0000	1.19
+++ runtime/mercury_thread.c	28 Feb 2003 09:39:35 -0000
@@ -15,6 +15,7 @@
 #include <errno.h>
 
 #ifdef	MR_THREAD_SAFE
+  MercuryThreadKey MR_exception_handler_key;
   MercuryThreadKey MR_engine_base_key;
   MercuryLock MR_global_lock;
 #endif
Index: runtime/mercury_thread.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_thread.h,v
retrieving revision 1.11
diff -u -r1.11 mercury_thread.h
--- runtime/mercury_thread.h	18 Feb 2002 07:01:21 -0000	1.11
+++ runtime/mercury_thread.h	28 Feb 2003 09:39:35 -0000
@@ -103,6 +103,12 @@
 	*/
   extern MercuryLock MR_global_lock;
 
+  	/*
+	** MR_exception_handler_key stores a key which can be used to get
+	** the current exception handler for the current thread.
+	*/
+  extern MercuryThreadKey MR_exception_handler_key;
+
 #else /* not MR_THREAD_SAFE */
 
   #define MR_LOCK(nothing, from)	do { } while (0)

--------------------------------------------------------------------------
mercury-reviews mailing list
post:  mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the reviews mailing list